forked from OSchip/llvm-project
Use of properties declared in protocols in the category
via the category's protocol list1s, with appropriate diagnsostics and a test case. llvm-svn: 60634
This commit is contained in:
parent
da93063acc
commit
d2c2ad515e
|
@ -883,6 +883,8 @@ public:
|
|||
|
||||
void addProperties(ObjCPropertyDecl **Properties, unsigned NumProperties);
|
||||
|
||||
void mergeProperties(ObjCPropertyDecl **Properties, unsigned NumProperties);
|
||||
|
||||
void addPropertyMethods(ASTContext &Context,
|
||||
ObjCPropertyDecl* Property,
|
||||
llvm::SmallVector<ObjCMethodDecl*, 32> &insMethods,
|
||||
|
|
|
@ -513,6 +513,31 @@ void ObjCCategoryDecl::addPropertyMethods(
|
|||
::addPropertyMethods(this, Context, property, insMethods, InsMap);
|
||||
}
|
||||
|
||||
/// mergeProperties - Adds properties to the end of list of current properties
|
||||
/// for this category.
|
||||
|
||||
void ObjCCategoryDecl::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*));
|
||||
delete[] PropertyDecl;
|
||||
PropertyDecl = newPropertyDecl;
|
||||
NumPropertyDecl += NumNewProperties;
|
||||
}
|
||||
else {
|
||||
addProperties(Properties, NumNewProperties);
|
||||
}
|
||||
}
|
||||
|
||||
/// addPropertyMethods - Goes through list of properties declared in this class
|
||||
/// and builds setter/getter method declartions depending on the setter/getter
|
||||
/// attributes of the property.
|
||||
|
|
|
@ -1075,10 +1075,10 @@ public:
|
|||
const IdentifierInfo *Name);
|
||||
void ComparePropertiesInBaseAndSuper(ObjCInterfaceDecl *IDecl);
|
||||
|
||||
void MergeProtocolPropertiesIntoClass(ObjCInterfaceDecl *IDecl,
|
||||
void MergeProtocolPropertiesIntoClass(Decl *CDecl,
|
||||
DeclTy *MergeProtocols);
|
||||
|
||||
void MergeOneProtocolPropertiesIntoClass(ObjCInterfaceDecl *IDecl,
|
||||
void MergeOneProtocolPropertiesIntoClass(Decl *CDecl,
|
||||
ObjCProtocolDecl *PDecl);
|
||||
|
||||
virtual void ActOnAtEnd(SourceLocation AtEndLoc, DeclTy *classDecl,
|
||||
|
|
|
@ -311,11 +311,35 @@ Sema::ComparePropertiesInBaseAndSuper(ObjCInterfaceDecl *IDecl) {
|
|||
|
||||
/// 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.
|
||||
/// of properties for current class/category if it is not there already.
|
||||
void
|
||||
Sema::MergeOneProtocolPropertiesIntoClass(ObjCInterfaceDecl *IDecl,
|
||||
Sema::MergeOneProtocolPropertiesIntoClass(Decl *CDecl,
|
||||
ObjCProtocolDecl *PDecl) {
|
||||
llvm::SmallVector<ObjCPropertyDecl*, 16> mergeProperties;
|
||||
ObjCInterfaceDecl *IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(CDecl);
|
||||
if (!IDecl) {
|
||||
// Category
|
||||
ObjCCategoryDecl *CatDecl = static_cast<ObjCCategoryDecl*>(CDecl);
|
||||
assert (CatDecl && "MergeOneProtocolPropertiesIntoClass");
|
||||
for (ObjCProtocolDecl::classprop_iterator P = PDecl->classprop_begin(),
|
||||
E = PDecl->classprop_end(); P != E; ++P) {
|
||||
ObjCPropertyDecl *Pr = (*P);
|
||||
ObjCCategoryDecl::classprop_iterator CP, CE;
|
||||
// Is this property already in category's list of properties?
|
||||
for (CP = CatDecl->classprop_begin(), CE = CatDecl->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->getIdentifier());
|
||||
}
|
||||
CatDecl->mergeProperties(&mergeProperties[0], mergeProperties.size());
|
||||
return;
|
||||
}
|
||||
for (ObjCProtocolDecl::classprop_iterator P = PDecl->classprop_begin(),
|
||||
E = PDecl->classprop_end(); P != E; ++P) {
|
||||
ObjCPropertyDecl *Pr = (*P);
|
||||
|
@ -337,13 +361,39 @@ Sema::MergeOneProtocolPropertiesIntoClass(ObjCInterfaceDecl *IDecl,
|
|||
|
||||
/// 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'
|
||||
/// inherited protocol into the list of properties for class/category 'CDecl'
|
||||
///
|
||||
|
||||
void
|
||||
Sema::MergeProtocolPropertiesIntoClass(ObjCInterfaceDecl *IDecl,
|
||||
Sema::MergeProtocolPropertiesIntoClass(Decl *CDecl,
|
||||
DeclTy *MergeItsProtocols) {
|
||||
Decl *ClassDecl = static_cast<Decl *>(MergeItsProtocols);
|
||||
ObjCInterfaceDecl *IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(CDecl);
|
||||
|
||||
if (!IDecl) {
|
||||
// Category
|
||||
ObjCCategoryDecl *CatDecl = static_cast<ObjCCategoryDecl*>(CDecl);
|
||||
assert (CatDecl && "MergeProtocolPropertiesIntoClass");
|
||||
if (ObjCCategoryDecl *MDecl = dyn_cast<ObjCCategoryDecl>(ClassDecl)) {
|
||||
for (ObjCCategoryDecl::protocol_iterator P = MDecl->protocol_begin(),
|
||||
E = MDecl->protocol_end(); P != E; ++P)
|
||||
// Merge properties of category (*P) into IDECL's
|
||||
MergeOneProtocolPropertiesIntoClass(CatDecl, *P);
|
||||
|
||||
// Go thru the list of protocols for this category and recursively merge
|
||||
// their properties into this class as well.
|
||||
for (ObjCCategoryDecl::protocol_iterator P = CatDecl->protocol_begin(),
|
||||
E = CatDecl->protocol_end(); P != E; ++P)
|
||||
MergeProtocolPropertiesIntoClass(CatDecl, *P);
|
||||
} else {
|
||||
ObjCProtocolDecl *MD = cast<ObjCProtocolDecl>(ClassDecl);
|
||||
for (ObjCProtocolDecl::protocol_iterator P = MD->protocol_begin(),
|
||||
E = MD->protocol_end(); P != E; ++P)
|
||||
MergeOneProtocolPropertiesIntoClass(CatDecl, (*P));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (ObjCInterfaceDecl *MDecl = dyn_cast<ObjCInterfaceDecl>(ClassDecl)) {
|
||||
for (ObjCInterfaceDecl::protocol_iterator P = MDecl->protocol_begin(),
|
||||
E = MDecl->protocol_end(); P != E; ++P)
|
||||
|
@ -1063,8 +1113,8 @@ void Sema::ActOnAtEnd(SourceLocation AtEndLoc, DeclTy *classDecl,
|
|||
// By the same token, they are also used to add new properties. No
|
||||
// need to compare the added property to those in the class.
|
||||
|
||||
// FIXME: If we merge properties into class we should probably
|
||||
// merge them into category as well?
|
||||
// Merge protocol properties into category
|
||||
MergeProtocolPropertiesIntoClass(C, C);
|
||||
for (ObjCCategoryDecl::classprop_iterator i = C->classprop_begin(),
|
||||
e = C->classprop_end(); i != e; ++i) {
|
||||
diagnosePropertySetterGetterMismatch((*i), InsMap[(*i)->getGetterName()],
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
@protocol P
|
||||
@property(readonly) int X;
|
||||
@end
|
||||
|
||||
@protocol P1<P>
|
||||
@property (copy) id ID;
|
||||
@end
|
||||
|
||||
@interface I
|
||||
@end
|
||||
|
||||
@interface I (Cat) <P>
|
||||
@property float X; // expected-warning {{property type 'float' does not match property type inherited from 'P'}}
|
||||
@end
|
||||
|
||||
@interface I (Cat2) <P1>
|
||||
@property (retain) id ID; // expected-warning {{property 'ID' 'copy' attribute does not match the property inherited from 'P1'}}
|
||||
@end
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue