diff options
author | Marek Polacek <polacek@redhat.com> | 2022-08-08 17:45:28 -0400 |
---|---|---|
committer | Marek Polacek <polacek@redhat.com> | 2022-08-26 12:56:34 -0400 |
commit | 0abb78dda084a14b3d955757c6431fff71c263f3 (patch) | |
tree | e50c14d175e4d5e2e61ea340f47f00f92cf039a6 /gcc/cp | |
parent | 1e2462890ac748a5e5b6a34fdeb61e7027863a90 (diff) | |
download | gcc-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.cc | 53 |
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); |