[cfe-commits] r76830 - in /cfe/trunk: include/clang/AST/ASTContext.h lib/AST/ASTContext.cpp lib/Sema/Sema.h lib/Sema/SemaDeclObjC.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaExprObjC.cpp lib/Sema/SemaOverload.cpp test/SemaObjC/comptypes-1.m test/SemaObjC/comptypes-7.m test/SemaObjC/conditional-expr.m

Steve Naroff snaroff at apple.com
Wed Jul 22 18:01:39 PDT 2009


Author: snaroff
Date: Wed Jul 22 20:01:38 2009
New Revision: 76830

URL: http://llvm.org/viewvc/llvm-project?rev=76830&view=rev
Log:
Remove a bunch of FIXME's related to ObjC type checking.

- Move Sema::ObjCQualifiedIdTypesAreCompatible(), Sema::QualifiedIdConformsQualifiedId(), and a couple helper functions to ASTContext.
- Change ASTContext::canAssignObjCInterfaces() to use ASTContext:: ObjCQualifiedIdTypesAreCompatible(). 
- Tweak several test cases to accommodate the new/improved type checking.


Modified:
    cfe/trunk/include/clang/AST/ASTContext.h
    cfe/trunk/lib/AST/ASTContext.cpp
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaDeclObjC.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaExprObjC.cpp
    cfe/trunk/lib/Sema/SemaOverload.cpp
    cfe/trunk/test/SemaObjC/comptypes-1.m
    cfe/trunk/test/SemaObjC/comptypes-7.m
    cfe/trunk/test/SemaObjC/conditional-expr.m

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

==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Wed Jul 22 20:01:38 2009
@@ -758,6 +758,9 @@
     assert(SelStructType && "isObjCSelType used before 'SEL' type is built");
     return T->getAsStructureType() == SelStructType;
   }
+  bool QualifiedIdConformsQualifiedId(QualType LHS, QualType RHS);
+  bool ObjCQualifiedIdTypesAreCompatible(QualType LHS, QualType RHS,
+                                         bool ForCompare);
 
   // Check the safety of assignment from LHS to RHS
   bool canAssignObjCInterfaces(const ObjCObjectPointerType *LHSOPT,

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

==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Wed Jul 22 20:01:38 2009
@@ -3023,43 +3023,219 @@
          LHS->getNumElements() == RHS->getNumElements();
 }
 
