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>.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@172686 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Douglas Gregor 2013-01-17 00:38:46 +00:00
Родитель a6f9707133
Коммит 0f9b9f3794
6 изменённых файлов: 74 добавлений и 2 удалений

Просмотреть файл

@ -66,6 +66,14 @@ ObjCContainerDecl::getIvarDecl(IdentifierInfo *Id) const {
// 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 @@ ObjCContainerDecl::getMethod(Selector Sel, bool isInstance) const {
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 @@ ObjCPropertyDecl::getDefaultSynthIvarName(ASTContext &Ctx) const {
/// 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 @@ ObjCMethodDecl *ObjCProtocolDecl::lookupMethod(Selector Sel,
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;

Просмотреть файл

@ -743,7 +743,9 @@ Sema::FindProtocolDeclaration(bool WarnOnDeclarations,
// 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);

Просмотреть файл

@ -1,3 +1,11 @@
@interface Foo(LeftSub) <P1>
- (void)left_sub;
@end
@protocol P3
- (void)p3_method;
@property (retain) id p3_prop;
@end
@interface Foo(LeftP3) <P3>
@end

Просмотреть файл

@ -7,3 +7,11 @@
int right_sub_ivar;
}
@end
@protocol P4
- (void)p4_method;
@property (retain) id p4_prop;
@end
@interface Foo(LeftP4) <P4>
@end

Просмотреть файл

@ -19,3 +19,5 @@
@protocol P2
@end
@protocol P3, P4;

Просмотреть файл

@ -47,6 +47,14 @@ void test_hidden_all_errors(Foo *foo) {
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 @@ void test_hidden_right_errors(Foo *foo) {
// 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@7{{'p3_prop' declared here}}
}
@import category_right.sub;
@ -69,4 +86,12 @@ void test_hidden_okay(Foo *foo) {
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;
}