[pushed] c++: clarify reshape_init designator handling
Jason Merrill <[email protected]>
| Newsgroups | gmane.comp.gcc.patches |
|---|---|
| Message-ID | <[email protected]> |
Tested x86_64-pc-linux-gnu, applying to trunk.
-- 8< --
While looking at r17-3010, I found the handling of designators in
reshape_init* unclear, particularly in reshape_init_r. Jakub's patch
recurses directly from reshape_init_class to itself to avoid this confusion.
With this patch, if we see a designator in reshape_init_r, it designates a
member of TYPE, which means brace elision if !first_initializer_p. For this
to be true I needed to adjust reshape_init_array_1 to use
reshape_single_init from c++/103337. And then if we see a designator and
TYPE is a class or array, we know we're initializing an element so we don't
consider initializing TYPE directly.
gcc/cp/ChangeLog:
* decl.cc (reshape_single_init): Declare sooner.
(reshape_init_array_1): Use it.
(reshape_init_class): Drop "subclass" case.
(reshape_init_r): d->cur->index always means initializing
an element.
---
gcc/cp/decl.cc | 50 ++++++++++++++++++++++++--------------------------
1 file changed, 24 insertions(+), 26 deletions(-)
diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index cb3eb74c3a1..cd533217ec4 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -7477,6 +7477,7 @@ struct reshape_iter
};
static tree reshape_init_r (tree, reshape_iter *, tree, tsubst_flags_t);
+static tree reshape_single_init (tree, tree, tsubst_flags_t);
/* FIELD is an element of TYPE_FIELDS or NULL. In the former case, the value
returned is the next FIELD_DECL (possibly FIELD itself) that can be
@@ -7663,6 +7664,11 @@ reshape_init_array_1 (tree elt_type, tree max_index, reshape_iter *d,
}
TREE_TYPE (elt_init) = elt_type;
}
+ else if (d->cur->index)
+ {
+ elt_init = reshape_single_init (elt_type, d->cur->value, complain);
+ d->cur++;
+ }
else
elt_init = reshape_init_r (elt_type, d,
/*first_initializer_p=*/NULL_TREE,
@@ -7860,7 +7866,6 @@ reshape_init_class (tree type, reshape_iter *d, bool first_initializer_p,
constructor_elt *old_cur = d->cur;
unsigned old_raw_idx = d->raw_idx;
bool direct_desig = false;
- bool subclass = false;
/* Handle C++20 designated initializers. */
if (d->cur->index)
@@ -8020,7 +8025,6 @@ reshape_init_class (tree type, reshape_iter *d, bool first_initializer_p,
gcc_assert (aafield);
field = aafield;
direct_desig = false;
- subclass = true;
}
}
@@ -8052,18 +8056,6 @@ reshape_init_class (tree type, reshape_iter *d, bool first_initializer_p,
d->cur->value, complain);
d->cur++;
}
- else if (subclass)
- {
- if (complain & tf_warning)
- warning (OPT_Wmissing_braces,
- "missing braces around initializer for %qT",
- TREE_TYPE (field));
- field_init = reshape_init_class (TREE_TYPE (field), d,
- /*first_initializer_p=*/NULL_TREE,
- complain);
- if (TREE_CODE (field_init) == CONSTRUCTOR)
- CONSTRUCTOR_BRACES_ELIDED_P (field_init) = true;
- }
else
field_init = reshape_init_r (TREE_TYPE (field), d,
/*first_initializer_p=*/NULL_TREE,
@@ -8189,6 +8181,21 @@ reshape_init_r (tree type, reshape_iter *d, tree first_initializer_p,
return init;
}
+ /* If we have a designator, d doesn't initialize TYPE directly, it
+ initializes an element, with brace elision if !first_initializer_p. But
+ if TYPE is non-aggregate (and we didn't already return error_mark_node),
+ we should have errored about the designator in has_designator_problem, so
+ now ignore it for error recovery. */
+ if (d->cur->index)
+ {
+ /* Deliberately not CP_AGGREGATE_TYPE_P to get a better diagnostic for
+ trying to designate a member of a non-aggregate class. */
+ if (AGGREGATE_TYPE_P (type))
+ goto skip_single;
+ else
+ gcc_checking_assert (seen_error ());
+ }
+
/* A non-aggregate type is always initialized with a single
initializer. */
if (!CP_AGGREGATE_TYPE_P (type)
@@ -8239,8 +8246,6 @@ reshape_init_r (tree type, reshape_iter *d, tree first_initializer_p,
initialized from that element." Even if T is an aggregate. */
if (cxx_dialect >= cxx11 && (CLASS_TYPE_P (type) || VECTOR_TYPE_P (type))
&& first_initializer_p
- /* But not if it's a designated init. */
- && !d->cur->index
&& d->end - d->cur == 1
&& TREE_CODE (init) != RAW_DATA_CST
&& reference_related_p (type, TREE_TYPE (init)))
@@ -8273,6 +8278,8 @@ reshape_init_r (tree type, reshape_iter *d, tree first_initializer_p,
LOOKUP_NORMAL, complain)))
return consume_init (init, d);
+ skip_single:
+
/* [dcl.init.string]
A char array (whether plain char, signed char, or unsigned char)
@@ -8317,7 +8324,7 @@ reshape_init_r (tree type, reshape_iter *d, tree first_initializer_p,
bool braces_elided_p = false;
if (!first_initializer_p)
{
- if (TREE_CODE (stripped_init) == CONSTRUCTOR)
+ if (TREE_CODE (stripped_init) == CONSTRUCTOR && !d->cur->index)
{
tree init_type = TREE_TYPE (init);
if (init_type && TYPE_PTRMEMFUNC_P (init_type))
@@ -8330,15 +8337,6 @@ reshape_init_r (tree type, reshape_iter *d, tree first_initializer_p,
to handle initialization of arrays and similar. */
else if (COMPOUND_LITERAL_P (stripped_init))
gcc_assert (!BRACE_ENCLOSED_INITIALIZER_P (stripped_init));
- /* If we have an unresolved designator, we need to find the member it
- designates within TYPE, so proceed to the routines below. For
- FIELD_DECL or INTEGER_CST designators, we're already initializing
- the designated element. */
- else if (d->cur->index
- && TREE_CODE (d->cur->index) == IDENTIFIER_NODE)
- /* Brace elision with designators is only permitted for anonymous
- aggregates. */
- gcc_checking_assert (ANON_AGGR_TYPE_P (type));
/* A CONSTRUCTOR of the target's type is a previously
digested initializer. */
else if (same_type_ignoring_top_level_qualifiers_p (type, init_type))
base-commit: 3e43b55eb8fb520b6ed161697249fcef6699d11b
--
2.55.0