[cfe-commits] r172686 - in /cfe/trunk: lib/AST/DeclObjC.cpp lib/Sema/SemaDeclObjC.cpp test/Modules/Inputs/category_left_sub.h test/Modules/Inputs/category_right_sub.h test/Modules/Inputs/category_top.h test/Modules/objc-categories.m
Douglas Gregor
dgregor at apple.com
Wed Jan 16 16:38:46 PST 2013
Author: dgregor
Date: Wed Jan 16 18:38:46 2013
New Revision: 172686
URL: http://llvm.org/viewvc/llvm-project?rev=172686&view=rev
Log:
Treat hidden Objective-C protocol definitions as if they were
undefined, and don't find methods or protocols within those protocol
definitions. This completes <rdar://problem/10634711>.
Modified:
cfe/trunk/lib/AST/DeclObjC.cpp
cfe/trunk/lib/Sema/SemaDeclObjC.cpp
cfe/trunk/test/Modules/Inputs/category_left_sub.h
cfe/trunk/test/Modules/Inputs/category_right_sub.h
cfe/trunk/test/Modules/Inputs/category_top.h
cfe/trunk/test/Modules/objc-categories.m
Modified: cfe/trunk/lib/AST/DeclObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclObjC.cpp?rev=172686&r1=172685&r2=172686&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclObjC.cpp (original)
+++ cfe/trunk/lib/AST/DeclObjC.cpp Wed Jan 16 18:38:46 2013
@@ -66,6 +66,14 @@
// Get the local instance/class method declared in this interface.
ObjCMethodDecl *
ObjCContainerDecl::getMethod(Selector Sel, bool isInstance) const {
+ // If this context is a hidden protocol definition, don't find any
+ // methods there.
+ if (const ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(this)) {
+ if (const ObjCProtocolDecl *Def = Proto->getDefinition())
+ if (Def->isHidden())
+ return 0;
+ }
+
// Since instance & class methods can have the same name, the loop below
// ensures we get the correct method.
//
@@ -87,6 +95,13 @@
ObjCPropertyDecl *
ObjCPropertyDecl::findPropertyDecl(const DeclContext *DC,
IdentifierInfo *propertyID) {
+ // If this context is a hidden protocol definition, don't find any
+ // property.
+ if (const ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(DC)) {
+ if (const ObjCProtocolDecl *Def = Proto->getDefinition())
+ if (Def->isHidden())
+ return 0;
+ }
DeclContext::lookup_const_result R = DC->lookup(propertyID);
for (DeclContext::lookup_const_iterator I = R.begin(), E = R.end(); I != E;
@@ -111,6 +126,12 @@
/// in 'PropertyId' and returns it. It returns 0, if not found.
ObjCPropertyDecl *
ObjCContainerDecl::FindPropertyDeclaration(IdentifierInfo *PropertyId) const {
+ // Don't find properties within hidden protocol definitions.
+ if (const ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(this)) {
+ if (const ObjCProtocolDecl *Def = Proto->getDefinition())
+ if (Def->isHidden())
+ return 0;
+ }
if (ObjCPropertyDecl *PD =
ObjCPropertyDecl::findPropertyDecl(cast<DeclContext>(this), PropertyId))
@@ -1343,6 +1364,12 @@
bool isInstance) const {
ObjCMethodDecl *MethodDecl = NULL;
+ // If there is no definition or the definition is hidden, we don't find
+ // anything.
+ const ObjCProtocolDecl *Def = getDefinition();
+ if (!Def || Def->isHidden())
+ return NULL;
+
if ((MethodDecl = getMethod(Sel, isInstance)))
return MethodDecl;
Modified: cfe/trunk/lib/Sema/SemaDeclObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclObjC.cpp?rev=172686&r1=172685&r2=172686&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclObjC.cpp Wed Jan 16 18:38:46 2013
@@ -743,7 +743,9 @@
// If this is a forward declaration and we are supposed to warn in this
// case, do it.
- if (WarnOnDeclarations && !PDecl->hasDefinition())
+ // FIXME: Recover nicely in the hidden case.
+ if (WarnOnDeclarations &&
+ (!PDecl->hasDefinition() || PDecl->getDefinition()->isHidden()))
Diag(ProtocolId[i].second, diag::warn_undef_protocolref)
<< ProtocolId[i].first;
Protocols.push_back(PDecl);
Modified: cfe/trunk/test/Modules/Inputs/category_left_sub.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/category_left_sub.h?rev=172686&r1=172685&r2=172686&view=diff
==============================================================================
--- cfe/trunk/test/Modules/Inputs/category_left_sub.h (original)
+++ cfe/trunk/test/Modules/Inputs/category_left_sub.h Wed Jan 16 18:38:46 2013
@@ -1,3 +1,11 @@
@interface Foo(LeftSub) <P1>
- (void)left_sub;
@end
+
+ at protocol P3
+- (void)p3_method;
+ at property (retain) id p3_prop;
+ at end
+
+ at interface Foo(LeftP3) <P3>
+ at end
Modified: cfe/trunk/test/Modules/Inputs/category_right_sub.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/category_right_sub.h?rev=172686&r1=172685&r2=172686&view=diff
==============================================================================
--- cfe/trunk/test/Modules/Inputs/category_right_sub.h (original)
+++ cfe/trunk/test/Modules/Inputs/category_right_sub.h Wed Jan 16 18:38:46 2013
@@ -7,3 +7,11 @@
int right_sub_ivar;
}
@end
+
+ at protocol P4
+- (void)p4_method;
+ at property (retain) id p4_prop;
+ at end
+
+ at interface Foo(LeftP4) <P4>
+ at end
Modified: cfe/trunk/test/Modules/Inputs/category_top.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/category_top.h?rev=172686&r1=172685&r2=172686&view=diff
==============================================================================
--- cfe/trunk/test/Modules/Inputs/category_top.h (original)
+++ cfe/trunk/test/Modules/Inputs/category_top.h Wed Jan 16 18:38:46 2013
@@ -19,3 +19,5 @@
@protocol P2
@end
+ at protocol P3, P4;
+
Modified: cfe/trunk/test/Modules/objc-categories.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/objc-categories.m?rev=172686&r1=172685&r2=172686&view=diff
==============================================================================
--- cfe/trunk/test/Modules/objc-categories.m (original)
+++ cfe/trunk/test/Modules/objc-categories.m Wed Jan 16 18:38:46 2013
@@ -47,6 +47,14 @@
int i = foo->right_sub_ivar; // expected-error{{'Foo' does not have a member named 'right_sub_ivar'}}
id<P1> p1 = foo; // expected-warning{{initializing 'id<P1>' with an expression of incompatible type 'Foo *'}}
id<P2> p2 = foo; // expected-warning{{initializing 'id<P2>' with an expression of incompatible type 'Foo *'}}
+ id<P3> p3;
+ [p3 p3_method]; // expected-warning{{instance method '-p3_method' not found (return type defaults to 'id')}}
+ id<P4> p4;
+ [p4 p4_method]; // expected-warning{{instance method '-p4_method' not found (return type defaults to 'id')}}
+ id p3p = p3.p3_prop; // expected-error{{property 'p3_prop' not found on object of type 'id<P3>'}}
+ p3p = foo.p3_prop; // expected-error{{property 'p3_prop' not found on object of type 'Foo *'}}
+ id p4p = p4.p4_prop; // expected-error{{property 'p4_prop' not found on object of type 'id<P4>'}}
+ p4p = foo.p4_prop; // expected-error{{property 'p4_prop' not found on object of type 'Foo *'}}
}
@import category_left.sub;
@@ -55,10 +63,19 @@
// These are okay
[foo left_sub]; // okay
id<P1> p1 = foo;
- // FIXME: these should fail
+ id<P3> p3;
+ [p3 p3_method];
+ id p3p = p3.p3_prop;
+ p3p = foo.p3_prop;
+ // These should fail
foo.right_sub_prop = foo; // expected-error{{property 'right_sub_prop' not found on object of type 'Foo *'}}
int i = foo->right_sub_ivar; // expected-error{{'Foo' does not have a member named 'right_sub_ivar'}}
id<P2> p2 = foo; // expected-warning{{initializing 'id<P2>' with an expression of incompatible type 'Foo *'}}
+ id<P4> p4;
+ [p4 p4_method]; // expected-warning{{instance method '-p4_method' not found (return type defaults to 'id')}}
+ id p4p = p4.p4_prop; // expected-error{{property 'p4_prop' not found on object of type 'id<P4>'}}
+ p4p = foo.p4_prop; // expected-error{{property 'p4_prop' not found on object of type 'Foo *'; did you mean 'p3_prop'?}}
+ // expected-note at 7{{'p3_prop' declared here}}
}
@import category_right.sub;
@@ -69,4 +86,12 @@
int i = foo->right_sub_ivar;
id<P1> p1 = foo;
id<P2> p2 = foo;
+ id<P3> p3;
+ [p3 p3_method];
+ id<P4> p4;
+ [p4 p4_method];
+ id p3p = p3.p3_prop;
+ p3p = foo.p3_prop;
+ id p4p = p4.p4_prop;
+ p4p = foo.p4_prop;
}
More information about the cfe-commits
mailing list