diff options
author | Jason Merrill <jason@redhat.com> | 2021-05-19 21:12:45 -0400 |
---|---|---|
committer | Jason Merrill <jason@redhat.com> | 2021-05-20 16:59:17 -0400 |
commit | 84fd1b5dff70cd74aee7e8b18f66959d8b8e1ce7 (patch) | |
tree | 3584ac15bb2a3eea9a0c8787fc9b66e5bbc4f396 /gcc/cp/decl.c | |
parent | 64ba45c76e831914764b70207d69a06f800b43a4 (diff) | |
download | gcc-84fd1b5dff70cd74aee7e8b18f66959d8b8e1ce7.zip gcc-84fd1b5dff70cd74aee7e8b18f66959d8b8e1ce7.tar.gz gcc-84fd1b5dff70cd74aee7e8b18f66959d8b8e1ce7.tar.bz2 |
c++: designated init with anonymous union [PR100489]
My patch for PR98463 added an assert that tripped on this testcase, because
we ended up with a U CONSTRUCTOR with an initializer for a, which is not a
member of U. We need to wrap the a initializer in another CONSTRUCTOR for
the anonymous union.
There was already support for this in process_init_constructor_record, but
not in process_init_constructor_union. But since this is about brace
elision, it really belongs under reshape_init rather than digest_init, so
this patch moves the handling to reshape_init_class, which also handles
unions.
PR c++/100489
gcc/cp/ChangeLog:
* decl.c (reshape_init_class): Handle designator for
member of anonymous aggregate here.
* typeck2.c (process_init_constructor_record): Not here.
gcc/testsuite/ChangeLog:
* g++.dg/cpp2a/desig18.C: New test.
Diffstat (limited to 'gcc/cp/decl.c')
-rw-r--r-- | gcc/cp/decl.c | 33 |
1 files changed, 29 insertions, 4 deletions
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 7c32f09..6107b55 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -6418,10 +6418,9 @@ reshape_init_class (tree type, reshape_iter *d, bool first_initializer_p, /* We already reshaped this. */ if (field != d->cur->index) { - tree id = DECL_NAME (d->cur->index); - gcc_assert (id); - gcc_checking_assert (d->cur->index - == get_class_binding (type, id)); + if (tree id = DECL_NAME (d->cur->index)) + gcc_checking_assert (d->cur->index + == get_class_binding (type, id)); field = d->cur->index; } } @@ -6442,6 +6441,32 @@ reshape_init_class (tree type, reshape_iter *d, bool first_initializer_p, d->cur->index); return error_mark_node; } + + /* If the element is an anonymous union object and the initializer + list is a designated-initializer-list, the anonymous union object + is initialized by the designated-initializer-list { D }, where D + is the designated-initializer-clause naming a member of the + anonymous union object. */ + tree ictx = DECL_CONTEXT (field); + if (!same_type_ignoring_top_level_qualifiers_p (ictx, type)) + { + gcc_assert (ANON_AGGR_TYPE_P (ictx)); + /* Find the anon aggr that is a direct member of TYPE. */ + while (true) + { + tree cctx = TYPE_CONTEXT (ictx); + if (same_type_ignoring_top_level_qualifiers_p (cctx, type)) + break; + ictx = cctx; + } + /* And then the TYPE member with that anon aggr type. */ + tree aafield = TYPE_FIELDS (type); + for (; aafield; aafield = TREE_CHAIN (aafield)) + if (TREE_TYPE (aafield) == ictx) + break; + gcc_assert (aafield); + field = aafield; + } } /* If we processed all the member of the class, we are done. */ |