[cfe-commits] r119036 - in /cfe/trunk: include/clang/AST/Expr.h include/clang/AST/OperationKinds.h lib/AST/Expr.cpp lib/AST/ExprConstant.cpp lib/Checker/GRExprEngine.cpp lib/CodeGen/CGExpr.cpp lib/CodeGen/CGExprComplex.cpp lib/CodeGen/CGExprScalar.cpp lib/Sema/SemaExpr.cpp

John McCall rjmccall at apple.com
Sun Nov 14 00:17:51 PST 2010


Author: rjmccall
Date: Sun Nov 14 02:17:51 2010
New Revision: 119036

URL: http://llvm.org/viewvc/llvm-project?rev=119036&view=rev
Log:
Add a few more complex-related cast kinds that arise due to arbitrary
implicit conversions;  the last batch was specific to promotions.
I think this is the full set we need.  I do think dividing the cast
kinds into floating and integral is probably a good idea.

Annotate a *lot* more C casts with useful cast kinds.


Modified:
    cfe/trunk/include/clang/AST/Expr.h
    cfe/trunk/include/clang/AST/OperationKinds.h
    cfe/trunk/lib/AST/Expr.cpp
    cfe/trunk/lib/AST/ExprConstant.cpp
    cfe/trunk/lib/Checker/GRExprEngine.cpp
    cfe/trunk/lib/CodeGen/CGExpr.cpp
    cfe/trunk/lib/CodeGen/CGExprComplex.cpp
    cfe/trunk/lib/CodeGen/CGExprScalar.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp

Modified: cfe/trunk/include/clang/AST/Expr.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Expr.h?rev=119036&r1=119035&r2=119036&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Expr.h (original)
+++ cfe/trunk/include/clang/AST/Expr.h Sun Nov 14 02:17:51 2010
@@ -1998,10 +1998,15 @@
     case CK_AnyPointerToBlockPointerCast:
     case CK_ObjCObjectLValueCast:
     case CK_FloatingRealToComplex:
+    case CK_FloatingComplexToReal:
+    case CK_FloatingComplexToBoolean:
     case CK_FloatingComplexCast:
+    case CK_FloatingComplexToIntegralComplex:
     case CK_IntegralRealToComplex:
+    case CK_IntegralComplexToReal:
+    case CK_IntegralComplexToBoolean:
     case CK_IntegralComplexCast:
-    case CK_IntegralToFloatingComplex:
+    case CK_IntegralComplexToFloatingComplex:
       assert(path_empty() && "Cast kind should not have a base path!");
       break;
     }

Modified: cfe/trunk/include/clang/AST/OperationKinds.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/OperationKinds.h?rev=119036&r1=119035&r2=119036&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/OperationKinds.h (original)
+++ cfe/trunk/include/clang/AST/OperationKinds.h Sun Nov 14 02:17:51 2010
@@ -123,17 +123,32 @@
   /// \brief Floating point real to floating point complex
   CK_FloatingRealToComplex,
 
+  /// \brief Floating pointer complex to floating point real
+  CK_FloatingComplexToReal,
+
+  /// \brief Converting a floating complex to bool
+  CK_FloatingComplexToBoolean,
+
   /// \brief Casting between floating point complex types of different size
   CK_FloatingComplexCast,
 
+  /// \brief Casting from a floating complex to an integral complex
+  CK_FloatingComplexToIntegralComplex,
+
   /// \brief Integral real to integral complex
   CK_IntegralRealToComplex,
 
+  /// \brief Integral complex to integral real
+  CK_IntegralComplexToReal,
+
+  /// \brief Converting an integral complex to bool
+  CK_IntegralComplexToBoolean,
+
   /// \brief Casting between integral complex types of different size
   CK_IntegralComplexCast,
 
-  /// \brief Casting from an integral complex to a floating complex.
-  CK_IntegralToFloatingComplex
+  /// \brief Casting from an integral complex to a floating complex
+  CK_IntegralComplexToFloatingComplex
 };
 
 

