Tweak Sema::ObjCQualifiedIdTypesAreCompatible() to handle qualified interface types on the RHS.

This eliminates a bogus warning identified in the test below.

This fixes <rdar://problem/5968256> clang on xcode: error: incompatible type initializing 'NSObject<XCSelectionSource> *', expected 'id<NSObject,XCSelectionSource>'

llvm-svn: 51832
This commit is contained in:
Steve Naroff 2008-06-01 02:43:50 +00:00
parent fb75d42faa
commit e643e12313
2 changed files with 64 additions and 5 deletions

View File

@ -367,14 +367,17 @@ bool Sema::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs,
if (const ObjCQualifiedIdType *lhsQID = lhs->getAsObjCQualifiedIdType()) {
const ObjCQualifiedIdType *rhsQID = rhs->getAsObjCQualifiedIdType();
const ObjCQualifiedInterfaceType *rhsQI = 0;
QualType rtype;
if (!rhsQID) {
// Not comparing two ObjCQualifiedIdType's?
if (!rhs->isPointerType()) return false;
QualType rtype = rhs->getAsPointerType()->getPointeeType();
rtype = rhs->getAsPointerType()->getPointeeType();
rhsQI = rtype->getAsObjCQualifiedInterfaceType();
if (rhsQI == 0) {
// If the RHS is an interface pointer ('NSString*'), handle it.
// If the RHS is a unqualified interface pointer "NSString*",
// make sure we check the class hierarchy.
if (const ObjCInterfaceType *IT = rtype->getAsObjCInterfaceType()) {
ObjCInterfaceDecl *rhsID = IT->getDecl();
for (unsigned i = 0; i != lhsQID->getNumProtocols(); ++i) {
@ -390,10 +393,10 @@ bool Sema::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs,
}
ObjCQualifiedIdType::qual_iterator RHSProtoI, RHSProtoE;
if (rhsQI) {
if (rhsQI) { // We have a qualified interface (e.g. "NSObject<Proto> *").
RHSProtoI = rhsQI->qual_begin();
RHSProtoE = rhsQI->qual_end();
} else if (rhsQID) {
} else if (rhsQID) { // We have a qualified id (e.g. "id<Proto> *").
RHSProtoI = rhsQID->qual_begin();
RHSProtoE = rhsQID->qual_end();
} else {
@ -415,6 +418,22 @@ bool Sema::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs,
break;
}
}
if (rhsQI) {
// If the RHS is a qualified interface pointer "NSString<P>*",
// make sure we check the class hierarchy.
if (const ObjCInterfaceType *IT = rtype->getAsObjCInterfaceType()) {
ObjCInterfaceDecl *rhsID = IT->getDecl();
for (unsigned i = 0; i != lhsQID->getNumProtocols(); ++i) {
// when comparing an id<P> on lhs with a static type on rhs,
// see if static class implements all of id's protocols, directly or
// through its super class and categories.
if (ClassImplementsProtocol(lhsQID->getProtocols(i), rhsID, true)) {
match = true;
break;
}
}
}
}
if (!match)
return false;
}

View File

@ -0,0 +1,40 @@
// RUN: clang -pedantic -fsyntax-only -verify %s
typedef signed char BOOL;
@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator;
@protocol NSObject
- (BOOL)isEqual:(id)object;
@end
@protocol NSCoding
- (void)encodeWithCoder:(NSCoder *)aCoder;
@end
@interface NSObject <NSObject> {}
@end
typedef float CGFloat;
@interface NSResponder : NSObject <NSCoding> {}
@end
@protocol XCSelectionSource;
@interface XCSelection : NSResponder {}
- (NSObject <XCSelectionSource> *) source;
@end
extern NSString * const XCActiveSelectionLevel;
@interface XCActionManager : NSResponder {}
+defaultActionManager;
-selectionAtLevel:(NSString *const)s;
@end
@implementation XDMenuItemsManager // expected-warning {{cannot find interface declaration for 'XDMenuItemsManager'}}
+ (void)initialize {
id<XCSelectionSource, NSObject> source =
[[[XCActionManager defaultActionManager] selectionAtLevel:XCActiveSelectionLevel] source];
}
@end