[cfe-commits] r172665 - in /cfe/trunk: include/clang/AST/ lib/ARCMigrate/ lib/AST/ lib/Rewrite/Frontend/ lib/Sema/ lib/Serialization/ lib/StaticAnalyzer/Checkers/ test/Modules/ test/Modules/Inputs/

Douglas Gregor dgregor at apple.com
Wed Jan 16 15:00:24 PST 2013


Author: dgregor
Date: Wed Jan 16 17:00:23 2013
New Revision: 172665

URL: http://llvm.org/viewvc/llvm-project?rev=172665&view=rev
Log:
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>.
 


Added:
    cfe/trunk/test/Modules/Inputs/category_left_sub.h
    cfe/trunk/test/Modules/Inputs/category_right_sub.h
Modified:
    cfe/trunk/include/clang/AST/DeclObjC.h
    cfe/trunk/lib/ARCMigrate/TransProperties.cpp
    cfe/trunk/lib/AST/ASTContext.cpp
    cfe/trunk/lib/AST/ASTImporter.cpp
    cfe/trunk/lib/AST/DeclObjC.cpp
    cfe/trunk/lib/AST/DumpXML.cpp
    cfe/trunk/lib/Rewrite/Frontend/RewriteModernObjC.cpp
    cfe/trunk/lib/Rewrite/Frontend/RewriteObjC.cpp
    cfe/trunk/lib/Sema/SemaCodeComplete.cpp
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaDeclObjC.cpp
    cfe/trunk/lib/Sema/SemaLookup.cpp
    cfe/trunk/lib/Sema/SemaObjCProperty.cpp
    cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
    cfe/trunk/lib/Serialization/ASTWriter.cpp
    cfe/trunk/lib/Serialization/ASTWriterDecl.cpp
    cfe/trunk/lib/StaticAnalyzer/Checkers/IvarInvalidationChecker.cpp
    cfe/trunk/lib/StaticAnalyzer/Checkers/ObjCUnusedIVarsChecker.cpp
    cfe/trunk/test/Modules/Inputs/category_top.h
    cfe/trunk/test/Modules/Inputs/module.map
    cfe/trunk/test/Modules/objc-categories.m

Modified: cfe/trunk/include/clang/AST/DeclObjC.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclObjC.h?rev=172665&r1=172664&r2=172665&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclObjC.h (original)
+++ cfe/trunk/include/clang/AST/DeclObjC.h Wed Jan 16 17:00:23 2013
@@ -894,7 +894,166 @@
                                               : 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 @@
     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 @@
       CategoryNameLoc(CategoryNameLoc),
       IvarLBraceLoc(IvarLBraceLoc), IvarRBraceLoc(IvarRBraceLoc) {
   }
+
 public:
 
   static ObjCCategoryDecl *Create(ASTContext &C, DeclContext *DC,
@@ -1394,8 +1554,13 @@
 
   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 @@
   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

Modified: cfe/trunk/lib/ARCMigrate/TransProperties.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ARCMigrate/TransProperties.cpp?rev=172665&r1=172664&r2=172665&view=diff
==============================================================================
--- cfe/trunk/lib/ARCMigrate/TransProperties.cpp (original)
+++ cfe/trunk/lib/ARCMigrate/TransProperties.cpp Wed Jan 16 17:00:23 2013
@@ -141,10 +141,12 @@
 
     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) {

Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=172665&r1=172664&r2=172665&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Wed Jan 16 17:00:23 2013
@@ -365,10 +365,12 @@
     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 @@
     }
     
     // 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 @@
 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())

Modified: cfe/trunk/lib/AST/ASTImporter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTImporter.cpp?rev=172665&r1=172664&r2=172665&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTImporter.cpp (original)
+++ cfe/trunk/lib/AST/ASTImporter.cpp Wed Jan 16 17:00:23 2013
@@ -3514,10 +3514,13 @@
   
   // 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>(

Modified: cfe/trunk/lib/AST/DeclObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclObjC.cpp?rev=172665&r1=172664&r2=172665&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclObjC.cpp (original)
+++ cfe/trunk/lib/AST/DeclObjC.cpp Wed Jan 16 17:00:23 2013
@@ -129,12 +129,15 @@
     }
     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 @@
   }
 }
 
