[cfe-commits] r65773 - in /cfe/trunk: include/clang/AST/DeclObjC.h lib/AST/ASTContext.cpp lib/AST/DeclObjC.cpp test/SemaObjC/protocol-typecheck.m test/SemaObjC/protocol-undef.m

Steve Naroff snaroff at apple.com
Sun Mar 1 08:12:45 PST 2009


Author: snaroff
Date: Sun Mar  1 10:12:44 2009
New Revision: 65773

URL: http://llvm.org/viewvc/llvm-project?rev=65773&view=rev
Log:
Fix <rdar://problem/6619539> incompatible pointer types sending 'XCElementSpacer *', expected 'XCElement *' (not handling protocol signatures correctly?).

- Reworked ASTContext::canAssignObjCInterfaces().
- Added ObjCProtocolDecl::lookupProtocolNamed().


Added:
    cfe/trunk/test/SemaObjC/protocol-typecheck.m
Modified:
    cfe/trunk/include/clang/AST/DeclObjC.h
    cfe/trunk/lib/AST/ASTContext.cpp
    cfe/trunk/lib/AST/DeclObjC.cpp
    cfe/trunk/test/SemaObjC/protocol-undef.m

Modified: cfe/trunk/include/clang/AST/DeclObjC.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclObjC.h?rev=65773&r1=65772&r2=65773&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/DeclObjC.h (original)
+++ cfe/trunk/include/clang/AST/DeclObjC.h Sun Mar  1 10:12:44 2009
@@ -596,6 +596,8 @@
     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);

Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=65773&r1=65772&r2=65773&view=diff

==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Sun Mar  1 10:12:44 2009
@@ -2501,33 +2501,29 @@
   // 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) {

Modified: cfe/trunk/lib/AST/DeclObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclObjC.cpp?rev=65773&r1=65772&r2=65773&view=diff

==============================================================================
--- cfe/trunk/lib/AST/DeclObjC.cpp (original)
+++ cfe/trunk/lib/AST/DeclObjC.cpp Sun Mar  1 10:12:44 2009
@@ -412,6 +412,19 @@
   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) {

Added: cfe/trunk/test/SemaObjC/protocol-typecheck.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/protocol-typecheck.m?rev=65773&view=auto

==============================================================================
--- cfe/trunk/test/SemaObjC/protocol-typecheck.m (added)
+++ cfe/trunk/test/SemaObjC/protocol-typecheck.m Sun Mar  1 10:12:44 2009
@@ -0,0 +1,25 @@
+// RUN: clang -fsyntax-only -verify %s
+
+ at interface NSObject @end
+ at protocol XCElementP @end
+ at protocol XCElementSpacerP <XCElementP>  @end
+
+ at protocol PWhatever @end
+
+ at interface XX
+
+- (void)setFlexElement:(NSObject <PWhatever, XCElementP> *)flexer;
+- (void)setFlexElement2:(NSObject <PWhatever, XCElementSpacerP> *)flexer;
+
+ at 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> *'}}
+}
+

Modified: cfe/trunk/test/SemaObjC/protocol-undef.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/protocol-undef.m?rev=65773&r1=65772&r2=65773&view=diff

==============================================================================
--- cfe/trunk/test/SemaObjC/protocol-undef.m (original)
+++ cfe/trunk/test/SemaObjC/protocol-undef.m Sun Mar  1 10:12:44 2009
@@ -40,8 +40,7 @@
 - (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





More information about the cfe-commits mailing list