[cfe-commits] r50587 - in /cfe/trunk: include/clang/AST/DeclObjC.h include/clang/Basic/DiagnosticKinds.def lib/AST/DeclObjC.cpp lib/Sema/Sema.h lib/Sema/SemaDeclObjC.cpp test/Sema/objc-property-3.m test/Sema/objc-property-4.m

Fariborz Jahanian fjahanian at apple.com
Fri May 2 12:17:31 PDT 2008


Author: fjahanian
Date: Fri May  2 14:17:30 2008
New Revision: 50587

URL: http://llvm.org/viewvc/llvm-project?rev=50587&view=rev
Log:
This patch is about merging ObjC2's properties declared in class
protocols into class's property list and performing semantics
on them for while doing so.

Added:
    cfe/trunk/test/Sema/objc-property-4.m
Modified:
    cfe/trunk/include/clang/AST/DeclObjC.h
    cfe/trunk/include/clang/Basic/DiagnosticKinds.def
    cfe/trunk/lib/AST/DeclObjC.cpp
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaDeclObjC.cpp
    cfe/trunk/test/Sema/objc-property-3.m

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

==============================================================================
--- cfe/trunk/include/clang/AST/DeclObjC.h (original)
+++ cfe/trunk/include/clang/AST/DeclObjC.h Fri May  2 14:17:30 2008
@@ -285,6 +285,12 @@
   ObjCCategoryDecl *FindCategoryDeclaration(IdentifierInfo *CategoryId) const;
   ObjCIvarDecl *FindIvarDeclaration(IdentifierInfo *IvarId) const;
   
+  typedef ObjCProtocolDecl * const * protocol_iterator;
+  protocol_iterator protocol_begin() const { return ReferencedProtocols; }
+  protocol_iterator protocol_end() const {
+    return ReferencedProtocols+NumReferencedProtocols;
+  }
+  
   typedef ObjCIvarDecl * const *ivar_iterator;
   ivar_iterator ivar_begin() const { return Ivars; }
   ivar_iterator ivar_end() const { return Ivars + ivar_size();}
@@ -314,6 +320,8 @@
   
   void addProperties(ObjCPropertyDecl **Properties, unsigned NumProperties);
   
+  void mergeProperties(ObjCPropertyDecl **Properties, unsigned NumProperties);
+  
   typedef ObjCPropertyDecl * const * classprop_iterator;
   classprop_iterator classprop_begin() const { return PropertyDecl; }
   classprop_iterator classprop_end() const {
@@ -517,6 +525,12 @@
     return ReferencedProtocols; 
   }
   unsigned getNumReferencedProtocols() const { return NumReferencedProtocols; }
+  typedef ObjCProtocolDecl * const * protocol_iterator;
+  protocol_iterator protocol_begin() const { return ReferencedProtocols; }
+  protocol_iterator protocol_end() const {
+    return ReferencedProtocols+NumReferencedProtocols;
+  }
+  
   unsigned getNumInstanceMethods() const { return NumInstanceMethods; }
   unsigned getNumClassMethods() const { return NumClassMethods; }
   

Modified: cfe/trunk/include/clang/Basic/DiagnosticKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=50587&r1=50586&r2=50587&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticKinds.def Fri May  2 14:17:30 2008
@@ -510,12 +510,11 @@
      "type of property '%0'  does not match type of ivar '%1'") 
 DIAG(warn_readonly_property, WARNING,
      "attribute 'readonly' of property '%0' restricts attribute "
-     "'readwrite' of '%1' property in super class")
+     "'readwrite' of property inherited from '%1'")
 DIAG(warn_property_attribute, WARNING,
-     "property '%0' '%1' attribute does not match super class '%2' "
-     "property")
+     "property '%0' '%1' attribute does not match the property inherited from'%2' ")
 DIAG(warn_property_type, WARNING,
-     "property type '%0' does not match super class '%1' property type")
+     "property type '%0' does not match property type inherited from '%1'")
 
 //===----------------------------------------------------------------------===//
 // Semantic Analysis

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

