diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 66261045a5b6..af50de6f9481 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -55,8 +55,7 @@ static bool EvaluateLValue(const Expr *E, APValue &Result, EvalInfo &Info); static bool EvaluatePointer(const Expr *E, APValue &Result, EvalInfo &Info); static bool EvaluateInteger(const Expr *E, APSInt &Result, EvalInfo &Info); static bool EvaluateFloat(const Expr *E, APFloat &Result, EvalInfo &Info); -static bool EvaluateComplexFloat(const Expr *E, APValue &Result, - EvalInfo &Info); +static bool EvaluateComplex(const Expr *E, APValue &Result, EvalInfo &Info); //===----------------------------------------------------------------------===// // Misc utilities @@ -1228,16 +1227,16 @@ bool FloatExprEvaluator::VisitCXXZeroInitValueExpr(CXXZeroInitValueExpr *E) { } //===----------------------------------------------------------------------===// -// Complex Float Evaluation +// Complex Evaluation (for float and integer) //===----------------------------------------------------------------------===// namespace { -class VISIBILITY_HIDDEN ComplexFloatExprEvaluator - : public StmtVisitor { +class VISIBILITY_HIDDEN ComplexExprEvaluator + : public StmtVisitor { EvalInfo &Info; public: - ComplexFloatExprEvaluator(EvalInfo &info) : Info(info) {} + ComplexExprEvaluator(EvalInfo &info) : Info(info) {} //===--------------------------------------------------------------------===// // Visitor Methods @@ -1250,12 +1249,28 @@ public: APValue VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); } APValue VisitImaginaryLiteral(ImaginaryLiteral *E) { - APFloat Result(0.0); - if (!EvaluateFloat(E->getSubExpr(), Result, Info)) - return APValue(); + Expr* SubExpr = E->getSubExpr(); + + if (SubExpr->getType()->isRealFloatingType()) { + APFloat Result(0.0); + + if (!EvaluateFloat(SubExpr, Result, Info)) + return APValue(); - return APValue(APFloat(Result.getSemantics(), APFloat::fcZero), - Result); + return APValue(APFloat(Result.getSemantics(), APFloat::fcZero), + Result); + } else { + assert(SubExpr->getType()->isIntegerType() && + "Unexpected imaginary literal."); + + llvm::APSInt Result; + if (!EvaluateInteger(SubExpr, Result, Info)) + return APValue(); + + llvm::APSInt Zero(Result.getBitWidth(), !Result.isSigned()); + Zero = 0; + return APValue(Zero, Result); + } } APValue VisitCastExpr(CastExpr *E) { @@ -1269,6 +1284,15 @@ public: return APValue(Result, APFloat(Result.getSemantics(), APFloat::fcZero)); + } else if (SubExpr->getType()->isIntegerType()) { + APSInt Result; + + if (!EvaluateInteger(SubExpr, Result, Info)) + return APValue(); + + llvm::APSInt Zero(Result.getBitWidth(), !Result.isSigned()); + Zero = 0; + return APValue(Result, Zero); } // FIXME: Handle more casts. @@ -1280,38 +1304,48 @@ public: }; } // end anonymous namespace -static bool EvaluateComplexFloat(const Expr *E, APValue &Result, EvalInfo &Info) +static bool EvaluateComplex(const Expr *E, APValue &Result, EvalInfo &Info) { - Result = ComplexFloatExprEvaluator(Info).Visit(const_cast(E)); - if (Result.isComplexFloat()) - assert(&Result.getComplexFloatReal().getSemantics() == - &Result.getComplexFloatImag().getSemantics() && - "Invalid complex evaluation."); - return Result.isComplexFloat(); + Result = ComplexExprEvaluator(Info).Visit(const_cast(E)); + assert((!Result.isComplexFloat() || + (&Result.getComplexFloatReal().getSemantics() == + &Result.getComplexFloatImag().getSemantics())) && + "Invalid complex evaluation."); + return Result.isComplexFloat() || Result.isComplexInt(); } -APValue ComplexFloatExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) +APValue ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { APValue Result, RHS; - if (!EvaluateComplexFloat(E->getLHS(), Result, Info)) + if (!EvaluateComplex(E->getLHS(), Result, Info)) return APValue(); - if (!EvaluateComplexFloat(E->getRHS(), RHS, Info)) + if (!EvaluateComplex(E->getRHS(), RHS, Info)) return APValue(); - + switch (E->getOpcode()) { default: return APValue(); case BinaryOperator::Add: - Result.getComplexFloatReal().add(RHS.getComplexFloatReal(), - APFloat::rmNearestTiesToEven); - Result.getComplexFloatImag().add(RHS.getComplexFloatImag(), - APFloat::rmNearestTiesToEven); + if (Result.isComplexFloat()) { + Result.getComplexFloatReal().add(RHS.getComplexFloatReal(), + APFloat::rmNearestTiesToEven); + Result.getComplexFloatImag().add(RHS.getComplexFloatImag(), + APFloat::rmNearestTiesToEven); + } else { + Result.getComplexIntReal() += RHS.getComplexIntReal(); + Result.getComplexIntImag() += RHS.getComplexIntImag(); + } case BinaryOperator::Sub: - Result.getComplexFloatReal().subtract(RHS.getComplexFloatReal(), - APFloat::rmNearestTiesToEven); - Result.getComplexFloatImag().subtract(RHS.getComplexFloatImag(), - APFloat::rmNearestTiesToEven); + if (Result.isComplexFloat()) { + Result.getComplexFloatReal().subtract(RHS.getComplexFloatReal(), + APFloat::rmNearestTiesToEven); + Result.getComplexFloatImag().subtract(RHS.getComplexFloatImag(), + APFloat::rmNearestTiesToEven); + } else { + Result.getComplexIntReal() -= RHS.getComplexIntReal(); + Result.getComplexIntImag() -= RHS.getComplexIntImag(); + } } return Result; @@ -1346,10 +1380,10 @@ bool Expr::Evaluate(EvalResult &Result, ASTContext &Ctx) const { return false; Result.Val = APValue(f); - } else if (getType()->isComplexType()) { - if (!EvaluateComplexFloat(this, Result.Val, Info)) + } else if (getType()->isAnyComplexType()) { + if (!EvaluateComplex(this, Result.Val, Info)) return false; - } else + } else return false; return true; diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp index 3b6ebb4d56f3..87868ed347a8 100644 --- a/clang/lib/CodeGen/CGExprConstant.cpp +++ b/clang/lib/CodeGen/CGExprConstant.cpp @@ -597,7 +597,9 @@ llvm::Constant *CodeGenModule::EmitConstantExpr(const Expr *E, assert(!Result.HasSideEffects && "Constant expr should not have any side effects!"); switch (Result.Val.getKind()) { - default: assert(0 && "unhandled value kind!"); + case APValue::Uninitialized: + assert(0 && "Constant expressions should be uninitialized."); + return llvm::UndefValue::get(getTypes().ConvertType(type)); case APValue::LValue: { llvm::Constant *Offset = llvm::ConstantInt::get(llvm::Type::Int64Ty, @@ -631,6 +633,14 @@ llvm::Constant *CodeGenModule::EmitConstantExpr(const Expr *E, } return C; } + case APValue::ComplexInt: { + llvm::Constant *Complex[2]; + + Complex[0] = llvm::ConstantInt::get(Result.Val.getComplexIntReal()); + Complex[1] = llvm::ConstantInt::get(Result.Val.getComplexIntImag()); + + return llvm::ConstantStruct::get(Complex, 2); + } case APValue::Float: return llvm::ConstantFP::get(Result.Val.getFloat()); case APValue::ComplexFloat: { diff --git a/clang/test/CodeGen/const-init.c b/clang/test/CodeGen/const-init.c index bded2e0a3f6f..3aabcfe60894 100644 --- a/clang/test/CodeGen/const-init.c +++ b/clang/test/CodeGen/const-init.c @@ -21,3 +21,6 @@ union s2 { }; int g0 = (int)(&(((union s2 *) 0)->f0.f0) - 0); + +_Complex int g1 = 1 + 10i; +_Complex double g2 = 1.0 + 10.0i;