diff options
author | Fariborz Jahanian <fjahanian@apple.com> | 2008-12-06 23:03:39 +0000 |
---|---|---|
committer | Fariborz Jahanian <fjahanian@apple.com> | 2008-12-06 23:03:39 +0000 |
commit | d2c2ad515e33ebf700942e90cddb4b72cc738d70 (patch) | |
tree | 619670989d3bd51cc3b99de6cd57af975d3004cf | |
parent | da93063acc9077f9607ae92c590738414f0030f2 (diff) | |
download | bcm5719-llvm-d2c2ad515e33ebf700942e90cddb4b72cc738d70.tar.gz bcm5719-llvm-d2c2ad515e33ebf700942e90cddb4b72cc738d70.zip |
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
-rw-r--r-- | clang/include/clang/AST/DeclObjC.h | 2 | ||||
-rw-r--r-- | clang/lib/AST/DeclObjC.cpp | 25 | ||||
-rw-r--r-- | clang/lib/Sema/Sema.h | 4 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclObjC.cpp | 62 | ||||
-rw-r--r-- | clang/test/SemaObjC/property-category-3.m | 21 |
5 files changed, 106 insertions, 8 deletions
diff --git a/clang/include/clang/AST/DeclObjC.h b/clang/include/clang/AST/DeclObjC.h index d2c707c955d..190c1c3509c 100644 --- a/clang/include/clang/AST/DeclObjC.h +++ b/clang/include/clang/AST/DeclObjC.h @@ -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, diff --git a/clang/lib/AST/DeclObjC.cpp b/clang/lib/AST/DeclObjC.cpp index 58d0383d1fe..0458282fb38 100644 --- a/clang/lib/AST/DeclObjC.cpp +++ b/clang/lib/AST/DeclObjC.cpp @@ -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. diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index a9ad257e41b..ef99aaaa46c 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -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, diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp index a5ffb709056..54934425806 100644 --- a/clang/lib/Sema/SemaDeclObjC.cpp +++ b/clang/lib/Sema/SemaDeclObjC.cpp @@ -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()], diff --git a/clang/test/SemaObjC/property-category-3.m b/clang/test/SemaObjC/property-category-3.m new file mode 100644 index 00000000000..d651b855bf4 --- /dev/null +++ b/clang/test/SemaObjC/property-category-3.m @@ -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 + + + |