==============================================================================
--- cfe/trunk/lib/AST/DeclObjC.cpp (original)
+++ cfe/trunk/lib/AST/DeclObjC.cpp Fri May  2 14:17:30 2008
@@ -242,6 +242,33 @@
   memcpy(PropertyDecl, Properties, NumProperties*sizeof(ObjCPropertyDecl*));
 }                                   
 
+/// mergeProperties - Adds properties to the end of list of current properties
+/// for this class.
+
+void ObjCInterfaceDecl::mergeProperties(ObjCPropertyDecl **Properties, 
+                                        unsigned NumNewProperties) {
+  if (NumNewProperties == 0) return;
+  
+  if (PropertyDecl) {
+    ObjCPropertyDecl **newPropertyDecl =  
+      new ObjCPropertyDecl*[NumNewProperties + NumPropertyDecl];
+    ObjCPropertyDecl **buf = newPropertyDecl;
+    // put back original properties in buffer.
+    memcpy(buf, PropertyDecl, NumPropertyDecl*sizeof(ObjCPropertyDecl*));
+    // Add new properties to this buffer.
+    memcpy(buf+NumPropertyDecl, Properties, 
+           NumNewProperties*sizeof(ObjCPropertyDecl*));
+    free(PropertyDecl);
+    PropertyDecl = newPropertyDecl;
+    NumPropertyDecl += NumNewProperties;
+  }
+  else {
+    PropertyDecl = new ObjCPropertyDecl*[NumNewProperties];
+    memcpy(PropertyDecl, Properties, NumNewProperties*sizeof(ObjCPropertyDecl*));
+    NumPropertyDecl = NumNewProperties;
+  }
+}
+
 /// addProperties - Insert property declaration AST nodes into
 /// ObjCProtocolDecl's PropertyDecl field.
 ///

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=50587&r1=50586&r2=50587&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Fri May  2 14:17:30 2008
@@ -662,9 +662,15 @@
   
   void DiagnosePropertyMismatch(ObjCPropertyDecl *Property, 
                                 ObjCPropertyDecl *SuperProperty,
-                                ObjCInterfaceDecl*SuperIDecl);
+                                const char *Name);
   void ComparePropertiesInBaseAndSuper(ObjCInterfaceDecl *IDecl);
   
+  void MergeProtocolPropertiesIntoClass(ObjCInterfaceDecl *IDecl,
+                                        DeclTy *MergeProtocols);
+  
+  void MergeOneProtocolPropertiesIntoClass(ObjCInterfaceDecl *IDecl,
+                                           ObjCProtocolDecl *PDecl);
+  
   virtual void ActOnAtEnd(SourceLocation AtEndLoc, DeclTy *classDecl,
                       DeclTy **allMethods = 0, unsigned allNum = 0,
                       DeclTy **allProperties = 0, unsigned pNum = 0);

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclObjC.cpp Fri May  2 14:17:30 2008
@@ -247,12 +247,10 @@
 /// DiagnosePropertyMismatch - Compares two properties for their
 /// attributes and types and warns on a variety of inconsistancies.
 ///
