[cfe-commits] r106597 - in /cfe/trunk: include/clang/AST/DeclObjC.h lib/AST/ASTContext.cpp lib/AST/ASTImporter.cpp lib/AST/DeclObjC.cpp lib/Frontend/PCHReaderDecl.cpp lib/Frontend/PCHWriterDecl.cpp lib/Sema/SemaCodeComplete.cpp lib/Sema/SemaDeclObjC.cpp lib/Sema/SemaObjCProperty.cpp test/SemaObjC/duplicate-property-class-extension.m

Fariborz Jahanian fjahanian at apple.com
Tue Jun 22 16:20:40 PDT 2010


Author: fjahanian
Date: Tue Jun 22 18:20:40 2010
New Revision: 106597

URL: http://llvm.org/viewvc/llvm-project?rev=106597&view=rev
Log:
Patch to provide separate ASTs for multiple ObjC class extension 
declarations (implements radar 7928731).


Modified:
    cfe/trunk/include/clang/AST/DeclObjC.h
    cfe/trunk/lib/AST/ASTContext.cpp
    cfe/trunk/lib/AST/ASTImporter.cpp
    cfe/trunk/lib/AST/DeclObjC.cpp
    cfe/trunk/lib/Frontend/PCHReaderDecl.cpp
    cfe/trunk/lib/Frontend/PCHWriterDecl.cpp
    cfe/trunk/lib/Sema/SemaCodeComplete.cpp
    cfe/trunk/lib/Sema/SemaDeclObjC.cpp
    cfe/trunk/lib/Sema/SemaObjCProperty.cpp
    cfe/trunk/test/SemaObjC/duplicate-property-class-extension.m

Modified: cfe/trunk/include/clang/AST/DeclObjC.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclObjC.h?rev=106597&r1=106596&r2=106597&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclObjC.h (original)
+++ cfe/trunk/include/clang/AST/DeclObjC.h Tue Jun 22 18:20:40 2010
@@ -550,8 +550,8 @@
   void setCategoryList(ObjCCategoryDecl *category) {
     CategoryList = category;
   }
-
-  ObjCCategoryDecl* getClassExtension() const;
+  
+  ObjCCategoryDecl* getFirstClassExtension() const;
 
   ObjCPropertyDecl
     *FindPropertyVisibleInPrimaryClass(IdentifierInfo *PropertyId) const;
@@ -983,6 +983,7 @@
   }
 
   bool IsClassExtension() const { return getIdentifier() == 0; }
+  const ObjCCategoryDecl *getNextClassExtension() const;
   
   typedef specific_decl_iterator<ObjCIvarDecl> ivar_iterator;
   ivar_iterator ivar_begin() const {
@@ -1308,7 +1309,7 @@
   SourceLocation AtLoc;   // location of @property
   TypeSourceInfo *DeclType;
   unsigned PropertyAttributes : 8;
-
+  unsigned PropertyAttributesAsWritten : 8;
   // @required/@optional
   unsigned PropertyImplementation : 2;
 
@@ -1322,7 +1323,9 @@
   ObjCPropertyDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
                    SourceLocation AtLocation, TypeSourceInfo *T)
     : NamedDecl(ObjCProperty, DC, L, Id), AtLoc(AtLocation), DeclType(T),
-      PropertyAttributes(OBJC_PR_noattr), PropertyImplementation(None),
+      PropertyAttributes(OBJC_PR_noattr), 
+      PropertyAttributesAsWritten(OBJC_PR_noattr),
+      PropertyImplementation(None),
       GetterName(Selector()),
       SetterName(Selector()),
       GetterMethodDecl(0), SetterMethodDecl(0) , PropertyIvarDecl(0) {}
@@ -1346,6 +1349,14 @@
     PropertyAttributes |= PRVal;
   }
 
