[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:
Argyrios Kyrtzidis 2014-03-28 22:45:38 +00:00
parent 237769ede5
commit 6af9bc565e
2 changed files with 39 additions and 12 deletions

View File

@ -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;
} }

View File

@ -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;