-/// 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 @@
       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 @@
         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 @@
          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 @@
   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 @@
     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 @@
   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 @@
 
   // 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 @@
                                                        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);
     }

Modified: cfe/trunk/lib/AST/DumpXML.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DumpXML.cpp?rev=172665&r1=172664&r2=172665&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DumpXML.cpp (original)
+++ cfe/trunk/lib/AST/DumpXML.cpp Wed Jan 16 17:00:23 2013
@@ -748,14 +748,6 @@
     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 @@
              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);

Modified: cfe/trunk/lib/Rewrite/Frontend/RewriteModernObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Rewrite/Frontend/RewriteModernObjC.cpp?rev=172665&r1=172664&r2=172665&view=diff
==============================================================================
--- cfe/trunk/lib/Rewrite/Frontend/RewriteModernObjC.cpp (original)
+++ cfe/trunk/lib/Rewrite/Frontend/RewriteModernObjC.cpp Wed Jan 16 17:00:23 2013
@@ -7298,11 +7298,8 @@
   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 += "_$_";

Modified: cfe/trunk/lib/Rewrite/Frontend/RewriteObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Rewrite/Frontend/RewriteObjC.cpp?rev=172665&r1=172664&r2=172665&view=diff
==============================================================================
--- cfe/trunk/lib/Rewrite/Frontend/RewriteObjC.cpp (original)
+++ cfe/trunk/lib/Rewrite/Frontend/RewriteObjC.cpp Wed Jan 16 17:00:23 2013
@@ -5744,11 +5744,8 @@
                                               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 += '_';

Modified: cfe/trunk/lib/Sema/SemaCodeComplete.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCodeComplete.cpp?rev=172665&r1=172664&r2=172665&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCodeComplete.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCodeComplete.cpp Wed Jan 16 17:00:23 2013
@@ -3433,9 +3433,11 @@
   } 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 @@
                    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 @@
 
     // 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 @@
   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 @@
   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 @@
                                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 @@
         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) {

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=172665&r1=172664&r2=172665&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Wed Jan 16 17:00:23 2013
@@ -10472,11 +10472,12 @@
             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);

Modified: cfe/trunk/lib/Sema/SemaDeclObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclObjC.cpp?rev=172665&r1=172664&r2=172665&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclObjC.cpp Wed Jan 16 17:00:23 2013
@@ -849,16 +849,12 @@
 
   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 @@
     // 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 @@
       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 @@
       // 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 @@
             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 @@
     // 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 @@
       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())

Modified: cfe/trunk/lib/Sema/SemaLookup.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLookup.cpp?rev=172665&r1=172664&r2=172665&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaLookup.cpp (original)
+++ cfe/trunk/lib/Sema/SemaLookup.cpp Wed Jan 16 17:00:23 2013
@@ -2913,10 +2913,12 @@
   // 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);
     }
 

Modified: cfe/trunk/lib/Sema/SemaObjCProperty.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaObjCProperty.cpp?rev=172665&r1=172664&r2=172665&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaObjCProperty.cpp (original)
+++ cfe/trunk/lib/Sema/SemaObjCProperty.cpp Wed Jan 16 17:00:23 2013
@@ -270,20 +270,22 @@
   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 @@
                                          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 @@
   // 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;
   }

Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=172665&r1=172664&r2=172665&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Wed Jan 16 17:00:23 2013
@@ -2404,7 +2404,7 @@
       if (Tail)
         ASTDeclReader::setNextObjCCategory(Tail, Cat);
       else
-        Interface->setCategoryList(Cat);
+        Interface->setCategoryListRaw(Cat);
       Tail = Cat;
     }
     
