diff options
author | Douglas Gregor <dgregor@apple.com> | 2013-01-16 23:00:23 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2013-01-16 23:00:23 +0000 |
commit | 048fbfa302717d66b549f77469500408ca682117 (patch) | |
tree | 9580828c2e508b6ad946be861a75c9c62cab5da8 /clang/lib/Sema | |
parent | e8baf33712857bdb1deeb6100087cc3bc93861ea (diff) | |
download | bcm5719-llvm-048fbfa302717d66b549f77469500408ca682117.tar.gz bcm5719-llvm-048fbfa302717d66b549f77469500408ca682117.zip |
Rework the traversal of Objective-C categories and extensions to
consider (sub)module visibility.
The bulk of this change replaces myriad hand-rolled loops over the
linked list of Objective-C categories/extensions attached to an
interface declaration with loops using one of the four new category
iterator kinds:
visible_categories_iterator: Iterates over all visible categories
and extensions, hiding any that have their "hidden" bit set. This is
by far the most commonly used iterator.
known_categories_iterator: Iterates over all categories and
extensions, ignoring the "hidden" bit. This tends to be used for
redeclaration-like traversals.
visible_extensions_iterator: Iterates over all visible extensions,
hiding any that have their "hidden" bit set.
known_extensions_iterator: Iterates over all extensions, whether
they are visible to normal name lookup or not.
The effect of this change is that any uses of the visible_ iterators
will respect module-import visibility. See the new tests for examples.
Note that the old accessors for categories and extensions are gone;
there are *Raw() forms for some of them, for those (few) areas of the
compiler that have to manipulate the linked list of categories
directly. This is generally discouraged.
Part two of <rdar://problem/10634711>.
llvm-svn: 172665
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/SemaCodeComplete.cpp | 75 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 11 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclObjC.cpp | 104 | ||||
-rw-r--r-- | clang/lib/Sema/SemaLookup.cpp | 8 | ||||
-rw-r--r-- | clang/lib/Sema/SemaObjCProperty.cpp | 39 |
5 files changed, 134 insertions, 103 deletions
diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp index 5d5226dddd8..5cbba239be1 100644 --- a/clang/lib/Sema/SemaCodeComplete.cpp +++ b/clang/lib/Sema/SemaCodeComplete.cpp @@ -3433,9 +3433,11 @@ static void AddObjCProperties(ObjCContainerDecl *Container, } else if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)){ if (AllowCategories) { // Look through categories. - for (ObjCCategoryDecl *Category = IFace->getCategoryList(); - Category; Category = Category->getNextClassCategory()) - AddObjCProperties(Category, AllowCategories, AllowNullaryMethods, + for (ObjCInterfaceDecl::known_categories_iterator + Cat = IFace->known_categories_begin(), + CatEnd = IFace->known_categories_end(); + Cat != CatEnd; ++Cat) + AddObjCProperties(*Cat, AllowCategories, AllowNullaryMethods, CurContext, AddedProperties, Results); } @@ -4806,9 +4808,13 @@ static void AddObjCMethods(ObjCContainerDecl *Container, CurContext, Selectors, AllowSameLength, Results, false); // Add methods in categories. - for (ObjCCategoryDecl *CatDecl = IFace->getCategoryList(); CatDecl; - CatDecl = CatDecl->getNextClassCategory()) { - AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents, + for (ObjCInterfaceDecl::known_categories_iterator + Cat = IFace->known_categories_begin(), + CatEnd = IFace->known_categories_end(); + Cat != CatEnd; ++Cat) { + ObjCCategoryDecl *CatDecl = *Cat; + + AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents, NumSelIdents, CurContext, Selectors, AllowSameLength, Results, InOriginalClass); @@ -5076,11 +5082,14 @@ static ObjCMethodDecl *AddSuperSendCompletion(Sema &S, bool NeedSuperKeyword, // Check in categories or class extensions. if (!SuperMethod) { - for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category; - Category = Category->getNextClassCategory()) - if ((SuperMethod = Category->getMethod(CurMethod->getSelector(), + for (ObjCInterfaceDecl::known_categories_iterator + Cat = Class->known_categories_begin(), + CatEnd = Class->known_categories_end(); + Cat != CatEnd; ++Cat) { + if ((SuperMethod = Cat->getMethod(CurMethod->getSelector(), CurMethod->isInstanceMethod()))) break; + } } } @@ -5807,11 +5816,15 @@ void Sema::CodeCompleteObjCInterfaceCategory(Scope *S, llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames; NamedDecl *CurClass = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName); - if (ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass)) - for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category; - Category = Category->getNextClassCategory()) - CategoryNames.insert(Category->getIdentifier()); - + if (ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass)){ + for (ObjCInterfaceDecl::visible_categories_iterator + Cat = Class->visible_categories_begin(), + CatEnd = Class->visible_categories_end(); + Cat != CatEnd; ++Cat) { + CategoryNames.insert(Cat->getIdentifier()); + } + } + // Add all of the categories we know about. Results.EnterNewScope(); TranslationUnitDecl *TU = Context.getTranslationUnitDecl(); @@ -5853,11 +5866,14 @@ void Sema::CodeCompleteObjCImplementationCategory(Scope *S, Results.EnterNewScope(); bool IgnoreImplemented = true; while (Class) { - for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category; - Category = Category->getNextClassCategory()) - if ((!IgnoreImplemented || !Category->getImplementation()) && - CategoryNames.insert(Category->getIdentifier())) - Results.AddResult(Result(Category, 0), CurContext, 0, false); + for (ObjCInterfaceDecl::visible_categories_iterator + Cat = Class->visible_categories_begin(), + CatEnd = Class->visible_categories_end(); + Cat != CatEnd; ++Cat) { + if ((!IgnoreImplemented || !Cat->getImplementation()) && + CategoryNames.insert(Cat->getIdentifier())) + Results.AddResult(Result(*Cat, 0), CurContext, 0, false); + } Class = Class->getSuperClass(); IgnoreImplemented = false; @@ -6033,12 +6049,14 @@ static void FindImplementableMethods(ASTContext &Context, KnownMethods, InOriginalClass); // Add methods from any class extensions and categories. - for (const ObjCCategoryDecl *Cat = IFace->getCategoryList(); Cat; - Cat = Cat->getNextClassCategory()) - FindImplementableMethods(Context, const_cast<ObjCCategoryDecl*>(Cat), - WantInstanceMethods, ReturnType, + for (ObjCInterfaceDecl::visible_categories_iterator + Cat = IFace->visible_categories_begin(), + CatEnd = IFace->visible_categories_end(); + Cat != CatEnd; ++Cat) { + FindImplementableMethods(Context, *Cat, WantInstanceMethods, ReturnType, KnownMethods, false); - + } + // Visit the superclass. if (IFace->getSuperClass()) FindImplementableMethods(Context, IFace->getSuperClass(), @@ -6898,9 +6916,12 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, IFace = Category->getClassInterface(); if (IFace) { - for (ObjCCategoryDecl *Category = IFace->getCategoryList(); Category; - Category = Category->getNextClassCategory()) - Containers.push_back(Category); + for (ObjCInterfaceDecl::visible_categories_iterator + Cat = IFace->visible_categories_begin(), + CatEnd = IFace->visible_categories_end(); + Cat != CatEnd; ++Cat) { + Containers.push_back(*Cat); + } } for (unsigned I = 0, N = Containers.size(); I != N; ++I) { diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 5d655e24c06..994b2126132 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -10472,11 +10472,12 @@ void Sema::ActOnFields(Scope* S, Diag(ClsIvar->getLocation(), diag::note_previous_definition); continue; } - for (const ObjCCategoryDecl *ClsExtDecl = - IDecl->getFirstClassExtension(); - ClsExtDecl; ClsExtDecl = ClsExtDecl->getNextClassExtension()) { - if (const ObjCIvarDecl *ClsExtIvar = - ClsExtDecl->getIvarDecl(ClsFields[i]->getIdentifier())) { + for (ObjCInterfaceDecl::known_extensions_iterator + Ext = IDecl->known_extensions_begin(), + ExtEnd = IDecl->known_extensions_end(); + Ext != ExtEnd; ++Ext) { + if (const ObjCIvarDecl *ClsExtIvar + = Ext->getIvarDecl(ClsFields[i]->getIdentifier())) { Diag(ClsFields[i]->getLocation(), diag::err_duplicate_ivar_declaration); Diag(ClsExtIvar->getLocation(), diag::note_previous_definition); diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp index e6c5d92f5ed..54cf1c26260 100644 --- a/clang/lib/Sema/SemaDeclObjC.cpp +++ b/clang/lib/Sema/SemaDeclObjC.cpp @@ -849,16 +849,12 @@ ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc, if (CategoryName) { /// Check for duplicate interface declaration for this category - ObjCCategoryDecl *CDeclChain; - for (CDeclChain = IDecl->getCategoryList(); CDeclChain; - CDeclChain = CDeclChain->getNextClassCategory()) { - if (CDeclChain->getIdentifier() == CategoryName) { - // Class extensions can be declared multiple times. - Diag(CategoryLoc, diag::warn_dup_category_def) - << ClassName << CategoryName; - Diag(CDeclChain->getLocation(), diag::note_previous_definition); - break; - } + if (ObjCCategoryDecl *Previous + = IDecl->FindCategoryDeclaration(CategoryName)) { + // Class extensions can be declared multiple times, categories cannot. + Diag(CategoryLoc, diag::warn_dup_category_def) + << ClassName << CategoryName; + Diag(Previous->getLocation(), diag::note_previous_definition); } } @@ -1738,24 +1734,27 @@ void Sema::MatchAllMethodDeclarations(const SelectorSet &InsMap, // when checking that methods in implementation match their declaration, // i.e. when WarnCategoryMethodImpl is false, check declarations in class // extension; as well as those in categories. - if (!WarnCategoryMethodImpl) - for (const ObjCCategoryDecl *CDeclChain = I->getCategoryList(); - CDeclChain; CDeclChain = CDeclChain->getNextClassCategory()) + if (!WarnCategoryMethodImpl) { + for (ObjCInterfaceDecl::visible_categories_iterator + Cat = I->visible_categories_begin(), + CatEnd = I->visible_categories_end(); + Cat != CatEnd; ++Cat) { MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen, - IMPDecl, - const_cast<ObjCCategoryDecl *>(CDeclChain), - IncompleteImpl, false, + IMPDecl, *Cat, IncompleteImpl, false, WarnCategoryMethodImpl); - else + } + } else { // Also methods in class extensions need be looked at next. - for (const ObjCCategoryDecl *ClsExtDecl = I->getFirstClassExtension(); - ClsExtDecl; ClsExtDecl = ClsExtDecl->getNextClassExtension()) + for (ObjCInterfaceDecl::visible_extensions_iterator + Ext = I->visible_extensions_begin(), + ExtEnd = I->visible_extensions_end(); + Ext != ExtEnd; ++Ext) { MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen, - IMPDecl, - const_cast<ObjCCategoryDecl *>(ClsExtDecl), - IncompleteImpl, false, + IMPDecl, *Ext, IncompleteImpl, false, WarnCategoryMethodImpl); - + } + } + // Check for any implementation of a methods declared in protocol. for (ObjCInterfaceDecl::all_protocol_iterator PI = I->all_referenced_protocol_begin(), @@ -1858,11 +1857,12 @@ void Sema::ImplMethodsVsClassMethods(Scope *S, ObjCImplDecl* IMPDecl, CheckProtocolMethodDefs(IMPDecl->getLocation(), *PI, IncompleteImpl, InsMap, ClsMap, I); // Check class extensions (unnamed categories) - for (const ObjCCategoryDecl *Categories = I->getFirstClassExtension(); - Categories; Categories = Categories->getNextClassExtension()) - ImplMethodsVsClassMethods(S, IMPDecl, - const_cast<ObjCCategoryDecl*>(Categories), - IncompleteImpl); + for (ObjCInterfaceDecl::visible_extensions_iterator + Ext = I->visible_extensions_begin(), + ExtEnd = I->visible_extensions_end(); + Ext != ExtEnd; ++Ext) { + ImplMethodsVsClassMethods(S, IMPDecl, *Ext, IncompleteImpl); + } } else if (ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(CDecl)) { // For extended class, unimplemented methods in its protocols will // be reported in the primary class. @@ -2414,11 +2414,12 @@ Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, // of the other class extensions. Mark them as synthesized as // property will be synthesized when property with same name is // seen in the @implementation. - for (const ObjCCategoryDecl *ClsExtDecl = - IDecl->getFirstClassExtension(); - ClsExtDecl; ClsExtDecl = ClsExtDecl->getNextClassExtension()) { - for (ObjCContainerDecl::prop_iterator I = ClsExtDecl->prop_begin(), - E = ClsExtDecl->prop_end(); I != E; ++I) { + for (ObjCInterfaceDecl::visible_extensions_iterator + Ext = IDecl->visible_extensions_begin(), + ExtEnd = IDecl->visible_extensions_end(); + Ext != ExtEnd; ++Ext) { + for (ObjCContainerDecl::prop_iterator I = Ext->prop_begin(), + E = Ext->prop_end(); I != E; ++I) { ObjCPropertyDecl *Property = *I; // Skip over properties declared @dynamic if (const ObjCPropertyImplDecl *PIDecl @@ -2426,18 +2427,19 @@ Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, if (PIDecl->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) continue; - - for (const ObjCCategoryDecl *CExtDecl = - IDecl->getFirstClassExtension(); - CExtDecl; CExtDecl = CExtDecl->getNextClassExtension()) { - if (ObjCMethodDecl *GetterMethod = - CExtDecl->getInstanceMethod(Property->getGetterName())) + + for (ObjCInterfaceDecl::visible_extensions_iterator + Ext = IDecl->visible_extensions_begin(), + ExtEnd = IDecl->visible_extensions_end(); + Ext != ExtEnd; ++Ext) { + if (ObjCMethodDecl *GetterMethod + = Ext->getInstanceMethod(Property->getGetterName())) GetterMethod->setPropertyAccessor(true); if (!Property->isReadOnly()) - if (ObjCMethodDecl *SetterMethod = - CExtDecl->getInstanceMethod(Property->getSetterName())) + if (ObjCMethodDecl *SetterMethod + = Ext->getInstanceMethod(Property->getSetterName())) SetterMethod->setPropertyAccessor(true); - } + } } } ImplMethodsVsClassMethods(S, IC, IDecl); @@ -2486,12 +2488,9 @@ Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, // Find category interface decl and then check that all methods declared // in this interface are implemented in the category @implementation. if (ObjCInterfaceDecl* IDecl = CatImplClass->getClassInterface()) { - for (ObjCCategoryDecl *Categories = IDecl->getCategoryList(); - Categories; Categories = Categories->getNextClassCategory()) { - if (Categories->getIdentifier() == CatImplClass->getIdentifier()) { - ImplMethodsVsClassMethods(S, CatImplClass, Categories); - break; - } + if (ObjCCategoryDecl *Cat + = IDecl->FindCategoryDeclaration(CatImplClass->getIdentifier())) { + ImplMethodsVsClassMethods(S, CatImplClass, Cat); } } } @@ -2726,9 +2725,12 @@ private: return; // - categories, - for (ObjCCategoryDecl *category = iface->getCategoryList(); - category; category = category->getNextClassCategory()) - search(category); + for (ObjCInterfaceDecl::visible_categories_iterator + cat = iface->visible_categories_begin(), + catEnd = iface->visible_categories_end(); + cat != catEnd; ++cat) { + search(*cat); + } // - the super class, and if (ObjCInterfaceDecl *super = iface->getSuperClass()) diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index 4ae27a4adc8..4bdc1dc253b 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -2913,10 +2913,12 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result, // Traverse the contexts of Objective-C classes. if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Ctx)) { // Traverse categories. - for (ObjCCategoryDecl *Category = IFace->getCategoryList(); - Category; Category = Category->getNextClassCategory()) { + for (ObjCInterfaceDecl::visible_categories_iterator + Cat = IFace->visible_categories_begin(), + CatEnd = IFace->visible_categories_end(); + Cat != CatEnd; ++Cat) { ShadowContextRAII Shadow(Visited); - LookupVisibleDecls(Category, Result, QualifiedNameLookup, false, + LookupVisibleDecls(*Cat, Result, QualifiedNameLookup, false, Consumer, Visited); } diff --git a/clang/lib/Sema/SemaObjCProperty.cpp b/clang/lib/Sema/SemaObjCProperty.cpp index a605ed52a67..2bdb54b1a52 100644 --- a/clang/lib/Sema/SemaObjCProperty.cpp +++ b/clang/lib/Sema/SemaObjCProperty.cpp @@ -270,20 +270,22 @@ Sema::HandlePropertyInClassExtension(Scope *S, IdentifierInfo *PropertyId = FD.D.getIdentifier(); ObjCInterfaceDecl *CCPrimary = CDecl->getClassInterface(); - if (CCPrimary) + if (CCPrimary) { // Check for duplicate declaration of this property in current and // other class extensions. - for (const ObjCCategoryDecl *ClsExtDecl = - CCPrimary->getFirstClassExtension(); - ClsExtDecl; ClsExtDecl = ClsExtDecl->getNextClassExtension()) { - if (ObjCPropertyDecl *prevDecl = - ObjCPropertyDecl::findPropertyDecl(ClsExtDecl, PropertyId)) { + for (ObjCInterfaceDecl::known_extensions_iterator + Ext = CCPrimary->known_extensions_begin(), + ExtEnd = CCPrimary->known_extensions_end(); + Ext != ExtEnd; ++Ext) { + if (ObjCPropertyDecl *prevDecl + = ObjCPropertyDecl::findPropertyDecl(*Ext, PropertyId)) { Diag(AtLoc, diag::err_duplicate_property); Diag(prevDecl->getLocation(), diag::note_property_declare); return 0; } } - + } + // Create a new ObjCPropertyDecl with the DeclContext being // the class extension. // FIXME. We should really be using CreatePropertyDecl for this. @@ -646,11 +648,14 @@ DiagnoseClassAndClassExtPropertyMismatch(Sema &S, ObjCInterfaceDecl *ClassDecl, ObjCPropertyDecl *property) { unsigned Attributes = property->getPropertyAttributesAsWritten(); bool warn = (Attributes & ObjCDeclSpec::DQ_PR_readonly); - for (const ObjCCategoryDecl *CDecl = ClassDecl->getFirstClassExtension(); - CDecl; CDecl = CDecl->getNextClassExtension()) { + for (ObjCInterfaceDecl::known_extensions_iterator + Ext = ClassDecl->known_extensions_begin(), + ExtEnd = ClassDecl->known_extensions_end(); + Ext != ExtEnd; ++Ext) { ObjCPropertyDecl *ClassExtProperty = 0; - for (ObjCContainerDecl::prop_iterator P = CDecl->prop_begin(), - E = CDecl->prop_end(); P != E; ++P) { + for (ObjCContainerDecl::prop_iterator P = Ext->prop_begin(), + E = Ext->prop_end(); + P != E; ++P) { if ((*P)->getIdentifier() == property->getIdentifier()) { ClassExtProperty = *P; break; @@ -1404,14 +1409,14 @@ bool Sema::isPropertyReadonly(ObjCPropertyDecl *PDecl, // Main class has the property as 'readonly'. Must search // through the category list to see if the property's // attribute has been over-ridden to 'readwrite'. - for (ObjCCategoryDecl *Category = IDecl->getCategoryList(); - Category; Category = Category->getNextClassCategory()) { - // Even if property is ready only, if a category has a user defined setter, - // it is not considered read only. - if (Category->getInstanceMethod(PDecl->getSetterName())) + for (ObjCInterfaceDecl::visible_categories_iterator + Cat = IDecl->visible_categories_begin(), + CatEnd = IDecl->visible_categories_end(); + Cat != CatEnd; ++Cat) { + if (Cat->getInstanceMethod(PDecl->getSetterName())) return false; ObjCPropertyDecl *P = - Category->FindPropertyDeclaration(PDecl->getIdentifier()); + Cat->FindPropertyDeclaration(PDecl->getIdentifier()); if (P && !P->isReadOnly()) return false; } |