[cfe-commits] r55155 - /cfe/trunk/lib/AST/ExprConstant.cpp
Daniel Dunbar
daniel at zuster.org
Fri Aug 22 11:04:33 PDT 2008
One comment here. It would be nice to keep a more coordinated record
that there are dangling issues here. If we explicitly know there are cases
we don't handle perhaps it is worth adding an XFAIL test case?
Of course... that does require supporting XFAIL test cases. :)
- Daniel
----- Original Message ----
From: Eli Friedman <eli.friedman at gmail.com>
To: cfe-commits at cs.uiuc.edu
Sent: Thursday, August 21, 2008 5:06:13 PM
Subject: [cfe-commits] r55155 - /cfe/trunk/lib/AST/ExprConstant.cpp
Author: efriedma
Date: Thu Aug 21 19:06:13 2008
New Revision: 55155
URL: http://llvm.org/viewvc/llvm-project?rev=55155&view=rev
Log:
Initial implementation of floats in Expr::tryEvaluate; this doesn't
implement some things, like unary operators and casts, but it's enough
to fix PR2703 as filed.
Modified:
cfe/trunk/lib/AST/ExprConstant.cpp
Modified: cfe/trunk/lib/AST/ExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=55155&r1=55154&r2=55155&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprConstant.cpp (original)
+++ cfe/trunk/lib/AST/ExprConstant.cpp Thu Aug 21 19:06:13 2008
@@ -19,6 +19,7 @@
#include "llvm/Support/Compiler.h"
using namespace clang;
using llvm::APSInt;
+using llvm::APFloat;
/// EvalInfo - This is a private struct used by the evaluator to capture
/// information about a subexpression as it is folded. It retains information
@@ -63,7 +64,7 @@
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);
//===----------------------------------------------------------------------===//
// Pointer Evaluation
@@ -477,23 +478,13 @@
if (!SubExpr->getType()->isRealFloatingType())
return Error(CastLoc, diag::err_expr_not_constant);
- // FIXME: Generalize floating point constant folding! For now we just permit
- // which is allowed by integer constant expressions.
-
- // Allow floating constants that are the immediate operands of casts or that
- // are parenthesized.
- const Expr *Operand = SubExpr;
- while (const ParenExpr *PE = dyn_cast<ParenExpr>(Operand))
- Operand = PE->getSubExpr();
-
- // If this isn't a floating literal, we can't handle it.
- const FloatingLiteral *FL = dyn_cast<FloatingLiteral>(Operand);
- if (!FL)
+ APFloat F(0.0);
+ if (!EvaluateFloat(SubExpr, F, Info))
return Error(CastLoc, diag::err_expr_not_constant);
-
+
// If the destination is boolean, compare against zero.
if (DestType->isBooleanType()) {
- Result = !FL->getValue().isZero();
+ Result = !F.isZero();
Result.zextOrTrunc(DestWidth);
Result.setIsUnsigned(DestType->isUnsignedIntegerType());
return true;
@@ -504,28 +495,98 @@
// FIXME: Warning for overflow.
uint64_t Space[4];
- (void)FL->getValue().convertToInteger(Space, DestWidth, DestSigned,
- llvm::APFloat::rmTowardZero);
+ (void)F.convertToInteger(Space, DestWidth, DestSigned,
+ llvm::APFloat::rmTowardZero);
Result = llvm::APInt(DestWidth, 4, Space);
Result.setIsUnsigned(!DestSigned);
return true;
}
//===----------------------------------------------------------------------===//
+// Float Evaluation
+//===----------------------------------------------------------------------===//
+
+namespace {
+class VISIBILITY_HIDDEN FloatExprEvaluator
+ : public StmtVisitor<FloatExprEvaluator, bool> {
+ EvalInfo &Info;
+ APFloat &Result;
+public:
+ FloatExprEvaluator(EvalInfo &info, APFloat &result)
+ : Info(info), Result(result) {}
+
+ bool VisitStmt(Stmt *S) {
+ return false;
+ }
+
+ bool VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); }
+
+ bool VisitBinaryOperator(const BinaryOperator *E);
+ bool VisitFloatingLiteral(const FloatingLiteral *E);
+};
+} // end anonymous namespace
+
+static bool EvaluateFloat(const Expr* E, APFloat& Result, EvalInfo &Info) {
+ return FloatExprEvaluator(Info, Result).Visit(const_cast<Expr*>(E));
+}
+
+bool FloatExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
+ // FIXME: Diagnostics? I really don't understand how the warnings
+ // and errors are supposed to work.
+ APFloat LHS(0.0), RHS(0.0);
+ if (!EvaluateFloat(E->getLHS(), Result, Info))
+ return false;
+ if (!EvaluateFloat(E->getRHS(), RHS, Info))
+ return false;
+
+ switch (E->getOpcode()) {
+ default: return false;
+ case BinaryOperator::Mul:
+ Result.multiply(RHS, APFloat::rmNearestTiesToEven);
+ return true;
+ case BinaryOperator::Add:
+ Result.add(RHS, APFloat::rmNearestTiesToEven);
+ return true;
+ case BinaryOperator::Sub:
+ Result.subtract(RHS, APFloat::rmNearestTiesToEven);
+ return true;
+ case BinaryOperator::Div:
+ Result.divide(RHS, APFloat::rmNearestTiesToEven);
+ return true;
+ case BinaryOperator::Rem:
+ Result.mod(RHS, APFloat::rmNearestTiesToEven);
+ return true;
+ }
+}
+
+bool FloatExprEvaluator::VisitFloatingLiteral(const FloatingLiteral *E) {
+ Result = E->getValue();
+ return true;
+}
+
+//===----------------------------------------------------------------------===//
// Top level TryEvaluate.
//===----------------------------------------------------------------------===//
bool Expr::tryEvaluate(APValue &Result, ASTContext &Ctx) const {
- llvm::APSInt sInt(32);
-
EvalInfo Info(Ctx);
if (getType()->isIntegerType()) {
+ llvm::APSInt sInt(32);
if (EvaluateInteger(this, sInt, Info)) {
Result = APValue(sInt);
return true;
}
- } else
- return false;
+ } else if (getType()->isPointerType()) {
+ if (EvaluatePointer(this, Result, Info)) {
+ return true;
+ }
+ } else if (getType()->isRealFloatingType()) {
+ llvm::APFloat f(0.0);
+ if (EvaluateFloat(this, f, Info)) {
+ Result = APValue(f);
+ return true;
+ }
+ }
return false;
}
_______________________________________________
cfe-commits mailing list
cfe-commits at cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
More information about the cfe-commits
mailing list