[cfe-commits] r96276 - in /cfe/trunk: include/clang/AST/DeclObjC.h lib/AST/DeclObjC.cpp lib/Sema/SemaDeclObjC.cpp test/SemaObjC/duplicate-property-class-extension.m

Fariborz Jahanian fjahanian at apple.com
Mon Feb 15 13:55:26 PST 2010


Author: fjahanian
Date: Mon Feb 15 15:55:26 2010
New Revision: 96276

URL: http://llvm.org/viewvc/llvm-project?rev=96276&view=rev
Log:
Class continuation now has its own property ast for
those declared in it. This is to allow duplicate
property diagnostics for properties declared in class extensions
multiple times (radar 7629420) and for future use.

Added:
    cfe/trunk/test/SemaObjC/duplicate-property-class-extension.m
Modified:
    cfe/trunk/include/clang/AST/DeclObjC.h
    cfe/trunk/lib/AST/DeclObjC.cpp
    cfe/trunk/lib/Sema/SemaDeclObjC.cpp

Modified: cfe/trunk/include/clang/AST/DeclObjC.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclObjC.h?rev=96276&r1=96275&r2=96276&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/DeclObjC.h (original)
+++ cfe/trunk/include/clang/AST/DeclObjC.h Mon Feb 15 15:55:26 2010
@@ -949,6 +949,8 @@
     ClassInterface->setCategoryList(this);
   }
 
+  bool IsClassExtension() const { return getIdentifier() == 0; }
+  
   SourceLocation getAtLoc() const { return AtLoc; }
   void setAtLoc(SourceLocation At) { AtLoc = At; }
 

Modified: cfe/trunk/lib/AST/DeclObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclObjC.cpp?rev=96276&r1=96275&r2=96276&view=diff

==============================================================================
--- cfe/trunk/lib/AST/DeclObjC.cpp (original)
+++ cfe/trunk/lib/AST/DeclObjC.cpp Mon Feb 15 15:55:26 2010
@@ -111,8 +111,9 @@
     // Look through categories.
     for (ObjCCategoryDecl *Category = OID->getCategoryList();
          Category; Category = Category->getNextClassCategory()) {
-      if (ObjCPropertyDecl *P = Category->FindPropertyDeclaration(PropertyId))
-        return P;
+      if (!Category->IsClassExtension())
+        if (ObjCPropertyDecl *P = Category->FindPropertyDeclaration(PropertyId))
+          return P;
     }
     // Look through protocols.
     for (ObjCInterfaceDecl::protocol_iterator I = OID->protocol_begin(),
@@ -124,10 +125,11 @@
       return OID->getSuperClass()->FindPropertyDeclaration(PropertyId);
   } else if (const ObjCCategoryDecl *OCD = dyn_cast<ObjCCategoryDecl>(this)) {
     // Look through protocols.
-    for (ObjCInterfaceDecl::protocol_iterator I = OCD->protocol_begin(),
-         E = OCD->protocol_end(); I != E; ++I) {
-      if (ObjCPropertyDecl *P = (*I)->FindPropertyDeclaration(PropertyId))
-        return P;
+    if (!OCD->IsClassExtension())
+      for (ObjCInterfaceDecl::protocol_iterator I = OCD->protocol_begin(),
+           E = OCD->protocol_end(); I != E; ++I) {
+        if (ObjCPropertyDecl *P = (*I)->FindPropertyDeclaration(PropertyId))
+          return P;
     }
   }
   return 0;

Modified: cfe/trunk/lib/Sema/SemaDeclObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclObjC.cpp?rev=96276&r1=96275&r2=96276&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclObjC.cpp Mon Feb 15 15:55:26 2010
@@ -446,18 +446,19 @@
     // Category
     ObjCCategoryDecl *CatDecl = static_cast<ObjCCategoryDecl*>(CDecl);
     assert (CatDecl && "MatchOneProtocolPropertiesInClass");
-    for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(),
-         E = PDecl->prop_end(); P != E; ++P) {
-      ObjCPropertyDecl *Pr = (*P);
-      ObjCCategoryDecl::prop_iterator CP, CE;
-      // Is this property already in  category's list of properties?
-      for (CP = CatDecl->prop_begin(), CE = CatDecl->prop_end(); CP != CE; ++CP)
-        if ((*CP)->getIdentifier() == Pr->getIdentifier())
-          break;
-      if (CP != CE)
-        // Property protocol already exist in class. Diagnose any mismatch.
-        DiagnosePropertyMismatch((*CP), Pr, PDecl->getIdentifier());
-    }
+    if (!CatDecl->IsClassExtension())
+      for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(),
+           E = PDecl->prop_end(); P != E; ++P) {
+        ObjCPropertyDecl *Pr = (*P);
+        ObjCCategoryDecl::prop_iterator CP, CE;
+        // Is this property already in  category's list of properties?
+        for (CP = CatDecl->prop_begin(), CE = CatDecl->prop_end(); CP != CE; ++CP)
+          if ((*CP)->getIdentifier() == Pr->getIdentifier())
+            break;
+        if (CP != CE)
+          // Property protocol already exist in class. Diagnose any mismatch.
+          DiagnosePropertyMismatch((*CP), Pr, PDecl->getIdentifier());
+      }
     return;
   }
   for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(),
