aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2013-01-16 23:00:23 +0000
committerDouglas Gregor <dgregor@apple.com>2013-01-16 23:00:23 +0000
commitd329724745b49f894b768d47275b7c2713106e89 (patch)
tree54fc9308cb83f0062cdccb86488b9c96a58fa36a
parent804381d8ce78f60c40dd59f5a0b468a7de78b025 (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
-rw-r--r--include/clang/AST/DeclObjC.h203
-rw-r--r--lib/ARCMigrate/TransProperties.cpp10
-rw-r--r--lib/AST/ASTContext.cpp29
-rw-r--r--lib/AST/ASTImporter.cpp11
-rw-r--r--lib/AST/DeclObjC.cpp129
-rw-r--r--lib/AST/DumpXML.cpp20
-rw-r--r--lib/Rewrite/Frontend/RewriteModernObjC.cpp7
-rw-r--r--lib/Rewrite/Frontend/RewriteObjC.cpp7
-rw-r--r--lib/Sema/SemaCodeComplete.cpp75
-rw-r--r--lib/Sema/SemaDecl.cpp11
-rw-r--r--lib/Sema/SemaDeclObjC.cpp104
-rw-r--r--lib/Sema/SemaLookup.cpp8
-rw-r--r--lib/Sema/SemaObjCProperty.cpp39
-rw-r--r--lib/Serialization/ASTReaderDecl.cpp12
-rw-r--r--lib/Serialization/ASTWriter.cpp10
-rw-r--r--lib/Serialization/ASTWriterDecl.cpp5
-rw-r--r--lib/StaticAnalyzer/Checkers/IvarInvalidationChecker.cpp8
-rw-r--r--lib/StaticAnalyzer/Checkers/ObjCUnusedIVarsChecker.cpp9
-rw-r--r--test/Modules/Inputs/category_left_sub.h3
-rw-r--r--test/Modules/Inputs/category_right_sub.h9
-rw-r--r--test/Modules/Inputs/category_top.h7
-rw-r--r--test/Modules/Inputs/module.map8
-rw-r--r--test/Modules/objc-categories.m31
23 files changed, 533 insertions, 222 deletions
diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h
index d1067432e3..e7fa5e7d2b 100644
--- a/include/clang/AST/DeclObjC.h
+++ b/include/clang/AST/DeclObjC.h
@@ -894,7 +894,166 @@ public:
: superCls;
}
- ObjCCategoryDecl* getCategoryList() const {
+ /// \brief Iterator that walks over the list of categories, filtering out
+ /// those that do not meet specific criteria.
+ ///
+ /// This class template is used for the various permutations of category
+ /// and extension iterators.
+ template<bool (*Filter)(ObjCCategoryDecl *)>
+ class filtered_category_iterator {
+ ObjCCategoryDecl *Current;
+
+ void findAcceptableCategory();
+
+ public:
+ typedef ObjCCategoryDecl * value_type;
+ typedef value_type reference;
+ typedef value_type pointer;
+ typedef std::ptrdiff_t difference_type;
+ typedef std::input_iterator_tag iterator_category;
+
+ filtered_category_iterator() : Current(0) { }
+ explicit filtered_category_iterator(ObjCCategoryDecl *Current)
+ : Current(Current)
+ {
+ findAcceptableCategory();
+ }
+
+ reference operator*() const { return Current; }
+ pointer operator->() const { return Current; }
+
+ filtered_category_iterator &operator++();
+
+ filtered_category_iterator operator++(int) {
+ filtered_category_iterator Tmp = *this;
+ ++(*this);
+ return Tmp;
+ }
+
+ friend bool operator==(filtered_category_iterator X,
+ filtered_category_iterator Y) {
+ return X.Current = Y.Current;
+ }
+
+ friend bool operator!=(filtered_category_iterator X,
+ filtered_category_iterator Y) {
+ return X.Current != Y.Current;
+ }
+ };
+
+private:
+ /// \brief Test whether the given category is visible.
+ ///
+ /// Used in the \c visible_categories_iterator.
+ static bool isVisibleCategory(ObjCCategoryDecl *Cat);
+
+public:
+ /// \brief Iterator that walks over the list of categories and extensions
+ /// that are visible, i.e., not hidden in a non-imported submodule.
+ typedef filtered_category_iterator<isVisibleCategory>
+ visible_categories_iterator;
+
+ /// \brief Retrieve an iterator to the beginning of the visible-categories
+ /// list.
+ visible_categories_iterator visible_categories_begin() const {
+ return visible_categories_iterator(getCategoryListRaw());
+ }
+
+ /// \brief Retrieve an iterator to the end of the visible-categories list.
+ visible_categories_iterator visible_categories_end() const {
+ return visible_categories_iterator();
+ }
+
+ /// \brief Determine whether the visible-categories list is empty.
+ bool visible_categories_empty() const {
+ return visible_categories_begin() == visible_categories_end();
+ }
+
+private:
+ /// \brief Test whether the given category... is a category.
+ ///
+ /// Used in the \c known_categories_iterator.
+ static bool isKnownCategory(ObjCCategoryDecl *) { return true; }
+
+public:
+ /// \brief Iterator that walks over all of the known categories and
+ /// extensions, including those that are hidden.
+ typedef filtered_category_iterator<isKnownCategory> known_categories_iterator;
+
+ /// \brief Retrieve an iterator to the beginning of the known-categories
+ /// list.
+ known_categories_iterator known_categories_begin() const {
+ return known_categories_iterator(getCategoryListRaw());
+ }
+
+ /// \brief Retrieve an iterator to the end of the known-categories list.
+ known_categories_iterator known_categories_end() const {
+ return known_categories_iterator();
+ }
+
+ /// \brief Determine whether the known-categories list is empty.
+ bool known_categories_empty() const {
+ return known_categories_begin() == known_categories_end();
+ }
+
+private:
+ /// \brief Test whether the given category is a visible extension.
+ ///
+ /// Used in the \c visible_extensions_iterator.
+ static bool isVisibleExtension(ObjCCategoryDecl *Cat);
+
+public:
+ /// \brief Iterator that walks over all of the visible extensions, skipping
+ /// any that are known but hidden.
+ typedef filtered_category_iterator<isVisibleExtension>
+ visible_extensions_iterator;
+
+ /// \brief Retrieve an iterator to the beginning of the visible-extensions
+ /// list.
+ visible_extensions_iterator visible_extensions_begin() const {
+ return visible_extensions_iterator(getCategoryListRaw());
+ }
+
+ /// \brief Retrieve an iterator to the end of the visible-extensions list.
+ visible_extensions_iterator visible_extensions_end() const {
+ return visible_extensions_iterator();
+ }
+
+ /// \brief Determine whether the visible-extensions list is empty.
+ bool visible_extensions_empty() const {
+ return visible_extensions_begin() == visible_extensions_end();
+ }
+
+private:
+ /// \brief Test whether the given category is an extension.
+ ///
+ /// Used in the \c known_extensions_iterator.
+ static bool isKnownExtension(ObjCCategoryDecl *Cat);
+
+public:
+ /// \brief Iterator that walks over all of the known extensions.
+ typedef filtered_category_iterator<isKnownExtension>
+ known_extensions_iterator;
+
+ /// \brief Retrieve an iterator to the beginning of the known-extensions
+ /// list.
+ known_extensions_iterator known_extensions_begin() const {
+ return known_extensions_iterator(getCategoryListRaw());
+ }
+
+ /// \brief Retrieve an iterator to the end of the known-extensions list.
+ known_extensions_iterator known_extensions_end() const {
+ return known_extensions_iterator();
+ }
+
+ /// \brief Determine whether the known-extensions list is empty.
+ bool known_extensions_empty() const {
+ return known_extensions_begin() == known_extensions_end();
+ }
+
+ /// \brief Retrieve the raw pointer to the start of the category/extension
+ /// list.
+ ObjCCategoryDecl* getCategoryListRaw() const {
// FIXME: Should make sure no callers ever do this.
if (!hasDefinition())
return 0;
@@ -905,12 +1064,12 @@ public:
return data().CategoryList;
}
- void setCategoryList(ObjCCategoryDecl *category) {
+ /// \brief Set the raw pointer to the start of the category/extension
+ /// list.
+ void setCategoryListRaw(ObjCCategoryDecl *category) {
data().CategoryList = category;
}
- ObjCCategoryDecl* getFirstClassExtension() const;
-
ObjCPropertyDecl
*FindPropertyVisibleInPrimaryClass(IdentifierInfo *PropertyId) const;
@@ -1351,6 +1510,7 @@ class ObjCCategoryDecl : public ObjCContainerDecl {
CategoryNameLoc(CategoryNameLoc),
IvarLBraceLoc(IvarLBraceLoc), IvarRBraceLoc(IvarRBraceLoc) {
}
+
public:
static ObjCCategoryDecl *Create(ASTContext &C, DeclContext *DC,
@@ -1394,8 +1554,13 @@ public:
ObjCCategoryDecl *getNextClassCategory() const { return NextClassCategory; }
+ /// \brief Retrieve the pointer to the next stored category (or extension),
+ /// which may be hidden.
+ ObjCCategoryDecl *getNextClassCategoryRaw() const {
+ return NextClassCategory;
+ }
+
bool IsClassExtension() const { return getIdentifier() == 0; }
- const ObjCCategoryDecl *getNextClassExtension() const;
typedef specific_decl_iterator<ObjCIvarDecl> ivar_iterator;
ivar_iterator ivar_begin() const {
@@ -2030,5 +2195,33 @@ public:
friend class ASTDeclReader;
};
+template<bool (*Filter)(ObjCCategoryDecl *)>
+void
+ObjCInterfaceDecl::filtered_category_iterator<Filter>::
+findAcceptableCategory() {
+ while (Current && !Filter(Current))
+ Current = Current->getNextClassCategoryRaw();
+}
+
+template<bool (*Filter)(ObjCCategoryDecl *)>
+inline ObjCInterfaceDecl::filtered_category_iterator<Filter> &
+ObjCInterfaceDecl::filtered_category_iterator<Filter>::operator++() {
+ Current = Current->getNextClassCategoryRaw();
+ findAcceptableCategory();
+ return *this;
+}
+
+inline bool ObjCInterfaceDecl::isVisibleCategory(ObjCCategoryDecl *Cat) {
+ return !Cat->isHidden();
+}
+
+inline bool ObjCInterfaceDecl::isVisibleExtension(ObjCCategoryDecl *Cat) {
+ return Cat->IsClassExtension() && !Cat->isHidden();
+}
+
+inline bool ObjCInterfaceDecl::isKnownExtension(ObjCCategoryDecl *Cat) {
+ return Cat->IsClassExtension();
+}
+
} // end namespace clang
#endif
diff --git a/lib/ARCMigrate/TransProperties.cpp b/lib/ARCMigrate/TransProperties.cpp
index 7196a54efc..b6ddc43dd6 100644
--- a/lib/ARCMigrate/TransProperties.cpp
+++ b/lib/ARCMigrate/TransProperties.cpp
@@ -141,10 +141,12 @@ public:
AtPropDeclsTy AtExtProps;
// Look through extensions.
- for (ObjCCategoryDecl *Cat = iface->getCategoryList();
- Cat; Cat = Cat->getNextClassCategory())
- if (Cat->IsClassExtension())
- collectProperties(Cat, AtExtProps, &AtProps);
+ for (ObjCInterfaceDecl::visible_extensions_iterator
+ ext = iface->visible_extensions_begin(),
+ extEnd = iface->visible_extensions_end();
+ ext != extEnd; ++ext) {
+ collectProperties(*ext, AtExtProps, &AtProps);
+ }
for (AtPropDeclsTy::iterator
I = AtExtProps.begin(), E = AtExtProps.end(); I != E; ++I) {
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);
diff --git a/lib/Rewrite/Frontend/RewriteModernObjC.cpp b/lib/Rewrite/Frontend/RewriteModernObjC.cpp
index d69106cfb0..53b5591ad4 100644
--- a/lib/Rewrite/Frontend/RewriteModernObjC.cpp
+++ b/lib/Rewrite/Frontend/RewriteModernObjC.cpp
@@ -7298,11 +7298,8 @@ void RewriteModernObjC::RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *IDecl,
WriteModernMetadataDeclarations(Context, Result);
ObjCInterfaceDecl *ClassDecl = IDecl->getClassInterface();
// Find category declaration for this implementation.
- ObjCCategoryDecl *CDecl=0;
- for (CDecl = ClassDecl->getCategoryList(); CDecl;
- CDecl = CDecl->getNextClassCategory())
- if (CDecl->getIdentifier() == IDecl->getIdentifier())
- break;
+ ObjCCategoryDecl *CDecl
+ = ClassDecl->FindCategoryDeclaration(IDecl->getIdentifier());
std::string FullCategoryName = ClassDecl->getNameAsString();
FullCategoryName += "_$_";
diff --git a/lib/Rewrite/Frontend/RewriteObjC.cpp b/lib/Rewrite/Frontend/RewriteObjC.cpp
index 23719cb345..18b75758ab 100644
--- a/lib/Rewrite/Frontend/RewriteObjC.cpp
+++ b/lib/Rewrite/Frontend/RewriteObjC.cpp
@@ -5744,11 +5744,8 @@ void RewriteObjCFragileABI::RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *ID
std::string &Result) {
ObjCInterfaceDecl *ClassDecl = IDecl->getClassInterface();
// Find category declaration for this implementation.
- ObjCCategoryDecl *CDecl;
- for (CDecl = ClassDecl->getCategoryList(); CDecl;
- CDecl = CDecl->getNextClassCategory())
- if (CDecl->getIdentifier() == IDecl->getIdentifier())
- break;
+ ObjCCategoryDecl *CDecl
+ = ClassDecl->FindCategoryDeclaration(IDecl->getIdentifier());
std::string FullCategoryName = ClassDecl->getNameAsString();
FullCategoryName += '_';
diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp
index 5d5226dddd..5cbba239be 100644
--- a/lib/Sema/SemaCodeComplete.cpp
+++ b/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->