Modified: cfe/trunk/lib/AST/Expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=119036&r1=119035&r2=119036&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Expr.cpp (original)
+++ cfe/trunk/lib/AST/Expr.cpp Sun Nov 14 02:17:51 2010
@@ -800,14 +800,24 @@
     return "ObjCObjectLValueCast";
   case CK_FloatingRealToComplex:
     return "FloatingRealToComplex";
+  case CK_FloatingComplexToReal:
+    return "FloatingComplexToReal";
+  case CK_FloatingComplexToBoolean:
+    return "FloatingComplexToBoolean";
   case CK_FloatingComplexCast:
     return "FloatingComplexCast";
+  case CK_FloatingComplexToIntegralComplex:
+    return "FloatingComplexToIntegralComplex";
   case CK_IntegralRealToComplex:
     return "IntegralRealToComplex";
+  case CK_IntegralComplexToReal:
+    return "IntegralComplexToReal";
+  case CK_IntegralComplexToBoolean:
+    return "IntegralComplexToBoolean";
   case CK_IntegralComplexCast:
     return "IntegralComplexCast";
-  case CK_IntegralToFloatingComplex:
-    return "IntegralToFloatingComplex";
+  case CK_IntegralComplexToFloatingComplex:
+    return "IntegralComplexToFloatingComplex";
   }
 
   llvm_unreachable("Unhandled cast kind!");

Modified: cfe/trunk/lib/AST/ExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=119036&r1=119035&r2=119036&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprConstant.cpp (original)
+++ cfe/trunk/lib/AST/ExprConstant.cpp Sun Nov 14 02:17:51 2010
@@ -2073,7 +2073,14 @@
                                     Result, Info.Ctx);
     return true;
   }
-  // FIXME: Handle complex types
+
+  if (E->getCastKind() == CK_FloatingComplexToReal) {
+    ComplexValue V;
+    if (!EvaluateComplex(SubExpr, V, Info))
+      return false;
+    Result = V.getComplexFloatReal();
+    return true;
+  }
 
   return false;
 }

Modified: cfe/trunk/lib/Checker/GRExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Checker/GRExprEngine.cpp?rev=119036&r1=119035&r2=119036&view=diff
==============================================================================
--- cfe/trunk/lib/Checker/GRExprEngine.cpp (original)
+++ cfe/trunk/lib/Checker/GRExprEngine.cpp Sun Nov 14 02:17:51 2010
@@ -2525,10 +2525,15 @@
   case CK_FloatingToIntegral:
   case CK_FloatingCast:
   case CK_FloatingRealToComplex:
+  case CK_FloatingComplexToReal:
+  case CK_FloatingComplexToBoolean:
   case CK_FloatingComplexCast:
+  case CK_FloatingComplexToIntegralComplex:
   case CK_IntegralRealToComplex:
+  case CK_IntegralComplexToReal:
+  case CK_IntegralComplexToBoolean:
   case CK_IntegralComplexCast:
-  case CK_IntegralToFloatingComplex:
+  case CK_IntegralComplexToFloatingComplex:
   case CK_AnyPointerToObjCPointerCast:
   case CK_AnyPointerToBlockPointerCast:
   case CK_DerivedToBase:

Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=119036&r1=119035&r2=119036&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExpr.cpp Sun Nov 14 02:17:51 2010
@@ -1815,10 +1815,15 @@
   case CK_FloatingToIntegral:
   case CK_FloatingCast:
   case CK_FloatingRealToComplex:
+  case CK_FloatingComplexToReal:
+  case CK_FloatingComplexToBoolean:
   case CK_FloatingComplexCast:
+  case CK_FloatingComplexToIntegralComplex:
   case CK_IntegralRealToComplex:
+  case CK_IntegralComplexToReal:
+  case CK_IntegralComplexToBoolean:
   case CK_IntegralComplexCast:
-  case CK_IntegralToFloatingComplex:
+  case CK_IntegralComplexToFloatingComplex:
   case CK_DerivedToBaseMemberPointer:
   case CK_BaseToDerivedMemberPointer:
   case CK_MemberPointerToBoolean:

