https://gcc.gnu.org/g:52366356fe7b638f66c4011b8a61fb6c22b08087

commit r15-7226-g52366356fe7b638f66c4011b8a61fb6c22b08087
Author: Richard Biener <rguent...@suse.de>
Date:   Mon Jan 27 11:28:47 2025 +0100

    middle-end/118643 - ICE with out-of-bound decl access
    
    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.

Diff:
---
 gcc/expr.cc                     |  7 ++++---
 gcc/testsuite/gcc.dg/pr118643.c | 11 +++++++++++
 2 files changed, 15 insertions(+), 3 deletions(-)

diff --git a/gcc/expr.cc b/gcc/expr.cc
index a310b2d91315..a06411e1c276 100644
--- a/gcc/expr.cc
+++ b/gcc/expr.cc
@@ -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
index 000000000000..ff2b081ae0b4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr118643.c
@@ -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);
+}

Reply via email to