]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
PR middle-end/122348: ICE in store_constructor from flexible array member
authorRoger Sayle <roger@nextmovesoftware.com>
Sun, 25 Jan 2026 21:06:39 +0000 (21:06 +0000)
committerRoger Sayle <roger@nextmovesoftware.com>
Sun, 25 Jan 2026 21:11:01 +0000 (21:11 +0000)
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  <roger@nextmovesoftware.com>

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.

gcc/expr.cc
gcc/testsuite/g++.dg/pr122348.C [new file with mode: 0644]
gcc/testsuite/gcc.dg/pr122348.c [new file with mode: 0644]

index 70b4eda6df37573eac1d21d5d1b22772458729c1..b6d593d09a2d1daa991f1fb6a621eff1a848c22b 100644 (file)
@@ -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 (file)
index 0000000..4494ef4
--- /dev/null
@@ -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 (file)
index 0000000..4494ef4
--- /dev/null
@@ -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);
+}