diff options
-rw-r--r-- | include/clang/AST/DeclObjC.h | 18 | ||||
-rw-r--r-- | lib/AST/DeclObjC.cpp | 33 | ||||
-rw-r--r-- | lib/Sema/SemaObjCProperty.cpp | 4 | ||||
-rw-r--r-- | test/SemaObjC/property-category-4.m | 36 | ||||
-rw-r--r-- | test/SemaObjC/property-category-impl.m | 5 |
5 files changed, 68 insertions, 28 deletions
diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index 86cf7fc5af..b9cb11d678 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -1137,7 +1137,7 @@ public: // found, we search referenced protocols and class categories. ObjCMethodDecl *lookupMethod(Selector Sel, bool isInstance, bool shallowCategoryLookup= false, - bool CategoryLookup= true) const; + const ObjCCategoryDecl *C= 0) const; ObjCMethodDecl *lookupInstanceMethod(Selector Sel, bool shallowCategoryLookup = false) const { return lookupMethod(Sel, true/*isInstance*/, shallowCategoryLookup); @@ -1156,15 +1156,15 @@ public: return lookupPrivateMethod(Sel, false); } - /// \brief Lookup a setter or getter in the class hierarchy. - /// In this lookup, only class hierarchy and not its categories - /// are looked up - ObjCMethodDecl *lookupPropertyAccessor(const Selector Sel) const { - return lookupMethod(Sel, true/*isInstance*/, - false /*shallowCategoryLookup*/, - false /*CategoryLookup*/); + /// \brief Lookup a setter or getter in the class hierarchy, + /// including in all categories except for category passed + /// as argument. + ObjCMethodDecl *lookupPropertyAccessor(const Selector Sel, + const ObjCCategoryDecl *Cat) const { + return lookupMethod(Sel, true/*isInstance*/, + false/*shallowCategoryLookup*/, Cat); } - + SourceLocation getEndOfDefinitionLoc() const { if (!hasDefinition()) return getLocation(); diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp index 43a128137b..ad09afe269 100644 --- a/lib/AST/DeclObjC.cpp +++ b/lib/AST/DeclObjC.cpp @@ -443,10 +443,12 @@ ObjCInterfaceDecl *ObjCInterfaceDecl::lookupInheritedClass( /// lookupMethod - This method returns an instance/class method by looking in /// the class, its categories, and its super classes (using a linear search). +/// When argument category "C" is specified, any implicit method found +/// in this category is ignored. ObjCMethodDecl *ObjCInterfaceDecl::lookupMethod(Selector Sel, bool isInstance, bool shallowCategoryLookup, - bool CategoryLookup) const { + const ObjCCategoryDecl *C) const { // FIXME: Should make sure no callers ever do this. if (!hasDefinition()) return 0; @@ -469,24 +471,25 @@ ObjCMethodDecl *ObjCInterfaceDecl::lookupMethod(Selector Sel, return MethodDecl; // Didn't find one yet - now look through categories. - if (CategoryLookup) - for (ObjCInterfaceDecl::visible_categories_iterator - Cat = ClassDecl->visible_categories_begin(), - CatEnd = ClassDecl->visible_categories_end(); - Cat != CatEnd; ++Cat) { - if ((MethodDecl = Cat->getMethod(Sel, isInstance))) + for (ObjCInterfaceDecl::visible_categories_iterator + Cat = ClassDecl->visible_categories_begin(), + CatEnd = ClassDecl->visible_categories_end(); + Cat != CatEnd; ++Cat) { + if ((MethodDecl = Cat->getMethod(Sel, isInstance))) + if (C != (*Cat) || !MethodDecl->isImplicit()) return MethodDecl; - if (!shallowCategoryLookup) { - // Didn't find one yet - look through protocols. - const ObjCList<ObjCProtocolDecl> &Protocols = - Cat->getReferencedProtocols(); - for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), - E = Protocols.end(); I != E; ++I) - if ((MethodDecl = (*I)->lookupMethod(Sel, isInstance))) + if (!shallowCategoryLookup) { + // Didn't find one yet - look through protocols. + const ObjCList<ObjCProtocolDecl> &Protocols = + Cat->getReferencedProtocols(); + for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), + E = Protocols.end(); I != E; ++I) + if ((MethodDecl = (*I)->lookupMethod(Sel, isInstance))) + if (C != (*Cat) || !MethodDecl->isImplicit()) return MethodDecl; - } } + } ClassDecl = ClassDecl->getSuperClass(); } diff --git a/lib/Sema/SemaObjCProperty.cpp b/lib/Sema/SemaObjCProperty.cpp index 2162bf06e9..19a369ff9d 100644 --- a/lib/Sema/SemaObjCProperty.cpp +++ b/lib/Sema/SemaObjCProperty.cpp @@ -1726,7 +1726,7 @@ void Sema::DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl* IMPDecl, // the class is going to implement them. if (!InsMap.count(Prop->getGetterName()) && (PrimaryClass == 0 || - !PrimaryClass->lookupPropertyAccessor(Prop->getGetterName()))) { + !PrimaryClass->lookupPropertyAccessor(Prop->getGetterName(), C))) { Diag(IMPDecl->getLocation(), isa<ObjCCategoryDecl>(CDecl) ? diag::warn_setter_getter_impl_required_in_category : @@ -1746,7 +1746,7 @@ void Sema::DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl* IMPDecl, // the class is going to implement them. if (!Prop->isReadOnly() && !InsMap.count(Prop->getSetterName()) && (PrimaryClass == 0 || - !PrimaryClass->lookupPropertyAccessor(Prop->getSetterName()))) { + !PrimaryClass->lookupPropertyAccessor(Prop->getSetterName(), C))) { Diag(IMPDecl->getLocation(), isa<ObjCCategoryDecl>(CDecl) ? diag::warn_setter_getter_impl_required_in_category : diff --git a/test/SemaObjC/property-category-4.m b/test/SemaObjC/property-category-4.m index f99bd52998..ccf5e9b2a8 100644 --- a/test/SemaObjC/property-category-4.m +++ b/test/SemaObjC/property-category-4.m @@ -85,3 +85,39 @@ @implementation I(CAT) @end + +// Test5 +@interface C @end + +@interface C (CAT) +- (int) p; +@end + + +@interface C (Category) +@property (readonly) int p; // no warning for this property - a getter is declared in another category +@property (readonly) int p1; // expected-note {{property declared here}} +@property (readonly) int p2; // no warning for this property - a getter is declared in this category +- (int) p2; +@end + +@implementation C (Category) // expected-warning {{property 'p1' requires method 'p1' to be defined - use @dynamic or provide a method implementation in this category}} +@end + +// Test6 +@protocol MyProtocol +@property (readonly) float anotherFloat; // expected-note {{property declared here}} +@property (readonly) float Float; // no warning for this property - a getter is declared in this protocol +- (float) Float; +@end + +@interface MyObject +{ float anotherFloat; } +@end + +@interface MyObject (CAT) <MyProtocol> +@end + +@implementation MyObject (CAT) // expected-warning {{property 'anotherFloat' requires method 'anotherFloat' to be defined - use @dynamic or provide a method implementation in this category}} +@end + diff --git a/test/SemaObjC/property-category-impl.m b/test/SemaObjC/property-category-impl.m index be42deaf90..135b005761 100644 --- a/test/SemaObjC/property-category-impl.m +++ b/test/SemaObjC/property-category-impl.m @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -fsyntax-only -verify -Wno-objc-root-class %s +// expected-no-diagnostics /* This test is for categories which don't implement the accessors but some accessors are implemented in their base class implementation. In this case,no warning must be issued. @@ -24,10 +25,10 @@ @end @interface MyClass (public) -@property(readwrite) int foo; // expected-note {{property declared here}} +@property(readwrite) int foo; @end -@implementation MyClass (public)// expected-warning {{property 'foo' requires method 'setFoo:' to be defined }} +@implementation MyClass (public) @end // rdar://12568064 |