aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/cp/decl.c33
-rw-r--r--gcc/cp/typeck2.c26
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/desig18.C17
3 files changed, 46 insertions, 30 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. */
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index ce3016c..5a7219d 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -1517,19 +1517,6 @@ process_init_constructor_record (tree type, tree init, int nested, int flags,
|| identifier_p (ce->index));
if (ce->index == field || ce->index == DECL_NAME (field))
next = ce->value;
- else if (ANON_AGGR_TYPE_P (fldtype)
- && search_anon_aggr (fldtype,
- TREE_CODE (ce->index) == FIELD_DECL
- ? DECL_NAME (ce->index)
- : ce->index))
- /* 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. */
- next = build_constructor_single (init_list_type_node,
- ce->index, ce->value);
else
{
ce = NULL;
@@ -1675,19 +1662,6 @@ process_init_constructor_record (tree type, tree init, int nested, int flags,
if (ce->index == field || ce->index == DECL_NAME (field))
break;
- if (ANON_AGGR_TYPE_P (TREE_TYPE (field)))
- {
- tree t
- = search_anon_aggr (TREE_TYPE (field),
- TREE_CODE (ce->index) == FIELD_DECL
- ? DECL_NAME (ce->index)
- : ce->index);
- if (t)
- {
- field = t;
- break;
- }
- }
}
}
if (field)
diff --git a/gcc/testsuite/g++.dg/cpp2a/desig18.C b/gcc/testsuite/g++.dg/cpp2a/desig18.C
new file mode 100644
index 0000000..4851579
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/desig18.C
@@ -0,0 +1,17 @@
+// PR c++/100489
+// { dg-options "" }
+
+union U
+{
+ union
+ {
+ unsigned char a;
+ };
+
+ unsigned char b[1];
+};
+
+void f(unsigned char a)
+{
+ union U u = { .a = a };
+}