diff options
author | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2014-03-28 22:45:38 +0000 |
---|---|---|
committer | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2014-03-28 22:45:38 +0000 |
commit | 6af9bc565ecae263c56acf920a495631b41dd3e6 (patch) | |
tree | a33f54f68bfbb81e4f85a683583fa529f0870191 /clang/lib/AST/DeclObjC.cpp | |
parent | 237769ede56a500f3e6f36dffbdb3f337c5f0ab4 (diff) | |
download | bcm5719-llvm-6af9bc565ecae263c56acf920a495631b41dd3e6.tar.gz bcm5719-llvm-6af9bc565ecae263c56acf920a495631b41dd3e6.zip |
[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
Diffstat (limited to 'clang/lib/AST/DeclObjC.cpp')
-rw-r--r-- | clang/lib/AST/DeclObjC.cpp | 39 |
1 files changed, 30 insertions, 9 deletions
diff --git a/clang/lib/AST/DeclObjC.cpp b/clang/lib/AST/DeclObjC.cpp index 84e329bf186..c53dba3bfdf 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; } |