There is only one last_field for a structure type, but there might
be multiple last_fields for a union type, therefore we should ORed
the result of TYPE_INCLUDES_FLEXARRAY for multiple last_fields of
a union type.

The patch has been bootstrapped and regression tested on both x86 and aarch64.
Okay for trunk and also GCC14?

thanks.

Qing

        PR c/120354

gcc/c/ChangeLog:

        * c-decl.cc (finish_struct): Or the results for TYPE_INCLUDES_FLEXARRAY.

gcc/testsuite/ChangeLog:

        * gcc.dg/pr120354.c: New test.
---
 gcc/c/c-decl.cc                 |  9 ++++++---
 gcc/testsuite/gcc.dg/pr120354.c | 33 +++++++++++++++++++++++++++++++++
 2 files changed, 39 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/pr120354.c

diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index 4733287eaf8..2b72b782fc5 100644
--- a/gcc/c/c-decl.cc
+++ b/gcc/c/c-decl.cc
@@ -9647,15 +9647,18 @@ finish_struct (location_t loc, tree t, tree fieldlist, 
tree attributes,
       DECL_NOT_FLEXARRAY (x) = !is_flexible_array_member_p (is_last_field, x);
 
       /* Set TYPE_INCLUDES_FLEXARRAY for the context of x, t.
-        when x is an array and is the last field.  */
+        when x is an array and is the last field.
+        There is only one last_field for a structure type, but there might
+        be multiple last_fields for a union type, therefore we should ORed
+        the result for multiple last_fields.  */
       if (TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE)
        TYPE_INCLUDES_FLEXARRAY (t)
-         = is_last_field && c_flexible_array_member_type_p (TREE_TYPE (x));
+         |= is_last_field && c_flexible_array_member_type_p (TREE_TYPE (x));
       /* Recursively set TYPE_INCLUDES_FLEXARRAY for the context of x, t
         when x is an union or record and is the last field.  */
       else if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (x)))
        TYPE_INCLUDES_FLEXARRAY (t)
-         = is_last_field && TYPE_INCLUDES_FLEXARRAY (TREE_TYPE (x));
+         |= is_last_field && TYPE_INCLUDES_FLEXARRAY (TREE_TYPE (x));
 
       if (warn_flex_array_member_not_at_end
          && !is_last_field
diff --git a/gcc/testsuite/gcc.dg/pr120354.c b/gcc/testsuite/gcc.dg/pr120354.c
new file mode 100644
index 00000000000..6749737a173
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr120354.c
@@ -0,0 +1,33 @@
+/* PR120354: Test for -Wflex-array-member-not-at-end on union with 
+   flexible array members.  */ 
+/* { dg-do compile } */
+/* { dg-options "-Wflex-array-member-not-at-end" } */
+
+struct P {};
+union L {};
+
+union X {
+    int x[];
+    struct P y;
+};
+
+struct T {
+    union X x; /* { dg-warning "structure containing a flexible array member 
is not at the end of another structure" } */
+    int plug;
+};
+
+struct Q {
+    int len;
+    int data[];
+};
+
+union Y {
+    struct Q q;
+    union L y;
+};
+
+struct S {
+    union Y y;  /* { dg-warning "structure containing a flexible array member 
is not at the end of another structure" } */
+    int plug;
+};
+
-- 
2.43.5

Reply via email to