https://gcc.gnu.org/g:9077e2067bc8667084745c7746b48d0e3e49b063

commit r16-7030-g9077e2067bc8667084745c7746b48d0e3e49b063
Author: Roger Sayle <[email protected]>
Date:   Sun Jan 25 21:06:39 2026 +0000

    PR middle-end/122348: ICE in store_constructor from flexible array member
    
    This patch resolves PR middle-end/122348, an ICE caused by passing a
    initialized structure containing a flexible array member by value.
    The semantics in C99 (and since gcc 4.4) are that the zero sized array
    at the end of the structure is ignored when passing by value.  Hence
    for the structure in the PR:
    
    struct S {
        int a;
        int b[];
    } s = { 0, { 42 } };
    
    when passed by value, sizeof(s) is considered to be 4 bytes, and on
    x86_64 passed in the 32-bit %edi register.  Unfortunately, the code
    in store_constructor isn't expecting initialized fields where the
    type's DECL_SIZE is NULL, which leads to the ICE.  Fixed by explicitly
    ignoring fields where DECL_SIZE is NULL_TREE.  On x86_64, passing "s"
    now compiles to just:
    
    f:      xorl    %edi, %edi
            jmp     foo
    
    2026-01-25  Roger Sayle  <[email protected]>
    
    gcc/ChangeLog
            PR middle-end/122348
            * expr.cc (store_constructor): Ignore fields where DECL_SIZE
            is NULL_TREE, i.e. flexible array members.
    
    gcc/testsuite/ChangeLog
            PR middle-end/122348
            * g++.dg/pr122348.C: New C++ testcase.
            * gcc.dg/pr122348.c: New C testcase.

Diff:
---
 gcc/expr.cc                     |  9 +++++++--
 gcc/testsuite/g++.dg/pr122348.C | 13 +++++++++++++
 gcc/testsuite/gcc.dg/pr122348.c | 13 +++++++++++++
 3 files changed, 33 insertions(+), 2 deletions(-)

diff --git a/gcc/expr.cc b/gcc/expr.cc
index 70b4eda6df37..b6d593d09a2d 100644
--- a/gcc/expr.cc
+++ b/gcc/expr.cc
@@ -7579,8 +7579,13 @@ store_constructor (tree exp, rtx target, int cleared, 
poly_int64 size,
            if (cleared && initializer_zerop (value))
              continue;
 
-           if (tree_fits_uhwi_p (DECL_SIZE (field)))
-             bitsize = tree_to_uhwi (DECL_SIZE (field));
+           /* Variable sized arrays are ignored.  */
+           tree decl_size = DECL_SIZE (field);
+           if (!decl_size)
+             continue;
+
+           if (tree_fits_uhwi_p (decl_size))
+             bitsize = tree_to_uhwi (decl_size);
            else
              gcc_unreachable ();
 
diff --git a/gcc/testsuite/g++.dg/pr122348.C b/gcc/testsuite/g++.dg/pr122348.C
new file mode 100644
index 000000000000..4494ef4030d3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr122348.C
@@ -0,0 +1,13 @@
+/* middle-end/122348 */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+struct S {
+    int a;
+    int b[];
+};
+const struct S s = { 0, { 42 } };
+void foo(struct S arg);
+void f(void) {
+    foo(s);
+}
diff --git a/gcc/testsuite/gcc.dg/pr122348.c b/gcc/testsuite/gcc.dg/pr122348.c
new file mode 100644
index 000000000000..4494ef4030d3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr122348.c
@@ -0,0 +1,13 @@
+/* middle-end/122348 */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+struct S {
+    int a;
+    int b[];
+};
+const struct S s = { 0, { 42 } };
+void foo(struct S arg);
+void f(void) {
+    foo(s);
+}

Reply via email to