From: Chris Lattner Date: Sat, 22 Sep 2007 19:04:13 +0000 (+0000) Subject: Use the APFloat routines to evaluate FP immediates as X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=987b15db39745cd7fb2e634ba1a4b85469ac9131;p=clang 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' git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@42238 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/AST/Expr.cpp b/AST/Expr.cpp index 01c563bdc2..98963de633 100644 --- a/AST/Expr.cpp +++ b/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 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 (const FloatingLiteral *FL = dyn_cast(Operand)) { - // FIXME: Evaluate this correctly! - Result = (int)FL->getValueAsDouble(); - break; + // 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. } - if (Loc) *Loc = Operand->getLocStart(); - return false; + + Result = llvm::APInt(DestWidth, 4, Space); + break; } case ConditionalOperatorClass: { const ConditionalOperator *Exp = cast(this);