forked from OSchip/llvm-project
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
This commit is contained in:
parent
b49d7cf19e
commit
fbbaf6afae
|
@ -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 {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
Loading…
Reference in New Issue