]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Update the C FE routine "add_flexible_array_elts_to_size" C++ FE routine "layout_var_...
authorQing Zhao <qing.zhao@oracle.com>
Mon, 6 May 2024 16:28:01 +0000 (16:28 +0000)
committerQing Zhao <qing.zhao@oracle.com>
Mon, 6 May 2024 18:35:09 +0000 (18:35 +0000)
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.

gcc/c/c-decl.cc
gcc/cp/decl.cc
gcc/testsuite/c-c++-common/fam-in-union-alone-in-struct-bos-1.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/fam-in-union-alone-in-struct-bos.c [new file with mode: 0644]

index 9ef2ab25773f8aa92da9ab95b2c29151fd4745d7..b691b91b3db410ad7ed3c6ca6397214bf2c51229 100644 (file)
@@ -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));
+       }
     }
 }
 \f
index e8622e22a4cf6056d25440b8bd8e382e26d09ce2..04a151c341ce9d14819d05a582c782f14866b319 100644 (file)
@@ -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 (file)
index 0000000..aae9cf3
--- /dev/null
@@ -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 (file)
index 0000000..21badc5
--- /dev/null
@@ -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;
+}