aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarek Polacek <polacek@redhat.com>2018-09-20 23:20:19 +0000
committerMarek Polacek <mpolacek@gcc.gnu.org>2018-09-20 23:20:19 +0000
commit17b20aa993c78aa77c9c87cd6d6b90186f4d7c42 (patch)
tree87096e6587e4e5c1116736373a57567b9d624638
parent0b7fb27b698da38fd13108ecc914613f85f66f9d (diff)
downloadgcc-17b20aa993c78aa77c9c87cd6d6b90186f4d7c42.zip
gcc-17b20aa993c78aa77c9c87cd6d6b90186f4d7c42.tar.gz
gcc-17b20aa993c78aa77c9c87cd6d6b90186f4d7c42.tar.bz2
PR c++/87109 - wrong ctor with maybe-rvalue semantics.
* call.c (build_user_type_conversion_1): Refine the maybe-rvalue check to only return if we're converting the return value to a base class. * g++.dg/cpp0x/ref-qual19.C: Adjust the expected results. * g++.dg/cpp0x/ref-qual20.C: New test. From-SVN: r264452
-rw-r--r--gcc/cp/ChangeLog7
-rw-r--r--gcc/cp/call.c8
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/ref-qual19.C8
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/ref-qual20.C70
5 files changed, 92 insertions, 7 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 0260ff6..b75d0c7 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,10 @@
+2018-09-20 Marek Polacek <polacek@redhat.com>
+
+ PR c++/87109 - wrong ctor with maybe-rvalue semantics.
+ * call.c (build_user_type_conversion_1): Refine the maybe-rvalue
+ check to only return if we're converting the return value to a base
+ class.
+
2018-09-20 Allan Sandfeld Jensen <allan.jensen@qt.io>
* g++spec.c (lang_specific_driver): Handle -r like -nostdlib.
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index ddf0ed0..b2ca667 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -4034,10 +4034,12 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags,
conv->bad_p = true;
/* We're performing the maybe-rvalue overload resolution and
- a conversion function is in play. This isn't going to work
- because we would not end up with a suitable constructor. */
+ a conversion function is in play. Reject converting the return
+ value of the conversion function to a base class. */
if ((flags & LOOKUP_PREFER_RVALUE) && !DECL_CONSTRUCTOR_P (cand->fn))
- return NULL;
+ for (conversion *t = cand->second_conv; t; t = next_conversion (t))
+ if (t->kind == ck_base)
+ return NULL;
/* Remember that this was a list-initialization. */
if (flags & LOOKUP_NO_NARROWING)
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index bcac8dc..3b73194 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2018-09-20 Marek Polacek <polacek@redhat.com>
+
+ PR c++/87109 - wrong ctor with maybe-rvalue semantics.
+ * g++.dg/cpp0x/ref-qual19.C: Adjust the expected results.
+ * g++.dg/cpp0x/ref-qual20.C: New test.
+
2018-09-20 Allan Sandfeld Jensen <allan.jensen@qt.io>
* g++.dg/ipa/pr64059.C: Removed now redundant -nostdlib.
diff --git a/gcc/testsuite/g++.dg/cpp0x/ref-qual19.C b/gcc/testsuite/g++.dg/cpp0x/ref-qual19.C
index 8494b83..50f9297 100644
--- a/gcc/testsuite/g++.dg/cpp0x/ref-qual19.C
+++ b/gcc/testsuite/g++.dg/cpp0x/ref-qual19.C
@@ -85,13 +85,13 @@ int
main ()
{
C c1 = f (A());
- if (c1.i != 1)
+ if (c1.i != 2)
__builtin_abort ();
C c2 = f2 (A());
if (c2.i != 2)
__builtin_abort ();
C c3 = f3 ();
- if (c3.i != 1)
+ if (c3.i != 2)
__builtin_abort ();
C c4 = f4 ();
if (c4.i != 2)
@@ -100,13 +100,13 @@ main ()
if (c5.i != 2)
__builtin_abort ();
D c6 = f6 (B());
- if (c6.i != 3)
+ if (c6.i != 4)
__builtin_abort ();
D c7 = f7 (B());
if (c7.i != 4)
__builtin_abort ();
D c8 = f8 ();
- if (c8.i != 3)
+ if (c8.i != 4)
__builtin_abort ();
D c9 = f9 ();
if (c9.i != 4)
diff --git a/gcc/testsuite/g++.dg/cpp0x/ref-qual20.C b/gcc/testsuite/g++.dg/cpp0x/ref-qual20.C
new file mode 100644
index 0000000..c8bd436
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/ref-qual20.C
@@ -0,0 +1,70 @@
+// PR c++/87109
+// { dg-do run { target c++11 } }
+
+#include <utility>
+
+struct Y {
+ int y;
+ Y(int y_) : y(y_) { }
+};
+struct X : public Y {
+ int x;
+ X(int x_, int y_) : x(x_), Y(y_) { }
+};
+
+struct A {
+ operator X() & { return { 0, 2 }; }
+ operator X() && { return { 0, -1 }; }
+};
+
+Y
+f (A a)
+{
+ return a;
+}
+
+Y
+f2 (A a)
+{
+ return std::move (a);
+}
+
+Y
+f3 ()
+{
+ A a;
+ return a;
+}
+
+Y
+f4 ()
+{
+ A a;
+ return std::move (a);
+}
+
+Y
+f5 ()
+{
+ return A();
+}
+
+int
+main ()
+{
+ Y y1 = f (A());
+ if (y1.y != 2)
+ __builtin_abort ();
+ Y y2 = f2 (A());
+ if (y2.y != -1)
+ __builtin_abort ();
+ Y y3 = f3 ();
+ if (y3.y != 2)
+ __builtin_abort ();
+ Y y4 = f4 ();
+ if (y4.y != -1)
+ __builtin_abort ();
+ Y y5 = f5 ();
+ if (y5.y != -1)
+ __builtin_abort ();
+}