aboutsummaryrefslogtreecommitdiff
path: root/gcc/testsuite/gcc.c-torture
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2024-06-04 12:28:01 +0200
committerJakub Jelinek <jakub@redhat.com>2024-06-04 12:28:01 +0200
commitb8e28381cb5c0cddfe5201faf799d8b27f5d7d6c (patch)
tree1290f91dd0807f18d187dcc78d2a657b694888b6 /gcc/testsuite/gcc.c-torture
parent09b4ab53155ea16e1fb12c2afcd9b6fe29a31c74 (diff)
downloadgcc-b8e28381cb5c0cddfe5201faf799d8b27f5d7d6c.zip
gcc-b8e28381cb5c0cddfe5201faf799d8b27f5d7d6c.tar.gz
gcc-b8e28381cb5c0cddfe5201faf799d8b27f5d7d6c.tar.bz2
builtins: Force SAVE_EXPR for __builtin_{add,sub,mul}_overflow and __builtin{add,sub}c [PR108789]
The following testcase is miscompiled, because we use save_expr on the .{ADD,SUB,MUL}_OVERFLOW call we are creating, but if the first two operands are not INTEGER_CSTs (in that case we just fold it right away) but are TREE_READONLY/!TREE_SIDE_EFFECTS, save_expr doesn't actually create a SAVE_EXPR at all and so we lower it to *arg2 = REALPART_EXPR (.ADD_OVERFLOW (arg0, arg1)), \ IMAGPART_EXPR (.ADD_OVERFLOW (arg0, arg1)) which evaluates the ifn twice and just hope it will be CSEd back. As *arg2 aliases *arg0, that is not the case. The builtins are really never const/pure as they store into what the third arguments points to, so after handling the INTEGER_CST+INTEGER_CST case, I think we should just always use SAVE_EXPR. Just building SAVE_EXPR by hand and setting TREE_SIDE_EFFECTS on it doesn't work, because c_fully_fold optimizes it away again, so the following patch marks the ifn calls as TREE_SIDE_EFFECTS (but doesn't do it for the __builtin_{add,sub,mul}_overflow_p case which were designed for use especially in constant expressions and don't really evaluate the realpart side, so we don't really need a SAVE_EXPR in that case). 2024-06-04 Jakub Jelinek <jakub@redhat.com> PR middle-end/108789 * builtins.cc (fold_builtin_arith_overflow): For ovf_only, don't call save_expr and don't build REALPART_EXPR, otherwise set TREE_SIDE_EFFECTS on call before calling save_expr. (fold_builtin_addc_subc): Set TREE_SIDE_EFFECTS on call before calling save_expr. * gcc.c-torture/execute/pr108789.c: New test.
Diffstat (limited to 'gcc/testsuite/gcc.c-torture')
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr108789.c39
1 files changed, 39 insertions, 0 deletions
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr108789.c b/gcc/testsuite/gcc.c-torture/execute/pr108789.c
new file mode 100644
index 0000000..32ee19b
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr108789.c
@@ -0,0 +1,39 @@
+/* PR middle-end/108789 */
+
+int
+add (unsigned *r, const unsigned *a, const unsigned *b)
+{
+ return __builtin_add_overflow (*a, *b, r);
+}
+
+int
+mul (unsigned *r, const unsigned *a, const unsigned *b)
+{
+ return __builtin_mul_overflow (*a, *b, r);
+}
+
+int
+main ()
+{
+ unsigned x;
+
+ /* 1073741824U + 1073741824U should not overflow. */
+ x = (__INT_MAX__ + 1U) / 2;
+ if (add (&x, &x, &x))
+ __builtin_abort ();
+
+ /* 256U * 256U should not overflow */
+ x = 1U << (sizeof (int) * __CHAR_BIT__ / 4);
+ if (mul (&x, &x, &x))
+ __builtin_abort ();
+
+ /* 2147483648U + 2147483648U should overflow */
+ x = __INT_MAX__ + 1U;
+ if (!add (&x, &x, &x))
+ __builtin_abort ();
+
+ /* 65536U * 65536U should overflow */
+ x = 1U << (sizeof (int) * __CHAR_BIT__ / 2);
+ if (!mul (&x, &x, &x))
+ __builtin_abort ();
+}