-/// canAssignObjCInterfaces - Return true if the two interface types are
-/// compatible for assignment from RHS to LHS.  This handles validation of any
-/// protocol qualifiers on the LHS or RHS.
-///
-/// FIXME: Move the following to ObjCObjectPointerType/ObjCInterfaceType.
-bool ASTContext::canAssignObjCInterfaces(const ObjCObjectPointerType *LHSOPT,
-                                         const ObjCObjectPointerType *RHSOPT) {
-  // If either type represents the built-in 'id' or 'Class' types, return true.
-  if (LHSOPT->isObjCBuiltinType() || RHSOPT->isObjCBuiltinType())
+//===----------------------------------------------------------------------===//
+// ObjCQualifiedIdTypesAreCompatible - Compatibility testing for qualified id's.
+//===----------------------------------------------------------------------===//
+
+/// ProtocolCompatibleWithProtocol - return 'true' if 'lProto' is in the
+/// inheritance hierarchy of 'rProto'.
+static bool ProtocolCompatibleWithProtocol(ObjCProtocolDecl *lProto,
+                                           ObjCProtocolDecl *rProto) {
+  if (lProto == rProto)
+    return true;
+  for (ObjCProtocolDecl::protocol_iterator PI = rProto->protocol_begin(),
+       E = rProto->protocol_end(); PI != E; ++PI)
+    if (ProtocolCompatibleWithProtocol(lProto, *PI))
+      return true;
+  return false;
+}
+
+/// ClassImplementsProtocol - Checks that 'lProto' protocol
+/// has been implemented in IDecl class, its super class or categories (if
+/// lookupCategory is true). 
+static bool ClassImplementsProtocol(ObjCProtocolDecl *lProto,
+                                    ObjCInterfaceDecl *IDecl, 
+                                    bool lookupCategory,
+                                    bool RHSIsQualifiedID = false) {
+  
+  // 1st, look up the class.
+  const ObjCList<ObjCProtocolDecl> &Protocols =
+    IDecl->getReferencedProtocols();
+
+  for (ObjCList<ObjCProtocolDecl>::iterator PI = Protocols.begin(),
+       E = Protocols.end(); PI != E; ++PI) {
+    if (ProtocolCompatibleWithProtocol(lProto, *PI))
+      return true;
+    // This is dubious and is added to be compatible with gcc.  In gcc, it is
+    // also allowed assigning a protocol-qualified 'id' type to a LHS object
+    // when protocol in qualified LHS is in list of protocols in the rhs 'id'
+    // object. This IMO, should be a bug.
+    // FIXME: Treat this as an extension, and flag this as an error when GCC
+    // extensions are not enabled.
+    if (RHSIsQualifiedID && ProtocolCompatibleWithProtocol(*PI, lProto))
+      return true;
+  }
+  
+  // 2nd, look up the category.
+  if (lookupCategory)
+    for (ObjCCategoryDecl *CDecl = IDecl->getCategoryList(); CDecl;
+         CDecl = CDecl->getNextClassCategory()) {
+      for (ObjCCategoryDecl::protocol_iterator PI = CDecl->protocol_begin(),
+           E = CDecl->protocol_end(); PI != E; ++PI)
+        if (ProtocolCompatibleWithProtocol(lProto, *PI))
+          return true;
+    }
+  
+  // 3rd, look up the super class(s)
+  if (IDecl->getSuperClass())
+    return 
+      ClassImplementsProtocol(lProto, IDecl->getSuperClass(), lookupCategory,
+                              RHSIsQualifiedID);
+  
+  return false;
+}
+
+/// QualifiedIdConformsQualifiedId - compare id<p,...> with id<p1,...>
+/// return true if lhs's protocols conform to rhs's protocol; false
+/// otherwise.
+bool ASTContext::QualifiedIdConformsQualifiedId(QualType lhs, QualType rhs) {
+  if (lhs->isObjCQualifiedIdType() && rhs->isObjCQualifiedIdType())
+    return ObjCQualifiedIdTypesAreCompatible(lhs, rhs, false);
+  return false;
+}
+
+/// ObjCQualifiedIdTypesAreCompatible - We know that one of lhs/rhs is an
+/// ObjCQualifiedIDType.
+bool ASTContext::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs,
+                                                   bool compare) {
+  // Allow id<P..> and an 'id' or void* type in all cases.
+  if (lhs->isVoidPointerType() || 
+      lhs->isObjCIdType() || lhs->isObjCClassType())
+    return true;
+  else if (rhs->isVoidPointerType() || 
+           rhs->isObjCIdType() || rhs->isObjCClassType())
     return true;
 
-  const ObjCInterfaceType* LHS = LHSOPT->getInterfaceType();
-  const ObjCInterfaceType* RHS = RHSOPT->getInterfaceType();
-  if (!LHS || !RHS) {
-    // We have qualified builtin types.
+  if (const ObjCObjectPointerType *lhsQID = lhs->getAsObjCQualifiedIdType()) {
+    const ObjCObjectPointerType *rhsOPT = rhs->getAsObjCObjectPointerType();
+    
+    if (!rhsOPT) return false;
+    
+    if (rhsOPT->qual_empty()) {
+      // If the RHS is a unqualified interface pointer "NSString*", 
+      // make sure we check the class hierarchy.
+      if (ObjCInterfaceDecl *rhsID = rhsOPT->getInterfaceDecl()) {
+        for (ObjCObjectPointerType::qual_iterator I = lhsQID->qual_begin(),
+             E = lhsQID->qual_end(); I != E; ++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(*I, rhsID, true))
+            return false;
+        }
+      }
+      // If there are no qualifiers and no interface, we have an 'id'.
+      return true;
+    }
+    // Both the right and left sides have qualifiers.    
+    for (ObjCObjectPointerType::qual_iterator I = lhsQID->qual_begin(),
+         E = lhsQID->qual_end(); I != E; ++I) {
+      ObjCProtocolDecl *lhsProto = *I;
+      bool match = false;
+
+      // 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.
+      for (ObjCObjectPointerType::qual_iterator J = rhsOPT->qual_begin(),
+           E = rhsOPT->qual_end(); J != E; ++J) {
+        ObjCProtocolDecl *rhsProto = *J;
+        if (ProtocolCompatibleWithProtocol(lhsProto, rhsProto) ||
+            (compare && ProtocolCompatibleWithProtocol(rhsProto, lhsProto))) {
+          match = true;
+          break;
+        }
+      }
+      // If the RHS is a qualified interface pointer "NSString<P>*", 
+      // make sure we check the class hierarchy.
+      if (ObjCInterfaceDecl *rhsID = rhsOPT->getInterfaceDecl()) {
+        for (ObjCObjectPointerType::qual_iterator I = lhsQID->qual_begin(),
+             E = lhsQID->qual_end(); I != E; ++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(*I, rhsID, true)) {
+            match = true;
+            break;
+          }
+        }
+      }
+      if (!match)
+        return false;
+    }
+    
+    return true;
+  }
+  
+  const ObjCObjectPointerType *rhsQID = rhs->getAsObjCQualifiedIdType();
+  assert(rhsQID && "One of the LHS/RHS should be id<x>");
+
+  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 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(*I, lhsID, 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) {
-      bool RHSImplementsProtocol = false;
+    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,
       // see if static class implements all of id's protocols, directly or
       // through its super class and categories.
-      for (ObjCObjectPointerType::qual_iterator J = RHSOPT->qual_begin(),
-           E = RHSOPT->qual_end(); J != E; ++J) {
-        if ((*J)->lookupProtocolNamed((*I)->getIdentifier())) {
-          RHSImplementsProtocol = true;
+      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 (!RHSImplementsProtocol)
+      if (!match)
         return false;
     }
-    // The RHS implements all protocols listed on the LHS.
     return true;
   }
-  return canAssignObjCInterfaces(LHS, RHS);
+  return false;
+}
+
+/// canAssignObjCInterfaces - Return true if the two interface types are
+/// compatible for assignment from RHS to LHS.  This handles validation of any
+/// protocol qualifiers on the LHS or RHS.
+///
+bool ASTContext::canAssignObjCInterfaces(const ObjCObjectPointerType *LHSOPT,
+                                         const ObjCObjectPointerType *RHSOPT) {
+  // If either type represents the built-in 'id' or 'Class' types, return true.
+  if (LHSOPT->isObjCBuiltinType() || RHSOPT->isObjCBuiltinType())
+    return true;
+
+  if (LHSOPT->isObjCQualifiedIdType() || RHSOPT->isObjCQualifiedIdType())
+    return ObjCQualifiedIdTypesAreCompatible(QualType(LHSOPT,0), 
+                                             QualType(RHSOPT,0), 
+                                             false);
+
+  const ObjCInterfaceType* LHS = LHSOPT->getInterfaceType();
+  const ObjCInterfaceType* RHS = RHSOPT->getInterfaceType();
+  if (LHS && RHS) // We have 2 user-defined types.
+    return canAssignObjCInterfaces(LHS, RHS);
+    
+  return false;
 }
 
 bool ASTContext::canAssignObjCInterfaces(const ObjCInterfaceType *LHS,
@@ -3087,7 +3263,7 @@
     // If the RHS doesn't implement the protocol on the left, the types
     // are incompatible.
     for (ObjCInterfaceType::qual_iterator RHSPI = RHS->qual_begin(),
-                                                  RHSPE = RHS->qual_end();
+                                          RHSPE = RHS->qual_end();
          RHSPI != RHSPE; RHSPI++) {
       if ((*RHSPI)->lookupProtocolNamed((*LHSPI)->getIdentifier())) {
         RHSImplementsProtocol = true;
@@ -3441,10 +3617,6 @@
     return QualType();
   }
   case Type::ObjCObjectPointer: {
-    // FIXME: Incorporate tests from Sema::ObjCQualifiedIdTypesAreCompatible().
-    if (LHS->isObjCQualifiedIdType() && RHS->isObjCQualifiedIdType())
-      return QualType();
-
     if (canAssignObjCInterfaces(LHS->getAsObjCObjectPointerType(), 
                                 RHS->getAsObjCObjectPointerType()))
       return LHS;

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=76830&r1=76829&r2=76830&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Wed Jul 22 20:01:38 2009
@@ -1201,7 +1201,6 @@
                            bool &IncompleteImpl);
   void WarnConflictingTypedMethods(ObjCMethodDecl *ImpMethod,
                                    ObjCMethodDecl *IntfMethod);
-  bool QualifiedIdConformsQualifiedId(QualType LHS, QualType RHS);
 
   NamespaceDecl *GetStdNamespace();
   
@@ -3197,9 +3196,6 @@
                                           unsigned NewWidth, bool NewSign,
                                           SourceLocation Loc, unsigned DiagID);
   
-  bool ObjCQualifiedIdTypesAreCompatible(QualType LHS, QualType RHS,
-                                         bool ForCompare);
-
   /// Checks that the Objective-C declaration is declared in the global scope.
   /// Emits an error and marks the declaration as invalid if it's not declared
   /// in the global scope.

Modified: cfe/trunk/lib/Sema/SemaDeclObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclObjC.cpp?rev=76830&r1=76829&r2=76830&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclObjC.cpp Wed Jul 22 20:01:38 2009
@@ -369,7 +369,7 @@
   if (!Context.typesAreCompatible(LHSType, RHSType)) {
     // FIXME: Incorporate this test with typesAreCompatible.
     if (LHSType->isObjCQualifiedIdType() && RHSType->isObjCQualifiedIdType())
-      if (ObjCQualifiedIdTypesAreCompatible(LHSType, RHSType, false))
+      if (Context.ObjCQualifiedIdTypesAreCompatible(LHSType, RHSType, false))
         return;
     Diag(Property->getLocation(), diag::warn_property_types_are_incompatible)
       << Property->getType() << SuperProperty->getType() << inheritedName;
@@ -804,8 +804,8 @@
                                        ObjCMethodDecl *IntfMethodDecl) {
   if (!Context.typesAreCompatible(IntfMethodDecl->getResultType(),
                                   ImpMethodDecl->getResultType()) &&
-      !QualifiedIdConformsQualifiedId(IntfMethodDecl->getResultType(),
-                                      ImpMethodDecl->getResultType())) {
+      !Context.QualifiedIdConformsQualifiedId(IntfMethodDecl->getResultType(),
+                                              ImpMethodDecl->getResultType())) {
     Diag(ImpMethodDecl->getLocation(), diag::warn_conflicting_ret_types) 
       << ImpMethodDecl->getDeclName() << IntfMethodDecl->getResultType()
       << ImpMethodDecl->getResultType();
@@ -816,7 +816,8 @@
        IF = IntfMethodDecl->param_begin(), EM = ImpMethodDecl->param_end();
        IM != EM; ++IM, ++IF) {
     if (Context.typesAreCompatible((*IF)->getType(), (*IM)->getType()) ||
-        QualifiedIdConformsQualifiedId((*IF)->getType(), (*IM)->getType()))
+        Context.QualifiedIdConformsQualifiedId((*IF)->getType(), 
+                                               (*IM)->getType()))
       continue;
     
     Diag((*IM)->getLocation(), diag::warn_conflicting_param_types) 

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=76830&r1=76829&r2=76830&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Wed Jul 22 20:01:38 2009
@@ -3171,7 +3171,7 @@
       compositeType = RHSTy;
     } else if ((LHSTy->isObjCQualifiedIdType() || 
                 RHSTy->isObjCQualifiedIdType()) &&
-                ObjCQualifiedIdTypesAreCompatible(LHSTy, RHSTy, true)) {
+                Context.ObjCQualifiedIdTypesAreCompatible(LHSTy, RHSTy, true)) {
       // Need to handle "id<xx>" explicitly. 
       // GCC allows qualified id and any Objective-C type to devolve to
       // id. Currently localizing to here until clear this should be
@@ -3436,17 +3436,6 @@
       return Compatible;
     return Incompatible;
   }
-  // FIXME: Look into removing. With ObjCObjectPointerType, I don't see a need.
-  if (lhsType->isObjCQualifiedIdType() || rhsType->isObjCQualifiedIdType()) {
-    if (ObjCQualifiedIdTypesAreCompatible(lhsType, rhsType, false))
-      return Compatible;
-    // Relax integer conversions like we do for pointers below.
-    if (rhsType->isIntegerType())
-      return IntToPointer;
-    if (lhsType->isIntegerType())
-      return PointerToInt;
-    return IncompatibleObjCQualifiedId;
-  }
   // Allow scalar to ExtVector assignments, and assignments of an ExtVector type
   // to the same ExtVector type.
   if (lhsType->isExtVectorType()) {
@@ -3528,6 +3517,8 @@
         return Compatible;
       if (Context.typesAreCompatible(lhsType, rhsType))
         return Compatible;
+      if (lhsType->isObjCQualifiedIdType() || rhsType->isObjCQualifiedIdType())
+        return IncompatibleObjCQualifiedId;
       return IncompatiblePointer;
     }
     if (const PointerType *RHSPT = rhsType->getAsPointerType()) {

Modified: cfe/trunk/lib/Sema/SemaExprObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprObjC.cpp?rev=76830&r1=76829&r2=76830&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaExprObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprObjC.cpp Wed Jul 22 20:01:38 2009
@@ -651,196 +651,3 @@
                                        rbrac, ArgExprs, NumArgs);
 }
 
