зеркало из https://github.com/microsoft/clang-1.git
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:
Родитель
a6f9707133
Коммит
0f9b9f3794
|
@ -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;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче