2
0
mirror of git://gcc.gnu.org/git/gcc.git synced 2025-04-10 07:30:27 +08:00

d: Fix assignment to anonymous union member corrupts sibling members in struct

gcc/d/ChangeLog:

	PR d/92309
	* types.cc (fixup_anonymous_offset): Don't set DECL_FIELD_OFFSET on
	anonymous fields.

gcc/testsuite/ChangeLog:

	PR d/92309
	* gdc.dg/pr92309.d: New test.
This commit is contained in:
Iain Buclaw 2020-03-16 23:53:20 +01:00
parent c62f5e6e1f
commit 2691ffe6db
4 changed files with 43 additions and 3 deletions

@ -1,3 +1,9 @@
2020-03-16 Iain Buclaw <ibuclaw@gdcproject.org>
PR d/92309
* types.cc (fixup_anonymous_offset): Don't set DECL_FIELD_OFFSET on
anonymous fields.
2020-03-16 Iain Buclaw <ibuclaw@gdcproject.org>
PR d/92216

@ -234,16 +234,20 @@ insert_aggregate_field (tree type, tree field, size_t offset)
static void
fixup_anonymous_offset (tree fields, tree offset)
{
/* No adjustment in field offset required. */
if (integer_zerop (offset))
return;
while (fields != NULL_TREE)
{
/* Traverse all nested anonymous aggregates to update their offset.
Set the anonymous decl offset to its first member. */
/* Traverse all nested anonymous aggregates to update the offset of their
fields. Note that the anonymous field itself is not adjusted, as it
already has an offset relative to its outer aggregate. */
tree ftype = TREE_TYPE (fields);
if (TYPE_NAME (ftype) && IDENTIFIER_ANON_P (TYPE_IDENTIFIER (ftype)))
{
tree vfields = TYPE_FIELDS (ftype);
fixup_anonymous_offset (vfields, offset);
DECL_FIELD_OFFSET (fields) = DECL_FIELD_OFFSET (vfields);
}
else
{

@ -1,3 +1,8 @@
2020-03-16 Iain Buclaw <ibuclaw@gdcproject.org>
PR d/92309
* gdc.dg/pr92309.d: New test.
2020-03-16 Iain Buclaw <ibuclaw@gdcproject.org>
PR d/92216

@ -0,0 +1,25 @@
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92309
// { dg-do run { target hw } }
// { dg-skip-if "needs gcc/config.d" { ! d_runtime } }
union U
{
struct
{
size_t a;
size_t b;
union
{
size_t c;
size_t d;
}
}
}
void main()
{
U u;
assert(u.a == 0);
u.d = 1;
assert(u.a == 0);
}