forked from OSchip/llvm-project
Warn for any kind of initialization if initializer does not
implement lhs's protocols. // rdar://9091389. llvm-svn: 129142
This commit is contained in:
parent
9242b33de7
commit
4806ff8af9
|
@ -629,6 +629,27 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
/// getImmSubClassOf - Returns Immediate sub-class of the specified interface class
|
||||
/// if 'Super' is a superclass of this class. null if no such super class.
|
||||
/// So in this example if 'this' is 'BClass' and 'Super' is 'AClass' then 'BClass'
|
||||
/// is returned.
|
||||
/// \code
|
||||
/// @interface BClass : AClass <SubFooable>
|
||||
/// @end
|
||||
/// \endcode
|
||||
|
||||
ObjCInterfaceDecl *getImmSubClassOf(const ObjCInterfaceDecl *Super) {
|
||||
ObjCInterfaceDecl *ImmSubClass = this;
|
||||
ObjCInterfaceDecl *I = this->getSuperClass();
|
||||
while (I != NULL) {
|
||||
if (Super == I)
|
||||
return ImmSubClass;
|
||||
ImmSubClass = I;
|
||||
I = I->getSuperClass();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ObjCIvarDecl *lookupInstanceVariable(IdentifierInfo *IVarName,
|
||||
ObjCInterfaceDecl *&ClassDeclared);
|
||||
ObjCIvarDecl *lookupInstanceVariable(IdentifierInfo *IVarName) {
|
||||
|
|
|
@ -4981,10 +4981,47 @@ bool ASTContext::canAssignObjCInterfaces(const ObjCObjectType *LHS,
|
|||
if (LHS->getNumProtocols() == 0)
|
||||
return true;
|
||||
|
||||
// Okay, we know the LHS has protocol qualifiers. If the RHS doesn't, then it
|
||||
// isn't a superset.
|
||||
if (RHS->getNumProtocols() == 0)
|
||||
return true; // FIXME: should return false!
|
||||
// Okay, we know the LHS has protocol qualifiers. If the RHS doesn't,
|
||||
// more detailed analysis is required.
|
||||
if (RHS->getNumProtocols() == 0) {
|
||||
// OK, if LHS is a superclass of RHS *and*
|
||||
// this superclass is assignment compatible with LHS.
|
||||
// false otherwise.
|
||||
ObjCInterfaceDecl *SuperClass =
|
||||
RHS->getInterface()->getImmSubClassOf(LHS->getInterface());
|
||||
if (SuperClass) {
|
||||
// OK if conversion of LHS to SuperClass results in narrowing of types
|
||||
// ; i.e., SuperClass may implement at least one of the protocols
|
||||
// in LHS's protocol list. Example, SuperObj<P1> = lhs<P1,P2> is ok.
|
||||
// But not SuperObj<P1,P2,P3> = lhs<P1,P2>.
|
||||
llvm::SmallPtrSet<ObjCProtocolDecl *, 8> SuperClassInheritedProtocols;
|
||||
CollectInheritedProtocols(SuperClass, SuperClassInheritedProtocols);
|
||||
// If super class has no protocols, it is not a match.
|
||||
if (SuperClassInheritedProtocols.empty())
|
||||
return false;
|
||||
|
||||
for (ObjCObjectType::qual_iterator LHSPI = LHS->qual_begin(),
|
||||
LHSPE = LHS->qual_end();
|
||||
LHSPI != LHSPE; LHSPI++) {
|
||||
bool SuperImplementsProtocol = false;
|
||||
ObjCProtocolDecl *LHSProto = (*LHSPI);
|
||||
|
||||
for (llvm::SmallPtrSet<ObjCProtocolDecl*,8>::iterator I =
|
||||
SuperClassInheritedProtocols.begin(),
|
||||
E = SuperClassInheritedProtocols.end(); I != E; ++I) {
|
||||
ObjCProtocolDecl *SuperClassProto = (*I);
|
||||
if (SuperClassProto->lookupProtocolNamed(LHSProto->getIdentifier())) {
|
||||
SuperImplementsProtocol = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!SuperImplementsProtocol)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
for (ObjCObjectType::qual_iterator LHSPI = LHS->qual_begin(),
|
||||
LHSPE = LHS->qual_end();
|
||||
|
|
|
@ -30,7 +30,7 @@ void f(B* b) {
|
|||
@protocol P2 @end
|
||||
@protocol P3 @end
|
||||
@interface foo<P1> {} @end
|
||||
@interface bar : foo <P1, P2> {} @end
|
||||
@interface bar : foo <P1, P2, P3> {} @end
|
||||
typedef bar baz;
|
||||
void f5(foo&);
|
||||
void f5b(foo<P1>&);
|
||||
|
|
|
@ -12,7 +12,7 @@ int main()
|
|||
MyClass *obj_cp;
|
||||
|
||||
obj_cp = obj_p;
|
||||
obj_p = obj_cp;
|
||||
obj_p = obj_cp; // expected-warning {{incompatible pointer types assigning to 'MyClass<MyProtocol> *' from 'MyClass *'}}
|
||||
|
||||
if (obj_cp == obj_p)
|
||||
foo();
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
// RUN: %clang_cc1 -fsyntax-only -verify %s
|
||||
// rdar://9091389
|
||||
|
||||
@protocol Fooable
|
||||
- (void)foo;
|
||||
@end
|
||||
|
||||
@protocol SubFooable <Fooable>
|
||||
@end
|
||||
|
||||
@interface AClass
|
||||
@end
|
||||
|
||||
@interface BClass : AClass <SubFooable>
|
||||
@end
|
||||
|
||||
@implementation BClass
|
||||
- (void)foo {
|
||||
}
|
||||
@end
|
||||
|
||||
void functionTakingAClassConformingToAProtocol(AClass <Fooable> *instance) { // expected-note {{passing argument to parameter 'instance' here}}
|
||||
}
|
||||
|
||||
int main () {
|
||||
AClass *aobject = 0;
|
||||
BClass *bobject = 0;
|
||||
functionTakingAClassConformingToAProtocol(aobject); // expected-warning {{incompatible pointer types passing 'AClass *' to parameter of type 'AClass<Fooable> *'}}
|
||||
functionTakingAClassConformingToAProtocol(bobject); // Shouldn't warn - does implement Fooable
|
||||
return 0;
|
||||
}
|
|
@ -37,7 +37,7 @@ void f4(NSString &tmpstr) {
|
|||
@protocol P2 @end
|
||||
@protocol P3 @end
|
||||
@interface foo<P1> {} @end
|
||||
@interface bar : foo <P1, P2> {} @end
|
||||
@interface bar : foo <P1, P2, P3> {} @end
|
||||
typedef bar baz;
|
||||
|
||||
struct ToBar {
|
||||
|
|
Loading…
Reference in New Issue