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.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@119036 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index b9d3d87..687b92e 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -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;