]> granicus.if.org Git - clang/commitdiff
Implement the missing pieces of Evaluate for _Complex types. With that complete...
authorEli Friedman <eli.friedman@gmail.com>
Tue, 10 Jan 2012 04:58:17 +0000 (04:58 +0000)
committerEli Friedman <eli.friedman@gmail.com>
Tue, 10 Jan 2012 04:58:17 +0000 (04:58 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@147840 91177308-0d34-0410-b5e6-96231b3b80d8

lib/AST/ExprConstant.cpp
lib/AST/Type.cpp
lib/CodeGen/CGExprConstant.cpp
lib/Sema/DeclSpec.cpp
test/Sema/complex-init-list.c
test/SemaCXX/constant-expression-cxx11.cpp

index 5fd710d90ec659a95da8bb9f4c1ba7054e938f6e..36addddcc5cf97efc19eb962099177698a8d8267 100644 (file)
@@ -3191,8 +3191,6 @@ namespace {
     // FIXME: Missing: unary -, unary ~, binary add/sub/mul/div,
     //                 binary comparisons, binary and/or/xor,
     //                 shufflevector, ExtVectorElementExpr
-    //        (Note that these require implementing conversions
-    //         between vector types.)
   };
 } // end anonymous namespace
 
@@ -4884,17 +4882,17 @@ public:
     return true;
   }
 
+  bool ZeroInitialization(const Expr *E);
+
   //===--------------------------------------------------------------------===//
   //                            Visitor Methods
   //===--------------------------------------------------------------------===//
 
   bool VisitImaginaryLiteral(const ImaginaryLiteral *E);
-
   bool VisitCastExpr(const CastExpr *E);
-
   bool VisitBinaryOperator(const BinaryOperator *E);
   bool VisitUnaryOperator(const UnaryOperator *E);
-  // FIXME Missing: ImplicitValueInitExpr, InitListExpr
+  bool VisitInitListExpr(const InitListExpr *E);
 };
 } // end anonymous namespace
 
@@ -4904,6 +4902,22 @@ static bool EvaluateComplex(const Expr *E, ComplexValue &Result,
   return ComplexExprEvaluator(Info, Result).Visit(E);
 }
 
+bool ComplexExprEvaluator::ZeroInitialization(const Expr *E) {
+  QualType ElemTy = cast<ComplexType>(E->getType())->getElementType();
+  if (ElemTy->isRealFloatingType()) {
+    Result.makeComplexFloat();
+    APFloat Zero = APFloat::getZero(Info.Ctx.getFloatTypeSemantics(ElemTy));
+    Result.FloatReal = Zero;
+    Result.FloatImag = Zero;
+  } else {
+    Result.makeComplexInt();
+    APSInt Zero = Info.Ctx.MakeIntValue(0, ElemTy);
+    Result.IntReal = Zero;
+    Result.IntImag = Zero;
+  }
+  return true;
+}
+
 bool ComplexExprEvaluator::VisitImaginaryLiteral(const ImaginaryLiteral *E) {
   const Expr* SubExpr = E->getSubExpr();
 
@@ -5207,6 +5221,26 @@ bool ComplexExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) {
   }
 }
 
+bool ComplexExprEvaluator::VisitInitListExpr(const InitListExpr *E) {
+  if (E->getNumInits() == 2) {
+    if (E->getType()->isComplexType()) {
+      Result.makeComplexFloat();
+      if (!EvaluateFloat(E->getInit(0), Result.FloatReal, Info))
+        return false;
+      if (!EvaluateFloat(E->getInit(1), Result.FloatImag, Info))
+        return false;
+    } else {
+      Result.makeComplexInt();
+      if (!EvaluateInteger(E->getInit(0), Result.IntReal, Info))
+        return false;
+      if (!EvaluateInteger(E->getInit(1), Result.IntImag, Info))
+        return false;
+    }
+    return true;
+  }
+  return ExprEvaluatorBaseTy::VisitInitListExpr(E);
+}
+
 //===----------------------------------------------------------------------===//
 // Void expression evaluation, primarily for a cast to void on the LHS of a
 // comma operator
index 3c4845d85a3539f08a120d70b7b9248a412031ae..4584ca09d9a4ff21471591a826e8cddc1e3f7865 100644 (file)
@@ -1148,8 +1148,10 @@ bool Type::isLiteralType() const {
   // C++0x [basic.types]p10:
   //   A type is a literal type if it is:
   //    -- a scalar type; or
-  // As an extension, Clang treats vector types as literal types.
-  if (BaseTy->isScalarType() || BaseTy->isVectorType())
+  // As an extension, Clang treats vector types and complex types as
+  // literal types.
+  if (BaseTy->isScalarType() || BaseTy->isVectorType() ||
+      BaseTy->isAnyComplexType())
     return true;
   //    -- a reference type; or
   if (BaseTy->isReferenceType())
index 826a950148aca313652d0f3302555a054fd83804..a8399d719f2f025458e76a75cecd76febae577ea 100644 (file)
@@ -681,31 +681,6 @@ public:
   }
 
   llvm::Constant *VisitInitListExpr(InitListExpr *ILE) {
-    if (ILE->getType()->isAnyComplexType() && ILE->getNumInits() == 2) {
-      // Complex type with element initializers
-      Expr *Real = ILE->getInit(0);
-      Expr *Imag = ILE->getInit(1);
-      llvm::Constant *Complex[2];
-      Complex[0] = CGM.EmitConstantExpr(Real, Real->getType(), CGF);
-      if (!Complex[0])
-        return 0;
-      Complex[1] = CGM.EmitConstantExpr(Imag, Imag->getType(), CGF);
-      if (!Complex[1])
-        return 0;
-      llvm::StructType *STy =
-          cast<llvm::StructType>(ConvertType(ILE->getType()));
-      return llvm::ConstantStruct::get(STy, Complex);
-    }
-
-    if (ILE->getType()->isScalarType()) {
-      // We have a scalar in braces. Just use the first element.
-      if (ILE->getNumInits() > 0) {
-        Expr *Init = ILE->getInit(0);
-        return CGM.EmitConstantExpr(Init, Init->getType(), CGF);
-      }
-      return CGM.EmitNullConstant(ILE->getType());
-    }
-
     if (ILE->getType()->isArrayType())
       return EmitArrayInitialization(ILE);
 
@@ -715,11 +690,7 @@ public:
     if (ILE->getType()->isUnionType())
       return EmitUnionInitialization(ILE);
 
-    // If ILE was a constant vector, we would have handled it already.
-    if (ILE->getType()->isVectorType())
-      return 0;
-
-    llvm_unreachable("Unable to handle InitListExpr");
+    return 0;
   }
 
   llvm::Constant *VisitCXXConstructExpr(CXXConstructExpr *E) {
index 2fb4f35cd8124ad66a9edeec87dd2f575349b1db..2b5efc692f4e2df943403b67fc3f8f384943ebf4 100644 (file)
@@ -867,7 +867,8 @@ void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP) {
       TypeSpecType = TST_double;   // _Complex -> _Complex double.
     } else if (TypeSpecType == TST_int || TypeSpecType == TST_char) {
       // Note that this intentionally doesn't include _Complex _Bool.
-      Diag(D, TSTLoc, diag::ext_integer_complex);
+      if (!PP.getLangOptions().CPlusPlus)
+        Diag(D, TSTLoc, diag::ext_integer_complex);
     } else if (TypeSpecType != TST_float && TypeSpecType != TST_double) {
       Diag(D, TSCLoc, diag::err_invalid_complex_spec)
         << getSpecifierName((TST)TypeSpecType);
index 5b5d7ce1436b48cae9124327d7bcefd07bfa2946..bfc6899ac235dcf9ec6f8817824717de50d413ff 100644 (file)
@@ -43,3 +43,6 @@ _Complex float sizetest1[] = { {1.0f, 1.0f}, {1.0f, 1.0f} }; // expected-warning
 _Complex float sizecheck1[(sizeof(sizetest1) == sizeof(*sizetest1)*2) ? 1 : -1];
 _Complex float sizetest2[] = { 1.0f, 1.0f, {1.0f, 1.0f} };  // expected-warning {{specifying real and imaginary components is an extension}}
 _Complex float sizecheck2[(sizeof(sizetest2) == sizeof(*sizetest2)*3) ? 1 : -1];
+
+// Constant-folding with init list.
+_Complex float x = 2 + (_Complex float) { 1, 2 };  // expected-warning {{specifying real and imaginary components is an extension}}
index ff9889276d919d8ccd5ffcc47dd395320f1d63d9..86a326a283d38e85f4ecaf95f8681a114cf49c37 100644 (file)
@@ -976,3 +976,12 @@ namespace ExternConstexpr {
     constexpr int k; // expected-error {{default initialization of an object of const type}}
   }
 }
+
+namespace ComplexConstexpr {
+  constexpr _Complex float test1 = {};
+  constexpr _Complex float test2 = {1};
+  constexpr _Complex double test3 = {1,2};
+  constexpr _Complex int test4 = {4};
+  constexpr _Complex int test5 = 4;
+  constexpr _Complex int test6 = {5,6};
+}