[cfe-commits] r74604 - in /cfe/trunk: include/clang/AST/Type.h lib/AST/Type.cpp lib/Sema/SemaExpr.cpp

Steve Naroff snaroff at apple.com
Wed Jul 1 07:36:54 PDT 2009


Author: snaroff
Date: Wed Jul  1 09:36:47 2009
New Revision: 74604

URL: http://llvm.org/viewvc/llvm-project?rev=74604&view=rev
Log:
Rework Sema::CheckConditionalOperands(). No functionality change.

This was necessary to simplify some other changes I'm making (wrt ObjC type cleanups).

The idea is to separate the constraint checks for block pointers, ObjC pointers, and C pointers (the previous code combined them into one clause).

Note: This routine will be further simplified when I integrate the ObjC type cleanups (forthcoming).


Modified:
    cfe/trunk/include/clang/AST/Type.h
    cfe/trunk/lib/AST/Type.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp

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

==============================================================================
--- cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/trunk/include/clang/AST/Type.h Wed Jul  1 09:36:47 2009
@@ -376,6 +376,7 @@
   bool isFunctionProtoType() const { return getAsFunctionProtoType() != 0; }
   bool isPointerType() const;
   bool isBlockPointerType() const;
+  bool isVoidPointerType() const;
   bool isReferenceType() const;
   bool isLValueReferenceType() const;
   bool isRValueReferenceType() const;

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

==============================================================================
--- cfe/trunk/lib/AST/Type.cpp (original)
+++ cfe/trunk/lib/AST/Type.cpp Wed Jul  1 09:36:47 2009
@@ -185,6 +185,12 @@
     return RT->getDecl()->isStruct();
   return false;
 }
+bool Type::isVoidPointerType() const {
+  if (const PointerType *PT = getAsPointerType())
+    return PT->getPointeeType()->isVoidType();
+  return false;
+}
+
 bool Type::isUnionType() const {
   if (const RecordType *RT = getAsRecordType())
     return RT->getDecl()->isUnion();

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Wed Jul  1 09:36:47 2009
@@ -3079,24 +3079,133 @@
     ImpCastExprToType(LHS, RHSTy); // promote the null to a pointer.
     return RHSTy;
   }