-//===----------------------------------------------------------------------===//
-// ObjCQualifiedIdTypesAreCompatible - Compatibility testing for qualified id's.
-//===----------------------------------------------------------------------===//
-
-/// ProtocolCompatibleWithProtocol - return 'true' if 'lProto' is in the
-/// inheritance hierarchy of 'rProto'.
-static bool ProtocolCompatibleWithProtocol(ObjCProtocolDecl *lProto,
-                                           ObjCProtocolDecl *rProto) {
-  if (lProto == rProto)
-    return true;
-  for (ObjCProtocolDecl::protocol_iterator PI = rProto->protocol_begin(),
-       E = rProto->protocol_end(); PI != E; ++PI)
-    if (ProtocolCompatibleWithProtocol(lProto, *PI))
-      return true;
-  return false;
-}
-
-/// ClassImplementsProtocol - Checks that 'lProto' protocol
-/// has been implemented in IDecl class, its super class or categories (if
-/// lookupCategory is true). 
-static bool ClassImplementsProtocol(ObjCProtocolDecl *lProto,
-                                    ObjCInterfaceDecl *IDecl, 
-                                    bool lookupCategory,
-                                    bool RHSIsQualifiedID = false) {
-  
-  // 1st, look up the class.
-  const ObjCList<ObjCProtocolDecl> &Protocols =
-    IDecl->getReferencedProtocols();
-
-  for (ObjCList<ObjCProtocolDecl>::iterator PI = Protocols.begin(),
-       E = Protocols.end(); PI != E; ++PI) {
-    if (ProtocolCompatibleWithProtocol(lProto, *PI))
-      return true;
-    // This is dubious and is added to be compatible with gcc.  In gcc, it is
-    // also allowed assigning a protocol-qualified 'id' type to a LHS object
-    // when protocol in qualified LHS is in list of protocols in the rhs 'id'
-    // object. This IMO, should be a bug.
-    // FIXME: Treat this as an extension, and flag this as an error when GCC
-    // extensions are not enabled.
-    if (RHSIsQualifiedID && ProtocolCompatibleWithProtocol(*PI, lProto))
-      return true;
-  }
-  
-  // 2nd, look up the category.
-  if (lookupCategory)
-    for (ObjCCategoryDecl *CDecl = IDecl->getCategoryList(); CDecl;
-         CDecl = CDecl->getNextClassCategory()) {
-      for (ObjCCategoryDecl::protocol_iterator PI = CDecl->protocol_begin(),
-           E = CDecl->protocol_end(); PI != E; ++PI)
-        if (ProtocolCompatibleWithProtocol(lProto, *PI))
-          return true;
-    }
-  
-  // 3rd, look up the super class(s)
-  if (IDecl->getSuperClass())
-    return 
-      ClassImplementsProtocol(lProto, IDecl->getSuperClass(), lookupCategory,
-                              RHSIsQualifiedID);
-  
-  return false;
-}
-
-/// QualifiedIdConformsQualifiedId - compare id<p,...> with id<p1,...>
-/// return true if lhs's protocols conform to rhs's protocol; false
-/// otherwise.
-bool Sema::QualifiedIdConformsQualifiedId(QualType lhs, QualType rhs) {
-  if (lhs->isObjCQualifiedIdType() && rhs->isObjCQualifiedIdType())
-    return ObjCQualifiedIdTypesAreCompatible(lhs, rhs, false);
-  return false;
-}
-
-/// ObjCQualifiedIdTypesAreCompatible - We know that one of lhs/rhs is an
-/// ObjCQualifiedIDType.
-/// FIXME: Move to ASTContext::typesAreCompatible() and friends.
-bool Sema::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs,
-                                             bool compare) {
-  // Allow id<P..> and an 'id' or void* type in all cases.
-  if (lhs->isVoidPointerType() || 
-      lhs->isObjCIdType() || lhs->isObjCClassType())
-    return true;
-  else if (rhs->isVoidPointerType() || 
-           rhs->isObjCIdType() || rhs->isObjCClassType())
-    return true;
-
-  if (const ObjCObjectPointerType *lhsQID = lhs->getAsObjCQualifiedIdType()) {
-    const ObjCObjectPointerType *rhsOPT = rhs->getAsObjCObjectPointerType();
-    
-    if (!rhsOPT) return false;
-    
-    if (rhsOPT->qual_empty()) {
-      // If the RHS is a unqualified interface pointer "NSString*", 
-      // make sure we check the class hierarchy.
-      if (ObjCInterfaceDecl *rhsID = rhsOPT->getInterfaceDecl()) {
-        for (ObjCObjectPointerType::qual_iterator I = lhsQID->qual_begin(),
-             E = lhsQID->qual_end(); I != E; ++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(*I, rhsID, true))
-            return false;
-        }
-      }
-      // If there are no qualifiers and no interface, we have an 'id'.
-      return true;
-    }
-    // Both the right and left sides have qualifiers.    
-    for (ObjCObjectPointerType::qual_iterator I = lhsQID->qual_begin(),
-         E = lhsQID->qual_end(); I != E; ++I) {
-      ObjCProtocolDecl *lhsProto = *I;
-      bool match = false;
-
-      // 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.
-      for (ObjCObjectPointerType::qual_iterator J = rhsOPT->qual_begin(),
-           E = rhsOPT->qual_end(); J != E; ++J) {
-        ObjCProtocolDecl *rhsProto = *J;
-        if (ProtocolCompatibleWithProtocol(lhsProto, rhsProto) ||
-            (compare && ProtocolCompatibleWithProtocol(rhsProto, lhsProto))) {
-          match = true;
-          break;
-        }
-      }
-      // If the RHS is a qualified interface pointer "NSString<P>*", 
-      // make sure we check the class hierarchy.
-      if (ObjCInterfaceDecl *rhsID = rhsOPT->getInterfaceDecl()) {
-        for (ObjCObjectPointerType::qual_iterator I = lhsQID->qual_begin(),
-             E = lhsQID->qual_end(); I != E; ++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(*I, rhsID, true)) {
-            match = true;
-            break;
-          }
-        }
-      }
-      if (!match)
-        return false;
-    }
-    
-    return true;
-  }
-  
-  const ObjCObjectPointerType *rhsQID = rhs->getAsObjCQualifiedIdType();
-  assert(rhsQID && "One of the LHS/RHS should be id<x>");
-
-  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 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(*I, lhsID, 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 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.
-      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;
-}
-

Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=76830&r1=76829&r2=76830&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Wed Jul 22 20:01:38 2009
@@ -1020,7 +1020,8 @@
     // Conversions with Objective-C's id<...>.
     if ((FromObjCPtr->isObjCQualifiedIdType() || 
          ToObjCPtr->isObjCQualifiedIdType()) &&
-        ObjCQualifiedIdTypesAreCompatible(ToType, FromType, /*compare=*/false)) {
+        Context.ObjCQualifiedIdTypesAreCompatible(ToType, FromType, 
+                                                  /*compare=*/false)) {
       ConvertedType = ToType;
       return true;
     }

