return true;
}
+/* Helper for build_aggr_conv. Return true if FIELD is in PSET, or if
+ FIELD has ANON_AGGR_TYPE_P and any initializable field in there recursively
+ is in PSET. */
+
+static bool
+field_in_pset (hash_set<tree> *pset, tree field)
+{
+ if (pset->contains (field))
+ return true;
+ if (ANON_AGGR_TYPE_P (TREE_TYPE (field)))
+ for (field = TYPE_FIELDS (TREE_TYPE (field));
+ field; field = DECL_CHAIN (field))
+ {
+ field = next_initializable_field (field);
+ if (field == NULL_TREE)
+ break;
+ if (field_in_pset (pset, field))
+ return true;
+ }
+ return false;
+}
+
/* Represent a conversion from CTOR, a braced-init-list, to TYPE, an
aggregate class, if such a conversion is possible. */
conversion *c;
tree field = next_initializable_field (TYPE_FIELDS (type));
tree empty_ctor = NULL_TREE;
+ hash_set<tree> *pset = NULL;
/* We already called reshape_init in implicit_conversion. */
context; they're always simple copy-initialization. */
flags = LOOKUP_IMPLICIT|LOOKUP_NO_NARROWING;
+ /* For designated initializers, verify that each initializer is convertible
+ to corresponding TREE_TYPE (ce->index) and mark those FIELD_DECLs as
+ visited. In the following loop then ignore already visited
+ FIELD_DECLs. */
+ if (CONSTRUCTOR_IS_DESIGNATED_INIT (ctor))
+ {
+ tree idx, val;
+ FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), i, idx, val)
+ {
+ if (idx && TREE_CODE (idx) == FIELD_DECL)
+ {
+ tree ftype = TREE_TYPE (idx);
+ bool ok;
+
+ if (TREE_CODE (ftype) == ARRAY_TYPE
+ && TREE_CODE (val) == CONSTRUCTOR)
+ ok = can_convert_array (ftype, val, flags, complain);
+ else
+ ok = can_convert_arg (ftype, TREE_TYPE (val), val, flags,
+ complain);
+
+ if (!ok)
+ goto fail;
+ /* For unions, there should be just one initializer. */
+ if (TREE_CODE (type) == UNION_TYPE)
+ {
+ field = NULL_TREE;
+ i = 1;
+ break;
+ }
+ if (pset == NULL)
+ pset = new hash_set<tree>;
+ pset->add (idx);
+ }
+ else
+ goto fail;
+ }
+ }
+
for (; field; field = next_initializable_field (DECL_CHAIN (field)))
{
tree ftype = TREE_TYPE (field);
tree val;
bool ok;
+ if (pset && field_in_pset (pset, field))
+ continue;
if (i < CONSTRUCTOR_NELTS (ctor))
- val = CONSTRUCTOR_ELT (ctor, i)->value;
+ {
+ val = CONSTRUCTOR_ELT (ctor, i)->value;
+ ++i;
+ }
else if (DECL_INITIAL (field))
val = get_nsdmi (field, /*ctor*/false, complain);
else if (TYPE_REF_P (ftype))
/* Value-initialization of reference is ill-formed. */
- return NULL;
+ goto fail;
else
{
if (empty_ctor == NULL_TREE)
empty_ctor = build_constructor (init_list_type_node, NULL);
val = empty_ctor;
}
- ++i;
if (TREE_CODE (ftype) == ARRAY_TYPE
&& TREE_CODE (val) == CONSTRUCTOR)
complain);
if (!ok)
- return NULL;
+ goto fail;
if (TREE_CODE (type) == UNION_TYPE)
break;
}
if (i < CONSTRUCTOR_NELTS (ctor))
- return NULL;
+ {
+ fail:
+ if (pset)
+ delete pset;
+ return NULL;
+ }
+ if (pset)
+ delete pset;
c = alloc_conversion (ck_aggr);
c->type = type;
c->rank = cr_exact;
if (expr && BRACE_ENCLOSED_INITIALIZER_P (expr))
{
- if (is_std_init_list (to))
+ if (is_std_init_list (to) && !CONSTRUCTOR_IS_DESIGNATED_INIT (expr))
return build_list_conv (to, expr, flags, complain);
/* As an extension, allow list-initialization of _Complex. */
- if (TREE_CODE (to) == COMPLEX_TYPE)
+ if (TREE_CODE (to) == COMPLEX_TYPE
+ && !CONSTRUCTOR_IS_DESIGNATED_INIT (expr))
{
conv = build_complex_conv (to, expr, flags, complain);
if (conv)
if (nelts == 0)
elt = build_value_init (to, tf_none);
- else if (nelts == 1)
+ else if (nelts == 1 && !CONSTRUCTOR_IS_DESIGNATED_INIT (expr))
elt = CONSTRUCTOR_ELT (expr, 0)->value;
else
elt = error_mark_node;
&& TYPE_MODE (TREE_TYPE (prom)) != TYPE_MODE (arg_type)
&& (complain & tf_warning))
warning_at (loc, OPT_Wabi, "scoped enum %qT passed through ... as "
- "%qT before -fabi-version=6, %qT after", arg_type,
+ "%qT before %<-fabi-version=6%>, %qT after", arg_type,
TREE_TYPE (prom), ENUM_UNDERLYING_TYPE (arg_type));
if (!abi_version_at_least (6))
arg = prom;
pedwarn (DECL_SOURCE_LOCATION (cand->fn), 0,
" in call to %qD", cand->fn);
pedwarn (input_location, 0,
- " (you can disable this with -fno-deduce-init-list)");
+ " (you can disable this with "
+ "%<-fno-deduce-init-list%>)");
}
}
tree arg = argarray[1];
location_t loc = cp_expr_loc_or_loc (arg, input_location);
- if (is_really_empty_class (type))
+ if (is_really_empty_class (type, /*ignore_vptr*/true))
{
/* Avoid copying empty classes. */
val = build2 (COMPOUND_EXPR, type, arg, to);
tweak:
- /* Extension: If the worst conversion for one candidate is worse than the
+ /* Extension: If the worst conversion for one candidate is better than the
worst conversion for the other, take the first. */
if (!pedantic && (complain & tf_warning_or_error))
{
if (warn)
{
auto_diagnostic_group d;
- pedwarn (input_location, 0,
- "ISO C++ says that these are ambiguous, even "
- "though the worst conversion for the first is better than "
- "the worst conversion for the second:");
- print_z_candidate (input_location, _("candidate 1:"), w);
- print_z_candidate (input_location, _("candidate 2:"), l);
+ if (pedwarn (input_location, 0,
+ "ISO C++ says that these are ambiguous, even "
+ "though the worst conversion for the first is "
+ "better than the worst conversion for the second:"))
+ {
+ print_z_candidate (input_location, _("candidate 1:"), w);
+ print_z_candidate (input_location, _("candidate 2:"), l);
+ }
}
else
add_warning (w, l);