From 96fc8e4086df323c49f17cac594db1d2f066a2e9 Mon Sep 17 00:00:00 2001 From: Abramo Bagnara Date: Sat, 11 Dec 2010 16:05:48 +0000 Subject: [PATCH] Improved complex constants evaluation. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@121616 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AST/ExprConstant.cpp | 102 ++++++++++++++++++++++++++++++++++++++- test/Sema/complex-int.c | 12 +++++ 2 files changed, 112 insertions(+), 2 deletions(-) diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 5e5c3a0e12..1e356f13d1 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -2091,12 +2091,13 @@ public: bool VisitCastExpr(CastExpr *E); bool VisitBinaryOperator(const BinaryOperator *E); + bool VisitUnaryOperator(const UnaryOperator *E); + bool VisitConditionalOperator(const ConditionalOperator *E); bool VisitChooseExpr(const ChooseExpr *E) { return Visit(E->getChosenSubExpr(Info.Ctx)); } bool VisitUnaryExtension(const UnaryOperator *E) { return Visit(E->getSubExpr()); } - // FIXME Missing: unary +/-/~, binary div, ImplicitValueInitExpr, - // conditional ?:, comma + // FIXME Missing: ImplicitValueInitExpr }; } // end anonymous namespace @@ -2227,6 +2228,17 @@ bool ComplexExprEvaluator::VisitCastExpr(CastExpr *E) { } bool ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { + if (E->getOpcode() == BO_Comma) { + if (!Visit(E->getRHS())) + return false; + + // If we can't evaluate the LHS, it might have side effects; + // conservatively mark it. + if (!E->getLHS()->isEvaluatable(Info.Ctx)) + Info.EvalResult.HasSideEffects = true; + + return true; + } if (!Visit(E->getLHS())) return false; @@ -2291,11 +2303,97 @@ bool ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { LHS.getComplexIntImag() * RHS.getComplexIntReal()); } break; + case BO_Div: + if (Result.isComplexFloat()) { + ComplexValue LHS = Result; + APFloat &LHS_r = LHS.getComplexFloatReal(); + APFloat &LHS_i = LHS.getComplexFloatImag(); + APFloat &RHS_r = RHS.getComplexFloatReal(); + APFloat &RHS_i = RHS.getComplexFloatImag(); + APFloat &Res_r = Result.getComplexFloatReal(); + APFloat &Res_i = Result.getComplexFloatImag(); + + APFloat Den = RHS_r; + Den.multiply(RHS_r, APFloat::rmNearestTiesToEven); + APFloat Tmp = RHS_i; + Tmp.multiply(RHS_i, APFloat::rmNearestTiesToEven); + Den.add(Tmp, APFloat::rmNearestTiesToEven); + + Res_r = LHS_r; + Res_r.multiply(RHS_r, APFloat::rmNearestTiesToEven); + Tmp = LHS_i; + Tmp.multiply(RHS_i, APFloat::rmNearestTiesToEven); + Res_r.add(Tmp, APFloat::rmNearestTiesToEven); + Res_r.divide(Den, APFloat::rmNearestTiesToEven); + + Res_i = LHS_i; + Res_i.multiply(RHS_r, APFloat::rmNearestTiesToEven); + Tmp = LHS_r; + Tmp.multiply(RHS_i, APFloat::rmNearestTiesToEven); + Res_i.subtract(Tmp, APFloat::rmNearestTiesToEven); + Res_i.divide(Den, APFloat::rmNearestTiesToEven); + } else { + if (RHS.getComplexIntReal() == 0 && RHS.getComplexIntImag() == 0) { + // FIXME: what about diagnostics? + return false; + } + ComplexValue LHS = Result; + APSInt Den = RHS.getComplexIntReal() * RHS.getComplexIntReal() + + RHS.getComplexIntImag() * RHS.getComplexIntImag(); + Result.getComplexIntReal() = + (LHS.getComplexIntReal() * RHS.getComplexIntReal() + + LHS.getComplexIntImag() * RHS.getComplexIntImag()) / Den; + Result.getComplexIntImag() = + (LHS.getComplexIntImag() * RHS.getComplexIntReal() - + LHS.getComplexIntReal() * RHS.getComplexIntImag()) / Den; + } + break; } return true; } +bool ComplexExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) { + // Get the operand value into 'Result'. + if (!Visit(E->getSubExpr())) + return false; + + switch (E->getOpcode()) { + default: + // FIXME: what about diagnostics? + return false; + case UO_Extension: + return true; + case UO_Plus: + // The result is always just the subexpr. + return true; + case UO_Minus: + if (Result.isComplexFloat()) { + Result.getComplexFloatReal().changeSign(); + Result.getComplexFloatImag().changeSign(); + } + else { + Result.getComplexIntReal() = -Result.getComplexIntReal(); + Result.getComplexIntImag() = -Result.getComplexIntImag(); + } + return true; + case UO_Not: + if (Result.isComplexFloat()) + Result.getComplexFloatImag().changeSign(); + else + Result.getComplexIntImag() = -Result.getComplexIntImag(); + return true; + } +} + +bool ComplexExprEvaluator::VisitConditionalOperator(const ConditionalOperator *E) { + bool Cond; + if (!HandleConversionToBool(E->getCond(), Cond, Info)) + return false; + + return Visit(Cond ? E->getTrueExpr() : E->getFalseExpr()); +} + //===----------------------------------------------------------------------===// // Top level Expr::Evaluate method. //===----------------------------------------------------------------------===// diff --git a/test/Sema/complex-int.c b/test/Sema/complex-int.c index cb76a342c2..32249b35e1 100644 --- a/test/Sema/complex-int.c +++ b/test/Sema/complex-int.c @@ -53,3 +53,15 @@ void test4(_Complex float *x) { void test5(_Complex int *x) { (*x)++; } + +int i1[(2+3i)*(5+7i) == 29i-11 ? 1 : -1]; +int i2[(29i-11)/(5+7i) == 2+3i ? 1 : -1]; +int i3[-(2+3i) == +(-3i-2) ? 1 : -1]; +int i4[~(2+3i) == 2-3i ? 1 : -1]; +int i5[(3i == -(-3i) ? ((void)3, 1i - 1) : 0) == 1i - 1 ? 1 : -1]; + +int f1[(2.0+3.0i)*(5.0+7.0i) == 29.0i-11.0 ? 1 : -1]; +int f2[(29.0i-11.0)/(5.0+7.0i) == 2.0+3.0i ? 1 : -1]; +int f3[-(2.0+3.0i) == +(-3.0i-2.0) ? 1 : -1]; +int f4[~(2.0+3.0i) == 2.0-3.0i ? 1 : -1]; +int f5[(3.0i == -(-3.0i) ? ((void)3.0, __extension__ (1.0i - 1.0)) : 0) == 1.0i - 1.0 ? 1 : -1]; -- 2.40.0