-// TODO: Incomplete. 
-//
 void
 Sema::DiagnosePropertyMismatch(ObjCPropertyDecl *Property, 
                                ObjCPropertyDecl *SuperProperty,
-                               ObjCInterfaceDecl *SuperIDecl) {
+                               const char *inheritedName) {
   ObjCPropertyDecl::PropertyAttributeKind CAttr = 
   Property->getPropertyAttributes();
   ObjCPropertyDecl::PropertyAttributeKind SAttr = 
@@ -260,36 +258,36 @@
   if ((CAttr & ObjCPropertyDecl::OBJC_PR_readonly)
       && (SAttr & ObjCPropertyDecl::OBJC_PR_readwrite))
     Diag(Property->getLocation(), diag::warn_readonly_property, 
-               Property->getName(), SuperIDecl->getName());
+               Property->getName(), inheritedName);
   if ((CAttr & ObjCPropertyDecl::OBJC_PR_copy)
       != (SAttr & ObjCPropertyDecl::OBJC_PR_copy))
     Diag(Property->getLocation(), diag::warn_property_attribute,
-         Property->getName(), "copy", SuperIDecl->getName(), 
+         Property->getName(), "copy", inheritedName, 
          SourceRange());
   else if ((CAttr & ObjCPropertyDecl::OBJC_PR_retain)
            != (SAttr & ObjCPropertyDecl::OBJC_PR_retain))
     Diag(Property->getLocation(), diag::warn_property_attribute,
-         Property->getName(), "retain", SuperIDecl->getName(), 
+         Property->getName(), "retain", inheritedName, 
          SourceRange());
   
   if ((CAttr & ObjCPropertyDecl::OBJC_PR_nonatomic)
       != (SAttr & ObjCPropertyDecl::OBJC_PR_nonatomic))
     Diag(Property->getLocation(), diag::warn_property_attribute,
-         Property->getName(), "atomic", SuperIDecl->getName(), 
+         Property->getName(), "atomic", inheritedName, 
          SourceRange());
   if (Property->getSetterName() != SuperProperty->getSetterName())
     Diag(Property->getLocation(), diag::warn_property_attribute,
-         Property->getName(), "setter", SuperIDecl->getName(), 
+         Property->getName(), "setter", inheritedName, 
          SourceRange());
   if (Property->getGetterName() != SuperProperty->getGetterName())
     Diag(Property->getLocation(), diag::warn_property_attribute,
-         Property->getName(), "getter", SuperIDecl->getName(), 
+         Property->getName(), "getter", inheritedName, 
          SourceRange());
   
   if (Property->getCanonicalType() != SuperProperty->getCanonicalType())
     Diag(Property->getLocation(), diag::warn_property_type,
          Property->getType().getAsString(),  
-         SuperIDecl->getName());
+         inheritedName);
   
 }
 
@@ -310,11 +308,69 @@
          E = IDecl->classprop_end(); I != E; ++I) {
       ObjCPropertyDecl *PDecl = (*I);
       if (SuperPDecl->getIdentifier() == PDecl->getIdentifier())
-          DiagnosePropertyMismatch(PDecl, SuperPDecl, SDecl);
+          DiagnosePropertyMismatch(PDecl, SuperPDecl, SDecl->getName());
     }
   }
 }
 
+/// MergeOneProtocolPropertiesIntoClass - This routine goes thru the list
+/// of properties declared in a protocol and adds them to the list
+/// of properties for current class if it is not there already.
+void
+Sema::MergeOneProtocolPropertiesIntoClass(ObjCInterfaceDecl *IDecl,
+                                          ObjCProtocolDecl *PDecl)
+{
+  llvm::SmallVector<ObjCPropertyDecl*, 16> mergeProperties;
+  for (ObjCProtocolDecl::classprop_iterator P = PDecl->classprop_begin(),
+       E = PDecl->classprop_end(); P != E; ++P) {
+    ObjCPropertyDecl *Pr = (*P);
+    ObjCInterfaceDecl::classprop_iterator CP, CE;
+    // Is this property already in  class's list of properties?
+    for (CP = IDecl->classprop_begin(), CE = IDecl->classprop_end(); 
+         CP != CE; ++CP)
+      if ((*CP)->getIdentifier() == Pr->getIdentifier())
+        break;
+    if (CP == CE)
+      // Add this property to list of properties for thie class.
+      mergeProperties.push_back(Pr);
+    else
+      // Property protocol already exist in class. Diagnose any mismatch.
+      DiagnosePropertyMismatch((*CP), Pr, PDecl->getName());
+    }
+  IDecl->mergeProperties(&mergeProperties[0], mergeProperties.size());
+}
+
+/// MergeProtocolPropertiesIntoClass - This routine merges properties
+/// declared in 'MergeItsProtocols' objects (which can be a class or an
+/// inherited protocol into the list of properties for class 'IDecl'
+///
+
+void
+Sema::MergeProtocolPropertiesIntoClass(ObjCInterfaceDecl *IDecl,
+                                       DeclTy *MergeItsProtocols) {
+  Decl *ClassDecl = static_cast<Decl *>(MergeItsProtocols);
+  if (ObjCInterfaceDecl *MDecl = 
+      dyn_cast<ObjCInterfaceDecl>(ClassDecl)) {
+    for (ObjCInterfaceDecl::protocol_iterator P = MDecl->protocol_begin(),
+         E = MDecl->protocol_end(); P != E; ++P)
+      MergeOneProtocolPropertiesIntoClass(IDecl, (*P));
+      // Merge properties of class (*P) into IDECL's
+      ;
+    // Go thru the list of protocols for this class and recursively merge
+    // their properties into this class as well.
+    for (ObjCInterfaceDecl::protocol_iterator P = IDecl->protocol_begin(),
+         E = IDecl->protocol_end(); P != E; ++P)
+      MergeProtocolPropertiesIntoClass(IDecl, (*P));
+  }
+  else if (ObjCProtocolDecl *MDecl = 
+           dyn_cast<ObjCProtocolDecl>(ClassDecl))
+    for (ObjCProtocolDecl::protocol_iterator P = MDecl->protocol_begin(),
+         E = MDecl->protocol_end(); P != E; ++P)
+      MergeOneProtocolPropertiesIntoClass(IDecl, (*P));
+  else
+    assert(false && "MergeProtocolPropertiesIntoClass - bad object kind");
+}
+
 /// ActOnForwardProtocolDeclaration - 
 Action::DeclTy *
 Sema::ActOnForwardProtocolDeclaration(SourceLocation AtProtocolLoc,
@@ -820,7 +876,8 @@
                   &clsMethods[0], clsMethods.size(), AtEndLoc);
     // Compares properties declaraed in this class to those of its 
     // super class.