Modified: cfe/trunk/lib/CodeGen/CGExprComplex.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprComplex.cpp?rev=119036&r1=119035&r2=119036&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprComplex.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprComplex.cpp Sun Nov 14 02:17:51 2010
@@ -274,6 +274,8 @@
                                                     bool isVolatile) {
   llvm::Value *Real=0, *Imag=0;
 
+  // FIXME: we should really not be suppressing volatile loads.
+
   if (!IgnoreReal) {
     llvm::Value *RealP = Builder.CreateStructGEP(SrcPtr, 0,
                                                  SrcPtr->getName() + ".realp");

Modified: cfe/trunk/lib/CodeGen/CGExprScalar.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprScalar.cpp?rev=119036&r1=119035&r2=119036&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprScalar.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprScalar.cpp Sun Nov 14 02:17:51 2010
@@ -1083,7 +1083,8 @@
   case CK_FloatingComplexCast:
   case CK_IntegralRealToComplex:
   case CK_IntegralComplexCast:
-  case CK_IntegralToFloatingComplex:
+  case CK_IntegralComplexToFloatingComplex:
+  case CK_FloatingComplexToIntegralComplex:
   case CK_ConstructorConversion:
     assert(0 && "Should be unreachable!");
     break;
@@ -1151,6 +1152,20 @@
     const MemberPointerType *MPT = E->getType()->getAs<MemberPointerType>();
     return CGF.CGM.getCXXABI().EmitMemberPointerIsNotNull(CGF, MemPtr, MPT);
   }
+
+  case CK_FloatingComplexToReal:
+  case CK_IntegralComplexToReal:
+    return CGF.EmitComplexExpr(E, false, true, false, true).first;
+
+  case CK_FloatingComplexToBoolean:
+  case CK_IntegralComplexToBoolean: {
+    CodeGenFunction::ComplexPairTy V
+      = CGF.EmitComplexExpr(E, false, false, false, false);
+
+    // TODO: kill this function off, inline appropriate case here
+    return EmitComplexToScalarConversion(V, E->getType(), DestTy);
+  }
+
   }
   
   // Handle cases where the source is an non-complex type.
@@ -1162,8 +1177,10 @@
     return EmitScalarConversion(Src, E->getType(), DestTy);
   }
 
+  // Handle cases where the source is a complex type.
+  // TODO: when we're certain about cast kinds, we should just be able
+  // to assert that no complexes make it here.
   if (E->getType()->isAnyComplexType()) {
-    // Handle cases where the source is a complex type.
     bool IgnoreImag = true;
     bool IgnoreImagAssign = true;
     bool IgnoreReal = IgnoreResultAssign;

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=119036&r1=119035&r2=119036&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Sun Nov 14 02:17:51 2010
@@ -406,7 +406,7 @@
         ImpCastExprToType(rhsExpr, lhs, CK_FloatingRealToComplex);
       } else {
         assert(rhs->isComplexIntegerType());
-        ImpCastExprToType(rhsExpr, lhs, CK_IntegralToFloatingComplex);
+        ImpCastExprToType(rhsExpr, lhs, CK_IntegralComplexToFloatingComplex);
       }
       return lhs;
     }
@@ -420,7 +420,7 @@
           ImpCastExprToType(lhsExpr, rhs, CK_FloatingRealToComplex);
         } else {
           assert(lhs->isComplexIntegerType());
-          ImpCastExprToType(lhsExpr, rhs, CK_IntegralToFloatingComplex);
+          ImpCastExprToType(lhsExpr, rhs, CK_IntegralComplexToFloatingComplex);
         }
       }
       return rhs;
@@ -537,7 +537,7 @@
       QualType result = Context.getComplexType(lhs);
 
       // _Complex int -> _Complex float
-      ImpCastExprToType(rhsExpr, result, CK_IntegralToFloatingComplex);
+      ImpCastExprToType(rhsExpr, result, CK_IntegralComplexToFloatingComplex);
 
       // float -> _Complex float
       if (!isCompAssign)
@@ -560,7 +560,7 @@
 
     // _Complex int -> _Complex float
     if (!isCompAssign)
-      ImpCastExprToType(lhsExpr, result, CK_IntegralToFloatingComplex);
+      ImpCastExprToType(lhsExpr, result, CK_IntegralComplexToFloatingComplex);
 
     // float -> _Complex float
     ImpCastExprToType(rhsExpr, result, CK_FloatingRealToComplex);