@@ -596,44 +597,59 @@
                             unsigned NumProtoRefs,
                             const SourceLocation *ProtoLocs,
                             SourceLocation EndProtoLoc) {
-  ObjCCategoryDecl *CDecl =
-    ObjCCategoryDecl::Create(Context, CurContext, AtInterfaceLoc, ClassLoc,
-                             CategoryLoc, CategoryName);
-  // FIXME: PushOnScopeChains?
-  CurContext->addDecl(CDecl);
-
+  ObjCCategoryDecl *CDecl = 0;
   ObjCInterfaceDecl *IDecl = getObjCInterfaceDecl(ClassName, ClassLoc);
-  /// Check that class of this category is already completely declared.
-  if (!IDecl || IDecl->isForwardDecl()) {
-    CDecl->setInvalidDecl();
-    Diag(ClassLoc, diag::err_undef_interface) << ClassName;
-    return DeclPtrTy::make(CDecl);
+  if (!CategoryName) {
+    // Class extensions require a special treatment. Use an existing one.
+    for (CDecl = IDecl->getCategoryList(); CDecl;
+         CDecl = CDecl->getNextClassCategory())
+      if (CDecl->IsClassExtension()) 
+        break;  
+  }
+  if (!CDecl) {
+    CDecl = ObjCCategoryDecl::Create(Context, CurContext, AtInterfaceLoc, ClassLoc,
+                                     CategoryLoc, CategoryName);
+    // FIXME: PushOnScopeChains?
+    CurContext->addDecl(CDecl);
+
+    /// Check that class of this category is already completely declared.
+    if (!IDecl || IDecl->isForwardDecl()) {
+      CDecl->setInvalidDecl();
+      Diag(ClassLoc, diag::err_undef_interface) << ClassName;
+      return DeclPtrTy::make(CDecl);
+    }
+
+    CDecl->setClassInterface(IDecl);
+    // Insert first use of class extension to the list of class's categories.
+    if (!CategoryName)
+      CDecl->insertNextClassCategory();
   }
 
-  CDecl->setClassInterface(IDecl);
-
   // If the interface is deprecated, warn about it.
   (void)DiagnoseUseOfDecl(IDecl, ClassLoc);
 
-  /// Check for duplicate interface declaration for this category
-  ObjCCategoryDecl *CDeclChain;
-  for (CDeclChain = IDecl->getCategoryList(); CDeclChain;
-       CDeclChain = CDeclChain->getNextClassCategory()) {
-    if (CategoryName && CDeclChain->getIdentifier() == CategoryName) {
-      Diag(CategoryLoc, diag::warn_dup_category_def)
-      << ClassName << CategoryName;
-      Diag(CDeclChain->getLocation(), diag::note_previous_definition);
-      break;
+  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 (!CDeclChain)
+      CDecl->insertNextClassCategory();
   }
-  if (!CDeclChain)
-    CDecl->insertNextClassCategory();
 
   if (NumProtoRefs) {
     CDecl->setProtocolList((ObjCProtocolDecl**)ProtoRefs, NumProtoRefs, 
                            ProtoLocs, Context);
     // Protocols in the class extension belong to the class.
-    if (!CDecl->getIdentifier())
+    if (CDecl->IsClassExtension())
      IDecl->mergeClassExtensionProtocolList((ObjCProtocolDecl**)ProtoRefs, 
                                             NumProtoRefs, ProtoLocs,
                                             Context); 
@@ -1102,11 +1118,12 @@
       CollectImmediateProperties((*PI), PropMap);
   }
   if (ObjCCategoryDecl *CATDecl = dyn_cast<ObjCCategoryDecl>(CDecl)) {
-    for (ObjCContainerDecl::prop_iterator P = CATDecl->prop_begin(),
-         E = CATDecl->prop_end(); P != E; ++P) {
-      ObjCPropertyDecl *Prop = (*P);
-      PropMap[Prop->getIdentifier()] = Prop;
-    }
+    if (!CATDecl->IsClassExtension())
+      for (ObjCContainerDecl::prop_iterator P = CATDecl->prop_begin(),
+           E = CATDecl->prop_end(); P != E; ++P) {
+        ObjCPropertyDecl *Prop = (*P);
+        PropMap[Prop->getIdentifier()] = Prop;
+      }
     // scan through class's protocols.
     for (ObjCInterfaceDecl::protocol_iterator PI = CATDecl->protocol_begin(),
          E = CATDecl->protocol_end(); PI != E; ++PI)
@@ -1261,7 +1278,7 @@
     // Check class extensions (unnamed categories)
     for (ObjCCategoryDecl *Categories = I->getCategoryList();
          Categories; Categories = Categories->getNextClassCategory()) {
-      if (!Categories->getIdentifier()) {
+      if (Categories->IsClassExtension()) {
         ImplMethodsVsClassMethods(IMPDecl, Categories, IncompleteImpl);
         break;
       }
@@ -1269,7 +1286,7 @@
   } else if (ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(CDecl)) {
     // For extended class, unimplemented methods in its protocols will
     // be reported in the primary class.
-    if (C->getIdentifier()) {
+    if (!C->IsClassExtension()) {
       for (ObjCCategoryDecl::protocol_iterator PI = C->protocol_begin(),
            E = C->protocol_end(); PI != E; ++PI)
         CheckProtocolMethodDefs(IMPDecl->getLocation(), *PI, IncompleteImpl,
@@ -1826,17 +1843,18 @@
 
     // Compare protocol properties with those in category
     CompareProperties(C, DeclPtrTy::make(C));
-    if (C->getIdentifier() == 0)
+    if (C->IsClassExtension())
       DiagnoseClassExtensionDupMethods(C, C->getClassInterface());
   }
   if (ObjCContainerDecl *CDecl = dyn_cast<ObjCContainerDecl>(ClassDecl)) {
-    // ProcessPropertyDecl is responsible for diagnosing conflicts with any
-    // user-defined setter/getter. It also synthesizes setter/getter methods
-    // and adds them to the DeclContext and global method pools.
-    for (ObjCContainerDecl::prop_iterator I = CDecl->prop_begin(),
-                                          E = CDecl->prop_end();
-         I != E; ++I)
-      ProcessPropertyDecl(*I, CDecl);
+    if (CDecl->getIdentifier())
+      // ProcessPropertyDecl is responsible for diagnosing conflicts with any
+      // user-defined setter/getter. It also synthesizes setter/getter methods
+      // and adds them to the DeclContext and global method pools.
+      for (ObjCContainerDecl::prop_iterator I = CDecl->prop_begin(),
+                                            E = CDecl->prop_end();
+           I != E; ++I)
+        ProcessPropertyDecl(*I, CDecl);
     CDecl->setAtEndRange(AtEnd);
   }
   if (ObjCImplementationDecl *IC=dyn_cast<ObjCImplementationDecl>(ClassDecl)) {
@@ -2137,7 +2155,22 @@
   // May modify Attributes.
   CheckObjCPropertyAttributes(T, AtLoc, Attributes);
   if (ObjCCategoryDecl *CDecl = dyn_cast<ObjCCategoryDecl>(ClassDecl))
-    if (!CDecl->getIdentifier()) {
+    if (CDecl->IsClassExtension()) {
+      // Diagnose if this property is already in continuation class.
+      DeclContext *DC = dyn_cast<DeclContext>(ClassDecl);
+      assert(DC && "ClassDecl is not a DeclContext");
+      DeclContext::lookup_result Found = DC->lookup(FD.D.getIdentifier());
+      if (Found.first != Found.second && isa<ObjCPropertyDecl>(*Found.first)) {
+        Diag(AtLoc, diag::err_duplicate_property);
+        Diag((*Found.first)->getLocation(), diag::note_property_declare);
+        return DeclPtrTy();
+      }
+      ObjCPropertyDecl *PDecl = ObjCPropertyDecl::Create(Context, DC,
+                                                         FD.D.getIdentifierLoc(),
+                                                         FD.D.getIdentifier(),
+                                                         AtLoc, T);
+      DC->addDecl(PDecl);
+      
       // This is a continuation class. property requires special
       // handling.
       if ((CCPrimary = CDecl->getClassInterface())) {
@@ -2201,6 +2234,7 @@
           ProcessPropertyDecl(PIDecl, CCPrimary);
           return DeclPtrTy();
         }
+        
         // No matching property found in the primary class. Just fall thru
         // and add property to continuation class's primary class.
         ClassDecl = CCPrimary;
@@ -2354,7 +2388,7 @@
     }
     if (const ObjCCategoryDecl *CD = 
         dyn_cast<ObjCCategoryDecl>(property->getDeclContext())) {
-      if (CD->getIdentifier()) {
+      if (!CD->IsClassExtension()) {
         Diag(PropertyLoc, diag::error_category_property) << CD->getDeclName();
         Diag(property->getLocation(), diag::note_property_declare);
         return DeclPtrTy();

Added: 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=96276&view=auto

==============================================================================
--- cfe/trunk/test/SemaObjC/duplicate-property-class-extension.m (added)
+++ cfe/trunk/test/SemaObjC/duplicate-property-class-extension.m Mon Feb 15 15:55:26 2010
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1  -fsyntax-only -verify %s
+
+ at interface Foo 
+ at property (readonly) char foo;
+ at end
+
+ at interface Foo ()
+ at property (readwrite) char foo; // expected-note {{property declared here}}
+ at end
+
+ at interface Foo ()
+ at property (readwrite) char foo;	// expected-error {{property has a previous declaration}}
+ at end





More information about the cfe-commits mailing list