aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2014-04-18 14:13:53 -0400
committerJason Merrill <jason@gcc.gnu.org>2014-04-18 14:13:53 -0400
commitfc45aeeeeccfe9e81f7e9619188c5450b1550634 (patch)
tree6c19266f53696d577686c93e35086a55129270f3 /gcc
parentc663bc6a4ff37bf6cb3d6d05c9862e17236051ec (diff)
downloadgcc-fc45aeeeeccfe9e81f7e9619188c5450b1550634.zip
gcc-fc45aeeeeccfe9e81f7e9619188c5450b1550634.tar.gz
gcc-fc45aeeeeccfe9e81f7e9619188c5450b1550634.tar.bz2
DR 1571
DR 1571 * call.c (reference_binding): Recurse on user-defined conversion. From-SVN: r209521
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog3
-rw-r--r--gcc/cp/call.c30
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/overload3.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/rv-init1.C26
4 files changed, 50 insertions, 11 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 23baee6..b7db350 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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.
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index fbd2f83..8c55c32 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -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;
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/overload3.C b/gcc/testsuite/g++.dg/cpp0x/overload3.C
index 2d95783..0eecabd 100644
--- a/gcc/testsuite/g++.dg/cpp0x/overload3.C
+++ b/gcc/testsuite/g++.dg/cpp0x/overload3.C
@@ -13,5 +13,5 @@ struct wrap
int main()
{
wrap w;
- f(w); // { dg-error "lvalue" }
+ f(w); // { dg-error "" }
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv-init1.C b/gcc/testsuite/g++.dg/cpp0x/rv-init1.C
new file mode 100644
index 0000000..2e8d4f7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/rv-init1.C
@@ -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 "" }