]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
middle-end/118643 - ICE with out-of-bound decl access
authorRichard Biener <rguenther@suse.de>
Mon, 27 Jan 2025 10:28:47 +0000 (11:28 +0100)
committerRichard Biener <rguenth@gcc.gnu.org>
Mon, 27 Jan 2025 12:31:35 +0000 (13:31 +0100)
When RTL expansion of an out-of-bound access of a register falls
back to a BIT_FIELD_REF we have to ensure that's valid.  The
following avoids negative offsets by expanding through a stack
temporary.

PR middle-end/118643
* expr.cc (expand_expr_real_1): Avoid falling back to BIT_FIELD_REF
expansion for negative offset.

* gcc.dg/pr118643.c: New testcase.

gcc/expr.cc
gcc/testsuite/gcc.dg/pr118643.c [new file with mode: 0644]

index a310b2d913154efed7eb90f3c57fdbedea118a18..a06411e1c27642acc1c5f5b755c9f827c9da9109 100644 (file)
@@ -11796,13 +11796,14 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
                && known_eq (GET_MODE_BITSIZE (DECL_MODE (base)), type_size))
              return expand_expr (build1 (VIEW_CONVERT_EXPR, type, base),
                                  target, tmode, modifier);
-           if (TYPE_MODE (type) == BLKmode)
+           if (TYPE_MODE (type) == BLKmode || maybe_lt (offset, 0))
              {
                temp = assign_stack_temp (DECL_MODE (base),
                                          GET_MODE_SIZE (DECL_MODE (base)));
                store_expr (base, temp, 0, false, false);
-               temp = adjust_address (temp, BLKmode, offset);
-               set_mem_size (temp, int_size_in_bytes (type));
+               temp = adjust_address (temp, TYPE_MODE (type), offset);
+               if (TYPE_MODE (type) == BLKmode)
+                 set_mem_size (temp, int_size_in_bytes (type));
                return temp;
              }
            exp = build3 (BIT_FIELD_REF, type, base, TYPE_SIZE (type),
diff --git a/gcc/testsuite/gcc.dg/pr118643.c b/gcc/testsuite/gcc.dg/pr118643.c
new file mode 100644 (file)
index 0000000..ff2b081
--- /dev/null
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O" } */
+
+typedef __attribute__((__vector_size__(1))) unsigned char V;
+
+V x;
+void foo()
+{
+  V v = x;
+  x = *(V *)(&v - 1);
+}