+  // Handle block pointer types.
+  if (LHSTy->isBlockPointerType() || RHSTy->isBlockPointerType()) {
+    if (!LHSTy->isBlockPointerType() || !RHSTy->isBlockPointerType()) {
+      if (LHSTy->isVoidPointerType() || RHSTy->isVoidPointerType()) {
+        QualType destType = Context.getPointerType(Context.VoidTy);
+        ImpCastExprToType(LHS, destType); 
+        ImpCastExprToType(RHS, destType);
+        return destType;
+      }
+      Diag(QuestionLoc, diag::err_typecheck_cond_incompatible_operands)
+            << LHSTy << RHSTy << LHS->getSourceRange() << RHS->getSourceRange();
+      return QualType();
+    }
+    // We have 2 block pointer types.
+    if (Context.getCanonicalType(LHSTy) == Context.getCanonicalType(RHSTy)) {
+      // Two identical block pointer types are always compatible.
+      return LHSTy;
+    }
+    // The block pointer types aren't identical, continue checking.
+    QualType lhptee = LHSTy->getAsBlockPointerType()->getPointeeType();
+    QualType rhptee = RHSTy->getAsBlockPointerType()->getPointeeType();
 
-  const PointerType *LHSPT = LHSTy->getAsPointerType();
-  const PointerType *RHSPT = RHSTy->getAsPointerType();
-  const BlockPointerType *LHSBPT = LHSTy->getAsBlockPointerType();
-  const BlockPointerType *RHSBPT = RHSTy->getAsBlockPointerType();
-
-  // Handle the case where both operands are pointers before we handle null
-  // pointer constants in case both operands are null pointer constants.
-  if ((LHSPT || LHSBPT) && (RHSPT || RHSBPT)) { // C99 6.5.15p3,6
+    if (!Context.typesAreCompatible(lhptee.getUnqualifiedType(),
+                                    rhptee.getUnqualifiedType())) {
+      Diag(QuestionLoc, diag::warn_typecheck_cond_incompatible_pointers)
+        << LHSTy << RHSTy << LHS->getSourceRange() << RHS->getSourceRange();
+      // In this situation, we assume void* type. No especially good
+      // reason, but this is what gcc does, and we do have to pick
+      // to get a consistent AST.
+      QualType incompatTy = Context.getPointerType(Context.VoidTy);
+      ImpCastExprToType(LHS, incompatTy);
+      ImpCastExprToType(RHS, incompatTy);
+      return incompatTy;
+    }
+    // The block pointer types are compatible.
+    ImpCastExprToType(LHS, LHSTy);
+    ImpCastExprToType(RHS, LHSTy);
+    return LHSTy;
+  }
+  // Need to handle "id<xx>" explicitly. Unlike "id", whose canonical type
+  // evaluates to "struct objc_object *" (and is handled above when comparing
+  // id with statically typed objects).
+  if (LHSTy->isObjCQualifiedIdType() || RHSTy->isObjCQualifiedIdType()) {
+    // GCC allows qualified id and any Objective-C type to devolve to
+    // id. Currently localizing to here until clear this should be
+    // part of ObjCQualifiedIdTypesAreCompatible.
+    if (ObjCQualifiedIdTypesAreCompatible(LHSTy, RHSTy, true) ||
+        (LHSTy->isObjCQualifiedIdType() &&
+         Context.isObjCObjectPointerType(RHSTy)) ||
+        (RHSTy->isObjCQualifiedIdType() &&
+         Context.isObjCObjectPointerType(LHSTy))) {
+      // FIXME: This is not the correct composite type. This only happens to
+      // work because id can more or less be used anywhere, however this may
+      // change the type of method sends.
+
+      // FIXME: gcc adds some type-checking of the arguments and emits
+      // (confusing) incompatible comparison warnings in some
+      // cases. Investigate.
+      QualType compositeType = Context.getObjCIdType();
+      ImpCastExprToType(LHS, compositeType);
+      ImpCastExprToType(RHS, compositeType);
+      return compositeType;
+    }
+  }
+  // Check constraints for Objective-C object pointers types.
+  if (Context.isObjCObjectPointerType(LHSTy) &&
+      Context.isObjCObjectPointerType(RHSTy)) {
+    
+    if (Context.getCanonicalType(LHSTy) == Context.getCanonicalType(RHSTy)) {
+      // Two identical object pointer types are always compatible.
+      return LHSTy;
+    }
+    // No need to check for block pointer types or qualified id types (they
+    // were handled above).
+    assert((LHSTy->isPointerType() && RHSTy->isPointerType()) &&
+           "Sema::CheckConditionalOperands(): Unexpected type");
+    QualType lhptee = LHSTy->getAsPointerType()->getPointeeType();
+    QualType rhptee = RHSTy->getAsPointerType()->getPointeeType();
+    
+    QualType compositeType = LHSTy;
+    
+    // If both operands are interfaces and either operand can be
+    // assigned to the other, use that type as the composite
+    // type. This allows
+    //   xxx ? (A*) a : (B*) b
+    // where B is a subclass of A.
+    //
+    // Additionally, as for assignment, if either type is 'id'
+    // allow silent coercion. Finally, if the types are
+    // incompatible then make sure to use 'id' as the composite
+    // type so the result is acceptable for sending messages to.
+
+    // FIXME: Consider unifying with 'areComparableObjCPointerTypes'.
+    // It could return the composite type.
+    const ObjCInterfaceType* LHSIface = lhptee->getAsObjCInterfaceType();
+    const ObjCInterfaceType* RHSIface = rhptee->getAsObjCInterfaceType();
+    if (LHSIface && RHSIface &&
+        Context.canAssignObjCInterfaces(LHSIface, RHSIface)) {
+      compositeType = LHSTy;
+    } else if (LHSIface && RHSIface &&
+               Context.canAssignObjCInterfaces(RHSIface, LHSIface)) {
+      compositeType = RHSTy;
+    } else if (Context.isObjCIdStructType(lhptee) ||
+               Context.isObjCIdStructType(rhptee)) {
+      compositeType = Context.getObjCIdType();
+    } else {
+      Diag(QuestionLoc, diag::ext_typecheck_cond_incompatible_operands)
+        << LHSTy << RHSTy
+        << LHS->getSourceRange() << RHS->getSourceRange();
+      QualType incompatTy = Context.getObjCIdType();
+      ImpCastExprToType(LHS, incompatTy);
+      ImpCastExprToType(RHS, incompatTy);
+      return incompatTy;
+    }
+    // The object pointer types are compatible.
+    ImpCastExprToType(LHS, compositeType);
+    ImpCastExprToType(RHS, compositeType);
+    return compositeType;
+  }
+  // Check constraints for C object pointers types (C99 6.5.15p3,6).
+  if (LHSTy->isPointerType() && RHSTy->isPointerType()) {
     // get the "pointed to" types
-    QualType lhptee = (LHSPT ? LHSPT->getPointeeType()
-                       : LHSBPT->getPointeeType());
-      QualType rhptee = (RHSPT ? RHSPT->getPointeeType()
-                         : RHSBPT->getPointeeType());
+    QualType lhptee = LHSTy->getAsPointerType()->getPointeeType();
+    QualType rhptee = RHSTy->getAsPointerType()->getPointeeType();
 
     // ignore qualifiers on void (C99 6.5.15p3, clause 6)
-    if (lhptee->isVoidType()
-        && (RHSBPT || rhptee->isIncompleteOrObjectType())) {
+    if (lhptee->isVoidType() && rhptee->isIncompleteOrObjectType()) {
       // Figure out necessary qualifiers (C99 6.5.15p6)
       QualType destPointee=lhptee.getQualifiedType(rhptee.getCVRQualifiers());
       QualType destType = Context.getPointerType(destPointee);
@@ -3104,8 +3213,7 @@
       ImpCastExprToType(RHS, destType); // promote to void*
       return destType;
     }
-    if (rhptee->isVoidType()
-        && (LHSBPT || lhptee->isIncompleteOrObjectType())) {
+    if (rhptee->isVoidType() && lhptee->isIncompleteOrObjectType()) {
       QualType destPointee=rhptee.getQualifiedType(lhptee.getCVRQualifiers());
       QualType destType = Context.getPointerType(destPointee);
       ImpCastExprToType(LHS, destType); // add qualifiers if necessary
@@ -3113,62 +3221,12 @@
       return destType;
     }
 
-    bool sameKind = (LHSPT && RHSPT) || (LHSBPT && RHSBPT);
-    if (sameKind
-        && Context.getCanonicalType(LHSTy) == Context.getCanonicalType(RHSTy)) {
+    if (Context.getCanonicalType(LHSTy) == Context.getCanonicalType(RHSTy)) {
       // Two identical pointer types are always compatible.
       return LHSTy;
     }
-
-    QualType compositeType = LHSTy;
-
-    // If either type is an Objective-C object type then check
-    // compatibility according to Objective-C.
-    if (Context.isObjCObjectPointerType(LHSTy) ||
-        Context.isObjCObjectPointerType(RHSTy)) {
-      // If both operands are interfaces and either operand can be
-      // assigned to the other, use that type as the composite
-      // type. This allows
-      //   xxx ? (A*) a : (B*) b
-      // where B is a subclass of A.
-      //
-      // Additionally, as for assignment, if either type is 'id'
-      // allow silent coercion. Finally, if the types are
-      // incompatible then make sure to use 'id' as the composite
-      // type so the result is acceptable for sending messages to.
-
-      // FIXME: Consider unifying with 'areComparableObjCPointerTypes'.
-      // It could return the composite type.
-      const ObjCInterfaceType* LHSIface = lhptee->getAsObjCInterfaceType();
-      const ObjCInterfaceType* RHSIface = rhptee->getAsObjCInterfaceType();
-      if (LHSIface && RHSIface &&
-          Context.canAssignObjCInterfaces(LHSIface, RHSIface)) {
-        compositeType = LHSTy;
-      } else if (LHSIface && RHSIface &&
-                 Context.canAssignObjCInterfaces(RHSIface, LHSIface)) {
-        compositeType = RHSTy;
-      } else if (Context.isObjCIdStructType(lhptee) ||
-                 Context.isObjCIdStructType(rhptee)) {
-        compositeType = Context.getObjCIdType();
-      } else if (LHSBPT || RHSBPT) {
-        if (!sameKind
-            || !Context.typesAreCompatible(lhptee.getUnqualifiedType(),
-                                           rhptee.getUnqualifiedType()))
-          Diag(QuestionLoc, diag::err_typecheck_cond_incompatible_operands)
-            << LHSTy << RHSTy << LHS->getSourceRange() << RHS->getSourceRange();
-        return QualType();
-      } else {
-        Diag(QuestionLoc, diag::ext_typecheck_cond_incompatible_operands)
-          << LHSTy << RHSTy
-          << LHS->getSourceRange() << RHS->getSourceRange();
-        QualType incompatTy = Context.getObjCIdType();
-        ImpCastExprToType(LHS, incompatTy);
-        ImpCastExprToType(RHS, incompatTy);
-        return incompatTy;
-      }
-    } else if (!sameKind
-               || !Context.typesAreCompatible(lhptee.getUnqualifiedType(),
-                                              rhptee.getUnqualifiedType())) {
+    if (!Context.typesAreCompatible(lhptee.getUnqualifiedType(),
+                                    rhptee.getUnqualifiedType())) {
       Diag(QuestionLoc, diag::warn_typecheck_cond_incompatible_pointers)
         << LHSTy << RHSTy << LHS->getSourceRange() << RHS->getSourceRange();
       // In this situation, we assume void* type. No especially good
@@ -3186,11 +3244,11 @@
     // type.
     // FIXME: Need to calculate the composite type.
     // FIXME: Need to add qualifiers
-    ImpCastExprToType(LHS, compositeType);
-    ImpCastExprToType(RHS, compositeType);
-    return compositeType;
+    ImpCastExprToType(LHS, LHSTy);
+    ImpCastExprToType(RHS, LHSTy);
+    return LHSTy;
   }
-
+  
   // GCC compatibility: soften pointer/integer mismatch.
   if (RHSTy->isPointerType() && LHSTy->isIntegerType()) {
     Diag(QuestionLoc, diag::warn_typecheck_cond_pointer_integer_mismatch)
@@ -3205,32 +3263,6 @@
     return LHSTy;
   }
 
-  // Need to handle "id<xx>" explicitly. Unlike "id", whose canonical type
-  // evaluates to "struct objc_object *" (and is handled above when comparing
-  // id with statically typed objects).
-  if (LHSTy->isObjCQualifiedIdType() || RHSTy->isObjCQualifiedIdType()) {
-    // GCC allows qualified id and any Objective-C type to devolve to
-    // id. Currently localizing to here until clear this should be
-    // part of ObjCQualifiedIdTypesAreCompatible.
-    if (ObjCQualifiedIdTypesAreCompatible(LHSTy, RHSTy, true) ||
-        (LHSTy->isObjCQualifiedIdType() &&
-         Context.isObjCObjectPointerType(RHSTy)) ||
-        (RHSTy->isObjCQualifiedIdType() &&
-         Context.isObjCObjectPointerType(LHSTy))) {
-      // FIXME: This is not the correct composite type. This only happens to
-      // work because id can more or less be used anywhere, however this may
-      // change the type of method sends.
-
-      // FIXME: gcc adds some type-checking of the arguments and emits
-      // (confusing) incompatible comparison warnings in some
-      // cases. Investigate.
-      QualType compositeType = Context.getObjCIdType();
-      ImpCastExprToType(LHS, compositeType);
-      ImpCastExprToType(RHS, compositeType);
-      return compositeType;
-    }
-  }
-
   // Otherwise, the operands are not compatible.
   Diag(QuestionLoc, diag::err_typecheck_cond_incompatible_operands)
     << LHSTy << RHSTy << LHS->getSourceRange() << RHS->getSourceRange();





More information about the cfe-commits mailing list