diff options
author | Marek Polacek <polacek@redhat.com> | 2019-03-13 20:04:33 +0000 |
---|---|---|
committer | Marek Polacek <mpolacek@gcc.gnu.org> | 2019-03-13 20:04:33 +0000 |
commit | ef7e79a3672d1b013646a1a6f8cd5931ef6bcd07 (patch) | |
tree | d47d790bc1e4b4c797c2003990ee1dbb7dcbf811 /gcc | |
parent | 2b0a62741e675068c13e81690758855846c88726 (diff) | |
download | gcc-ef7e79a3672d1b013646a1a6f8cd5931ef6bcd07.zip gcc-ef7e79a3672d1b013646a1a6f8cd5931ef6bcd07.tar.gz gcc-ef7e79a3672d1b013646a1a6f8cd5931ef6bcd07.tar.bz2 |
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 9 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/Wredundant-move8.C | 38 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/Wredundant-move9.C | 108 |
5 files changed, 161 insertions, 3 deletions
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 <jason@redhat.com> 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<T&> (&arg). */ + /* We're looking for *std::move<T&> ((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 <janus@gcc.gnu.org> 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<typename _Tp> + struct remove_reference + { typedef _Tp type; }; + + template<typename _Tp> + struct remove_reference<_Tp&> + { typedef _Tp type; }; + + template<typename _Tp> + struct remove_reference<_Tp&&> + { typedef _Tp type; }; + + template<typename _Tp> + constexpr typename std::remove_reference<_Tp>::type&& + move(_Tp&& __t) noexcept + { return static_cast<typename std::remove_reference<_Tp>::type&&>(__t); } +} + +template <typename S> struct D { + template <typename T> D (D<T> x) : k(&x.foo ()) {} + S &foo (); + int *k; +}; + +D<int> bar (); + +struct F { + D<int> baz () { + D<F> f = bar (); + return std::move (*reinterpret_cast<D<int> *> (&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<typename _Tp> + struct remove_reference + { typedef _Tp type; }; + + template<typename _Tp> + struct remove_reference<_Tp&> + { typedef _Tp type; }; + + template<typename _Tp> + struct remove_reference<_Tp&&> + { typedef _Tp type; }; + + template<typename _Tp> + constexpr typename std::remove_reference<_Tp>::type&& + move(_Tp&& __t) noexcept + { return static_cast<typename std::remove_reference<_Tp>::type&&>(__t); } +} + +template<typename Tp> +struct T { + T() { } + T(const T&) { } + T(T&&) { } +}; + +template<typename Tp> +struct U { + U() { } + U(const U&) { } + U(U&&) { } + U(T<Tp>) { } +}; + +T<int> +fn1 (T<int> t) +{ + return t; +} + +T<int> +fn2 (T<int> t) +{ + // Will use move even without std::move. + return std::move (t); // { dg-warning "redundant move in return statement" } +} + +T<int> +fn3 (const T<int> t) +{ + // t is const: will decay into copy. + return t; +} + +T<int> +fn4 (const T<int> 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<int> +fn6 (T<int> t, bool b) +{ + if (b) + throw std::move (t); + return std::move (t); // { dg-warning "redundant move in return statement" } +} + +U<int> +fn7 (T<int> t) +{ + // Core 1579 means we'll get a move here. + return t; +} + +U<int> +fn8 (T<int> 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<int> +fn9 (T<int>& t) +{ + // T is a reference and the move isn't redundant. + return std::move (t); +} + +T<int> +fn10 (T<int>&& t) +{ + // T is a reference and the move isn't redundant. + return std::move (t); +} |