summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
Diffstat (limited to 'clang')
-rw-r--r--clang/include/clang/AST/DeclObjC.h14
-rw-r--r--clang/include/clang/Basic/DiagnosticKinds.def7
-rw-r--r--clang/lib/AST/DeclObjC.cpp27
-rw-r--r--clang/lib/Sema/Sema.h8
-rw-r--r--clang/lib/Sema/SemaDeclObjC.cpp81
-rw-r--r--clang/test/Sema/objc-property-3.m4
-rw-r--r--clang/test/Sema/objc-property-4.m30
7 files changed, 152 insertions, 19 deletions
diff --git a/clang/include/clang/AST/DeclObjC.h b/clang/include/clang/AST/DeclObjC.h
index 93a34577643..5e927089621 100644
--- a/clang/include/clang/AST/DeclObjC.h
+++ b/clang/include/clang/AST/DeclObjC.h
@@ -285,6 +285,12 @@ public:
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 @@ public:
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 @@ public:
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; }
diff --git a/clang/include/clang/Basic/DiagnosticKinds.def b/clang/include/clang/Basic/DiagnosticKinds.def
index 396bd40ae84..f8583a90198 100644
--- a/clang/include/clang/Basic/DiagnosticKinds.def
+++ b/clang/include/clang/Basic/DiagnosticKinds.def
@@ -510,12 +510,11 @@ DIAG(error_property_ivar_type, ERROR,
"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
diff --git a/clang/lib/AST/DeclObjC.cpp b/clang/lib/AST/DeclObjC.cpp
index ef4a6e1c3d0..89f6d2c5019 100644
--- a/clang/lib/AST/DeclObjC.cpp
+++ b/clang/lib/AST/DeclObjC.cpp
@@ -242,6 +242,33 @@ void ObjCInterfaceDecl::addProperties(ObjCPropertyDecl **Properties,
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.
///
diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h
index 1bed03c1fca..68a834c6b4c 100644
--- a/clang/lib/Sema/Sema.h
+++ b/clang/lib/Sema/Sema.h
@@ -662,9 +662,15 @@ public:
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);
diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp
index e95ad6469ba..afac82ca76f 100644
--- a/clang/lib/Sema/SemaDeclObjC.cpp
+++ b/clang/lib/Sema/SemaDeclObjC.cpp
@@ -247,12 +247,10 @@ Sema::FindProtocolDeclaration(SourceLocation TypeLoc,
/// 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 @@ Sema::DiagnosePropertyMismatch(ObjCPropertyDecl *Property,
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 @@ Sema::ComparePropertiesInBaseAndSuper(ObjCInterfaceDecl *IDecl) {
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 @@ void Sema::ActOnAtEnd(SourceLocation AtEndLoc, DeclTy *classDecl,
&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);
diff --git a/clang/test/Sema/objc-property-3.m b/clang/test/Sema/objc-property-3.m
index 565a006fe44..dd45ab43f49 100644
--- a/clang/test/Sema/objc-property-3.m
+++ b/clang/test/Sema/objc-property-3.m
@@ -9,7 +9,7 @@
@end
@interface NOW : I
-@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}}
-@property (readwrite, copy) I* d2; // expected-warning {{property type 'I *' does not match super class 'I' property type}}
+@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'}}
+@property (readwrite, copy) I* d2; // expected-warning {{property type 'I *' does not match property type inherited from 'I'}}
@end
diff --git a/clang/test/Sema/objc-property-4.m b/clang/test/Sema/objc-property-4.m
new file mode 100644
index 00000000000..b5a8f8b1ccb
--- /dev/null
+++ b/clang/test/Sema/objc-property-4.m
@@ -0,0 +1,30 @@
+// RUN: clang -verify %s
+
+@interface Object
+@end
+
+@protocol ProtocolObject
+@property int class;
+@property (copy) id MayCauseError;
+@end
+
+@protocol ProtocolDerivedGCObject <ProtocolObject>
+@property int Dclass;
+@end
+
+@interface GCObject : Object <ProtocolDerivedGCObject> {
+ int ifield;
+ int iOwnClass;
+ int iDclass;
+}
+@property int OwnClass;
+@end
+
+@interface ReleaseObject : GCObject <ProtocolObject> {
+ int newO;
+ int oldO;
+}
+@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'}}
+@end
+
OpenPOWER on IntegriCloud