Modified: cfe/trunk/test/SemaObjC/comptypes-1.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/comptypes-1.m?rev=76830&r1=76829&r2=76830&view=diff

==============================================================================
--- cfe/trunk/test/SemaObjC/comptypes-1.m (original)
+++ cfe/trunk/test/SemaObjC/comptypes-1.m Wed Jul 22 20:01:38 2009
@@ -66,9 +66,7 @@
 
   /* Any comparison between 'MyClass *' and anything which is not an 'id'
      must generate a warning.  */
-  /* FIXME: GCC considers this a warning ("comparison of distinct pointer types"). */
-  /* There is a corresponding FIXME in ASTContext::mergeTypes() */
-  if (obj_p == obj_c) foo() ;
+  if (obj_p == obj_c) foo() ; // expected-warning {{comparison of distinct pointer types ('id<MyProtocol>' and 'MyClass *')}}
 
   if (obj_c == obj_cp) foo() ; // expected-warning {{comparison of distinct pointer types ('MyClass *' and 'MyOtherClass *')}} 
   if (obj_cp == obj_c) foo() ; // expected-warning {{comparison of distinct pointer types ('MyOtherClass *' and 'MyClass *')}}

Modified: cfe/trunk/test/SemaObjC/comptypes-7.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/comptypes-7.m?rev=76830&r1=76829&r2=76830&view=diff

