https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87150
--- Comment #5 from Jakub Jelinek <jakub at gcc dot gnu.org> --- r251035 clearly has code that handles that rule: + + if (flags & LOOKUP_PREFER_RVALUE) + { + /* The implicit move specified in 15.8.3/3 fails "...if the type of + the first parameter of the selected constructor is not an rvalue + reference to the object’s type (possibly cv-qualified)...." */ + gcc_assert (!(complain & tf_error)); + tree ptype = convs[0]->type; + if (TREE_CODE (ptype) != REFERENCE_TYPE + || !TYPE_REF_IS_RVALUE (ptype) + || CONVERSION_RANK (convs[0]) > cr_exact) + return error_mark_node; + } The thing is that LOOKUP_PREFER_RVALUE isn't set in this case, as we trigger first: else if (MAYBE_CLASS_TYPE_P (to) && MAYBE_CLASS_TYPE_P (from) && is_properly_derived_from (from, to)) { if (conv->kind == ck_rvalue) conv = next_conversion (conv); conv = build_conv (ck_base, to, conv); /* The derived-to-base conversion indicates the initialization of a parameter with base type from an object of a derived type. A temporary object is created to hold the result of the conversion unless we're binding directly to a reference. */ conv->need_temporary_p = !(flags & LOOKUP_NO_TEMP_BIND); } else return NULL; in standard_conversion, where *conv $17 = {kind = ck_rvalue, rank = cr_identity, user_conv_p = 0, ellipsis_p = 0, this_p = 0, bad_p = 0, need_temporary_p = 0, base_p = 0, rvaluedness_matches_p = 1, check_narrowing = 0, check_narrowing_const_only = 0, type = <record_type 0x7fffefdd32a0 S2>, u = {next = 0x2f92e80, expr = <error_mark 0x2f92e80>, list = 0x2f92e80}, cand = 0x0} and *next_conversion (conv) $18 = {kind = ck_identity, rank = cr_identity, user_conv_p = 0, ellipsis_p = 0, this_p = 0, bad_p = 0, need_temporary_p = 0, base_p = 0, rvaluedness_matches_p = 0, check_narrowing = 0, check_narrowing_const_only = 0, type = <record_type 0x7fffefdd32a0 S2>, u = { next = 0x7fffefdbd6c0, expr = <indirect_ref 0x7fffefdbd6c0>, list = 0x7fffefdbd6c0}, cand = 0x0} so we are no longer using ck_rvalue conversion with rvaluedness_matches_p, but ck_base conversion instead.