From 322abe35731e55e290185392d8c2c14dbc3e3be3 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Sat, 22 Sep 2007 19:04:13 +0000 Subject: [PATCH] Use the APFloat routines to evaluate FP immediates as integer constant expressions. The only questionable thing is that we now reject: void foo() { switch (1) { case (int)1.0e10000: ; } } with: t.c:5:13: error: case label does not reduce to an integer constant case (int)1.0e10000: ~~~~~^~~~~~~~~ GCC accepts this, emitting the pedwarn: t.c:5: warning: floating constant exceeds range of 'double' llvm-svn: 42238 --- clang/AST/Expr.cpp | 37 ++++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/clang/AST/Expr.cpp b/clang/AST/Expr.cpp index 01c563bdc2c8..98963de63378 100644 --- a/clang/AST/Expr.cpp +++ b/clang/AST/Expr.cpp @@ -715,16 +715,16 @@ bool Expr::isIntegerConstantExpr(llvm::APSInt &Result, ASTContext &Ctx, if (Loc) *Loc = SubExpr->getLocStart(); return false; } - + + uint32_t DestWidth = + static_cast(Ctx.getTypeSize(getType(), CastLoc)); + // Handle simple integer->integer casts. if (SubExpr->getType()->isIntegerType()) { if (!SubExpr->isIntegerConstantExpr(Result, Ctx, Loc, isEvaluated)) return false; // Figure out if this is a truncate, extend or noop cast. - unsigned DestWidth = - static_cast(Ctx.getTypeSize(getType(), CastLoc)); - // If the input is signed, do a sign extend, noop, or truncate. if (SubExpr->getType()->isSignedIntegerType()) Result.sextOrTrunc(DestWidth); @@ -738,14 +738,29 @@ bool Expr::isIntegerConstantExpr(llvm::APSInt &Result, ASTContext &Ctx, const Expr *Operand = SubExpr; while (const ParenExpr *PE = dyn_cast(Operand)) Operand = PE->getSubExpr(); - - if (const FloatingLiteral *FL = dyn_cast(Operand)) { - // FIXME: Evaluate this correctly! - Result = (int)FL->getValueAsDouble(); - break; + + // If this isn't a floating literal, we can't handle it. + const FloatingLiteral *FL = dyn_cast(Operand); + if (!FL) { + if (Loc) *Loc = Operand->getLocStart(); + return false; } - if (Loc) *Loc = Operand->getLocStart(); - return false; + + // Determine whether we are converting to unsigned or signed. + bool DestSigned = getType()->isSignedIntegerType(); + + uint64_t Space[4]; + + llvm::APFloat::opStatus Status = + FL->getValue().convertToInteger(Space, DestWidth, DestSigned, + llvm::APFloat::rmNearestTiesToEven); + if (Status != llvm::APFloat::opOK && Status != llvm::APFloat::opInexact) { + if (Loc) *Loc = Operand->getLocStart(); + return false; // FIXME: need to accept this as an extension. + } + + Result = llvm::APInt(DestWidth, 4, Space); + break; } case ConditionalOperatorClass: { const ConditionalOperator *Exp = cast(this);