@@ -2419,13 +2419,15 @@
         Tail(0) 
     {
       // Populate the name -> category map with the set of known categories.
-      for (ObjCCategoryDecl *Cat = Interface->getCategoryList(); Cat;
-           Cat = Cat->getNextClassCategory()) {
+      for (ObjCInterfaceDecl::known_categories_iterator
+             Cat = Interface->known_categories_begin(),
+             CatEnd = Interface->known_categories_end();
+           Cat != CatEnd; ++Cat) {
         if (Cat->getDeclName())
-          NameCategoryMap[Cat->getDeclName()] = Cat;
+          NameCategoryMap[Cat->getDeclName()] = *Cat;
         
         // Keep track of the tail of the category list.
-        Tail = Cat;
+        Tail = *Cat;
       }
     }
 

Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=172665&r1=172664&r2=172665&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriter.cpp Wed Jan 16 17:00:23 2013
@@ -3238,10 +3238,12 @@
     Categories.push_back(0);
     
     // Add the categories.
-    for (ObjCCategoryDecl *Cat = Class->getCategoryList();
-         Cat; Cat = Cat->getNextClassCategory(), ++Size) {
-      assert(getDeclID(Cat) != 0 && "Bogus category");
-      AddDeclRef(Cat, Categories);
+    for (ObjCInterfaceDecl::known_categories_iterator
+           Cat = Class->known_categories_begin(),
+           CatEnd = Class->known_categories_end();
+         Cat != CatEnd; ++Cat, ++Size) {
+      assert(getDeclID(*Cat) != 0 && "Bogus category");
+      AddDeclRef(*Cat, Categories);
     }
     
     // Update the size.

Modified: cfe/trunk/lib/Serialization/ASTWriterDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterDecl.cpp?rev=172665&r1=172664&r2=172665&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriterDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriterDecl.cpp Wed Jan 16 17:00:23 2013
@@ -491,13 +491,14 @@
            PEnd = Data.AllReferencedProtocols.end();
          P != PEnd; ++P)
       Writer.AddDeclRef(*P, Record);
+
     
-    if (ObjCCategoryDecl *Cat = D->getCategoryList()) {
+    if (ObjCCategoryDecl *Cat = D->getCategoryListRaw()) {
       // Ensure that we write out the set of categories for this class.
       Writer.ObjCClassesWithCategories.insert(D);
       
       // Make sure that the categories get serialized.
-      for (; Cat; Cat = Cat->getNextClassCategory())
+      for (; Cat; Cat = Cat->getNextClassCategoryRaw())
         (void)Writer.GetDeclRef(Cat);
     }
   }  

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/IvarInvalidationChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/IvarInvalidationChecker.cpp?rev=172665&r1=172664&r2=172665&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/IvarInvalidationChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/IvarInvalidationChecker.cpp Wed Jan 16 17:00:23 2013
@@ -238,9 +238,11 @@
 
     // Visit all categories in case the invalidation method is declared in
     // a category.
-    for (const ObjCCategoryDecl *I = InterfD->getFirstClassExtension(); I;
-        I = I->getNextClassExtension()) {
-      containsInvalidationMethod(I, OutInfo);
+    for (ObjCInterfaceDecl::visible_extensions_iterator
+           Ext = InterfD->visible_extensions_begin(),
+           ExtEnd = InterfD->visible_extensions_end();
+         Ext != ExtEnd; ++Ext) {
+      containsInvalidationMethod(*Ext, OutInfo);
     }
 
     containsInvalidationMethod(InterfD->getSuperClass(), OutInfo);

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/ObjCUnusedIVarsChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/ObjCUnusedIVarsChecker.cpp?rev=172665&r1=172664&r2=172665&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/ObjCUnusedIVarsChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/ObjCUnusedIVarsChecker.cpp Wed Jan 16 17:00:23 2013
@@ -89,10 +89,11 @@
       Scan(M, *I);
 
     // Scan the associated categories as well.
-    for (const ObjCCategoryDecl *CD =
-          ID->getClassInterface()->getCategoryList(); CD ;
-          CD = CD->getNextClassCategory()) {
-      if (const ObjCCategoryImplDecl *CID = CD->getImplementation())
+    for (ObjCInterfaceDecl::visible_categories_iterator
+           Cat = ID->getClassInterface()->visible_categories_begin(),
+           CatEnd = ID->getClassInterface()->visible_categories_end();
+         Cat != CatEnd; ++Cat) {
+      if (const ObjCCategoryImplDecl *CID = Cat->getImplementation())
         Scan(M, CID);
     }
   }

Added: cfe/trunk/test/Modules/Inputs/category_left_sub.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/category_left_sub.h?rev=172665&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/category_left_sub.h (added)
+++ cfe/trunk/test/Modules/Inputs/category_left_sub.h Wed Jan 16 17:00:23 2013
@@ -0,0 +1,3 @@
+ at interface Foo(LeftSub) <P1>
+- (void)left_sub;
+ at end

Added: cfe/trunk/test/Modules/Inputs/category_right_sub.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/category_right_sub.h?rev=172665&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/category_right_sub.h (added)
+++ cfe/trunk/test/Modules/Inputs/category_right_sub.h Wed Jan 16 17:00:23 2013
@@ -0,0 +1,9 @@
+ at interface Foo(RightSub) <P2>
+ at property id right_sub_prop;
+ at end
+
+ at interface Foo() {
+ at public
+  int right_sub_ivar;
+}
+ at end

Modified: cfe/trunk/test/Modules/Inputs/category_top.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/category_top.h?rev=172665&r1=172664&r2=172665&view=diff
==============================================================================
--- cfe/trunk/test/Modules/Inputs/category_top.h (original)
+++ cfe/trunk/test/Modules/Inputs/category_top.h Wed Jan 16 17:00:23 2013
@@ -12,3 +12,10 @@
 @interface Foo(Top3)
 -(void)top3;
 @end
+
+ at protocol P1
+ at end
+
+ at protocol P2
+ at end
+

Modified: cfe/trunk/test/Modules/Inputs/module.map
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/module.map?rev=172665&r1=172664&r2=172665&view=diff
==============================================================================
--- cfe/trunk/test/Modules/Inputs/module.map (original)
+++ cfe/trunk/test/Modules/Inputs/module.map Wed Jan 16 17:00:23 2013
@@ -37,10 +37,18 @@
 module category_left { 
   header "category_left.h" 
   export category_top
+
+  explicit module sub {
+    header "category_left_sub.h"
+  }
 }
 module category_right { 
   header "category_right.h" 
   export category_top
+
+  explicit module sub {
+    header "category_right_sub.h"
+  }
 }
 module category_bottom { 
   header "category_bottom.h" 

Modified: cfe/trunk/test/Modules/objc-categories.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/objc-categories.m?rev=172665&r1=172664&r2=172665&view=diff
==============================================================================
--- cfe/trunk/test/Modules/objc-categories.m (original)
+++ cfe/trunk/test/Modules/objc-categories.m Wed Jan 16 17:00:23 2013
@@ -39,3 +39,34 @@
 void test_other(Foo *foo) {
   [foo other];
 }
+
+// Make sure we don't see categories that should be hidden
+void test_hidden_all_errors(Foo *foo) {
+  [foo left_sub]; // expected-warning{{instance method '-left_sub' not found (return type defaults to 'id')}}
+  foo.right_sub_prop = foo; // expected-error{{property 'right_sub_prop' not found on object of type 'Foo *'}}
+  int i = foo->right_sub_ivar; // expected-error{{'Foo' does not have a member named 'right_sub_ivar'}}
+  id<P1> p1 = foo; // expected-warning{{initializing 'id<P1>' with an expression of incompatible type 'Foo *'}}
+  id<P2> p2 = foo; // expected-warning{{initializing 'id<P2>' with an expression of incompatible type 'Foo *'}}
+}
+
+ at import category_left.sub;
+
+void test_hidden_right_errors(Foo *foo) {
+  // These are okay
+  [foo left_sub]; // okay
+  id<P1> p1 = foo;
+  // FIXME: these should fail
+  foo.right_sub_prop = foo; // expected-error{{property 'right_sub_prop' not found on object of type 'Foo *'}}
+  int i = foo->right_sub_ivar; // expected-error{{'Foo' does not have a member named 'right_sub_ivar'}}
+  id<P2> p2 = foo; // expected-warning{{initializing 'id<P2>' with an expression of incompatible type 'Foo *'}}
+}
+
+ at import category_right.sub;
+
+void test_hidden_okay(Foo *foo) {
+  [foo left_sub];
+  foo.right_sub_prop = foo;
+  int i = foo->right_sub_ivar;
+  id<P1> p1 = foo;
+  id<P2> p2 = foo;
+}





More information about the cfe-commits mailing list