]> granicus.if.org Git - clang/commitdiff
Add a few more complex-related cast kinds that arise due to arbitrary
authorJohn McCall <rjmccall@apple.com>
Sun, 14 Nov 2010 08:17:51 +0000 (08:17 +0000)
committerJohn McCall <rjmccall@apple.com>
Sun, 14 Nov 2010 08:17:51 +0000 (08:17 +0000)
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.

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

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

index eda2368344453eaf5b688be3755f0319d5a7fe60..950f579c51192f99e42e46bfe687b29df25d99c2 100644 (file)
@@ -1998,10 +1998,15 @@ private:
     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;
     }
index 7cfeed2ab5094e1f0acfc91a7115de45832ee21e..d6a7ecf43be0b54db1a1cead7e93957b96549db5 100644 (file)
@@ -123,17 +123,32 @@ enum CastKind {
   /// \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
 };
 
 
index cc209a458a121daa6c0817b1b1ced1474d160b48..d5bdc88ccfeccdd225e912b167ab67da667aa7ac 100644 (file)
@@ -800,14 +800,24 @@ const char *CastExpr::getCastKindName() const {
     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!");
index 172a811bee1c55c9ca932f22542c1548eac20288..8a6d4ba7c425d8bf4da16e1860d677d420cb4061 100644 (file)
@@ -2073,7 +2073,14 @@ bool FloatExprEvaluator::VisitCastExpr(CastExpr *E) {
                                     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;
 }
index 19238bf2afb5118d21e4a32d8bbdb15d8df27843..4a1df68e5be9af80d15633a841a8e55a8d00f400 100644 (file)
@@ -2525,10 +2525,15 @@ void GRExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
   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:
index 6739fd679cfd1e0097a419c733dc3fde8d0dfc8f..3356cf46fbd9a3d2ea87bed3828aa468aa292e19 100644 (file)
@@ -1815,10 +1815,15 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
   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:
index 637441f4e199df9f472221ccadd001a15fd7d11b..ad0786fd9b0e51f14e1a3679ab11bd8329b0ddb5 100644 (file)
@@ -274,6 +274,8 @@ ComplexPairTy ComplexExprEmitter::EmitLoadOfComplex(llvm::Value *SrcPtr,
                                                     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");
index 5b419c02f8bdbb0f31cc0cae64932b6b0e9c5156..8d72e47fb860360529dec512e8db5527a17227dd 100644 (file)
@@ -1083,7 +1083,8 @@ Value *ScalarExprEmitter::EmitCastExpr(CastExpr *CE) {
   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 @@ Value *ScalarExprEmitter::EmitCastExpr(CastExpr *CE) {
     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 @@ Value *ScalarExprEmitter::EmitCastExpr(CastExpr *CE) {
     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;
index b9d3d8756598f5d3050c1b62bfffe21650cab2d8..687b92e21bb21057a4aaeb334c34963ab3d0ec69 100644 (file)
@@ -406,7 +406,7 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr,
         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 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr,
           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 Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr,
       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 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr,
 
     // _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 @@ Sema::ActOnInitList(SourceLocation LBraceLoc, MultiExprArg initlist,
   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 @@ bool Sema::CheckCastTypes(SourceRange TyR, QualType castType, Expr *&castExpr,
       << 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 @@ bool Sema::CheckCastTypes(SourceRange TyR, QualType castType, Expr *&castExpr,
   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 @@ bool Sema::CheckCastTypes(SourceRange TyR, QualType castType, Expr *&castExpr,
         << 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 @@ bool Sema::CheckExtVectorCast(SourceRange R, QualType DestTy, Expr *&CastExpr,
 
   QualType DestElemTy = DestTy->getAs<ExtVectorType>()->getElementType();
   ImpCastExprToType(CastExpr, DestElemTy,
-                    getScalarCastKind(Context, CastExpr, DestElemTy));
+                    PrepareScalarCast(*this, CastExpr, DestElemTy));
 
   Kind = CK_VectorSplat;
   return false;