]> granicus.if.org Git - clang/commitdiff
This test checks for duplicate implementation of the same
authorFariborz Jahanian <fjahanian@apple.com>
Fri, 5 Dec 2008 22:32:48 +0000 (22:32 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Fri, 5 Dec 2008 22:32:48 +0000 (22:32 +0000)
property. It also checks for duplicate use of the same ivar
in two different iproperty implementations. It also caught
an error for a test case used in CodeGen :).

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@60610 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/DeclObjC.h
include/clang/Basic/DiagnosticKinds.def
lib/AST/DeclObjC.cpp
lib/Sema/SemaDeclObjC.cpp
test/CodeGenObjC/property.m
test/SemaObjC/property-impl-misuse.m [new file with mode: 0644]

index 19fd11d1da254fd1a4a15300bb4d834d1c25c7ea..d2c707c955de59b98405e3bf542ebcc19f3fa11a 100644 (file)
@@ -1005,6 +1005,9 @@ public:
     PropertyImplementations.push_back(property);
   }
 
+  ObjCPropertyImplDecl *FindPropertyImplDecl(IdentifierInfo *propertyId) const;
+  ObjCPropertyImplDecl *FindPropertyImplIvarDecl(IdentifierInfo *ivarId) const;
+  
   unsigned getNumPropertyImplementations() const
   { return PropertyImplementations.size(); }
   
@@ -1101,6 +1104,10 @@ public:
   void addPropertyImplementation(ObjCPropertyImplDecl *property) {
     PropertyImplementations.push_back(property);
   } 
