forked from OSchip/llvm-project
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:
parent
05f10357a9
commit
0b973d091a
|
@ -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:
|
||||
|
|
|
@ -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}}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue