aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/AST/DeclObjC.h18
-rw-r--r--lib/AST/DeclObjC.cpp33
-rw-r--r--lib/Sema/SemaObjCProperty.cpp4
-rw-r--r--test/SemaObjC/property-category-4.m36
-rw-r--r--test/SemaObjC/property-category-impl.m5
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