aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorQing Zhao <qing.zhao@oracle.com>2024-05-06 16:28:01 +0000
committerQing Zhao <qing.zhao@oracle.com>2024-05-06 18:35:09 +0000
commit6634a409124a884ff66b3756568a7daae7d3c295 (patch)
treeee2176800591f6bd6078c3754f2fe8486ee5f2e6 /gcc
parent93f6a47583f3fa8a1b66856ecb19ec28f26b2ba4 (diff)
downloadgcc-6634a409124a884ff66b3756568a7daae7d3c295.zip
gcc-6634a409124a884ff66b3756568a7daae7d3c295.tar.gz
gcc-6634a409124a884ff66b3756568a7daae7d3c295.tar.bz2
Update the C FE routine "add_flexible_array_elts_to_size" C++ FE routine "layout_var_decl" to handle the cases when the DECL is union.
PR c/53548 Add testing cases to test the _bos for flexible array members in unions or alone in structures. gcc/c/ChangeLog: PR c/53548 * c-decl.cc (add_flexible_array_elts_to_size): Handle the cases when the DECL is union. gcc/cp/ChangeLog: PR c/53548 * decl.cc (layout_var_decl): Handle the cases when the DECL is union with a flexible array member initializer. gcc/testsuite/ChangeLog: PR c/53548 * c-c++-common/fam-in-union-alone-in-struct-bos-1.c: New test. * c-c++-common/fam-in-union-alone-in-struct-bos.c: New test.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/c/c-decl.cc29
-rw-r--r--gcc/cp/decl.cc32
-rw-r--r--gcc/testsuite/c-c++-common/fam-in-union-alone-in-struct-bos-1.c66
-rw-r--r--gcc/testsuite/c-c++-common/fam-in-union-alone-in-struct-bos.c45
4 files changed, 159 insertions, 13 deletions
diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index 9ef2ab2..b691b91 100644
--- a/gcc/c/c-decl.cc
+++ b/gcc/c/c-decl.cc
@@ -5339,8 +5339,9 @@ zero_length_array_type_p (const_tree type)
}
/* INIT is a constructor that forms DECL's initializer. If the final
- element initializes a flexible array field, add the size of that
- initializer to DECL's size. */
+ element initializes a flexible array field, adjust the size of the
+ DECL with the initializer based on whether the DECL is a union or
+ a structure. */
static void
add_flexible_array_elts_to_size (tree decl, tree init)
@@ -5355,10 +5356,26 @@ add_flexible_array_elts_to_size (tree decl, tree init)
if (flexible_array_member_type_p (type))
{
complete_array_type (&type, elt, false);
- DECL_SIZE (decl)
- = size_binop (PLUS_EXPR, DECL_SIZE (decl), TYPE_SIZE (type));
- DECL_SIZE_UNIT (decl)
- = size_binop (PLUS_EXPR, DECL_SIZE_UNIT (decl), TYPE_SIZE_UNIT (type));
+ /* For a structure, add the size of the initializer to the DECL's
+ size. */
+ if (TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE)
+ {
+ DECL_SIZE (decl)
+ = size_binop (PLUS_EXPR, DECL_SIZE (decl), TYPE_SIZE (type));
+ DECL_SIZE_UNIT (decl)
+ = size_binop (PLUS_EXPR, DECL_SIZE_UNIT (decl),
+ TYPE_SIZE_UNIT (type));
+ }
+ /* For a union, the DECL's size is the maximum of the current size
+ and the size of the initializer. */
+ else
+ {
+ DECL_SIZE (decl)
+ = size_binop (MAX_EXPR, DECL_SIZE (decl), TYPE_SIZE (type));
+ DECL_SIZE_UNIT (decl)
+ = size_binop (MAX_EXPR, DECL_SIZE_UNIT (decl),
+ TYPE_SIZE_UNIT (type));
+ }
}
}
diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index e8622e2..04a151c 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -6563,8 +6563,9 @@ layout_var_decl (tree decl)
}
}
- /* If the final element initializes a flexible array field, add the size of
- that initializer to DECL's size. */
+ /* If the final element initializes a flexible array field, adjust
+ the size of the DECL with the initializer based on whether the
+ DECL is a union or a structure. */
if (type != error_mark_node
&& DECL_INITIAL (decl)
&& TREE_CODE (DECL_INITIAL (decl)) == CONSTRUCTOR
@@ -6585,11 +6586,28 @@ layout_var_decl (tree decl)
&& TREE_CODE (vtype) == ARRAY_TYPE
&& COMPLETE_TYPE_P (vtype))
{
- DECL_SIZE (decl)
- = size_binop (PLUS_EXPR, DECL_SIZE (decl), TYPE_SIZE (vtype));
- DECL_SIZE_UNIT (decl)
- = size_binop (PLUS_EXPR, DECL_SIZE_UNIT (decl),
- TYPE_SIZE_UNIT (vtype));
+ /* For a structure, add the size of the initializer to the DECL's
+ size. */
+ if (TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE)
+ {
+ DECL_SIZE (decl)
+ = size_binop (PLUS_EXPR, DECL_SIZE (decl),
+ TYPE_SIZE (vtype));
+ DECL_SIZE_UNIT (decl)
+ = size_binop (PLUS_EXPR, DECL_SIZE_UNIT (decl),
+ TYPE_SIZE_UNIT (vtype));
+ }
+ /* For a union, the DECL's size is the maximum of the current size
+ and the size of the initializer. */
+ else
+ {
+ DECL_SIZE (decl)
+ = size_binop (MAX_EXPR, DECL_SIZE (decl),
+ TYPE_SIZE (vtype));
+ DECL_SIZE_UNIT (decl)
+ = size_binop (MAX_EXPR, DECL_SIZE_UNIT (decl),
+ TYPE_SIZE_UNIT (vtype));
+ }
}
}
}
diff --git a/gcc/testsuite/c-c++-common/fam-in-union-alone-in-struct-bos-1.c b/gcc/testsuite/c-c++-common/fam-in-union-alone-in-struct-bos-1.c
new file mode 100644
index 0000000..aae9cf3
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/fam-in-union-alone-in-struct-bos-1.c
@@ -0,0 +1,66 @@
+/* testing flexible array members in unions and alone in structures:
+ __bos/__bdos */
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+union with_fam_1 {
+ char a;
+ int b[];
+} *with_fam_1_v;
+
+union with_fam_2 {
+ int a;
+ char b[];
+} *with_fam_2_v;
+
+union with_fam_3 {
+ char a[];
+ int b[];
+} *with_fam_3_v;
+
+struct only_fam {
+ int b[];
+} *only_fam_v;
+
+struct only_fam_2 {
+ unsigned int : 2;
+ unsigned int : 3;
+ int b[];
+} *only_fam_2_v;
+
+void __attribute__((__noinline__))
+setup (int n1, int n2, int n3, int n4, int n5)
+{
+ with_fam_1_v = (union with_fam_1 *) __builtin_malloc (n1 * sizeof (int));
+ with_fam_2_v = (union with_fam_2 *) __builtin_malloc (n2 * sizeof (char));
+ with_fam_3_v = (union with_fam_3 *) __builtin_malloc (n3 * sizeof (int));
+ only_fam_v = (struct only_fam *) __builtin_malloc (n4 * sizeof (int));
+ only_fam_2_v = (struct only_fam_2 *) __builtin_malloc (n5 * sizeof (int));
+ return;
+}
+
+void __attribute__((__noinline__)) stuff(
+ union with_fam_1 *with_fam_1_v,
+ union with_fam_2 *with_fam_2_v,
+ union with_fam_3 *with_fam_3_v,
+ struct only_fam *only_fam_v,
+ struct only_fam_2 *only_fam_2_v)
+{
+ if (__builtin_object_size(with_fam_1_v->b, 1) != -1)
+ __builtin_abort ();
+ if (__builtin_object_size(with_fam_2_v->b, 1) != -1)
+ __builtin_abort ();
+ if (__builtin_object_size(with_fam_3_v->b, 1) != -1)
+ __builtin_abort ();
+ if (__builtin_object_size(only_fam_v->b, 1) != -1)
+ __builtin_abort ();
+ if (__builtin_object_size(only_fam_2_v->b, 1) != -1)
+ __builtin_abort ();
+}
+
+int main (int argc, char *argv[])
+{
+ setup (2, 3, 4, 5, 6);
+ stuff (with_fam_1_v, with_fam_2_v, with_fam_3_v, only_fam_v, only_fam_2_v);
+ return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/fam-in-union-alone-in-struct-bos.c b/gcc/testsuite/c-c++-common/fam-in-union-alone-in-struct-bos.c
new file mode 100644
index 0000000..21badc5
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/fam-in-union-alone-in-struct-bos.c
@@ -0,0 +1,45 @@
+/* testing flexible array members in unions and alone in structures:
+ __bos/__bdos */
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+union with_fam_1 {
+ char a;
+ int b[];
+} with_fam_1_v = {.b = {1, 2, 3, 4, 5}};
+
+union with_fam_2 {
+ int a;
+ char b[];
+} with_fam_2_v = {.a = 0x1f2f3f4f};
+
+union with_fam_3 {
+ char a[];
+ int b[];
+} with_fam_3_v = {.b = {0x1f2f3f4f, 0x5f6f7f7f}};
+
+struct only_fam {
+ int b[];
+} only_fam_v = {{7, 11}};
+
+struct only_fam_2 {
+ unsigned int : 2;
+ unsigned int : 3;
+ int b[];
+} only_fam_2_v = {{7, 11}};
+
+int main ()
+{
+ if (__builtin_object_size(with_fam_1_v.b, 1) != 20)
+ __builtin_abort ();
+ if (__builtin_object_size(with_fam_2_v.b, 1) != 4)
+ __builtin_abort ();
+ if (__builtin_object_size(with_fam_3_v.b, 1) != 8)
+ __builtin_abort ();
+ if (__builtin_object_size(only_fam_v.b, 1) != 8)
+ __builtin_abort ();
+ if (__builtin_object_size(only_fam_2_v.b, 1) != 8)
+ __builtin_abort ();
+
+ return 0;
+}