creating a garbage BASELINK; constructors can't be inherited. */
ctors = get_class_binding (totype, complete_ctor_identifier);
- /* FIXME P0135 doesn't say what to do in C++17 about list-initialization from
- a single element. For now, let's handle constructors as before and also
- consider conversion operators from the element. */
- if (cxx_dialect >= cxx17
- && BRACE_ENCLOSED_INITIALIZER_P (expr)
- && CONSTRUCTOR_NELTS (expr) == 1)
- fromtype = TREE_TYPE (CONSTRUCTOR_ELT (expr, 0)->value);
-
if (MAYBE_CLASS_TYPE_P (fromtype))
{
tree to_nonref = non_reference (totype);
if (conv_fns)
{
if (BRACE_ENCLOSED_INITIALIZER_P (expr))
- /* FIXME see above about C++17. */
first_arg = CONSTRUCTOR_ELT (expr, 0)->value;
else
first_arg = expr;
&& !AGGR_INIT_VIA_CTOR_P (init));
}
+/* True iff C is a conversion that binds a reference to a prvalue. */
+
+static bool
+conv_binds_ref_to_prvalue (conversion *c)
+{
+ if (c->kind != ck_ref_bind)
+ return false;
+ if (c->need_temporary_p)
+ return true;
+
+ c = next_conversion (c);
+
+ if (c->kind == ck_rvalue)
+ return true;
+ if (c->kind == ck_user && TREE_CODE (c->type) != REFERENCE_TYPE)
+ return true;
+
+ return false;
+}
+
/* Subroutine of the various build_*_call functions. Overload resolution
has chosen a winning candidate CAND; build up a CALL_EXPR accordingly.
ARGS is a TREE_LIST of the unconverted arguments to the call. FLAGS is a
joust (cand, w->loser, 1, complain);
}
+ /* Core issue 2327: P0135 doesn't say how to handle the case where the
+ argument to the copy constructor ends up being a prvalue after
+ conversion. Let's do the normal processing, but pretend we aren't
+ actually using the copy constructor. */
+ bool force_elide = false;
+ if (cxx_dialect >= cxx17
+ && cand->num_convs == 1
+ && DECL_COMPLETE_CONSTRUCTOR_P (fn)
+ && (DECL_COPY_CONSTRUCTOR_P (fn)
+ || DECL_MOVE_CONSTRUCTOR_P (fn))
+ && conv_binds_ref_to_prvalue (convs[0]))
+ {
+ force_elide = true;
+ goto not_really_used;
+ }
+
/* OK, we're actually calling this inherited constructor; set its deletedness
appropriately. We can get away with doing this here because calling is
the only way to refer to a constructor. */
/* else continue to get conversion error. */
}
+ not_really_used:
+
/* N3276 magic doesn't apply to nested calls. */
tsubst_flags_t decltype_flag = (complain & tf_decltype);
complain &= ~tf_decltype;
/* Avoid actually calling copy constructors and copy assignment operators,
if possible. */
- if (! flag_elide_constructors)
+ if (! flag_elide_constructors && !force_elide)
/* Do things the hard way. */;
else if (cand->num_convs == 1
&& (DECL_COPY_CONSTRUCTOR_P (fn)
/* It's unsafe to elide the constructor when handling
a noexcept-expression, it may evaluate to the wrong
value (c++/53025). */
- && cp_noexcept_operand == 0)
+ && (force_elide || cp_noexcept_operand == 0))
{
tree targ;
tree arg = argarray[num_artificial_parms_for (fn)];
subobject. */
if (CHECKING_P && cxx_dialect >= cxx17)
gcc_assert (TREE_CODE (arg) != TARGET_EXPR
+ || force_elide
/* It's from binding the ref parm to a packed field. */
|| convs[0]->need_temporary_p
|| seen_error ()
/* [class.copy]: the copy constructor is implicitly defined even if
the implementation elided its use. */
- if (!trivial)
+ if (!trivial && !force_elide)
{
if (!mark_used (fn, complain) && !(complain & tf_error))
return error_mark_node;
}
}
+ gcc_assert (!force_elide);
+
if (!already_used
&& !mark_used (fn, complain))
return error_mark_node;
{
tree arg = (**args)[0];
- /* FIXME P0135 doesn't say how to handle direct initialization from a
- type with a suitable conversion operator. Let's handle it like
- copy-initialization, but allowing explict conversions. */
- tsubst_flags_t sub_complain = tf_warning;
- if (!is_dummy_object (instance))
- /* If we're using this to initialize a non-temporary object, don't
- require the destructor to be accessible. */
- sub_complain |= tf_no_cleanup;
if (BRACE_ENCLOSED_INITIALIZER_P (arg)
- && !CONSTRUCTOR_IS_DIRECT_INIT (arg))
- /* An init-list arg needs to convert to the parm type (83937), so fall
- through to normal processing. */
- arg = error_mark_node;
- else if (!reference_related_p (class_type, TREE_TYPE (arg)))
- arg = perform_implicit_conversion_flags (class_type, arg,
- sub_complain,
- flags);
+ && !TYPE_HAS_LIST_CTOR (class_type)
+ && CONSTRUCTOR_NELTS (arg) == 1)
+ arg = CONSTRUCTOR_ELT (arg, 0)->value;
+
if ((TREE_CODE (arg) == TARGET_EXPR
|| TREE_CODE (arg) == CONSTRUCTOR)
&& (same_type_ignoring_top_level_qualifiers_p