aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarek Polacek <polacek@redhat.com>2024-05-23 15:49:42 -0400
committerMarek Polacek <polacek@redhat.com>2024-05-28 15:03:44 -0400
commitefaaae49b307fcc7e771518da3edae49f92c19db (patch)
treeea97b2f94b7833ce721aae9ab08a18f018078fbb
parent5ada486079d6aa20c64985a20681573f4ac1c86e (diff)
downloadgcc-efaaae49b307fcc7e771518da3edae49f92c19db.zip
gcc-efaaae49b307fcc7e771518da3edae49f92c19db.tar.gz
gcc-efaaae49b307fcc7e771518da3edae49f92c19db.tar.bz2
c++: extend -Wself-move for mem-init-list [PR109396]
We already warn for: x = std::move (x); which triggers: warning: moving 'x' of type 'int' to itself [-Wself-move] but bug 109396 reports that this doesn't work for a member-initializer-list: X() : x(std::move (x)) so this patch amends that. PR c++/109396 gcc/cp/ChangeLog: * cp-tree.h (maybe_warn_self_move): Declare. * init.cc (perform_member_init): Call maybe_warn_self_move. * typeck.cc (maybe_warn_self_move): No longer static. Change the return type to bool. Also warn when called from a member-initializer-list. Drop the inform call. gcc/testsuite/ChangeLog: * g++.dg/warn/Wself-move2.C: New test.
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/init.cc5
-rw-r--r--gcc/cp/typeck.cc32
-rw-r--r--gcc/testsuite/g++.dg/warn/Wself-move2.C37
4 files changed, 59 insertions, 16 deletions
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 655850a..6206482 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -8263,6 +8263,7 @@ extern cp_expr build_c_cast (location_t loc, tree type,
cp_expr expr);
extern tree cp_build_c_cast (location_t, tree, tree,
tsubst_flags_t);
+extern bool maybe_warn_self_move (location_t, tree, tree);
extern cp_expr build_x_modify_expr (location_t, tree,
enum tree_code, tree,
tree, tsubst_flags_t);
diff --git a/gcc/cp/init.cc b/gcc/cp/init.cc
index 52396d8..4a7ed7f 100644
--- a/gcc/cp/init.cc
+++ b/gcc/cp/init.cc
@@ -999,7 +999,7 @@ perform_member_init (tree member, tree init, hash_set<tree> &uninitialized)
if (decl == error_mark_node)
return;
- if ((warn_init_self || warn_uninitialized)
+ if ((warn_init_self || warn_uninitialized || warn_self_move)
&& init
&& TREE_CODE (init) == TREE_LIST
&& TREE_CHAIN (init) == NULL_TREE)
@@ -1013,7 +1013,8 @@ perform_member_init (tree member, tree init, hash_set<tree> &uninitialized)
warning_at (DECL_SOURCE_LOCATION (current_function_decl),
OPT_Winit_self, "%qD is initialized with itself",
member);
- else
+ else if (!maybe_warn_self_move (input_location, member,
+ TREE_VALUE (init)))
find_uninit_fields (&val, &uninitialized, decl);
}
diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc
index 4a153a8..1b7a31d 100644
--- a/gcc/cp/typeck.cc
+++ b/gcc/cp/typeck.cc
@@ -9355,27 +9355,27 @@ cp_build_c_cast (location_t loc, tree type, tree expr,
/* 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. */
+ assignment. Return true if we warned. */
-static void
+bool
maybe_warn_self_move (location_t loc, tree lhs, tree rhs)
{
if (!warn_self_move)
- return;
+ return false;
/* C++98 doesn't know move. */
if (cxx_dialect < cxx11)
- return;
+ return false;
if (processing_template_decl)
- return;
+ return false;
if (!REFERENCE_REF_P (rhs)
|| TREE_CODE (TREE_OPERAND (rhs, 0)) != CALL_EXPR)
- return;
+ return false;
tree fn = TREE_OPERAND (rhs, 0);
if (!is_std_move_p (fn))
- return;
+ return false;
/* Just a little helper to strip * and various NOPs. */
auto extract_op = [] (tree &op) {
@@ -9393,13 +9393,17 @@ maybe_warn_self_move (location_t loc, tree lhs, tree rhs)
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");
- }
+ if (cp_tree_equal (lhs, arg)
+ /* Also warn in a member-initializer-list, as in : i(std::move(i)). */
+ || (TREE_CODE (lhs) == FIELD_DECL
+ && TREE_CODE (arg) == COMPONENT_REF
+ && cp_tree_equal (TREE_OPERAND (arg, 0), current_class_ref)
+ && TREE_OPERAND (arg, 1) == lhs))
+ if (warning_at (loc, OPT_Wself_move,
+ "moving %qE of type %qT to itself", orig_lhs, type))
+ return true;
+
+ return false;
}
/* For use from the C common bits. */
diff --git a/gcc/testsuite/g++.dg/warn/Wself-move2.C b/gcc/testsuite/g++.dg/warn/Wself-move2.C
new file mode 100644
index 0000000..0c0e1b9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wself-move2.C
@@ -0,0 +1,37 @@
+// PR c++/109396
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wall" }
+
+// 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); }
+}
+struct A {
+ int i_;
+
+ A(int) : i_(i_) { } // { dg-warning "itself" }
+ A(int, int) : i_(this->i_) { } // { dg-warning "itself" }
+};
+
+struct B {
+ int i_;
+
+ B(int) : i_(std::move(i_)) { } // { dg-warning "itself" }
+ B(int, int) : i_(std::move(this->i_)) { } // { dg-warning "itself" }
+};
+