From 6af9bc565ecae263c56acf920a495631b41dd3e6 Mon Sep 17 00:00:00 2001 From: Argyrios Kyrtzidis Date: Fri, 28 Mar 2014 22:45:38 +0000 Subject: [PATCH] [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 --- clang/lib/AST/DeclObjC.cpp | 39 +++++++++++++++++----- clang/test/SemaObjC/attr-designated-init.m | 12 +++++-- 2 files changed, 39 insertions(+), 12 deletions(-) diff --git a/clang/lib/AST/DeclObjC.cpp b/clang/lib/AST/DeclObjC.cpp index 84e329bf1862..c53dba3bfdfd 100644 --- a/clang/lib/AST/DeclObjC.cpp +++ b/clang/lib/AST/DeclObjC.cpp @@ -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; } diff --git a/clang/test/SemaObjC/attr-designated-init.m b/clang/test/SemaObjC/attr-designated-init.m index c743afe82fb0..6ef34390069a 100644 --- a/clang/test/SemaObjC/attr-designated-init.m +++ b/clang/test/SemaObjC/attr-designated-init.m @@ -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;