]> granicus.if.org Git - clang/commitdiff
Restore patch for PR8453 which was undone in r117829
authorFariborz Jahanian <fjahanian@apple.com>
Mon, 1 Nov 2010 20:47:16 +0000 (20:47 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Mon, 1 Nov 2010 20:47:16 +0000 (20:47 +0000)
(was project bugs).

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@117951 91177308-0d34-0410-b5e6-96231b3b80d8

lib/AST/ASTContext.cpp
test/SemaObjC/comptypes-10.m [new file with mode: 0644]

index 99023eeb7aadb23981ad6b187e2068ccbf0dc9ed..366fe7d28f1799f8fe9f7cec1c9bfb92575c7977 100644 (file)
@@ -4404,33 +4404,17 @@ bool ASTContext::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs,
 
   if (const ObjCObjectPointerType *lhsOPT =
         lhs->getAsObjCInterfacePointerType()) {
-    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.
+    // If 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 lhs with a static type on rhs,
+      // when comparing an id<P> on rhs with a static type on lhs,
       // 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;
@@ -4443,6 +4427,35 @@ bool ASTContext::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs,
       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 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;
diff --git a/test/SemaObjC/comptypes-10.m b/test/SemaObjC/comptypes-10.m
new file mode 100644 (file)
index 0000000..0a22190
--- /dev/null
@@ -0,0 +1,34 @@
+// 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>'}}
+}