aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMarek Polacek <polacek@redhat.com>2019-03-13 20:04:33 +0000
committerMarek Polacek <mpolacek@gcc.gnu.org>2019-03-13 20:04:33 +0000
commitef7e79a3672d1b013646a1a6f8cd5931ef6bcd07 (patch)
treed47d790bc1e4b4c797c2003990ee1dbb7dcbf811 /gcc
parent2b0a62741e675068c13e81690758855846c88726 (diff)
downloadgcc-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/ChangeLog5
-rw-r--r--gcc/cp/typeck.c9
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/Wredundant-move8.C38
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/Wredundant-move9.C108
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);
+}