==============================================================================
--- cfe/trunk/test/SemaObjC/comptypes-7.m (original)
+++ cfe/trunk/test/SemaObjC/comptypes-7.m Wed Jul 22 20:01:38 2009
@@ -28,7 +28,7 @@
   obj = j; // expected-warning {{incompatible pointer types assigning 'int *', expected 'id'}}
 
   obj_p = i; // expected-warning {{incompatible integer to pointer conversion assigning 'int', expected 'id<MyProtocol>'}}
-  obj_p = j; // expected-warning {{incompatible type assigning 'int *', expected 'id<MyProtocol>'}}
+  obj_p = j; // expected-warning {{incompatible pointer types assigning 'int *', expected 'id<MyProtocol>'}}
   
   obj_c = i; // expected-warning {{incompatible integer to pointer conversion assigning 'int', expected 'MyClass *'}}
   obj_c = j; // expected-warning {{incompatible pointer types assigning 'int *', expected 'MyClass *'}}
@@ -42,7 +42,7 @@
   i = obj_C; // expected-warning {{incompatible pointer to integer conversion assigning 'Class', expected 'int'}}
   
   j = obj;   // expected-warning {{incompatible pointer types assigning 'id', expected 'int *'}}
-  j = obj_p; // expected-warning {{incompatible type assigning 'id<MyProtocol>', expected 'int *'}}
+  j = obj_p; // expected-warning {{incompatible pointer types assigning 'id<MyProtocol>', expected 'int *'}}
   j = obj_c; // expected-warning {{incompatible pointer types assigning 'MyClass *', expected 'int *'}}
   j = obj_C; // expected-warning {{incompatible pointer types assigning 'Class', expected 'int *'}}
   

