aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorMarek Polacek <polacek@redhat.com>2022-08-08 17:45:28 -0400
committerMarek Polacek <polacek@redhat.com>2022-08-26 12:56:34 -0400
commit0abb78dda084a14b3d955757c6431fff71c263f3 (patch)
treee50c14d175e4d5e2e61ea340f47f00f92cf039a6 /gcc/cp
parent1e2462890ac748a5e5b6a34fdeb61e7027863a90 (diff)
downloadgcc-0abb78dda084a14b3d955757c6431fff71c263f3.zip
gcc-0abb78dda084a14b3d955757c6431fff71c263f3.tar.gz
gcc-0abb78dda084a14b3d955757c6431fff71c263f3.tar.bz2
c++: Implement -Wself-move warning [PR81159]
About 5 years ago we got a request to implement -Wself-move, which warns about useless moves like this: int x; x = std::move (x); This patch implements that warning. PR c++/81159 gcc/c-family/ChangeLog: * c.opt (Wself-move): New option. gcc/cp/ChangeLog: * typeck.cc (maybe_warn_self_move): New. (cp_build_modify_expr): Call maybe_warn_self_move. gcc/ChangeLog: * doc/invoke.texi: Document -Wself-move. gcc/testsuite/ChangeLog: * g++.dg/warn/Wself-move1.C: New test.
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/typeck.cc53
1 files changed, 52 insertions, 1 deletions
diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc
index 7fde65a..b99947c 100644
--- a/gcc/cp/typeck.cc
+++ b/gcc/cp/typeck.cc
@@ -8897,7 +8897,56 @@ cp_build_c_cast (location_t loc, tree type, tree expr,
return error_mark_node;
}
-
+
+/* Warn when a value is moved to itself with std::move. LHS is the target,
+ RHS may be the std::move call, and LOC is the location of the whole
+ assignment. */
+
+static void
+maybe_warn_self_move (location_t loc, tree lhs, tree rhs)
+{
+ if (!warn_self_move)
+ return;
+
+ /* C++98 doesn't know move. */
+ if (cxx_dialect < cxx11)
+ return;
+
+ if (processing_template_decl)
+ return;
+
+ if (!REFERENCE_REF_P (rhs)
+ || TREE_CODE (TREE_OPERAND (rhs, 0)) != CALL_EXPR)
+ return;
+ tree fn = TREE_OPERAND (rhs, 0);
+ if (!is_std_move_p (fn))
+ return;
+
+ /* Just a little helper to strip * and various NOPs. */
+ auto extract_op = [] (tree &op) {
+ STRIP_NOPS (op);
+ while (INDIRECT_REF_P (op))
+ op = TREE_OPERAND (op, 0);
+ op = maybe_undo_parenthesized_ref (op);
+ STRIP_ANY_LOCATION_WRAPPER (op);
+ };
+
+ tree arg = CALL_EXPR_ARG (fn, 0);
+ extract_op (arg);
+ if (TREE_CODE (arg) == ADDR_EXPR)
+ arg = TREE_OPERAND (arg, 0);
+ tree type = TREE_TYPE (lhs);
+ tree orig_lhs = lhs;
+ extract_op (lhs);
+ if (cp_tree_equal (lhs, arg))
+ {
+ auto_diagnostic_group d;
+ if (warning_at (loc, OPT_Wself_move,
+ "moving %qE of type %qT to itself", orig_lhs, type))
+ inform (loc, "remove %<std::move%> call");
+ }
+}
+
/* For use from the C common bits. */
tree
build_modify_expr (location_t location,
@@ -9101,6 +9150,8 @@ cp_build_modify_expr (location_t loc, tree lhs, enum tree_code modifycode,
if (modifycode == NOP_EXPR)
{
+ maybe_warn_self_move (loc, lhs, rhs);
+
if (c_dialect_objc ())
{
result = objc_maybe_build_modify_expr (lhs, rhs);