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.

llvm-svn: 146842
This commit is contained in:
Richard Smith 2011-12-18 02:33:09 +00:00
parent 05f10357a9
commit 0b973d091a
2 changed files with 23 additions and 3 deletions

View File

@ -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:

View File

@ -102,3 +102,9 @@ namespace IntOrEnum {
template<int n> struct S {};
S<p> 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}}
}