aboutsummaryrefslogtreecommitdiff
path: root/lib/AST/ExprConstant.cpp
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2011-12-18 02:33:09 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2011-12-18 02:33:09 +0000
commit2116b144cf07f2574d20517187eb8863645376eb (patch)
treefeb8e4d4d5b0e3a20f6281f2a854d2dd065340a4 /lib/AST/ExprConstant.cpp
parenta1be278c4f3a234ff61f04018d26c6beecde1654 (diff)
PR11604: don't allow floating-literal-to-integer casts in ICEs if the (truncated)
floating literal value does not fit into the destination type. Such casts have undefined behavior at translation time; treating them as non-ICE matches the behavior of modern gcc versions. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@146842 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/AST/ExprConstant.cpp')
-rw-r--r--lib/AST/ExprConstant.cpp20
1 files changed, 17 insertions, 3 deletions
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index 0d32ebf1c6..88a033151a 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -5252,9 +5252,23 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
case Expr::CXXConstCastExprClass:
case Expr::ObjCBridgedCastExprClass: {
const Expr *SubExpr = cast<CastExpr>(E)->getSubExpr();
- if (isa<ExplicitCastExpr>(E) &&
- isa<FloatingLiteral>(SubExpr->IgnoreParenImpCasts()))
- return NoDiag();
+ if (isa<ExplicitCastExpr>(E)) {
+ if (const FloatingLiteral *FL
+ = dyn_cast<FloatingLiteral>(SubExpr->IgnoreParenImpCasts())) {
+ unsigned DestWidth = Ctx.getIntWidth(E->getType());
+ bool DestSigned = E->getType()->isSignedIntegerOrEnumerationType();
+ APSInt IgnoredVal(DestWidth, !DestSigned);
+ bool Ignored;
+ // If the value does not fit in the destination type, the behavior is
+ // undefined, so we are not required to treat it as a constant
+ // expression.
+ if (FL->getValue().convertToInteger(IgnoredVal,
+ llvm::APFloat::rmTowardZero,
+ &Ignored) & APFloat::opInvalidOp)
+ return ICEDiag(2, E->getLocStart());
+ return NoDiag();
+ }
+ }
switch (cast<CastExpr>(E)->getCastKind()) {
case CK_LValueToRValue:
case CK_NoOp: