From ef7e79a3672d1b013646a1a6f8cd5931ef6bcd07 Mon Sep 17 00:00:00 2001 From: Marek Polacek Date: Wed, 13 Mar 2019 20:04:33 +0000 Subject: [PATCH] PR c++/89660 - bogus error with -Wredundant-move. * typeck.c (maybe_warn_pessimizing_move): Only accept (T &) &arg as the std::move's argument. Don't call convert_for_initialization when warn_redundant_move isn't on. * g++.dg/cpp0x/Wredundant-move8.C: New test. * g++.dg/cpp0x/Wredundant-move9.C: New test. From-SVN: r269660 --- gcc/cp/ChangeLog | 5 ++ gcc/cp/typeck.c | 9 ++- gcc/testsuite/ChangeLog | 4 + gcc/testsuite/g++.dg/cpp0x/Wredundant-move8.C | 38 +++++++++ gcc/testsuite/g++.dg/cpp0x/Wredundant-move9.C | 108 ++++++++++++++++++++++++++ 5 files changed, 161 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/Wredundant-move8.C create mode 100644 gcc/testsuite/g++.dg/cpp0x/Wredundant-move9.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index fa0fdea..ca8bc03 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -12,6 +12,11 @@ * parser.c (cp_parser_lambda_introducer): Give error when combining init-capture and simple-capture. + PR c++/89660 - bogus error with -Wredundant-move. + * typeck.c (maybe_warn_pessimizing_move): Only accept (T &) &arg + as the std::move's argument. Don't call convert_for_initialization + when warn_redundant_move isn't on. + 2019-03-11 Jason Merrill PR c++/86521 - wrong overload resolution with ref-qualifiers. diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 51f4781..f77e9c6 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -9409,7 +9409,7 @@ maybe_warn_pessimizing_move (tree retval, tree functype) if (!CLASS_TYPE_P (functype)) return; - /* We're looking for *std::move (&arg). */ + /* We're looking for *std::move ((T &) &arg). */ if (REFERENCE_REF_P (retval) && TREE_CODE (TREE_OPERAND (retval, 0)) == CALL_EXPR) { @@ -9417,7 +9417,9 @@ maybe_warn_pessimizing_move (tree retval, tree functype) if (is_std_move_p (fn)) { tree arg = CALL_EXPR_ARG (fn, 0); - STRIP_NOPS (arg); + if (TREE_CODE (arg) != NOP_EXPR) + return; + arg = TREE_OPERAND (arg, 0); if (TREE_CODE (arg) != ADDR_EXPR) return; arg = TREE_OPERAND (arg, 0); @@ -9433,7 +9435,8 @@ maybe_warn_pessimizing_move (tree retval, tree functype) } /* Warn if the move is redundant. It is redundant when we would do maybe-rvalue overload resolution even without std::move. */ - else if (treat_lvalue_as_rvalue_p (arg, /*parm_ok*/true)) + else if (warn_redundant_move + && treat_lvalue_as_rvalue_p (arg, /*parm_ok*/true)) { /* Make sure that the overload resolution would actually succeed if we removed the std::move call. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index ed025c9..5f72cc2 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -3,6 +3,10 @@ PR c++/89686 - mixing init-capture and simple-capture in lambda. * g++.dg/cpp2a/lambda-pack-init2.C: New test. + PR c++/89660 - bogus error with -Wredundant-move. + * g++.dg/cpp0x/Wredundant-move8.C: New test. + * g++.dg/cpp0x/Wredundant-move9.C: New test. + 2019-03-13 Janus Weil PR fortran/89601 diff --git a/gcc/testsuite/g++.dg/cpp0x/Wredundant-move8.C b/gcc/testsuite/g++.dg/cpp0x/Wredundant-move8.C new file mode 100644 index 0000000..c290585 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/Wredundant-move8.C @@ -0,0 +1,38 @@ +// PR c++/89660 +// { 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); } +} + +template struct D { + template D (D x) : k(&x.foo ()) {} + S &foo (); + int *k; +}; + +D bar (); + +struct F { + D baz () { + D f = bar (); + return std::move (*reinterpret_cast *> (&f)); // { dg-bogus "redundant move in return statement" } + } +}; diff --git a/gcc/testsuite/g++.dg/cpp0x/Wredundant-move9.C b/gcc/testsuite/g++.dg/cpp0x/Wredundant-move9.C new file mode 100644 index 0000000..fdd3ce1 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/Wredundant-move9.C @@ -0,0 +1,108 @@ +// { 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); } +} + +template +struct T { + T() { } + T(const T&) { } + T(T&&) { } +}; + +template +struct U { + U() { } + U(const U&) { } + U(U&&) { } + U(T) { } +}; + +T +fn1 (T t) +{ + return t; +} + +T +fn2 (T t) +{ + // Will use move even without std::move. + return std::move (t); // { dg-warning "redundant move in return statement" } +} + +T +fn3 (const T t) +{ + // t is const: will decay into copy. + return t; +} + +T +fn4 (const T t) +{ + // t is const: will decay into copy despite std::move, so it's redundant. + // We used to warn about this, but no longer since c++/87378. + return std::move (t); +} + +int +fn5 (int i) +{ + // Not a class type. + return std::move (i); +} + +T +fn6 (T t, bool b) +{ + if (b) + throw std::move (t); + return std::move (t); // { dg-warning "redundant move in return statement" } +} + +U +fn7 (T t) +{ + // Core 1579 means we'll get a move here. + return t; +} + +U +fn8 (T t) +{ + // Core 1579 means we'll get a move here. Even without std::move. + return std::move (t); // { dg-warning "redundant move in return statement" } +} + +T +fn9 (T& t) +{ + // T is a reference and the move isn't redundant. + return std::move (t); +} + +T +fn10 (T&& t) +{ + // T is a reference and the move isn't redundant. + return std::move (t); +} -- 2.7.4