Warn for any kind of initialization if initializer does not

implement lhs's protocols. // rdar://9091389.
 

llvm-svn: 129142
This commit is contained in:
Fariborz Jahanian 2011-04-08 18:25:29 +00:00
parent 9242b33de7
commit 4806ff8af9
6 changed files with 96 additions and 7 deletions

View File

@ -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) {

View File

@ -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();

View File

@ -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>&);

View File

@ -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();

View File

@ -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;
}

View File

@ -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 {