@@ -4252,43 +4252,131 @@
   return Owned(E);
 }
 
-static CastKind getScalarCastKind(ASTContext &Context,
-                                  Expr *Src, QualType DestTy) {
+enum ScalarKind {
+  SK_Pointer,
+  SK_Bool,
+  SK_Integral,
+  SK_Floating,
+  SK_IntegralComplex,
+  SK_FloatingComplex
+};
+static ScalarKind ClassifyScalarType(QualType QT) {
+  assert(QT->isScalarType());
+
+  const Type *T = QT->getCanonicalTypeUnqualified().getTypePtr();
+  if (T->hasPointerRepresentation())
+    return SK_Pointer;
+  if (T->isBooleanType())
+    return SK_Bool;
+  if (T->isRealFloatingType())
+    return SK_Floating;
+  if (const ComplexType *CT = dyn_cast<ComplexType>(T)) {
+    if (CT->getElementType()->isRealFloatingType())
+      return SK_FloatingComplex;
+    return SK_IntegralComplex;
+  }
+  assert(T->isIntegerType());
+  return SK_Integral;
+}
+
+/// Prepares for a scalar cast, performing all the necessary stages
+/// except the final cast and returning the kind required.
+static CastKind PrepareScalarCast(Sema &S, Expr *&Src, QualType DestTy) {
+  // Both Src and Dest are scalar types, i.e. arithmetic or pointer.
+  // Also, callers should have filtered out the invalid cases with
+  // pointers.  Everything else should be possible.
+
   QualType SrcTy = Src->getType();
-  if (Context.hasSameUnqualifiedType(SrcTy, DestTy))
+  if (S.Context.hasSameUnqualifiedType(SrcTy, DestTy))
     return CK_NoOp;
 
-  if (SrcTy->hasPointerRepresentation()) {
-    if (DestTy->hasPointerRepresentation())
-      return DestTy->isObjCObjectPointerType() ?
-                CK_AnyPointerToObjCPointerCast :
-                CK_BitCast;
+  switch (ClassifyScalarType(SrcTy)) {
+  case SK_Pointer:
     if (DestTy->isIntegerType())
       return CK_PointerToIntegral;
-  }
+    assert(DestTy->hasPointerRepresentation());
+    return DestTy->isObjCObjectPointerType() ?
+                CK_AnyPointerToObjCPointerCast :
+                CK_BitCast;
 
-  if (SrcTy->isIntegerType()) {
-    if (DestTy->isIntegerType())
-      return CK_IntegralCast;
-    if (DestTy->hasPointerRepresentation()) {
-      if (Src->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull))
+  case SK_Bool: // casting from bool is like casting from an integer
+  case SK_Integral:
+    switch (ClassifyScalarType(DestTy)) {
+    case SK_Pointer:
+      if (Src->isNullPointerConstant(S.Context, Expr::NPC_ValueDependentIsNull))
         return CK_NullToPointer;
       return CK_IntegralToPointer;
-    }
-    if (DestTy->isRealFloatingType())
+
+    case SK_Bool: // TODO: there should be an int->bool cast kind
+    case SK_Integral:
+      return CK_IntegralCast;
+    case SK_Floating:
       return CK_IntegralToFloating;
-  }
+    case SK_IntegralComplex:
+      return CK_IntegralRealToComplex;
+    case SK_FloatingComplex:
+      S.ImpCastExprToType(Src, cast<ComplexType>(DestTy)->getElementType(),
+                          CK_IntegralToFloating);
+      return CK_FloatingRealToComplex;
+    }
+    break;
 
-  if (SrcTy->isRealFloatingType()) {
-    if (DestTy->isRealFloatingType())
+  case SK_Floating:
+    switch (ClassifyScalarType(DestTy)) {
+    case SK_Floating:
       return CK_FloatingCast;
-    if (DestTy->isIntegerType())
+    case SK_Bool: // TODO: there should be a float->bool cast kind
+    case SK_Integral:
       return CK_FloatingToIntegral;
+    case SK_FloatingComplex:
+      return CK_FloatingRealToComplex;
+    case SK_IntegralComplex:
+      S.ImpCastExprToType(Src, cast<ComplexType>(DestTy)->getElementType(),
+                          CK_FloatingToIntegral);
+      return CK_IntegralRealToComplex;
+    case SK_Pointer: llvm_unreachable("valid float->pointer cast?");
+    }
+    break;
+
+  case SK_FloatingComplex:
+    switch (ClassifyScalarType(DestTy)) {
+    case SK_FloatingComplex:
+      return CK_FloatingComplexCast;
+    case SK_IntegralComplex:
+      return CK_FloatingComplexToIntegralComplex;
+    case SK_Floating:
+      return CK_FloatingComplexToReal;
+    case SK_Bool:
+      return CK_FloatingComplexToBoolean;
+    case SK_Integral:
+      S.ImpCastExprToType(Src, cast<ComplexType>(SrcTy)->getElementType(),
+                          CK_FloatingComplexToReal);
+      return CK_FloatingToIntegral;
+    case SK_Pointer: llvm_unreachable("valid complex float->pointer cast?");
+    }
+    break;
+
+  case SK_IntegralComplex:
+    switch (ClassifyScalarType(DestTy)) {
+    case SK_FloatingComplex:
+      return CK_IntegralComplexToFloatingComplex;
+    case SK_IntegralComplex:
+      return CK_IntegralComplexCast;
+    case SK_Integral:
+      return CK_IntegralComplexToReal;
+    case SK_Bool:
+      return CK_IntegralComplexToBoolean;
+    case SK_Floating:
+      S.ImpCastExprToType(Src, cast<ComplexType>(SrcTy)->getElementType(),
+                          CK_IntegralComplexToReal);
+      return CK_IntegralToFloating;
+    case SK_Pointer: llvm_unreachable("valid complex int->pointer cast?");
+    }
+    break;
   }
 
-  // FIXME: Assert here.
-  // assert(false && "Unhandled cast combination!");
-  return CK_Unknown;
+  llvm_unreachable("Unhandled scalar cast");
+  return CK_BitCast;
 }
 
 /// CheckCastTypes - Check type constraints for casting between types.
@@ -4353,6 +4441,9 @@
       << castType << castExpr->getSourceRange();
   }
 
