diff options
author | John McCall <rjmccall@apple.com> | 2010-02-28 13:00:19 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2010-02-28 13:00:19 +0000 |
commit | 162914910367140f2ab2576508a43717b8df9d1c (patch) | |
tree | 8cc79f253841766e9246aa0280bd05a8ba30ba3a /clang/lib/AST/ExprConstant.cpp | |
parent | c12b133d00f9797c19fe8a9e2c8aadda3353e2fd (diff) | |
download | bcm5719-llvm-162914910367140f2ab2576508a43717b8df9d1c.tar.gz bcm5719-llvm-162914910367140f2ab2576508a43717b8df9d1c.zip |
Support constant-evaluation of __builtin_nans* as well as the correct constant
evaluation of __builtin_nan*. Most of the work to make this work is in LLVM.
Fixes <rdar://problem/7696712> and part of PR 5255.
llvm-svn: 97383
Diffstat (limited to 'clang/lib/AST/ExprConstant.cpp')
-rw-r--r-- | clang/lib/AST/ExprConstant.cpp | 46 |
1 files changed, 33 insertions, 13 deletions
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 1a44cd02d9c..e03669246e8 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -1560,6 +1560,31 @@ static bool EvaluateFloat(const Expr* E, APFloat& Result, EvalInfo &Info) { return FloatExprEvaluator(Info, Result).Visit(const_cast<Expr*>(E)); } +static bool TryEvaluateBuiltinNaN(ASTContext &Context, + QualType ResultTy, + const Expr *Arg, + bool SNaN, + llvm::APFloat &Result) { + const StringLiteral *S = dyn_cast<StringLiteral>(Arg->IgnoreParenCasts()); + if (!S) return false; + + const llvm::fltSemantics &Sem = Context.getFloatTypeSemantics(ResultTy); + + llvm::APInt fill; + + // Treat empty strings as if they were zero. + if (S->getString().empty()) + fill = llvm::APInt(32, 0); + else if (S->getString().getAsInteger(0, fill)) + return false; + + if (SNaN) + Result = llvm::APFloat::getSNaN(Sem, false, &fill); + else + Result = llvm::APFloat::getQNaN(Sem, false, &fill); + return true; +} + bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) { switch (E->isBuiltinCall(Info.Ctx)) { default: return false; @@ -1575,24 +1600,19 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) { return true; } + case Builtin::BI__builtin_nans: + case Builtin::BI__builtin_nansf: + case Builtin::BI__builtin_nansl: + return TryEvaluateBuiltinNaN(Info.Ctx, E->getType(), E->getArg(0), + true, Result); + case Builtin::BI__builtin_nan: case Builtin::BI__builtin_nanf: case Builtin::BI__builtin_nanl: // If this is __builtin_nan() turn this into a nan, otherwise we // can't constant fold it. - if (const StringLiteral *S = - dyn_cast<StringLiteral>(E->getArg(0)->IgnoreParenCasts())) { - if (!S->isWide()) { - const llvm::fltSemantics &Sem = - Info.Ctx.getFloatTypeSemantics(E->getType()); - unsigned Type = 0; - if (!S->getString().empty() && S->getString().getAsInteger(0, Type)) - return false; - Result = llvm::APFloat::getNaN(Sem, false, Type); - return true; - } - } - return false; + return TryEvaluateBuiltinNaN(Info.Ctx, E->getType(), E->getArg(0), + false, Result); case Builtin::BI__builtin_fabs: case Builtin::BI__builtin_fabsf: |