BOOL_BITFIELD bad_p : 1;
/* If KIND is ck_ref_bind ck_base_conv, true to indicate that a
temporary should be created to hold the result of the
- conversion. If KIND is ck_ambig, true if the context is
+ conversion. If KIND is ck_ambig or ck_user, true means force
copy-initialization. */
BOOL_BITFIELD need_temporary_p : 1;
/* If KIND is ck_ptr or ck_pmem, true to indicate that a conversion
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;
|| (fcode == REAL_TYPE && !(flags & LOOKUP_NO_NON_INTEGRAL)))
|| SCOPED_ENUM_P (from))
return NULL;
+
+ /* If we're parsing an enum with no fixed underlying type, we're
+ dealing with an incomplete type, which renders the conversion
+ ill-formed. */
+ if (!COMPLETE_TYPE_P (from))
+ return NULL;
+
conv = build_conv (ck_std, to, conv);
/* Give this a better rank if it's a promotion. */
from = TREE_TYPE (expr);
}
+ bool copy_list_init = false;
if (expr && BRACE_ENCLOSED_INITIALIZER_P (expr))
{
maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS);
/* Otherwise, if T is a reference type, a prvalue temporary of the type
referenced by T is copy-list-initialized, and the reference is bound
to that temporary. */
- CONSTRUCTOR_IS_DIRECT_INIT (expr) = false;
+ copy_list_init = true;
skip:;
}
if (conv->user_conv_p)
{
+ if (copy_list_init)
+ /* Remember this was copy-list-initialization. */
+ conv->need_temporary_p = true;
+
/* If initializing the temporary used a conversion function,
recalculate the second conversion sequence. */
for (conversion *t = conv; t; t = next_conversion (t))
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;
error ("invalid use of void expression");
return NULL;
}
- else if (invalid_nonstatic_memfn_p (arg->exp.locus, arg, complain))
+ else if (invalid_nonstatic_memfn_p (EXPR_LOCATION (arg), arg, complain))
return NULL;
}
return args;
continue;
}
+ /* -- If any of the deallocation functions is a destroying
+ operator delete, all deallocation functions that are not
+ destroying operator deletes are eliminated from further
+ consideration. */
+ bool fn_destroying = destroying_delete_p (fn);
+ bool elt_destroying = destroying_delete_p (elt);
+ if (elt_destroying != fn_destroying)
+ {
+ if (elt_destroying)
+ fn = elt;
+ continue;
+ }
+
/* -- If the type has new-extended alignment, a function with a
parameter of type std::align_val_t is preferred; otherwise a
function without such a parameter is preferred. If exactly one
return expr;
}
+/* Get any location for EXPR, falling back to input_location.
+
+ If the result is in a system header and is the virtual location for
+ a token coming from the expansion of a macro, unwind it to the
+ location of the expansion point of the macro (e.g. to avoid the
+ diagnostic being suppressed for expansions of NULL where "NULL" is
+ in a system header). */
+
+static location_t
+get_location_for_expr_unwinding_for_system_header (tree expr)
+{
+ location_t loc = EXPR_LOC_OR_LOC (expr, input_location);
+ loc = expansion_point_location_if_in_system_header (loc);
+ return loc;
+}
+
/* Perform warnings about peculiar, but valid, conversions from/to NULL.
Also handle a subset of zero as null warnings.
EXPR is implicitly converted to type TOTYPE.
if (null_node_p (expr) && TREE_CODE (totype) != BOOLEAN_TYPE
&& ARITHMETIC_TYPE_P (totype))
{
- location_t loc = EXPR_LOC_OR_LOC (expr, input_location);
- loc = expansion_point_location_if_in_system_header (loc);
+ location_t loc = get_location_for_expr_unwinding_for_system_header (expr);
if (fn)
{
auto_diagnostic_group d;
else if (TREE_CODE (TREE_TYPE (expr)) == BOOLEAN_TYPE
&& TYPE_PTR_P (totype))
{
- location_t loc = EXPR_LOC_OR_LOC (expr, input_location);
+ location_t loc = get_location_for_expr_unwinding_for_system_header (expr);
if (fn)
{
auto_diagnostic_group d;
else if (null_ptr_cst_p (expr) &&
(TYPE_PTR_OR_PTRMEM_P (totype) || NULLPTR_TYPE_P (totype)))
{
- location_t loc =
- expansion_point_location_if_in_system_header (input_location);
+ location_t loc = get_location_for_expr_unwinding_for_system_header (expr);
maybe_warn_zero_as_null_pointer_constant (expr, loc);
}
}
if (DECL_NONCONVERTING_P (convfn) && DECL_CONSTRUCTOR_P (convfn)
&& BRACE_ENCLOSED_INITIALIZER_P (expr)
/* Unless this is for direct-list-initialization. */
- && !CONSTRUCTOR_IS_DIRECT_INIT (expr)
+ && (!CONSTRUCTOR_IS_DIRECT_INIT (expr) || convs->need_temporary_p)
/* And in C++98 a default constructor can't be explicit. */
&& cxx_dialect >= cxx11)
{
/* If we're initializing from {}, it's value-initialization. */
if (BRACE_ENCLOSED_INITIALIZER_P (expr)
&& CONSTRUCTOR_NELTS (expr) == 0
- && TYPE_HAS_DEFAULT_CONSTRUCTOR (totype))
+ && TYPE_HAS_DEFAULT_CONSTRUCTOR (totype)
+ && !processing_template_decl)
{
bool direct = CONSTRUCTOR_IS_DIRECT_INIT (expr);
if (abstract_virtuals_error_sfinae (NULL_TREE, totype, complain))
return expr;
}
- expr = mark_rvalue_use (expr);
+ /* We don't know here whether EXPR is being used as an lvalue or
+ rvalue, but we know it's read. */
+ mark_exp_read (expr);
/* Pass LOOKUP_NO_CONVERSION so rvalue/base handling knows not to allow
any more UDCs. */
{
/* Conversion to std::initializer_list<T>. */
tree elttype = TREE_VEC_ELT (CLASSTYPE_TI_ARGS (totype), 0);
- tree new_ctor = build_constructor (init_list_type_node, NULL);
unsigned len = CONSTRUCTOR_NELTS (expr);
- tree array, val, field;
- vec<constructor_elt, va_gc> *vec = NULL;
- unsigned ix;
+ tree array;
- /* Convert all the elements. */
- FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (expr), ix, val)
+ if (len)
{
- tree sub = convert_like_real (convs->u.list[ix], val, fn, argnum,
- false, false, complain);
- if (sub == error_mark_node)
- return sub;
- if (!BRACE_ENCLOSED_INITIALIZER_P (val)
- && !check_narrowing (TREE_TYPE (sub), val, complain))
- return error_mark_node;
- CONSTRUCTOR_APPEND_ELT (CONSTRUCTOR_ELTS (new_ctor), NULL_TREE, sub);
- if (!TREE_CONSTANT (sub))
- TREE_CONSTANT (new_ctor) = false;
+ tree val; unsigned ix;
+
+ tree new_ctor = build_constructor (init_list_type_node, NULL);
+
+ /* Convert all the elements. */
+ FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (expr), ix, val)
+ {
+ tree sub = convert_like_real (convs->u.list[ix], val, fn,
+ argnum, false, false, complain);
+ if (sub == error_mark_node)
+ return sub;
+ if (!BRACE_ENCLOSED_INITIALIZER_P (val)
+ && !check_narrowing (TREE_TYPE (sub), val, complain))
+ return error_mark_node;
+ CONSTRUCTOR_APPEND_ELT (CONSTRUCTOR_ELTS (new_ctor),
+ NULL_TREE, sub);
+ if (!TREE_CONSTANT (sub))
+ TREE_CONSTANT (new_ctor) = false;
+ }
+ /* Build up the array. */
+ elttype = cp_build_qualified_type
+ (elttype, cp_type_quals (elttype) | TYPE_QUAL_CONST);
+ array = build_array_of_n_type (elttype, len);
+ array = finish_compound_literal (array, new_ctor, complain);
+ /* Take the address explicitly rather than via decay_conversion
+ to avoid the error about taking the address of a temporary. */
+ array = cp_build_addr_expr (array, complain);
}
- /* Build up the array. */
- elttype = cp_build_qualified_type
- (elttype, cp_type_quals (elttype) | TYPE_QUAL_CONST);
- array = build_array_of_n_type (elttype, len);
- array = finish_compound_literal (array, new_ctor, complain);
- /* Take the address explicitly rather than via decay_conversion
- to avoid the error about taking the address of a temporary. */
- array = cp_build_addr_expr (array, complain);
+ else
+ array = nullptr_node;
+
array = cp_convert (build_pointer_type (elttype), array, complain);
if (array == error_mark_node)
return error_mark_node;
totype = complete_type_or_maybe_complain (totype, NULL_TREE, complain);
if (!totype)
return error_mark_node;
- field = next_initializable_field (TYPE_FIELDS (totype));
+ tree field = next_initializable_field (TYPE_FIELDS (totype));
+ vec<constructor_elt, va_gc> *vec = NULL;
CONSTRUCTOR_APPEND_ELT (vec, field, array);
field = next_initializable_field (DECL_CHAIN (field));
CONSTRUCTOR_APPEND_ELT (vec, field, size_int (len));
- new_ctor = build_constructor (totype, vec);
+ tree new_ctor = build_constructor (totype, vec);
return get_target_expr_sfinae (new_ctor, complain);
}
&& 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);
Specifically, we need to do the reference binding comparison at the
end of this function. */
- if (ics1->user_conv_p || ics1->kind == ck_list || ics1->kind == ck_aggr)
+ if (ics1->user_conv_p || ics1->kind == ck_list
+ || ics1->kind == ck_aggr || ics2->kind == ck_aggr)
{
conversion *t1;
conversion *t2;
- for (t1 = ics1; t1->kind != ck_user; t1 = next_conversion (t1))
+ for (t1 = ics1; t1 && t1->kind != ck_user; t1 = next_conversion (t1))
if (t1->kind == ck_ambig || t1->kind == ck_aggr
|| t1->kind == ck_list)
break;
- for (t2 = ics2; t2->kind != ck_user; t2 = next_conversion (t2))
+ for (t2 = ics2; t2 && t2->kind != ck_user; t2 = next_conversion (t2))
if (t2->kind == ck_ambig || t2->kind == ck_aggr
|| t2->kind == ck_list)
break;
- if (t1->kind != t2->kind)
+ if (!t1 || !t2 || t1->kind != t2->kind)
return 0;
else if (t1->kind == ck_user)
{
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);
&& (TREE_STATIC (decl) || CP_DECL_THREAD_LOCAL_P (decl)))
{
/* Namespace-scope or local static; give it a mangled name. */
- /* FIXME share comdat with decl? */
+
+ /* If an initializer is visible to multiple translation units, those
+ translation units must agree on the addresses of the
+ temporaries. Therefore the temporaries must be given a consistent name
+ and vague linkage. The mangled name of a temporary is the name of the
+ non-temporary object in whose initializer they appear, prefixed with
+ GR and suffixed with a sequence number mangled using the usual rules
+ for a seq-id. Temporaries are numbered with a pre-order, depth-first,
+ left-to-right walk of the complete initializer. */
TREE_STATIC (var) = TREE_STATIC (decl);
+ TREE_PUBLIC (var) = TREE_PUBLIC (decl);
+ if (vague_linkage_p (decl))
+ comdat_linkage (var);
+
CP_DECL_THREAD_LOCAL_P (var) = CP_DECL_THREAD_LOCAL_P (decl);
set_decl_tls_model (var, DECL_TLS_MODEL (decl));