if (const ObjCObjectPointerType *lhsOPT =
lhs->getAsObjCInterfacePointerType()) {
- // If both the right and left sides have qualifiers.
+ if (lhsOPT->qual_empty()) {
+ bool match = false;
+ if (ObjCInterfaceDecl *lhsID = lhsOPT->getInterfaceDecl()) {
+ for (ObjCObjectPointerType::qual_iterator I = rhsQID->qual_begin(),
+ E = rhsQID->qual_end(); I != E; ++I) {
+ // when comparing an id<P> on rhs with a static type on lhs,
+ // static class must implement all of id's protocols directly or
+ // indirectly through its super class.
+ if (lhsID->ClassImplementsProtocol(*I, true)) {
+ match = true;
+ break;
+ }
+ }
+ if (!match)
+ return false;
+ }
+ return true;
+ }
+ // Both the right and left sides have qualifiers.
for (ObjCObjectPointerType::qual_iterator I = lhsOPT->qual_begin(),
E = lhsOPT->qual_end(); I != E; ++I) {
ObjCProtocolDecl *lhsProto = *I;
bool match = false;
- // when comparing an id<P> on rhs with a static type on lhs,
+ // 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.
- // First, lhs protocols in the qualifier list must be found, direct
- // or indirect in rhs's qualifier list or it is a mismatch.
for (ObjCObjectPointerType::qual_iterator J = rhsQID->qual_begin(),
E = rhsQID->qual_end(); J != E; ++J) {
ObjCProtocolDecl *rhsProto = *J;
if (!match)
return false;
}
-
- // Static class's protocols, or its super class or category protocols
- // must be found, direct or indirect in rhs's qualifier list or it is a mismatch.
- if (ObjCInterfaceDecl *lhsID = lhsOPT->getInterfaceDecl()) {
- llvm::SmallPtrSet<ObjCProtocolDecl *, 8> LHSInheritedProtocols;
- CollectInheritedProtocols(lhsID, LHSInheritedProtocols);
- // This is rather dubious but matches gcc's behavior. If lhs has
- // no type qualifier and its class has no static protocol(s) assume
- // assume that it is mismatch.
- if (LHSInheritedProtocols.empty() && lhsOPT->qual_empty())
- return false;
- for (llvm::SmallPtrSet<ObjCProtocolDecl*,8>::iterator I =
- LHSInheritedProtocols.begin(),
- E = LHSInheritedProtocols.end(); I != E; ++I) {
- bool match = false;
- ObjCProtocolDecl *lhsProto = (*I);
- for (ObjCObjectPointerType::qual_iterator J = rhsQID->qual_begin(),
- E = rhsQID->qual_end(); J != E; ++J) {
- ObjCProtocolDecl *rhsProto = *J;
- if (ProtocolCompatibleWithProtocol(lhsProto, rhsProto) ||
- (compare && ProtocolCompatibleWithProtocol(rhsProto, lhsProto))) {
- match = true;
- break;
- }
- }
- if (!match)
- return false;
- }
- }
return true;
}
return false;
+++ /dev/null
-// RUN: %clang_cc1 -fsyntax-only -verify %s
-//rdar: //8591619
-// pr8453
-
-@protocol NSCopying @end
-@protocol NSPROTO @end
-@protocol NSPROTO1 @end
-@protocol NSPROTO2 @end
-
-@interface NSObject <NSCopying, NSPROTO, NSPROTO1> {
- Class isa;
-}
-@end
-
-void gorf(NSObject <NSCopying> *); // expected-note {{passing argument to parameter here}}
-
-NSObject <NSCopying> *foo(id <NSCopying> bar, id id_obj)
-{
- NSObject <NSCopying> *Init = bar; // expected-warning {{initializing 'NSObject<NSCopying> *' with an expression of incompatible type 'id<NSCopying>'}}
- NSObject *Init1 = bar; // expected-warning {{initializing 'NSObject *' with an expression of incompatible type 'id<NSCopying>'}}
-
- NSObject <NSCopying> *I = id_obj;
- NSObject *I1 = id_obj;
- gorf(bar); // expected-warning {{passing 'id<NSCopying>' to parameter of incompatible type 'NSObject<NSCopying> *'}}
-
- gorf(id_obj);
-
- return bar; // expected-warning {{returning 'id<NSCopying>' from a function with incompatible result type 'NSObject<NSCopying> *'}}
-}
-
-void test(id <NSCopying, NSPROTO, NSPROTO2> bar)
-{
- NSObject <NSCopying> *Init = bar; // expected-warning {{initializing 'NSObject<NSCopying> *' with an expression of incompatible type 'id<NSCopying,NSPROTO,NSPROTO2>'}}
-}