From 17b20aa993c78aa77c9c87cd6d6b90186f4d7c42 Mon Sep 17 00:00:00 2001 From: Marek Polacek Date: Thu, 20 Sep 2018 23:20:19 +0000 Subject: [PATCH] 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 --- gcc/cp/ChangeLog | 7 ++++ gcc/cp/call.c | 8 ++-- gcc/testsuite/ChangeLog | 6 +++ gcc/testsuite/g++.dg/cpp0x/ref-qual19.C | 8 ++-- gcc/testsuite/g++.dg/cpp0x/ref-qual20.C | 70 +++++++++++++++++++++++++++++++++ 5 files changed, 92 insertions(+), 7 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/ref-qual20.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 0260ff670b9..b75d0c70589 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2018-09-20 Marek Polacek + + 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 * g++spec.c (lang_specific_driver): Handle -r like -nostdlib. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index ddf0ed044a0..b2ca667c8b4 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 bcac8dc0e89..3b731944529 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2018-09-20 Marek Polacek + + 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 * 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 8494b83e5b0..50f92977c49 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 00000000000..c8bd43643af --- /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 + +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 (); +} -- 2.11.4.GIT