]> granicus.if.org Git - clang/commitdiff
PR11604: don't allow floating-literal-to-integer casts in ICEs if the (truncated)
authorRichard Smith <richard-llvm@metafoo.co.uk>
Sun, 18 Dec 2011 02:33:09 +0000 (02:33 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Sun, 18 Dec 2011 02:33:09 +0000 (02:33 +0000)
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

lib/AST/ExprConstant.cpp
test/SemaCXX/constant-expression.cpp

index 0d32ebf1c67718074652676500b5d19f45e54c71..88a033151a85c0d3454b78beca037dbd1dfdb181 100644 (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:
index 2d2f1aee2b46163084c45973ada77f875bd2cb59..0367cc554687a5b0d6a16fa201b0bd6bc4d2c591 100644 (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}}
+}