Patch to provide separate ASTs for multiple ObjC class extension 
declarations (implements radar 7928731).



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@106597 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp
index f730a3a..2877d52 100644
--- a/lib/Sema/SemaCodeComplete.cpp
+++ b/lib/Sema/SemaCodeComplete.cpp
@@ -3929,14 +3929,11 @@
 
     // Add methods from any class extensions (but not from categories;
     // those should go into category implementations).
-    for (ObjCCategoryDecl *Cat = IFace->getCategoryList(); Cat;
-         Cat = Cat->getNextClassCategory()) {
-      if (!Cat->IsClassExtension())
-        continue;
-
-      FindImplementableMethods(Context, Cat, WantInstanceMethods, ReturnType,
+    for (const ObjCCategoryDecl *Cat = IFace->getFirstClassExtension(); Cat;
+         Cat = Cat->getNextClassExtension())
+      FindImplementableMethods(Context, const_cast<ObjCCategoryDecl*>(Cat), 
+                               WantInstanceMethods, ReturnType,
                                IsInImplementation, KnownMethods);      
-    }
   }
 
   if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Container)) {
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp
index 5a2765c..21aeb59 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -414,7 +414,7 @@
                             unsigned NumProtoRefs,
                             const SourceLocation *ProtoLocs,
                             SourceLocation EndProtoLoc) {
-  ObjCCategoryDecl *CDecl = 0;
+  ObjCCategoryDecl *CDecl;
   ObjCInterfaceDecl *IDecl = getObjCInterfaceDecl(ClassName, ClassLoc, true);
 
   /// Check that class of this category is already completely declared.
@@ -429,28 +429,21 @@
     return DeclPtrTy::make(CDecl);
   }
 
-  if (!CategoryName) {
-    // Class extensions require a special treatment. Use an existing one.
-    // Note that 'getClassExtension()' can return NULL.
-    CDecl = IDecl->getClassExtension();
-    if (IDecl->getImplementation()) {
-      Diag(ClassLoc, diag::err_class_extension_after_impl) << ClassName;
-      Diag(IDecl->getImplementation()->getLocation(), 
-           diag::note_implementation_declared);
-    }
+  if (!CategoryName && IDecl->getImplementation()) {
+    Diag(ClassLoc, diag::err_class_extension_after_impl) << ClassName;
+    Diag(IDecl->getImplementation()->getLocation(), 
+          diag::note_implementation_declared);
   }
 
-  if (!CDecl) {
-    CDecl = ObjCCategoryDecl::Create(Context, CurContext, AtInterfaceLoc,
-                                     ClassLoc, CategoryLoc, CategoryName);
-    // FIXME: PushOnScopeChains?
-    CurContext->addDecl(CDecl);
+  CDecl = ObjCCategoryDecl::Create(Context, CurContext, AtInterfaceLoc,
+                                   ClassLoc, CategoryLoc, CategoryName);
+  // FIXME: PushOnScopeChains?
+  CurContext->addDecl(CDecl);
 
-    CDecl->setClassInterface(IDecl);
-    // Insert first use of class extension to the list of class's categories.
-    if (!CategoryName)
-      CDecl->insertNextClassCategory();
-  }
+  CDecl->setClassInterface(IDecl);
+  // Insert class extension to the list of class's categories.
+  if (!CategoryName)
+    CDecl->insertNextClassCategory();
 
   // If the interface is deprecated, warn about it.
   (void)DiagnoseUseOfDecl(IDecl, ClassLoc);
@@ -969,13 +962,11 @@
       CheckProtocolMethodDefs(IMPDecl->getLocation(), *PI, IncompleteImpl,
                               InsMap, ClsMap, I);
     // Check class extensions (unnamed categories)
-    for (ObjCCategoryDecl *Categories = I->getCategoryList();
-         Categories; Categories = Categories->getNextClassCategory()) {
-      if (Categories->IsClassExtension()) {
-        ImplMethodsVsClassMethods(S, IMPDecl, Categories, IncompleteImpl);
-        break;
-      }
-    }
+    for (const ObjCCategoryDecl *Categories = I->getFirstClassExtension();
+         Categories; Categories = Categories->getNextClassExtension())
+      ImplMethodsVsClassMethods(S, IMPDecl, 
+                                const_cast<ObjCCategoryDecl*>(Categories), 
+                                IncompleteImpl);
   } else if (ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(CDecl)) {
     // For extended class, unimplemented methods in its protocols will
     // be reported in the primary class.
@@ -1821,7 +1812,8 @@
   }
   
   // Find ivars to construct/destruct in class extension.
-  if (const ObjCCategoryDecl *CDecl = OI->getClassExtension()) {
+  for (const ObjCCategoryDecl *CDecl = OI->getFirstClassExtension(); CDecl;
+      CDecl = CDecl->getNextClassExtension()) {
     for (ObjCCategoryDecl::ivar_iterator I = CDecl->ivar_begin(),
          E = CDecl->ivar_end(); I != E; ++I) {
       ObjCIvarDecl *Iv = (*I);
diff --git a/lib/Sema/SemaObjCProperty.cpp b/lib/Sema/SemaObjCProperty.cpp
index f25ba64..a27d2a8 100644
--- a/lib/Sema/SemaObjCProperty.cpp
+++ b/lib/Sema/SemaObjCProperty.cpp
@@ -123,6 +123,10 @@
       CreatePropertyDecl(S, CCPrimary, AtLoc,
                          FD, GetterSel, SetterSel, isAssign, isReadWrite,
                          Attributes, T, MethodImplKind, DC);
+    // Mark written attribute as having no attribute because
+    // this is not a user-written property declaration in primary
+    // class.
+    PDecl->setPropertyAttributesAsWritten(ObjCPropertyDecl::OBJC_PR_noattr);
 
     // A case of continuation class adding a new property in the class. This
     // is not what it was meant for. However, gcc supports it and so should we.
@@ -134,7 +138,7 @@
 
   // The property 'PIDecl's readonly attribute will be over-ridden
   // with continuation class's readwrite property attribute!
-  unsigned PIkind = PIDecl->getPropertyAttributes();
+  unsigned PIkind = PIDecl->getPropertyAttributesAsWritten();
   if (isReadWrite && (PIkind & ObjCPropertyDecl::OBJC_PR_readonly)) {
     unsigned retainCopyNonatomic =
     (ObjCPropertyDecl::OBJC_PR_retain |
@@ -266,6 +270,8 @@
   if (Attributes & ObjCDeclSpec::DQ_PR_nonatomic)
     PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_nonatomic);
 
+  PDecl->setPropertyAttributesAsWritten(PDecl->getPropertyAttributes());
+  
   if (MethodImplKind == tok::objc_required)
     PDecl->setPropertyImplementation(ObjCPropertyDecl::Required);
   else if (MethodImplKind == tok::objc_optional)