aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFariborz Jahanian <fjahanian@apple.com>2013-04-25 21:59:34 +0000
committerFariborz Jahanian <fjahanian@apple.com>2013-04-25 21:59:34 +0000
commitf3f0f357f8d6b4511b6d605cc8a39ae3787fef6d (patch)
treeb28ea54ce22492210224a02008ecc48211bdf883
parent9ed6d8068f767819951bc4eebf6f4912087c442a (diff)
Objective-C: This is a small modification to my
patch -n r180198. When reporting on missing property accessor implementation in categories, do not report when they are declared in primary class, class's protocol, or one of it super classes or in of the other categories. // rdar://13713098 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@180580 91177308-0d34-0410-b5e6-96231b3b80d8
-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