Fix handling of overflow in C casts in integer constant expressions (PR c/93241).
authorJoseph Myers <joseph@codesourcery.com>
Mon, 13 Jan 2020 16:39:04 +0000 (16:39 +0000)
committerJoseph Myers <joseph@codesourcery.com>
Mon, 13 Jan 2020 16:39:04 +0000 (16:39 +0000)
Bug 93241 reports a case where certain C expressions involving casts,
that would not be valid in an evaluated part of an integer constant
expression (because of e.g. involving integer overflow), are wrongly
rejected in an unevaluated part of an integer constant expression even
though all the operands and operations are ones that are valid in that
context.  This is a rejects-valid regression in GCC 4.5 and later
relative to 4.4 (for some testcases; the one in the bug uses
_Static_assert which isn't supported in those older releases).

The rule in the C front end is that an expression with those
properties (valid in an unevaluated part of an integer constant
expression but not an evaluated part) must be represented either as an
INTEGER_CST with TREE_OVERFLOW set or as a C_MAYBE_CONST_EXPR with
C_MAYBE_CONST_EXPR_INT_OPERANDS set.  This patch fixes build_c_cast to
check for that case and call note_integer_operands as needed.

Bootstrapped with no regressions for x86_64-pc-linux-gnu.

PR c/93241
gcc/c:
* c-typeck.c (build_c_cast): Check for expressions with integer
operands that can occur in an unevaluated part of an integer
constant expression and call note_integer_operands as needed.

gcc/testsuite:
* gcc.dg/c11-static-assert-10.c, gcc.dg/c99-const-expr-15.c: New
tests.

gcc/c/ChangeLog
gcc/c/c-typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/c11-static-assert-10.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/c99-const-expr-15.c [new file with mode: 0644]

index d0b6559437675f0dc88d059aefe4388bed62d5c8..b8e807e11a9aa080cea8b2c6193bd0e10afc7108 100644 (file)
@@ -1,3 +1,10 @@
+2020-01-13  Joseph Myers  <joseph@codesourcery.com>
+
+       PR c/93241
+       * c-typeck.c (build_c_cast): Check for expressions with integer
+       operands that can occur in an unevaluated part of an integer
+       constant expression and call note_integer_operands as needed.
+
 2019-01-08  Richard Biener  <rguenther@suse.de>
 
        PR middle-end/93199
index c746f23b33630ce38087037b5a3436d6a6f615c6..9866c83faf22cf34eccd538133fde7cb5ef845cf 100644 (file)
@@ -5709,6 +5709,8 @@ build_c_cast (location_t loc, tree type, tree expr)
 {
   tree value;
 
+  bool int_operands = EXPR_INT_CONST_OPERANDS (expr);
+
   if (TREE_CODE (expr) == EXCESS_PRECISION_EXPR)
     expr = TREE_OPERAND (expr, 0);
 
@@ -5943,6 +5945,14 @@ build_c_cast (location_t loc, tree type, tree expr)
               || TREE_CODE (expr) == COMPLEX_CST)))
       value = build1 (NOP_EXPR, type, value);
 
+  /* If the expression has integer operands and so can occur in an
+     unevaluated part of an integer constant expression, ensure the
+     return value reflects this.  */
+  if (int_operands
+      && INTEGRAL_TYPE_P (type)
+      && !EXPR_INT_CONST_OPERANDS (value))
+    value = note_integer_operands (value);
+
   protected_set_expr_location (value, loc);
   return value;
 }
index f14638c5079a322ca4c23cf24c729f263a9f5492..976003a0739b5b7db88208348f74aabf6e5ba64f 100644 (file)
@@ -1,3 +1,9 @@
+2020-01-13  Joseph Myers  <joseph@codesourcery.com>
+
+       PR c/93241
+       * gcc.dg/c11-static-assert-10.c, gcc.dg/c99-const-expr-15.c: New
+       tests.
+
 2020-01-13  Martin Sebor  <msebor@redhat.com>
 
        PR tree-optimization/93213
diff --git a/gcc/testsuite/gcc.dg/c11-static-assert-10.c b/gcc/testsuite/gcc.dg/c11-static-assert-10.c
new file mode 100644 (file)
index 0000000..2fe210b
--- /dev/null
@@ -0,0 +1,9 @@
+/* Test for constant expressions: casts with integer overflow.  PR
+   c/93241.  */
+/* { dg-do compile } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+#include <limits.h>
+
+_Static_assert (0 ? (_Bool) (INT_MAX + 1) : 1, "");
+_Static_assert (0 ? (short) ((INT_MAX + 1) != 0) : 1, "");
diff --git a/gcc/testsuite/gcc.dg/c99-const-expr-15.c b/gcc/testsuite/gcc.dg/c99-const-expr-15.c
new file mode 100644 (file)
index 0000000..b1744b6
--- /dev/null
@@ -0,0 +1,9 @@
+/* Test for constant expressions: casts with integer overflow.  PR
+   c/93241.  */
+/* { dg-do compile } */
+/* { dg-options "-std=c99 -pedantic-errors" } */
+
+#include <limits.h>
+
+struct s { int a : (0 ? (_Bool) (INT_MAX + 1) : 1); };
+struct t { int a : (0 ? (short) ((INT_MAX + 1) != 0) : 1); };