]> granicus.if.org Git - clang/commitdiff
Fix <rdar://problem/6619539> incompatible pointer types sending 'XCElementSpacer...
authorSteve Naroff <snaroff@apple.com>
Sun, 1 Mar 2009 16:12:44 +0000 (16:12 +0000)
committerSteve Naroff <snaroff@apple.com>
Sun, 1 Mar 2009 16:12:44 +0000 (16:12 +0000)
- Reworked ASTContext::canAssignObjCInterfaces().
- Added ObjCProtocolDecl::lookupProtocolNamed().

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

include/clang/AST/DeclObjC.h
lib/AST/ASTContext.cpp
lib/AST/DeclObjC.cpp
test/SemaObjC/protocol-typecheck.m [new file with mode: 0644]
test/SemaObjC/protocol-undef.m

index 33662b287d580a9ce0ed0092894662260a4531db..9bb327874b4f050c09d2ade54411e27fb1821682 100644 (file)
@@ -596,6 +596,8 @@ public:
     ReferencedProtocols.set(List, Num, C);
   }
   
+  ObjCProtocolDecl *lookupProtocolNamed(IdentifierInfo *PName);
+  
   // Lookup a method. First, we search locally. If a method isn't
   // found, we search referenced protocols and class categories.
   ObjCMethodDecl *lookupInstanceMethod(Selector Sel);
index 749655d8712ec34d6a7f347d4d2e50f9da5fb5b0..2100a66c3896921a346b9ced4d6c8e704fe513c9 100644 (file)
@@ -2501,33 +2501,29 @@ bool ASTContext::canAssignObjCInterfaces(const ObjCInterfaceType *LHS,
   // Finally, we must have two protocol-qualified interfaces.
   const ObjCQualifiedInterfaceType *LHSP =cast<ObjCQualifiedInterfaceType>(LHS);
   const ObjCQualifiedInterfaceType *RHSP =cast<ObjCQualifiedInterfaceType>(RHS);
-  ObjCQualifiedInterfaceType::qual_iterator LHSPI = LHSP->qual_begin();
-  ObjCQualifiedInterfaceType::qual_iterator LHSPE = LHSP->qual_end();
-  ObjCQualifiedInterfaceType::qual_iterator RHSPI = RHSP->qual_begin();
-  ObjCQualifiedInterfaceType::qual_iterator RHSPE = RHSP->qual_end();
-  
-  // All protocols in LHS must have a presence in RHS.  Since the protocol lists
-  // are both sorted alphabetically and have no duplicates, we can scan RHS and
-  // LHS in a single parallel scan until we run out of elements in LHS.
-  assert(LHSPI != LHSPE && "Empty LHS protocol list?");
-  ObjCProtocolDecl *LHSProto = *LHSPI;
-  
-  while (RHSPI != RHSPE) {
-    ObjCProtocolDecl *RHSProto = *RHSPI++;
-    // If the RHS has a protocol that the LHS doesn't, ignore it.
-    if (RHSProto != LHSProto)
-      continue;
-    
-    // Otherwise, the RHS does have this element.
-    ++LHSPI;
-    if (LHSPI == LHSPE)
-      return true;  // All protocols in LHS exist in RHS.
-    
-    LHSProto = *LHSPI;
-  }
   
-  // If we got here, we didn't find one of the LHS's protocols in the RHS list.
-  return false;
+  // All LHS protocols must have a presence on the RHS.  
+  assert(LHSP->qual_begin() != LHSP->qual_end() && "Empty LHS protocol list?");
+  
+  for (ObjCQualifiedInterfaceType::qual_iterator LHSPI = LHSP->qual_begin(),
+                                                 LHSPE = LHSP->qual_end();
+       LHSPI != LHSPE; LHSPI++) {
+    bool RHSImplementsProtocol = false;
+
+    // If the RHS doesn't implement the protocol on the left, the types
+    // are incompatible.
+    for (ObjCQualifiedInterfaceType::qual_iterator RHSPI = RHSP->qual_begin(),
+                                                   RHSPE = RHSP->qual_end();
+         !RHSImplementsProtocol && (RHSPI != RHSPE); RHSPI++) {
+      if ((*RHSPI)->lookupProtocolNamed((*LHSPI)->getIdentifier()))
+        RHSImplementsProtocol = true;
+    }
+    // FIXME: For better diagnostics, consider passing back the protocol name.
+    if (!RHSImplementsProtocol)
+      return false;
+  }
+  // The RHS implements all protocols listed on the LHS.
+  return true;
 }
 
 bool ASTContext::areComparableObjCPointerTypes(QualType LHS, QualType RHS) {
index bdbcce750d0bd4b8dacdb24c53e18e9b9c14cb4d..4d2fcb69ac7ffe86e504a77094de127ebdb023b8 100644 (file)
@@ -412,6 +412,19 @@ void ObjCProtocolDecl::Destroy(ASTContext &C) {
   ObjCContainerDecl::Destroy(C);
 }
 
+ObjCProtocolDecl *ObjCProtocolDecl::lookupProtocolNamed(IdentifierInfo *Name) {
+  ObjCProtocolDecl *PDecl = this;
+
+  if (Name == getIdentifier())
+    return PDecl;
+
+  for (protocol_iterator I = protocol_begin(), E = protocol_end(); I != E; ++I)
+    if ((PDecl = (*I)->lookupProtocolNamed(Name)))
+      return PDecl;
+      
+  return NULL;
+}
+
 // lookupInstanceMethod - Lookup a instance method in the protocol and protocols
 // it inherited.
 ObjCMethodDecl *ObjCProtocolDecl::lookupInstanceMethod(Selector Sel) {
diff --git a/test/SemaObjC/protocol-typecheck.m b/test/SemaObjC/protocol-typecheck.m
new file mode 100644 (file)
index 0000000..5ffe73f
--- /dev/null
@@ -0,0 +1,25 @@
+// RUN: clang -fsyntax-only -verify %s
+
+@interface NSObject @end
+@protocol XCElementP @end
+@protocol XCElementSpacerP <XCElementP>  @end
+
+@protocol PWhatever @end
+
+@interface XX
+
+- (void)setFlexElement:(NSObject <PWhatever, XCElementP> *)flexer;
+- (void)setFlexElement2:(NSObject <PWhatever, XCElementSpacerP> *)flexer;
+
+@end
+
+void func() {
+  NSObject <PWhatever, XCElementSpacerP> * flexer;
+  NSObject <PWhatever, XCElementP> * flexer2;
+  XX *obj;
+  [obj setFlexElement:flexer];
+  // FIXME: GCC provides the following diagnostic (which is much better):
+  // protocol-typecheck.m:21: warning: class 'NSObject <PWhatever, XCElementP>' does not implement the 'XCElementSpacerP' protocol
+  [obj setFlexElement2:flexer2]; // expected-warning{{incompatible pointer types sending 'NSObject<PWhatever,XCElementP> *', expected 'NSObject<PWhatever,XCElementSpacerP> *'}}
+}
+
index c35d3f86360abd26797078024111a7e4899607f4..a490fa26fd873f89c34ace0b9d1903fc62eda88a 100644 (file)
@@ -40,8 +40,7 @@ typedef NSObject <OzzyActionDelegateP> OzzyActionDelegate;
 - (void)_recalculateStoredArraysForAnchor:(OzzyAnchor *)anchor {
   Ozzy * contentGroup = anchor.contentGroup;
   if (contentGroup == ((void *)0)) {
-    // GCC doesn't warn about the following (which seems wrong).
-    contentGroup = anchor; // expected-warning{{incompatible pointer types assigning 'OzzyAnchor *', expected 'Ozzy *'}}
+    contentGroup = anchor;
   }
 }
 @end