summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFariborz Jahanian <fjahanian@apple.com>2008-12-05 22:32:48 +0000
committerFariborz Jahanian <fjahanian@apple.com>2008-12-05 22:32:48 +0000
commitfbbaf6afaea9715fdba1d2c868287b94eeae189c (patch)
tree6dd94f0b42f8994f49e833977ff7f9d37d8b755e
parentb49d7cf19e943878c24745da2d061bb8f7f1cb5e (diff)
downloadbcm5719-llvm-fbbaf6afaea9715fdba1d2c868287b94eeae189c.tar.gz
bcm5719-llvm-fbbaf6afaea9715fdba1d2c868287b94eeae189c.zip
This test checks for duplicate implementation of the same
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 :). llvm-svn: 60610
-rw-r--r--clang/include/clang/AST/DeclObjC.h7
-rw-r--r--clang/include/clang/Basic/DiagnosticKinds.def4
-rw-r--r--clang/lib/AST/DeclObjC.cpp54
-rw-r--r--clang/lib/Sema/SemaDeclObjC.cpp35
-rw-r--r--clang/test/CodeGenObjC/property.m8
-rw-r--r--clang/test/SemaObjC/property-impl-misuse.m16
6 files changed, 118 insertions, 6 deletions
diff --git a/clang/include/clang/AST/DeclObjC.h b/clang/include/clang/AST/DeclObjC.h
index 19fd11d1da2..d2c707c955d 100644
--- a/clang/include/clang/AST/DeclObjC.h
+++ b/clang/include/clang/AST/DeclObjC.h
@@ -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 {
diff --git a/clang/include/clang/Basic/DiagnosticKinds.def b/clang/include/clang/Basic/DiagnosticKinds.def
index 31708b01124..0205789bd83 100644
--- a/clang/include/clang/Basic/DiagnosticKinds.def
+++ b/clang/include/clang/Basic/DiagnosticKinds.def
@@ -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,
diff --git a/clang/lib/AST/DeclObjC.cpp b/clang/lib/AST/DeclObjC.cpp
index a313acf2007..d873ad0746b 100644
--- a/clang/lib/AST/DeclObjC.cpp
+++ b/clang/lib/AST/DeclObjC.cpp
@@ -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.
diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp
index a58d1da6322..03c803054ca 100644
--- a/clang/lib/Sema/SemaDeclObjC.cpp
+++ b/clang/lib/Sema/SemaDeclObjC.cpp
@@ -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;
}
diff --git a/clang/test/CodeGenObjC/property.m b/clang/test/CodeGenObjC/property.m
index 4598aaa79aa..91d3659dcde 100644
--- a/clang/test/CodeGenObjC/property.m
+++ b/clang/test/CodeGenObjC/property.m
@@ -9,6 +9,7 @@
@interface A : Root {
int x;
+ int y, ro, z;
id ob0, ob1, ob2, ob3, ob4;
}
@property int x;
@@ -24,10 +25,9 @@
@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/clang/test/SemaObjC/property-impl-misuse.m b/clang/test/SemaObjC/property-impl-misuse.m
new file mode 100644
index 00000000000..e1913be0e36
--- /dev/null
+++ b/clang/test/SemaObjC/property-impl-misuse.m
@@ -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
OpenPOWER on IntegriCloud