Modified: cfe/trunk/test/SemaObjC/conditional-expr.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/conditional-expr.m?rev=76830&r1=76829&r2=76830&view=diff

==============================================================================
--- cfe/trunk/test/SemaObjC/conditional-expr.m (original)
+++ cfe/trunk/test/SemaObjC/conditional-expr.m Wed Jul 22 20:01:38 2009
@@ -27,9 +27,8 @@
 @implementation DTFilterOutputStream2 // expected-warning {{incomplete implementation}} expected-warning {{method definition for 'nextOutputStream' not found}}
 - (id)initWithNextOutputStream:(id <DTOutputStreams>) outputStream {
   id <DTOutputStreams> nextOutputStream = [self nextOutputStream];
-  // GCC warns about both of these.
   self = nextOutputStream; // expected-warning {{incompatible type assigning 'id<DTOutputStreams>', expected 'DTFilterOutputStream2 *'}}
-  return nextOutputStream ? nextOutputStream : self;
+  return nextOutputStream ? nextOutputStream : self; // expected-warning {{incompatible operand types ('id<DTOutputStreams>' and 'DTFilterOutputStream2 *')}}
 }
 @end
 
@@ -37,9 +36,8 @@
 @implementation DTFilterOutputStream3 // expected-warning {{cannot find interface declaration for 'DTFilterOutputStream3'}}
 - (id)initWithNextOutputStream:(id <DTOutputStreams>) outputStream {
   id <DTOutputStreams> nextOutputStream = [self nextOutputStream]; // expected-warning {{method '-nextOutputStream' not found (return type defaults to 'id')}}
-  // GCC warns about both of these as well (no errors).
   self = nextOutputStream; // expected-warning {{incompatible type assigning 'id<DTOutputStreams>', expected 'DTFilterOutputStream3 *'}}
-  return nextOutputStream ? nextOutputStream : self;
+  return nextOutputStream ? nextOutputStream : self; // expected-warning {{incompatible operand types ('id<DTOutputStreams>' and 'DTFilterOutputStream3 *')}}
 }
 @end
 
@@ -86,7 +84,7 @@
 }
 
 void f5(int cond, id<P0> x, C *y) {
-  (cond ? x : y).intProp = 1; // expected-error {{property 'intProp' not found on object of type 'C *'}}
+  (cond ? x : y).intProp = 1; // expected-warning {{incompatible operand types ('id<P0>' and 'C *')}} expected-error {{property 'intProp' not found on object of type 'id'}}
 }
 
 void f6(int cond, C *x, D *y) {





More information about the cfe-commits mailing list