+  PropertyAttributeKind getPropertyAttributesAsWritten() const {
+    return PropertyAttributeKind(PropertyAttributesAsWritten);
+  }
+  
+  void setPropertyAttributesAsWritten(PropertyAttributeKind PRVal) {
+    PropertyAttributesAsWritten = PRVal;
+  }
+  
  void makeitReadWriteAttribute(void) {
     PropertyAttributes &= ~OBJC_PR_readonly;
     PropertyAttributes |= OBJC_PR_readwrite;

Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=106597&r1=106596&r2=106597&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Tue Jun 22 18:20:40 2010
@@ -868,7 +868,8 @@
 void ASTContext::CollectNonClassIvars(const ObjCInterfaceDecl *OI,
                                 llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars) {
   // Find ivars declared 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) {
       Ivars.push_back(*I);
@@ -933,7 +934,8 @@
 unsigned ASTContext::CountNonClassIvars(const ObjCInterfaceDecl *OI) {
   unsigned count = 0;  
   // Count ivars declared in class extension.
-  if (const ObjCCategoryDecl *CDecl = OI->getClassExtension())
+  for (const ObjCCategoryDecl *CDecl = OI->getFirstClassExtension(); CDecl;
+       CDecl = CDecl->getNextClassExtension())
     count += CDecl->ivar_size();
 
   // Count ivar defined in this class's implementation.  This

Modified: cfe/trunk/lib/AST/ASTImporter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTImporter.cpp?rev=106597&r1=106596&r2=106597&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTImporter.cpp (original)
+++ cfe/trunk/lib/AST/ASTImporter.cpp Tue Jun 22 18:20:40 2010
@@ -2636,6 +2636,8 @@
   LexicalDC->addDecl(ToProperty);
 
   ToProperty->setPropertyAttributes(D->getPropertyAttributes());
+  ToProperty->setPropertyAttributesAsWritten(
+                                      D->getPropertyAttributesAsWritten());
   ToProperty->setGetterName(Importer.Import(D->getGetterName()));
   ToProperty->setSetterName(Importer.Import(D->getSetterName()));
   ToProperty->setGetterMethodDecl(

Modified: cfe/trunk/lib/AST/DeclObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclObjC.cpp?rev=106597&r1=106596&r2=106597&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclObjC.cpp (original)
+++ cfe/trunk/lib/AST/DeclObjC.cpp Tue Jun 22 18:20:40 2010
@@ -223,17 +223,24 @@
   setProtocolList(ProtocolRefs.data(), NumProtoRefs, ProtocolLocs.data(), C);
 }
 
-/// getClassExtension - Find class extension of the given class.
-// FIXME. can speed it up, if need be.
-ObjCCategoryDecl* ObjCInterfaceDecl::getClassExtension() const {
-  const ObjCInterfaceDecl* ClassDecl = this;
-  for (ObjCCategoryDecl *CDecl = ClassDecl->getCategoryList(); CDecl;
+/// 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) {
   ObjCInterfaceDecl* ClassDecl = this;
@@ -242,11 +249,13 @@
       clsDeclared = ClassDecl;
       return I;
     }
-    if (const ObjCCategoryDecl *CDecl = ClassDecl->getClassExtension())
+    for (const ObjCCategoryDecl *CDecl = ClassDecl->getFirstClassExtension();
+         CDecl; CDecl = CDecl->getNextClassExtension()) {
       if (ObjCIvarDecl *I = CDecl->getIvarDecl(ID)) {
         clsDeclared = ClassDecl;
         return I;
       }
+    }
       
     ClassDecl = ClassDecl->getSuperClass();
   }

Modified: cfe/trunk/lib/Frontend/PCHReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHReaderDecl.cpp?rev=106597&r1=106596&r2=106597&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/PCHReaderDecl.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHReaderDecl.cpp Tue Jun 22 18:20:40 2010
@@ -444,6 +444,8 @@
   // FIXME: stable encoding
   D->setPropertyAttributes(
                       (ObjCPropertyDecl::PropertyAttributeKind)Record[Idx++]);
+  D->setPropertyAttributesAsWritten(
+                      (ObjCPropertyDecl::PropertyAttributeKind)Record[Idx++]);
   // FIXME: stable encoding
   D->setPropertyImplementation(
                             (ObjCPropertyDecl::PropertyControl)Record[Idx++]);

Modified: cfe/trunk/lib/Frontend/PCHWriterDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHWriterDecl.cpp?rev=106597&r1=106596&r2=106597&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/PCHWriterDecl.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHWriterDecl.cpp Tue Jun 22 18:20:40 2010
@@ -425,6 +425,7 @@
   Writer.AddTypeSourceInfo(D->getTypeSourceInfo(), Record);
   // FIXME: stable encoding
   Record.push_back((unsigned)D->getPropertyAttributes());
+  Record.push_back((unsigned)D->getPropertyAttributesAsWritten());
   // FIXME: stable encoding
   Record.push_back((unsigned)D->getPropertyImplementation());
   Writer.AddDeclarationName(D->getGetterName(), Record);

Modified: cfe/trunk/lib/Sema/SemaCodeComplete.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCodeComplete.cpp?rev=106597&r1=106596&r2=106597&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCodeComplete.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCodeComplete.cpp Tue Jun 22 18:20:40 2010
@@ -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)) {

Modified: cfe/trunk/lib/Sema/SemaDeclObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclObjC.cpp?rev=106597&r1=106596&r2=106597&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclObjC.cpp Tue Jun 22 18:20:40 2010
@@ -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);

Modified: cfe/trunk/lib/Sema/SemaObjCProperty.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaObjCProperty.cpp?rev=106597&r1=106596&r2=106597&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaObjCProperty.cpp (original)
+++ cfe/trunk/lib/Sema/SemaObjCProperty.cpp Tue Jun 22 18:20:40 2010
@@ -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)

Modified: cfe/trunk/test/SemaObjC/duplicate-property-class-extension.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/duplicate-property-class-extension.m?rev=106597&r1=106596&r2=106597&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/duplicate-property-class-extension.m (original)
+++ cfe/trunk/test/SemaObjC/duplicate-property-class-extension.m Tue Jun 22 18:20:40 2010
@@ -1,13 +1,21 @@
 // RUN: %clang_cc1  -fsyntax-only -verify %s
 
 @interface Foo 
- at property (readonly) char foo;
+ at property (readonly) char foo; // expected-note {{property declared here}}
 @end
 
 @interface Foo ()
- at property (readwrite) char foo; // expected-note {{property declared here}}
+ at property (readwrite) char foo; // OK 
+ at property (readwrite) char NewProperty; // expected-note 2 {{property declared here}} 
 @end
 
 @interface Foo ()
- at property (readwrite) char foo;	// expected-error {{property has a previous declaration}}
+ at property (readwrite) char foo;	//  OK again, make primary property readwrite for 2nd time!
+ at property (readwrite) char NewProperty; // expected-error {{illegal declaration of property in continuation class 'Foo': attribute must be readwrite, while its primary must be readonly}}
 @end
+
+ at interface Foo ()
+ at property (readonly) char foo;	// expected-error {{illegal declaration of property in continuation class 'Foo': attribute must be readwrite, while its primary must be readonly}}
+ at property (readwrite) char NewProperty; // expected-error {{illegal declaration of property in continuation class 'Foo': attribute must be readwrite, while its primary must be readonly}}
+ at end
+





More information about the cfe-commits mailing list