[SemaObjC] For the semantics of the designated-initializer attribute, consider that the ObjC interface of the class
includes its class extensions. This is follow-up for rdar://16305347 llvm-svn: 205065
This commit is contained in:
parent
237769ede5
commit
6af9bc565e
|
@ -353,6 +353,20 @@ ObjCInterfaceDecl::findInterfaceWithDesignatedInitializers() const {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool isIntroducingInitializers(const ObjCInterfaceDecl *D) {
|
||||||
|
for (const auto *MD : D->instance_methods()) {
|
||||||
|
if (MD->getMethodFamily() == OMF_init && !MD->isOverriding())
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
for (const auto *Ext : D->visible_extensions()) {
|
||||||
|
for (const auto *MD : Ext->instance_methods()) {
|
||||||
|
if (MD->getMethodFamily() == OMF_init && !MD->isOverriding())
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool ObjCInterfaceDecl::inheritsDesignatedInitializers() const {
|
bool ObjCInterfaceDecl::inheritsDesignatedInitializers() const {
|
||||||
switch (data().InheritedDesignatedInitializers) {
|
switch (data().InheritedDesignatedInitializers) {
|
||||||
case DefinitionData::IDI_Inherited:
|
case DefinitionData::IDI_Inherited:
|
||||||
|
@ -360,17 +374,10 @@ bool ObjCInterfaceDecl::inheritsDesignatedInitializers() const {
|
||||||
case DefinitionData::IDI_NotInherited:
|
case DefinitionData::IDI_NotInherited:
|
||||||
return false;
|
return false;
|
||||||
case DefinitionData::IDI_Unknown: {
|
case DefinitionData::IDI_Unknown: {
|
||||||
bool isIntroducingInitializers = false;
|
|
||||||
for (const auto *MD : instance_methods()) {
|
|
||||||
if (MD->getMethodFamily() == OMF_init && !MD->isOverriding()) {
|
|
||||||
isIntroducingInitializers = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// If the class introduced initializers we conservatively assume that we
|
// If the class introduced initializers we conservatively assume that we
|
||||||
// don't know if any of them is a designated initializer to avoid possible
|
// don't know if any of them is a designated initializer to avoid possible
|
||||||
// misleading warnings.
|
// misleading warnings.
|
||||||
if (isIntroducingInitializers) {
|
if (isIntroducingInitializers(this)) {
|
||||||
data().InheritedDesignatedInitializers = DefinitionData::IDI_NotInherited;
|
data().InheritedDesignatedInitializers = DefinitionData::IDI_NotInherited;
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
|
@ -398,6 +405,11 @@ void ObjCInterfaceDecl::getDesignatedInitializers(
|
||||||
for (const auto *MD : IFace->instance_methods())
|
for (const auto *MD : IFace->instance_methods())
|
||||||
if (MD->isThisDeclarationADesignatedInitializer())
|
if (MD->isThisDeclarationADesignatedInitializer())
|
||||||
Methods.push_back(MD);
|
Methods.push_back(MD);
|
||||||
|
for (const auto *Ext : IFace->visible_extensions()) {
|
||||||
|
for (const auto *MD : Ext->instance_methods())
|
||||||
|
if (MD->isThisDeclarationADesignatedInitializer())
|
||||||
|
Methods.push_back(MD);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ObjCInterfaceDecl::isDesignatedInitializer(Selector Sel,
|
bool ObjCInterfaceDecl::isDesignatedInitializer(Selector Sel,
|
||||||
|
@ -412,13 +424,22 @@ bool ObjCInterfaceDecl::isDesignatedInitializer(Selector Sel,
|
||||||
if (!IFace)
|
if (!IFace)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (const ObjCMethodDecl *MD = IFace->getMethod(Sel, /*isInstance=*/true)) {
|
if (const ObjCMethodDecl *MD = IFace->getInstanceMethod(Sel)) {
|
||||||
if (MD->isThisDeclarationADesignatedInitializer()) {
|
if (MD->isThisDeclarationADesignatedInitializer()) {
|
||||||
if (InitMethod)
|
if (InitMethod)
|
||||||
*InitMethod = MD;
|
*InitMethod = MD;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (const auto *Ext : IFace->visible_extensions()) {
|
||||||
|
if (const ObjCMethodDecl *MD = Ext->getInstanceMethod(Sel)) {
|
||||||
|
if (MD->isThisDeclarationADesignatedInitializer()) {
|
||||||
|
if (InitMethod)
|
||||||
|
*InitMethod = MD;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ __attribute__((objc_root_class))
|
||||||
-(void)meth {}
|
-(void)meth {}
|
||||||
-(id)init NS_DESIGNATED_INITIALIZER { return 0; } // expected-error {{only applies to init methods of interface or class extension declarations}}
|
-(id)init NS_DESIGNATED_INITIALIZER { return 0; } // expected-error {{only applies to init methods of interface or class extension declarations}}
|
||||||
+(id)init { return 0; }
|
+(id)init { return 0; }
|
||||||
-(id)init3 { return 0; } // expected-warning {{secondary initializer missing a 'self' call to another initializer}}
|
-(id)init3 { return 0; }
|
||||||
-(id)init4 NS_DESIGNATED_INITIALIZER { return 0; } // expected-error {{only applies to init methods of interface or class extension declarations}} \
|
-(id)init4 NS_DESIGNATED_INITIALIZER { return 0; } // expected-error {{only applies to init methods of interface or class extension declarations}} \
|
||||||
// expected-warning {{secondary initializer missing a 'self' call to another initializer}}
|
// expected-warning {{secondary initializer missing a 'self' call to another initializer}}
|
||||||
@end
|
@end
|
||||||
|
@ -36,9 +36,12 @@ __attribute__((objc_root_class))
|
||||||
@interface B1
|
@interface B1
|
||||||
-(id)initB1 NS_DESIGNATED_INITIALIZER; // expected-note 6 {{method marked as designated initializer of the class here}}
|
-(id)initB1 NS_DESIGNATED_INITIALIZER; // expected-note 6 {{method marked as designated initializer of the class here}}
|
||||||
-(id)initB2;
|
-(id)initB2;
|
||||||
-(id)initB3 NS_DESIGNATED_INITIALIZER; // expected-note 4 {{method marked as designated initializer of the class here}}
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
@interface B1()
|
||||||
|
-(id)initB3 NS_DESIGNATED_INITIALIZER; // expected-note 4 {{method marked as designated initializer of the class here}}
|
||||||
|
@end;
|
||||||
|
|
||||||
@implementation B1
|
@implementation B1
|
||||||
-(id)initB1 { return 0; }
|
-(id)initB1 { return 0; }
|
||||||
-(id)initB2 { return 0; } // expected-warning {{secondary initializer missing a 'self' call to another initializer}}
|
-(id)initB2 { return 0; } // expected-warning {{secondary initializer missing a 'self' call to another initializer}}
|
||||||
|
@ -49,10 +52,13 @@ __attribute__((objc_root_class))
|
||||||
-(id)initS1 NS_DESIGNATED_INITIALIZER; // expected-note {{method marked as designated initializer of the class here}}
|
-(id)initS1 NS_DESIGNATED_INITIALIZER; // expected-note {{method marked as designated initializer of the class here}}
|
||||||
-(id)initS2 NS_DESIGNATED_INITIALIZER;
|
-(id)initS2 NS_DESIGNATED_INITIALIZER;
|
||||||
-(id)initS3 NS_DESIGNATED_INITIALIZER; // expected-note 2 {{method marked as designated initializer of the class here}}
|
-(id)initS3 NS_DESIGNATED_INITIALIZER; // expected-note 2 {{method marked as designated initializer of the class here}}
|
||||||
-(id)initS4 NS_DESIGNATED_INITIALIZER; // expected-note 2 {{method marked as designated initializer of the class here}}
|
|
||||||
-(id)initB1;
|
-(id)initB1;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
@interface S1()
|
||||||
|
-(id)initS4 NS_DESIGNATED_INITIALIZER; // expected-note 2 {{method marked as designated initializer of the class here}}
|
||||||
|
@end
|
||||||
|
|
||||||
@implementation S1
|
@implementation S1
|
||||||
-(id)initS1 { // expected-warning {{designated initializer missing a 'super' call to a designated initializer of the super class}}
|
-(id)initS1 { // expected-warning {{designated initializer missing a 'super' call to a designated initializer of the super class}}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
Loading…
Reference in New Issue