+
+  ObjCPropertyImplDecl *FindPropertyImplDecl(IdentifierInfo *propertyId) const;
+  ObjCPropertyImplDecl *FindPropertyImplIvarDecl(IdentifierInfo *ivarId) const;
+
   typedef llvm::SmallVector<ObjCPropertyImplDecl*, 8>::const_iterator
   propimpl_iterator;
   propimpl_iterator propimpl_begin() const { 
index 31708b01124181714d7635364cdfe89a8af20ce3..0205789bd8326a031178faf42ddc0bbd9f701e1d 100644 (file)
@@ -575,6 +575,10 @@ DIAG(err_setter_type_void, ERROR,
      "type of setter must be void")
 DIAG(warn_conflicting_types, WARNING,
      "conflicting types for %0")
+DIAG(error_property_implemented, ERROR,
+     "property %0 is already implemented")
+DIAG(error_duplicate_ivar_use, ERROR,
+     "synthesized properties %0 and %1 both claim ivar %2")
 
 /// C++ parser diagnostics
 DIAG(err_expected_unqualified_id, ERROR,
index a313acf20078b83c82ff99ff8b17fe5e24c482e0..d873ad0746be4b60ac0f133ebbbac11120df9c27 100644 (file)
@@ -716,6 +716,60 @@ ObjCMethodDecl *ObjCImplementationDecl::getClassMethod(Selector Sel) const {
   return NULL;
 }
 
+/// FindPropertyImplDecl - This method looks up a previous ObjCPropertyImplDecl
+/// added to the list of those properties @synthesized/@dynamic in this
+/// @implementation block.
+///
+ObjCPropertyImplDecl *ObjCImplementationDecl::FindPropertyImplDecl(IdentifierInfo *Id) const {
+  for (propimpl_iterator i = propimpl_begin(), e = propimpl_end(); i != e; ++i) {
+    ObjCPropertyImplDecl *PID = *i;
+    if (PID->getPropertyDecl()->getIdentifier() == Id)
+      return PID;
+  }
+  return 0;
+}
+
+/// FindPropertyImplIvarDecl - This method lookup the ivar in the list of
+/// properties implemented in this @implementation block and returns it if 
+/// found.
+///
+ObjCPropertyImplDecl *ObjCImplementationDecl::FindPropertyImplIvarDecl(IdentifierInfo *ivarId) const {
+  for (propimpl_iterator i = propimpl_begin(), e = propimpl_end(); i != e; ++i) {
+    ObjCPropertyImplDecl *PID = *i;
+    if (PID->getPropertyIvarDecl() &&
+        PID->getPropertyIvarDecl()->getIdentifier() == ivarId)
+      return PID;
+  }
+  return 0;
+}
+
+/// FindPropertyImplIvarDecl - This method lookup the ivar in the list of
+/// properties implemented in this category @implementation block and returns it if 
+/// found.
+///
+ObjCPropertyImplDecl *ObjCCategoryImplDecl::FindPropertyImplIvarDecl(IdentifierInfo *ivarId) const {
+  for (propimpl_iterator i = propimpl_begin(), e = propimpl_end(); i != e; ++i) {
+    ObjCPropertyImplDecl *PID = *i;
+    if (PID->getPropertyIvarDecl() &&
+        PID->getPropertyIvarDecl()->getIdentifier() == ivarId)
+      return PID;
+  }
+  return 0;
+}
+
+/// FindPropertyImplDecl - This method looks up a previous ObjCPropertyImplDecl
+/// added to the list of those properties @synthesized/@dynamic in this
+/// category @implementation block.
+///
+ObjCPropertyImplDecl *ObjCCategoryImplDecl::FindPropertyImplDecl(IdentifierInfo *Id) const {
+  for (propimpl_iterator i = propimpl_begin(), e = propimpl_end(); i != e; ++i) {
+    ObjCPropertyImplDecl *PID = *i;
+    if (PID->getPropertyDecl()->getIdentifier() == Id)
+      return PID;
+  }
+  return 0;
+}
+
 // lookupInstanceMethod - This method returns an instance method by looking in
 // the class implementation. Unlike interfaces, we don't look outside the
 // implementation.
index a58d1da632270418d274f1a4a7549388bf226700..03c803054ca405212b129860bd9cf1f04f73964e 100644 (file)
@@ -1506,10 +1506,41 @@ Sema::DeclTy *Sema::ActOnPropertyImplDecl(SourceLocation AtLoc,
                                   ObjCPropertyImplDecl::Synthesize 
                                   : ObjCPropertyImplDecl::Dynamic),
                                  Ivar);
-  if (IC)
+  if (IC) {
+    if (Synthesize)
+      if (ObjCPropertyImplDecl *PPIDecl = 
+          IC->FindPropertyImplIvarDecl(PropertyIvar)) {
+        Diag(PropertyLoc, diag::error_duplicate_ivar_use) 
+          << PropertyId << PPIDecl->getPropertyDecl()->getIdentifier() 
+          << PropertyIvar;
+        Diag(PPIDecl->getLocation(), diag::note_previous_use);
+      }
+    
+    if (ObjCPropertyImplDecl *PPIDecl = IC->FindPropertyImplDecl(PropertyId)) {
+      Diag(PropertyLoc, diag::error_property_implemented) << PropertyId;
+      Diag(PPIDecl->getLocation(), diag::note_previous_declaration);
+      return 0;
+    }
     IC->addPropertyImplementation(PIDecl);
-  else
+  }
+  else {
+    if (Synthesize)
+      if (ObjCPropertyImplDecl *PPIDecl = 
+          CatImplClass->FindPropertyImplIvarDecl(PropertyIvar)) {
+        Diag(PropertyLoc, diag::error_duplicate_ivar_use) 
+          << PropertyId << PPIDecl->getPropertyDecl()->getIdentifier() 
+          << PropertyIvar;
+        Diag(PPIDecl->getLocation(), diag::note_previous_use);
+      }
+    
+    if (ObjCPropertyImplDecl *PPIDecl = 
+          CatImplClass->FindPropertyImplDecl(PropertyId)) {
+      Diag(PropertyLoc, diag::error_property_implemented) << PropertyId;
+      Diag(PPIDecl->getLocation(), diag::note_previous_declaration);
+      return 0;
+    }    
     CatImplClass->addPropertyImplementation(PIDecl);
+  }
     
   return PIDecl;
 }
index 4598aaa79aad73a38bc0aaeddba7025c39c87959..91d3659dcde7c4c43978893aa5c8bffdbe04f5ab 100644 (file)
@@ -9,6 +9,7 @@
 
 @interface A : Root {
   int x;
+  int y, ro, z;
   id ob0, ob1, ob2, ob3, ob4;
 }
 @property int x;
 
 @implementation A
 @dynamic x;
-@synthesize x;
-@synthesize y = x;
-@synthesize z = x;
-@synthesize ro = x;
+@synthesize y;
+@synthesize z = z;
+@synthesize ro;
 @synthesize ob0;
 @synthesize ob1;
 @synthesize ob2;
diff --git a/test/SemaObjC/property-impl-misuse.m b/test/SemaObjC/property-impl-misuse.m
new file mode 100644 (file)
index 0000000..e1913be
--- /dev/null
@@ -0,0 +1,16 @@
+// RUN: clang -fsyntax-only -verify %s
+
+@interface I {
+  int Y;
+}
+@property int X;
+@property int Y;
+@property int Z;
+@end
+
+@implementation I
+@dynamic X; // expected-note {{previous declaration is here}}
+@dynamic X; // expected-error {{property 'X' is already implemented}}
+@synthesize Y; // expected-note {{previous use is here}}
+@synthesize Z=Y; // expected-error {{synthesized properties 'Z' and 'Y' both claim ivar 'Y'}}
+@end