+  // The type we're casting to is known to be a scalar or vector.
+
+  // Require the operand to be a scalar or vector.
   if (!castExpr->getType()->isScalarType() &&
       !castExpr->getType()->isVectorType()) {
     return Diag(castExpr->getLocStart(),
@@ -4368,9 +4459,16 @@
   if (castExpr->getType()->isVectorType())
     return CheckVectorCast(TyR, castExpr->getType(), castType, Kind);
 
+  // The source and target types are both scalars, i.e.
+  //   - arithmetic types (fundamental, enum, and complex)
+  //   - all kinds of pointers
+  // Note that member pointers were filtered out with C++, above.
+
   if (isa<ObjCSelectorExpr>(castExpr))
     return Diag(castExpr->getLocStart(), diag::err_cast_selector_expr);
 
+  // If either type is a pointer, the other type has to be either an
+  // integer or a pointer.
   if (!castType->isArithmeticType()) {
     QualType castExprType = castExpr->getType();
     if (!castExprType->isIntegralType(Context) && 
@@ -4385,9 +4483,9 @@
         << castType << castExpr->getSourceRange();
   }
 
-  Kind = getScalarCastKind(Context, castExpr, castType);
+  Kind = PrepareScalarCast(*this, castExpr, castType);
 
-  if (Kind == CK_Unknown || Kind == CK_BitCast)
+  if (Kind == CK_BitCast)
     CheckCastAlign(castExpr, castType, TyR);
 
   return false;
@@ -4439,7 +4537,7 @@
 
   QualType DestElemTy = DestTy->getAs<ExtVectorType>()->getElementType();
   ImpCastExprToType(CastExpr, DestElemTy,
-                    getScalarCastKind(Context, CastExpr, DestElemTy));
+                    PrepareScalarCast(*this, CastExpr, DestElemTy));
 
   Kind = CK_VectorSplat;
   return false;





More information about the cfe-commits mailing list