From: Richard Smith Date: Sun, 18 Dec 2011 02:33:09 +0000 (+0000) Subject: PR11604: don't allow floating-literal-to-integer casts in ICEs if the (truncated) X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2116b144cf07f2574d20517187eb8863645376eb;p=clang 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 --- 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(E)->getSubExpr(); - if (isa(E) && - isa(SubExpr->IgnoreParenImpCasts())) - return NoDiag(); + if (isa(E)) { + if (const FloatingLiteral *FL + = dyn_cast(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(E)->getCastKind()) { case CK_LValueToRValue: case CK_NoOp: diff --git a/test/SemaCXX/constant-expression.cpp b/test/SemaCXX/constant-expression.cpp index 2d2f1aee2b..0367cc5546 100644 --- a/test/SemaCXX/constant-expression.cpp +++ b/test/SemaCXX/constant-expression.cpp @@ -102,3 +102,9 @@ namespace IntOrEnum { template struct S {}; S

s; // expected-error {{not an integral constant expression}} } + +namespace FloatConvert { + typedef int a[(int)42.3]; + typedef int a[(int)42.997]; + typedef int b[(int)4e10]; // expected-error {{variable length}} +}