PR c++/87109 - wrong ctor with maybe-rvalue semantics.
authorMarek Polacek <polacek@redhat.com>
Thu, 20 Sep 2018 23:20:19 +0000 (23:20 +0000)
committerMarek Polacek <mpolacek@gcc.gnu.org>
Thu, 20 Sep 2018 23:20:19 +0000 (23:20 +0000)
* 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

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/ref-qual19.C
gcc/testsuite/g++.dg/cpp0x/ref-qual20.C [new file with mode: 0644]

index 0260ff670b9a6cd8bf128c7a866a2cf306099061..b75d0c70589c31c1732042ded4937182b0643cf5 100644 (file)
@@ -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.
index ddf0ed044a023668cd955b057fa1234a486a3e9b..b2ca667c8b42ca6cf75101293a8293bb2ddc5e5f 100644 (file)
@@ -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)
index bcac8dc0e89ad6d4e26135c7b169b648aa591593..3b731944529bfbb518ce337125eda891d2f8d5f4 100644 (file)
@@ -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.
index 8494b83e5b087c9d65014aa189115ec5af6a2204..50f92977c49d2a44ecb61f0c0936c5c75c903166 100644 (file)
@@ -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 (file)
index 0000000..c8bd436
--- /dev/null
@@ -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 ();
+}