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.
This commit is contained in:
parent
93f6a47583
commit
6634a40912
4 changed files with 159 additions and 13 deletions
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
Loading…
Add table
Reference in a new issue