[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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue