diff options
author | Eli Friedman <eli.friedman@gmail.com> | 2012-01-10 04:58:17 +0000 |
---|---|---|
committer | Eli Friedman <eli.friedman@gmail.com> | 2012-01-10 04:58:17 +0000 |
commit | 7ead5c7b6fd48cf549e55b4db499c26ecf88ae75 (patch) | |
tree | eeafa766caa81cbf5da3282bf0ca565d5a5b260f | |
parent | 610a60c0e68e34db5a5247d6102e58f37510fef8 (diff) |
Implement the missing pieces of Evaluate for _Complex types. With that complete, remove some code from CGExprConstant which is no longer necessary. While I'm here, a couple minor tweaks to _Complex-in-C++. (Specifically, make _Complex types literal types, and don't warn for _Complex int.)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@147840 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/AST/ExprConstant.cpp | 44 | ||||
-rw-r--r-- | lib/AST/Type.cpp | 6 | ||||
-rw-r--r-- | lib/CodeGen/CGExprConstant.cpp | 31 | ||||
-rw-r--r-- | lib/Sema/DeclSpec.cpp | 3 | ||||
-rw-r--r-- | test/Sema/complex-init-list.c | 3 | ||||
-rw-r--r-- | test/SemaCXX/constant-expression-cxx11.cpp | 9 |
6 files changed, 58 insertions, 38 deletions
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 5fd710d90e..36addddcc5 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -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 diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 3c4845d85a..4584ca09d9 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -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()) diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp index 826a950148..a8399d719f 100644 --- a/lib/CodeGen/CGExprConstant.cpp +++ b/lib/CodeGen/CGExprConstant.cpp @@ -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) { diff --git a/lib/Sema/DeclSpec.cpp b/lib/Sema/DeclSpec.cpp index 2fb4f35cd8..2b5efc692f 100644 --- a/lib/Sema/DeclSpec.cpp +++ b/lib/Sema/DeclSpec.cpp @@ -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); diff --git a/test/Sema/complex-init-list.c b/test/Sema/complex-init-list.c index 5b5d7ce143..bfc6899ac2 100644 --- a/test/Sema/complex-init-list.c +++ b/test/Sema/complex-init-list.c @@ -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}} diff --git a/test/SemaCXX/constant-expression-cxx11.cpp b/test/SemaCXX/constant-expression-cxx11.cpp index ff9889276d..86a326a283 100644 --- a/test/SemaCXX/constant-expression-cxx11.cpp +++ b/test/SemaCXX/constant-expression-cxx11.cpp @@ -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}; +} |