[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;
}
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 {
switch (data().InheritedDesignatedInitializers) {
case DefinitionData::IDI_Inherited:
@ -360,17 +374,10 @@ bool ObjCInterfaceDecl::inheritsDesignatedInitializers() const {
case DefinitionData::IDI_NotInherited:
return false;
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
// don't know if any of them is a designated initializer to avoid possible
// misleading warnings.
if (isIntroducingInitializers) {
if (isIntroducingInitializers(this)) {
data().InheritedDesignatedInitializers = DefinitionData::IDI_NotInherited;
return false;
} else {
@ -398,6 +405,11 @@ void ObjCInterfaceDecl::getDesignatedInitializers(
for (const auto *MD : IFace->instance_methods())
if (MD->isThisDeclarationADesignatedInitializer())
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,
@ -412,13 +424,22 @@ bool ObjCInterfaceDecl::isDesignatedInitializer(Selector Sel,
if (!IFace)
return false;
if (const ObjCMethodDecl *MD = IFace->getMethod(Sel, /*isInstance=*/true)) {
if (const ObjCMethodDecl *MD = IFace->getInstanceMethod(Sel)) {
if (MD->isThisDeclarationADesignatedInitializer()) {
if (InitMethod)
*InitMethod = MD;
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;
}

View File

@ -27,7 +27,7 @@ __attribute__((objc_root_class))
-(void)meth {}
-(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)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}} \
// expected-warning {{secondary initializer missing a 'self' call to another initializer}}
@end
@ -36,9 +36,12 @@ __attribute__((objc_root_class))
@interface B1
-(id)initB1 NS_DESIGNATED_INITIALIZER; // expected-note 6 {{method marked as designated initializer of the class here}}
-(id)initB2;
-(id)initB3 NS_DESIGNATED_INITIALIZER; // expected-note 4 {{method marked as designated initializer of the class here}}
@end
@interface B1()
-(id)initB3 NS_DESIGNATED_INITIALIZER; // expected-note 4 {{method marked as designated initializer of the class here}}
@end;
@implementation B1
-(id)initB1 { return 0; }
-(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)initS2 NS_DESIGNATED_INITIALIZER;
-(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;
@end
@interface S1()
-(id)initS4 NS_DESIGNATED_INITIALIZER; // expected-note 2 {{method marked as designated initializer of the class here}}
@end
@implementation S1
-(id)initS1 { // expected-warning {{designated initializer missing a 'super' call to a designated initializer of the super class}}
return 0;