From ec2de569275fe76e9f7e4ca931e987be5638359f Mon Sep 17 00:00:00 2001 From: Marek Polacek Date: Wed, 6 Mar 2019 15:34:50 +0000 Subject: [PATCH] PR c++/87378 - bogus -Wredundant-move warning. * typeck.c (maybe_warn_pessimizing_move): See if the maybe-rvalue overload resolution would actually succeed. * g++.dg/cpp0x/Wredundant-move1.C (fn4): Drop dg-warning. * g++.dg/cpp0x/Wredundant-move7.C: New test. From-SVN: r269427 --- gcc/cp/ChangeLog | 6 ++ gcc/cp/typeck.c | 22 +++++-- gcc/testsuite/ChangeLog | 6 ++ gcc/testsuite/g++.dg/cpp0x/Wredundant-move1.C | 3 +- gcc/testsuite/g++.dg/cpp0x/Wredundant-move7.C | 59 +++++++++++++++++++ 5 files changed, 91 insertions(+), 5 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/Wredundant-move7.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index d2cb7fd1132..cfd86b250d7 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2019-03-06 Marek Polacek + + PR c++/87378 - bogus -Wredundant-move warning. + * typeck.c (maybe_warn_pessimizing_move): See if the maybe-rvalue + overload resolution would actually succeed. + 2019-03-05 Jason Merrill * class.c (is_really_empty_class): Add ignore_vptr parm. diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 1bf9ad88141..43ff3d63abd 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -9429,10 +9429,24 @@ maybe_warn_pessimizing_move (tree retval, tree functype) do maybe-rvalue overload resolution even without std::move. */ else if (treat_lvalue_as_rvalue_p (arg, /*parm_ok*/true)) { - auto_diagnostic_group d; - if (warning_at (loc, OPT_Wredundant_move, - "redundant move in return statement")) - inform (loc, "remove % call"); + /* Make sure that the overload resolution would actually succeed + if we removed the std::move call. */ + tree t = convert_for_initialization (NULL_TREE, functype, + move (arg), + (LOOKUP_NORMAL + | LOOKUP_ONLYCONVERTING + | LOOKUP_PREFER_RVALUE), + ICR_RETURN, NULL_TREE, 0, + tf_none); + /* If this worked, implicit rvalue would work, so the call to + std::move is redundant. */ + if (t != error_mark_node) + { + auto_diagnostic_group d; + if (warning_at (loc, OPT_Wredundant_move, + "redundant move in return statement")) + inform (loc, "remove % call"); + } } } } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 828ed02d93a..9b2951f631f 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2019-03-06 Marek Polacek + + PR c++/87378 - bogus -Wredundant-move warning. + * g++.dg/cpp0x/Wredundant-move1.C (fn4): Drop dg-warning. + * g++.dg/cpp0x/Wredundant-move7.C: New test. + 2019-03-06 Richard Biener PR testsuite/89551 diff --git a/gcc/testsuite/g++.dg/cpp0x/Wredundant-move1.C b/gcc/testsuite/g++.dg/cpp0x/Wredundant-move1.C index 5d4a25dbc3b..e70f3cde625 100644 --- a/gcc/testsuite/g++.dg/cpp0x/Wredundant-move1.C +++ b/gcc/testsuite/g++.dg/cpp0x/Wredundant-move1.C @@ -59,7 +59,8 @@ T fn4 (const T t) { // t is const: will decay into copy despite std::move, so it's redundant. - return std::move (t); // { dg-warning "redundant move in return statement" } + // We used to warn about this, but no longer since c++/87378. + return std::move (t); } int diff --git a/gcc/testsuite/g++.dg/cpp0x/Wredundant-move7.C b/gcc/testsuite/g++.dg/cpp0x/Wredundant-move7.C new file mode 100644 index 00000000000..015d7c4f7a4 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/Wredundant-move7.C @@ -0,0 +1,59 @@ +// PR c++/87378 +// { dg-do compile { target c++11 } } +// { dg-options "-Wredundant-move" } + +// Define std::move. +namespace std { + template + struct remove_reference + { typedef _Tp type; }; + + template + struct remove_reference<_Tp&> + { typedef _Tp type; }; + + template + struct remove_reference<_Tp&&> + { typedef _Tp type; }; + + template + constexpr typename std::remove_reference<_Tp>::type&& + move(_Tp&& __t) noexcept + { return static_cast::type&&>(__t); } +} + +struct S1 { S1(S1 &&); }; +struct S2 : S1 {}; + +S1 +f (S2 s) +{ + return std::move(s); // { dg-bogus "redundant move in return statement" } +} + +struct R1 { + R1(R1 &&); + R1(const R1 &&); +}; +struct R2 : R1 {}; + +R1 +f2 (const R2 s) +{ + return std::move(s); // { dg-bogus "redundant move in return statement" } +} + +struct T1 { + T1(const T1 &); + T1(T1 &&); + T1(const T1 &&); +}; +struct T2 : T1 {}; + +T1 +f3 (const T2 s) +{ + // Without std::move: const T1 & + // With std::move: const T1 && + return std::move(s); // { dg-bogus "redundant move in return statement" } +} -- 2.30.2