DR 1571
	* call.c (reference_binding): Recurse on user-defined conversion.

From-SVN: r209521
This commit is contained in:
Jason Merrill 2014-04-18 14:13:53 -04:00 committed by Jason Merrill
parent c663bc6a4f
commit fc45aeeeec
4 changed files with 50 additions and 11 deletions

View file

@ -1,5 +1,8 @@
2014-04-18 Jason Merrill <jason@redhat.com>
DR 1571
* call.c (reference_binding): Recurse on user-defined conversion.
PR c++/60872
* call.c (standard_conversion): Don't try to apply restrict to void.

View file

@ -1684,20 +1684,30 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags,
if (!conv)
return NULL;
if (conv->user_conv_p)
{
/* If initializing the temporary used a conversion function,
recalculate the second conversion sequence. */
for (conversion *t = conv; t; t = next_conversion (t))
if (t->kind == ck_user
&& DECL_CONV_FN_P (t->cand->fn))
{
tree ftype = TREE_TYPE (TREE_TYPE (t->cand->fn));
int sflags = (flags|LOOKUP_NO_CONVERSION)&~LOOKUP_NO_TEMP_BIND;
conversion *new_second
= reference_binding (rto, ftype, NULL_TREE, c_cast_p,
sflags, complain);
if (!new_second)
return NULL;
return merge_conversion_sequences (t, new_second);
}
}
conv = build_conv (ck_ref_bind, rto, conv);
/* This reference binding, unlike those above, requires the
creation of a temporary. */
conv->need_temporary_p = true;
if (TYPE_REF_IS_RVALUE (rto))
{
conv->rvaluedness_matches_p = 1;
/* In the second case, if the reference is an rvalue reference and
the second standard conversion sequence of the user-defined
conversion sequence includes an lvalue-to-rvalue conversion, the
program is ill-formed. */
if (conv->user_conv_p && next_conversion (conv)->kind == ck_rvalue)
conv->bad_p = 1;
}
conv->rvaluedness_matches_p = TYPE_REF_IS_RVALUE (rto);
return conv;
}

View file

@ -13,5 +13,5 @@ struct wrap
int main()
{
wrap w;
f(w); // { dg-error "lvalue" }
f(w); // { dg-error "" }
}

View file

@ -0,0 +1,26 @@
// Core DR 1604/1571/1572
// { dg-require-effective-target c++11 }
struct Banana { };
struct Enigma { operator const Banana(); };
struct Doof { operator Banana&(); };
void enigmatic() {
typedef const Banana ConstBanana;
Banana &&banana1 = ConstBanana(); // { dg-error "" }
Banana &&banana2 = Enigma(); // { dg-error "" }
Banana &&banana3 = Doof(); // { dg-error "" }
}
class A {
public:
operator volatile int &();
};
A a;
const int & ir1a = a.operator volatile int&(); // { dg-error "" }
const int & ir2a = a; // { dg-error "" }
struct X {
operator int&();
} x;
int&& rri2 = X(); // { dg-error "" }