Skip to content

Commit a372919

Browse files
committed
[clang-tidy] Let bugprone-use-after-move also handle calls to std::forward
Fixes #82023
1 parent 26cc6f1 commit a372919

File tree

3 files changed

+60
-17
lines changed

3 files changed

+60
-17
lines changed

clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.cpp

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -330,7 +330,8 @@ void UseAfterMoveFinder::getReinits(
330330
traverse(TK_AsIs, DeclRefMatcher),
331331
unless(parmVarDecl(hasType(
332332
references(qualType(isConstQualified())))))),
333-
unless(callee(functionDecl(hasName("::std::move")))))))
333+
unless(callee(functionDecl(
334+
hasAnyName("::std::move", "::std::forward")))))))
334335
.bind("reinit");
335336

336337
Stmts->clear();
@@ -387,22 +388,23 @@ void UseAfterMoveCheck::registerMatchers(MatchFinder *Finder) {
387388
// the bool.
388389
auto TryEmplaceMatcher =
389390
cxxMemberCallExpr(callee(cxxMethodDecl(hasName("try_emplace"))));
390-
auto CallMoveMatcher =
391-
callExpr(argumentCountIs(1), callee(functionDecl(hasName("::std::move"))),
392-
hasArgument(0, declRefExpr().bind("arg")),
393-
unless(inDecltypeOrTemplateArg()),
394-
unless(hasParent(TryEmplaceMatcher)), expr().bind("call-move"),
395-
anyOf(hasAncestor(compoundStmt(
396-
hasParent(lambdaExpr().bind("containing-lambda")))),
397-
hasAncestor(functionDecl(anyOf(
398-
cxxConstructorDecl(
399-
hasAnyConstructorInitializer(withInitializer(
400-
expr(anyOf(equalsBoundNode("call-move"),
401-
hasDescendant(expr(
402-
equalsBoundNode("call-move")))))
403-
.bind("containing-ctor-init"))))
404-
.bind("containing-ctor"),
405-
functionDecl().bind("containing-func"))))));
391+
auto CallMoveMatcher = callExpr(
392+
argumentCountIs(1),
393+
callee(functionDecl(hasAnyName("::std::move", "::std::forward"))),
394+
hasArgument(0, declRefExpr().bind("arg")),
395+
unless(inDecltypeOrTemplateArg()), unless(hasParent(TryEmplaceMatcher)),
396+
expr().bind("call-move"),
397+
anyOf(hasAncestor(compoundStmt(
398+
hasParent(lambdaExpr().bind("containing-lambda")))),
399+
hasAncestor(functionDecl(
400+
anyOf(cxxConstructorDecl(
401+
hasAnyConstructorInitializer(withInitializer(
402+
expr(anyOf(equalsBoundNode("call-move"),
403+
hasDescendant(expr(
404+
equalsBoundNode("call-move")))))
405+
.bind("containing-ctor-init"))))
406+
.bind("containing-ctor"),
407+
functionDecl().bind("containing-func"))))));
406408

407409
Finder->addMatcher(
408410
traverse(

clang-tools-extra/docs/ReleaseNotes.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,10 @@ Changes in existing checks
130130
<clang-tidy/checks/bugprone/unused-local-non-trivial-variable>` check by
131131
ignoring local variable with ``[maybe_unused]`` attribute.
132132

133+
- Improved :doc:`bugprone-use-after-move
134+
<clang-tidy/checks/bugprone/use-after-move>` check to also handle
135+
calls to ``std::forward``.
136+
133137
- Cleaned up :doc:`cppcoreguidelines-prefer-member-initializer
134138
<clang-tidy/checks/cppcoreguidelines/prefer-member-initializer>`
135139
by removing enforcement of rule `C.48

clang-tools-extra/test/clang-tidy/checkers/bugprone/use-after-move.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,18 @@ constexpr typename std::remove_reference<_Tp>::type &&move(_Tp &&__t) noexcept {
111111
return static_cast<typename remove_reference<_Tp>::type &&>(__t);
112112
}
113113

114+
template <class _Tp>
115+
constexpr _Tp&&
116+
forward(typename std::remove_reference<_Tp>::type& __t) noexcept {
117+
return static_cast<_Tp&&>(__t);
118+
}
119+
120+
template <class _Tp>
121+
constexpr _Tp&&
122+
forward(typename std::remove_reference<_Tp>::type&& __t) noexcept {
123+
return static_cast<_Tp&&>(__t);
124+
}
125+
114126
} // namespace std
115127

116128
class A {
@@ -1525,3 +1537,28 @@ class PR38187 {
15251537
private:
15261538
std::string val_;
15271539
};
1540+
1541+
namespace issue82023
1542+
{
1543+
1544+
struct S {
1545+
S();
1546+
S(S&&);
1547+
};
1548+
1549+
void consume(S s);
1550+
1551+
template <typename T>
1552+
void forward(T&& t) {
1553+
consume(std::forward<T>(t));
1554+
consume(std::forward<T>(t));
1555+
// CHECK-NOTES: [[@LINE-1]]:27: warning: 't' used after it was moved
1556+
// CHECK-NOTES: [[@LINE-3]]:11: note: move occurred here
1557+
}
1558+
1559+
void create() {
1560+
S s;
1561+
forward(std::move(s));
1562+
}
1563+
1564+
} // namespace issue82023

0 commit comments

Comments
 (0)