Introduce five new cast kinds for various conversions into and
between complex types.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@118994 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 2edf62a..cc209a4 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -798,9 +798,19 @@
     return "AnyPointerToBlockPointerCast";
   case CK_ObjCObjectLValueCast:
     return "ObjCObjectLValueCast";
+  case CK_FloatingRealToComplex:
+    return "FloatingRealToComplex";
+  case CK_FloatingComplexCast:
+    return "FloatingComplexCast";
+  case CK_IntegralRealToComplex:
+    return "IntegralRealToComplex";
+  case CK_IntegralComplexCast:
+    return "IntegralComplexCast";
+  case CK_IntegralToFloatingComplex:
+    return "IntegralToFloatingComplex";
   }
 
-  assert(0 && "Unhandled cast kind!");
+  llvm_unreachable("Unhandled cast kind!");
   return 0;
 }
 
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index dfeb32d..172a811 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -2165,6 +2165,8 @@
   QualType EltType = E->getType()->getAs<ComplexType>()->getElementType();
   QualType SubType = SubExpr->getType();
 
+  // TODO: just trust CastKind
+
   if (SubType->isRealFloatingType()) {
     APFloat &Real = Result.FloatReal;
     if (!EvaluateFloat(SubExpr, Real, Info))
diff --git a/lib/Checker/GRExprEngine.cpp b/lib/Checker/GRExprEngine.cpp
index 73b5bf8..19238bf 100644
--- a/lib/Checker/GRExprEngine.cpp
+++ b/lib/Checker/GRExprEngine.cpp
@@ -2524,6 +2524,11 @@
   case CK_IntegralToFloating:
   case CK_FloatingToIntegral:
   case CK_FloatingCast:
+  case CK_FloatingRealToComplex:
+  case CK_FloatingComplexCast:
+  case CK_IntegralRealToComplex:
+  case CK_IntegralComplexCast:
+  case CK_IntegralToFloatingComplex:
   case CK_AnyPointerToObjCPointerCast:
   case CK_AnyPointerToBlockPointerCast:
   case CK_DerivedToBase:
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp
index bb2eb3c..6739fd6 100644
--- a/lib/CodeGen/CGExpr.cpp
+++ b/lib/CodeGen/CGExpr.cpp
@@ -1814,6 +1814,11 @@
   case CK_IntegralToFloating:
   case CK_FloatingToIntegral:
   case CK_FloatingCast:
+  case CK_FloatingRealToComplex:
+  case CK_FloatingComplexCast:
+  case CK_IntegralRealToComplex:
+  case CK_IntegralComplexCast:
+  case CK_IntegralToFloatingComplex:
   case CK_DerivedToBaseMemberPointer:
   case CK_BaseToDerivedMemberPointer:
   case CK_MemberPointerToBoolean:
diff --git a/lib/CodeGen/CGExprComplex.cpp b/lib/CodeGen/CGExprComplex.cpp
index 517a8da..637441f 100644
--- a/lib/CodeGen/CGExprComplex.cpp
+++ b/lib/CodeGen/CGExprComplex.cpp
@@ -350,6 +350,8 @@
 
 ComplexPairTy ComplexExprEmitter::EmitCast(CastExpr::CastKind CK, Expr *Op, 
                                            QualType DestTy) {
+  // FIXME: this should be based off of the CastKind.
+
   // Two cases here: cast from (complex to complex) and (scalar to complex).
   if (Op->getType()->isAnyComplexType())
     return EmitComplexToComplexCast(Visit(Op), Op->getType(), DestTy);
diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp
index d07d203..5b419c0 100644
--- a/lib/CodeGen/CGExprScalar.cpp
+++ b/lib/CodeGen/CGExprScalar.cpp
@@ -1079,7 +1079,11 @@
     return CGF.CGM.getCXXABI().EmitMemberPointerConversion(CGF, CE, Src);
   }
   
-
+  case CK_FloatingRealToComplex:
+  case CK_FloatingComplexCast:
+  case CK_IntegralRealToComplex:
+  case CK_IntegralComplexCast:
+  case CK_IntegralToFloatingComplex:
   case CK_ConstructorConversion:
     assert(0 && "Should be unreachable!");
     break;
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 590685d..b9d3d87 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -399,18 +399,30 @@
   if (LHSComplexFloat || RHSComplexFloat) {
     // if we have an integer operand, the result is the complex type.
 
-    if (LHSComplexFloat &&
-        (rhs->isIntegerType() || rhs->isComplexIntegerType())) {
-      // convert the rhs to the lhs complex type.
-      ImpCastExprToType(rhsExpr, lhs, CK_Unknown);
+    if (!RHSComplexFloat && !rhs->isRealFloatingType()) {
+      if (rhs->isIntegerType()) {
+        QualType fp = cast<ComplexType>(lhs)->getElementType();
+        ImpCastExprToType(rhsExpr, fp, CK_IntegralToFloating);
+        ImpCastExprToType(rhsExpr, lhs, CK_FloatingRealToComplex);
+      } else {
+        assert(rhs->isComplexIntegerType());
+        ImpCastExprToType(rhsExpr, lhs, CK_IntegralToFloatingComplex);
+      }
       return lhs;
     }
 
-    if (!LHSComplexFloat && RHSComplexFloat &&
-        (lhs->isIntegerType() || lhs->isComplexIntegerType())) {
-      // convert the lhs to the rhs complex type.
-      if (!isCompAssign)
-        ImpCastExprToType(lhsExpr, rhs, CK_Unknown);
+    if (!LHSComplexFloat && !lhs->isRealFloatingType()) {
+      if (!isCompAssign) {
+        // int -> float -> _Complex float
+        if (lhs->isIntegerType()) {
+          QualType fp = cast<ComplexType>(rhs)->getElementType();
+          ImpCastExprToType(lhsExpr, fp, CK_IntegralToFloating);
+          ImpCastExprToType(lhsExpr, rhs, CK_FloatingRealToComplex);
+        } else {
+          assert(lhs->isComplexIntegerType());
+          ImpCastExprToType(lhsExpr, rhs, CK_IntegralToFloatingComplex);
+        }
+      }
       return rhs;
     }
 
@@ -430,13 +442,13 @@
     if (LHSComplexFloat && RHSComplexFloat) {
       if (order > 0) {
         // _Complex float -> _Complex double
-        ImpCastExprToType(rhsExpr, lhs, CK_Unknown);
+        ImpCastExprToType(rhsExpr, lhs, CK_FloatingComplexCast);
         return lhs;
 
       } else if (order < 0) {
         // _Complex float -> _Complex double
         if (!isCompAssign)
-          ImpCastExprToType(lhsExpr, rhs, CK_Unknown);
+          ImpCastExprToType(lhsExpr, rhs, CK_FloatingComplexCast);
         return rhs;
       }
       return lhs;
@@ -447,7 +459,9 @@
     if (LHSComplexFloat) {
       if (order > 0) { // LHS is wider
         // float -> _Complex double
-        ImpCastExprToType(rhsExpr, lhs, CK_Unknown);
+        QualType fp = cast<ComplexType>(lhs)->getElementType();
+        ImpCastExprToType(rhsExpr, fp, CK_FloatingCast);
+        ImpCastExprToType(rhsExpr, lhs, CK_FloatingRealToComplex);
         return lhs;        
       }
 
@@ -455,11 +469,11 @@
       QualType result = (order == 0 ? lhs : Context.getComplexType(rhs));
 
       // double -> _Complex double
-      ImpCastExprToType(rhsExpr, result, CK_Unknown);
+      ImpCastExprToType(rhsExpr, result, CK_FloatingRealToComplex);
 
       // _Complex float -> _Complex double
       if (!isCompAssign && order < 0)
-        ImpCastExprToType(lhsExpr, result, CK_Unknown);
+        ImpCastExprToType(lhsExpr, result, CK_FloatingComplexCast);
 
       return result;
     }
@@ -470,8 +484,10 @@
 
     if (order < 0) { // RHS is wider
       // float -> _Complex double
-      if (!isCompAssign)
-        ImpCastExprToType(lhsExpr, rhs, CK_Unknown);
+      if (!isCompAssign) {
+        ImpCastExprToType(lhsExpr, rhs, CK_FloatingCast);
+        ImpCastExprToType(lhsExpr, rhs, CK_FloatingRealToComplex);
+      }
       return rhs;
     }
 
@@ -480,11 +496,11 @@
 
     // double -> _Complex double
     if (!isCompAssign)
-      ImpCastExprToType(lhsExpr, result, CK_Unknown);
+      ImpCastExprToType(lhsExpr, result, CK_FloatingRealToComplex);
 
     // _Complex float -> _Complex double
     if (order > 0)
-      ImpCastExprToType(rhsExpr, result, CK_Unknown);
+      ImpCastExprToType(rhsExpr, result, CK_FloatingComplexCast);
 
     return result;
   }
@@ -521,11 +537,11 @@
       QualType result = Context.getComplexType(lhs);
 
       // _Complex int -> _Complex float
-      ImpCastExprToType(rhsExpr, result, CK_Unknown);
+      ImpCastExprToType(rhsExpr, result, CK_IntegralToFloatingComplex);
 
       // float -> _Complex float
       if (!isCompAssign)
-        ImpCastExprToType(lhsExpr, result, CK_Unknown);
+        ImpCastExprToType(lhsExpr, result, CK_FloatingRealToComplex);
 
       return result;
     }
@@ -544,10 +560,10 @@
 
     // _Complex int -> _Complex float
     if (!isCompAssign)
-      ImpCastExprToType(lhsExpr, result, CK_Unknown);
+      ImpCastExprToType(lhsExpr, result, CK_IntegralToFloatingComplex);
 
     // float -> _Complex float
-    ImpCastExprToType(rhsExpr, result, CK_Unknown);
+    ImpCastExprToType(rhsExpr, result, CK_FloatingRealToComplex);
 
     return result;
   }
@@ -563,21 +579,21 @@
     assert(order && "inequal types with equal element ordering");
     if (order > 0) {
       // _Complex int -> _Complex long
-      ImpCastExprToType(rhsExpr, lhs, CK_Unknown);
+      ImpCastExprToType(rhsExpr, lhs, CK_IntegralComplexCast);
       return lhs;
     }
 
     if (!isCompAssign)
-      ImpCastExprToType(lhsExpr, rhs, CK_Unknown);
+      ImpCastExprToType(lhsExpr, rhs, CK_IntegralComplexCast);
     return rhs;
   } else if (lhsComplexInt) {
     // int -> _Complex int
-    ImpCastExprToType(rhsExpr, lhs, CK_Unknown);
+    ImpCastExprToType(rhsExpr, lhs, CK_IntegralRealToComplex);
     return lhs;
   } else if (rhsComplexInt) {
     // int -> _Complex int
     if (!isCompAssign)
-      ImpCastExprToType(lhsExpr, rhs, CK_Unknown);
+      ImpCastExprToType(lhsExpr, rhs, CK_IntegralRealToComplex);
     return rhs;
   }