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 | d329724745b49f894b768d47275b7c2713106e89 (patch) | |
tree | 54fc9308cb83f0062cdccb86488b9c96a58fa36a /lib/AST | |
parent | 804381d8ce78f60c40dd59f5a0b468a7de78b025 (diff) |
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>.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@172665 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/AST')
-rw-r--r-- | lib/AST/ASTContext.cpp | 29 | ||||
-rw-r--r-- | lib/AST/ASTImporter.cpp | 11 | ||||
-rw-r--r-- | lib/AST/DeclObjC.cpp | 129 | ||||
-rw-r--r-- | lib/AST/DumpXML.cpp | 20 |
4 files changed, 107 insertions, 82 deletions
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 83e6d6bd28..df64237f70 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -365,10 +365,12 @@ static void addRedeclaredMethods(const ObjCMethodDecl *ObjCMethod, if (!ID) return; // Add redeclared method here. - for (const ObjCCategoryDecl *ClsExtDecl = ID->getFirstClassExtension(); - ClsExtDecl; ClsExtDecl = ClsExtDecl->getNextClassExtension()) { + for (ObjCInterfaceDecl::known_extensions_iterator + Ext = ID->known_extensions_begin(), + ExtEnd = ID->known_extensions_end(); + Ext != ExtEnd; ++Ext) { if (ObjCMethodDecl *RedeclaredMethod = - ClsExtDecl->getMethod(ObjCMethod->getSelector(), + Ext->getMethod(ObjCMethod->getSelector(), ObjCMethod->isInstanceMethod())) Redeclared.push_back(RedeclaredMethod); } @@ -1689,9 +1691,13 @@ void ASTContext::CollectInheritedProtocols(const Decl *CDecl, } // Categories of this Interface. - for (const ObjCCategoryDecl *CDeclChain = OI->getCategoryList(); - CDeclChain; CDeclChain = CDeclChain->getNextClassCategory()) - CollectInheritedProtocols(CDeclChain, Protocols); + for (ObjCInterfaceDecl::visible_categories_iterator + Cat = OI->visible_categories_begin(), + CatEnd = OI->visible_categories_end(); + Cat != CatEnd; ++Cat) { + CollectInheritedProtocols(*Cat, Protocols); + } + if (ObjCInterfaceDecl *SD = OI->getSuperClass()) while (SD) { CollectInheritedProtocols(SD, Protocols); @@ -1721,10 +1727,13 @@ void ASTContext::CollectInheritedProtocols(const Decl *CDecl, unsigned ASTContext::CountNonClassIvars(const ObjCInterfaceDecl *OI) const { unsigned count = 0; // Count ivars declared in class extension. - for (const ObjCCategoryDecl *CDecl = OI->getFirstClassExtension(); CDecl; - CDecl = CDecl->getNextClassExtension()) - count += CDecl->ivar_size(); - + for (ObjCInterfaceDecl::known_extensions_iterator + Ext = OI->known_extensions_begin(), + ExtEnd = OI->known_extensions_end(); + Ext != ExtEnd; ++Ext) { + count += Ext->ivar_size(); + } + // Count ivar defined in this class's implementation. This // includes synthesized ivars. if (ObjCImplementationDecl *ImplDecl = OI->getImplementation()) diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index 9bfaa13ddd..305815ebeb 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -3514,10 +3514,13 @@ bool ASTNodeImporter::ImportDefinition(ObjCInterfaceDecl *From, // Import categories. When the categories themselves are imported, they'll // hook themselves into this interface. - for (ObjCCategoryDecl *FromCat = From->getCategoryList(); FromCat; - FromCat = FromCat->getNextClassCategory()) - Importer.Import(FromCat); - + for (ObjCInterfaceDecl::known_categories_iterator + Cat = From->known_categories_begin(), + CatEnd = From->known_categories_end(); + Cat != CatEnd; ++Cat) { + Importer.Import(*Cat); + } + // If we have an @implementation, import it as well. if (From->getImplementation()) { ObjCImplementationDecl *Impl = cast_or_null<ObjCImplementationDecl>( diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp index 816c43200a..0b1a1ec456 100644 --- a/lib/AST/DeclObjC.cpp +++ b/lib/AST/DeclObjC.cpp @@ -129,12 +129,15 @@ ObjCContainerDecl::FindPropertyDeclaration(IdentifierInfo *PropertyId) const { } case Decl::ObjCInterface: { const ObjCInterfaceDecl *OID = cast<ObjCInterfaceDecl>(this); - // Look through categories. - for (ObjCCategoryDecl *Cat = OID->getCategoryList(); - Cat; Cat = Cat->getNextClassCategory()) + // Look through categories (but not extensions). + for (ObjCInterfaceDecl::visible_categories_iterator + Cat = OID->visible_categories_begin(), + CatEnd = OID->visible_categories_end(); + Cat != CatEnd; ++Cat) { if (!Cat->IsClassExtension()) if (ObjCPropertyDecl *P = Cat->FindPropertyDeclaration(PropertyId)) return P; + } // Look through protocols. for (ObjCInterfaceDecl::all_protocol_iterator @@ -296,24 +299,6 @@ void ObjCInterfaceDecl::startDefinition() { } } -/// getFirstClassExtension - Find first class extension of the given class. -ObjCCategoryDecl* ObjCInterfaceDecl::getFirstClassExtension() const { - for (ObjCCategoryDecl *CDecl = getCategoryList(); CDecl; - CDecl = CDecl->getNextClassCategory()) - if (CDecl->IsClassExtension()) - return CDecl; - return 0; -} - -/// getNextClassCategory - Find next class extension in list of categories. -const ObjCCategoryDecl* ObjCCategoryDecl::getNextClassExtension() const { - for (const ObjCCategoryDecl *CDecl = getNextClassCategory(); CDecl; - CDecl = CDecl->getNextClassCategory()) - if (CDecl->IsClassExtension()) - return CDecl; - return 0; -} - ObjCIvarDecl *ObjCInterfaceDecl::lookupInstanceVariable(IdentifierInfo *ID, ObjCInterfaceDecl *&clsDeclared) { // FIXME: Should make sure no callers ever do this. @@ -329,9 +314,12 @@ ObjCIvarDecl *ObjCInterfaceDecl::lookupInstanceVariable(IdentifierInfo *ID, clsDeclared = ClassDecl; return I; } - for (const ObjCCategoryDecl *CDecl = ClassDecl->getFirstClassExtension(); - CDecl; CDecl = CDecl->getNextClassExtension()) { - if (ObjCIvarDecl *I = CDecl->getIvarDecl(ID)) { + + for (ObjCInterfaceDecl::visible_extensions_iterator + Ext = ClassDecl->visible_extensions_begin(), + ExtEnd = ClassDecl->visible_extensions_end(); + Ext != ExtEnd; ++Ext) { + if (ObjCIvarDecl *I = Ext->getIvarDecl(ID)) { clsDeclared = ClassDecl; return I; } @@ -390,21 +378,22 @@ ObjCMethodDecl *ObjCInterfaceDecl::lookupMethod(Selector Sel, return MethodDecl; // Didn't find one yet - now look through categories. - ObjCCategoryDecl *CatDecl = ClassDecl->getCategoryList(); - while (CatDecl) { - if ((MethodDecl = CatDecl->getMethod(Sel, isInstance))) + for (ObjCInterfaceDecl::visible_categories_iterator + Cat = ClassDecl->visible_categories_begin(), + CatEnd = ClassDecl->visible_categories_end(); + Cat != CatEnd; ++Cat) { + if ((MethodDecl = Cat->getMethod(Sel, isInstance))) return MethodDecl; if (!shallowCategoryLookup) { // Didn't find one yet - look through protocols. const ObjCList<ObjCProtocolDecl> &Protocols = - CatDecl->getReferencedProtocols(); + Cat->getReferencedProtocols(); for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), E = Protocols.end(); I != E; ++I) if ((MethodDecl = (*I)->lookupMethod(Sel, isInstance))) return MethodDecl; } - CatDecl = CatDecl->getNextClassCategory(); } ClassDecl = ClassDecl->getSuperClass(); @@ -816,10 +805,13 @@ static void CollectOverriddenMethodsRecurse(const ObjCContainerDecl *Container, P != PEnd; ++P) CollectOverriddenMethodsRecurse(*P, Method, Methods, MovedToSuper); - for (const ObjCCategoryDecl *Category = Interface->getCategoryList(); - Category; Category = Category->getNextClassCategory()) - CollectOverriddenMethodsRecurse(Category, Method, Methods, + for (ObjCInterfaceDecl::visible_categories_iterator + Cat = Interface->visible_categories_begin(), + CatEnd = Interface->visible_categories_end(); + Cat != CatEnd; ++Cat) { + CollectOverriddenMethodsRecurse(*Cat, Method, Methods, MovedToSuper); + } if (const ObjCInterfaceDecl *Super = Interface->getSuperClass()) return CollectOverriddenMethodsRecurse(Super, Method, Methods, @@ -881,11 +873,14 @@ static void collectOnCategoriesAfterLocation(SourceLocation Loc, if (!Class) return; - for (const ObjCCategoryDecl *Category = Class->getCategoryList(); - Category; Category = Category->getNextClassCategory()) - if (SM.isBeforeInTranslationUnit(Loc, Category->getLocation())) - CollectOverriddenMethodsRecurse(Category, Method, Methods, true); - + for (ObjCInterfaceDecl::visible_categories_iterator + Cat = Class->visible_categories_begin(), + CatEnd = Class->visible_categories_end(); + Cat != CatEnd; ++Cat) { + if (SM.isBeforeInTranslationUnit(Loc, Cat->getLocation())) + CollectOverriddenMethodsRecurse(*Cat, Method, Methods, true); + } + collectOnCategoriesAfterLocation(Loc, Class->getSuperClass(), SM, Method, Methods); } @@ -1072,12 +1067,13 @@ ObjCIvarDecl *ObjCInterfaceDecl::all_declared_ivar_begin() { for (curIvar = data().IvarList; I != E; curIvar = *I, ++I) curIvar->setNextIvar(*I); } - - for (const ObjCCategoryDecl *CDecl = getFirstClassExtension(); CDecl; - CDecl = CDecl->getNextClassExtension()) { - if (!CDecl->ivar_empty()) { - ObjCCategoryDecl::ivar_iterator I = CDecl->ivar_begin(), - E = CDecl->ivar_end(); + + for (ObjCInterfaceDecl::known_extensions_iterator + Ext = known_extensions_begin(), + ExtEnd = known_extensions_end(); + Ext != ExtEnd; ++Ext) { + if (!Ext->ivar_empty()) { + ObjCCategoryDecl::ivar_iterator I = Ext->ivar_begin(),E = Ext->ivar_end(); if (!data().IvarList) { data().IvarList = *I; ++I; curIvar = data().IvarList; @@ -1115,29 +1111,41 @@ ObjCInterfaceDecl::FindCategoryDeclaration(IdentifierInfo *CategoryId) const { if (data().ExternallyCompleted) LoadExternalDefinition(); - for (ObjCCategoryDecl *Category = getCategoryList(); - Category; Category = Category->getNextClassCategory()) - if (Category->getIdentifier() == CategoryId) - return Category; + for (visible_categories_iterator Cat = visible_categories_begin(), + CatEnd = visible_categories_end(); + Cat != CatEnd; + ++Cat) { + if (Cat->getIdentifier() == CategoryId) + return *Cat; + } + return 0; } ObjCMethodDecl * ObjCInterfaceDecl::getCategoryInstanceMethod(Selector Sel) const { - for (ObjCCategoryDecl *Category = getCategoryList(); - Category; Category = Category->getNextClassCategory()) - if (ObjCCategoryImplDecl *Impl = Category->getImplementation()) + for (visible_categories_iterator Cat = visible_categories_begin(), + CatEnd = visible_categories_end(); + Cat != CatEnd; + ++Cat) { + if (ObjCCategoryImplDecl *Impl = Cat->getImplementation()) if (ObjCMethodDecl *MD = Impl->getInstanceMethod(Sel)) return MD; + } + return 0; } ObjCMethodDecl *ObjCInterfaceDecl::getCategoryClassMethod(Selector Sel) const { - for (ObjCCategoryDecl *Category = getCategoryList(); - Category; Category = Category->getNextClassCategory()) - if (ObjCCategoryImplDecl *Impl = Category->getImplementation()) + for (visible_categories_iterator Cat = visible_categories_begin(), + CatEnd = visible_categories_end(); + Cat != CatEnd; + ++Cat) { + if (ObjCCategoryImplDecl *Impl = Cat->getImplementation()) if (ObjCMethodDecl *MD = Impl->getClassMethod(Sel)) return MD; + } + return 0; } @@ -1169,10 +1177,13 @@ bool ObjCInterfaceDecl::ClassImplementsProtocol(ObjCProtocolDecl *lProto, // 2nd, look up the category. if (lookupCategory) - for (ObjCCategoryDecl *CDecl = IDecl->getCategoryList(); CDecl; - CDecl = CDecl->getNextClassCategory()) { - for (ObjCCategoryDecl::protocol_iterator PI = CDecl->protocol_begin(), - E = CDecl->protocol_end(); PI != E; ++PI) + for (visible_categories_iterator Cat = visible_categories_begin(), + CatEnd = visible_categories_end(); + Cat != CatEnd; + ++Cat) { + for (ObjCCategoryDecl::protocol_iterator PI = Cat->protocol_begin(), + E = Cat->protocol_end(); + PI != E; ++PI) if (getASTContext().ProtocolCompatibleWithProtocol(lProto, *PI)) return true; } @@ -1393,9 +1404,9 @@ ObjCCategoryDecl *ObjCCategoryDecl::Create(ASTContext &C, DeclContext *DC, IvarLBraceLoc, IvarRBraceLoc); if (IDecl) { // Link this category into its class's category list. - CatDecl->NextClassCategory = IDecl->getCategoryList(); + CatDecl->NextClassCategory = IDecl->getCategoryListRaw(); if (IDecl->hasDefinition()) { - IDecl->setCategoryList(CatDecl); + IDecl->setCategoryListRaw(CatDecl); if (ASTMutationListener *L = C.getASTMutationListener()) L->AddedObjCCategoryToInterface(CatDecl, IDecl); } diff --git a/lib/AST/DumpXML.cpp b/lib/AST/DumpXML.cpp index 1e7523f3b9..be22ae450b 100644 --- a/lib/AST/DumpXML.cpp +++ b/lib/AST/DumpXML.cpp @@ -748,14 +748,6 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>, visitDeclContext(D); } - // ObjCInterfaceDecl - void visitCategoryList(ObjCCategoryDecl *D) { - if (!D) return; - - TemporaryContainer C(*this, "categories"); - for (; D; D = D->getNextClassCategory()) - visitDeclRef(D); - } void visitObjCInterfaceDeclAttrs(ObjCInterfaceDecl *D) { setPointer("typeptr", D->getTypeForDecl()); setFlag("forward_decl", !D->isThisDeclarationADefinition()); @@ -770,7 +762,17 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>, I = D->protocol_begin(), E = D->protocol_end(); I != E; ++I) visitDeclRef(*I); } - visitCategoryList(D->getCategoryList()); + + if (!D->visible_categories_empty()) { + TemporaryContainer C(*this, "categories"); + + for (ObjCInterfaceDecl::visible_categories_iterator + Cat = D->visible_categories_begin(), + CatEnd = D->visible_categories_end(); + Cat != CatEnd; ++Cat) { + visitDeclRef(*Cat); + } + } } void visitObjCInterfaceDeclAsContext(ObjCInterfaceDecl *D) { visitDeclContext(D); |