-    ComparePropertiesInBaseAndSuper (I);
+    ComparePropertiesInBaseAndSuper(I);
+    MergeProtocolPropertiesIntoClass(I, I);
   } else if (ObjCProtocolDecl *P = dyn_cast<ObjCProtocolDecl>(ClassDecl)) {
     P->addMethods(&insMethods[0], insMethods.size(),
                   &clsMethods[0], clsMethods.size(), AtEndLoc);

Modified: cfe/trunk/test/Sema/objc-property-3.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/objc-property-3.m?rev=50587&r1=50586&r2=50587&view=diff

==============================================================================
--- cfe/trunk/test/Sema/objc-property-3.m (original)
+++ cfe/trunk/test/Sema/objc-property-3.m Fri May  2 14:17:30 2008
@@ -9,7 +9,7 @@
 @end
 
 @interface NOW : I
- at property (readonly, retain) id d1; // expected-warning {{attribute 'readonly' of property 'd1' restricts attribute 'readwrite' of 'I' property in super class}} expected-warning {{property 'd1' 'copy' attribute does not match super class 'I' property}}
- at property (readwrite, copy) I* d2; // expected-warning {{property type 'I *' does not match super class 'I' property type}}
+ at property (readonly, retain) id d1; // expected-warning {{attribute 'readonly' of property 'd1' restricts attribute 'readwrite' of property inherited from 'I'}} expected-warning {{property 'd1' 'copy' attribute does not match the property inherited from'I'}}
+ at property (readwrite, copy) I* d2; // expected-warning {{property type 'I *' does not match property type inherited from 'I'}}
 @end
 

Added: cfe/trunk/test/Sema/objc-property-4.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/objc-property-4.m?rev=50587&view=auto

==============================================================================
--- cfe/trunk/test/Sema/objc-property-4.m (added)
+++ cfe/trunk/test/Sema/objc-property-4.m Fri May  2 14:17:30 2008
@@ -0,0 +1,30 @@
+// RUN: clang -verify %s
+
+ at interface Object 
+ at end
+
+ at protocol ProtocolObject
+ at property int class;
+ at property (copy) id MayCauseError;
+ at end
+
+ at protocol ProtocolDerivedGCObject <ProtocolObject>
+ at property int Dclass;
+ at end
+
+ at interface GCObject  : Object <ProtocolDerivedGCObject> {
+    int ifield;
+    int iOwnClass;
+    int iDclass;
+}
+ at property int OwnClass;
+ at end
+
+ at interface ReleaseObject : GCObject <ProtocolObject> {
+   int newO;
+   int oldO;
+}
+ at property (retain) id MayCauseError;  // expected-warning {{property 'MayCauseError' 'copy' attribute does not match the property inherited from'GCObject'}} \
+				      expected-warning {{property 'MayCauseError' 'copy' attribute does not match the property inherited from'ProtocolObject'}}
+ at end
+





More information about the cfe-commits mailing list