[clang-tools-extra] [clang-tidy] Fix false positive in bugprone-use-after-move for std::tie (PR #192895)
Zeyi Xu via cfe-commits
cfe-commits at lists.llvm.org
Wed May 27 23:25:09 PDT 2026
================
@@ -134,6 +134,17 @@ makeReinitMatcher(const ValueDecl *MovedVariable,
// built-in types.
binaryOperation(hasOperatorName("="),
hasLHS(ignoringParenImpCasts(DeclRefMatcher))),
+ // std::tie() assignment: std::tie(a, b) = expr reinitializes
+ // all variables passed to std::tie because the tuple
+ // assignment writes back through the stored references.
+ // ignoringImplicit strips the MaterializeTemporaryExpr that
+ // Clang inserts when calling operator= on the prvalue tuple.
+ binaryOperation(
+ hasOperatorName("="),
+ hasLHS(ignoringImplicit(
----------------
zeyi2 wrote:
I found that this case still gives a false-positive:
```cpp
void parenthesizedStdTieInLoop() {
std::string a, b;
while (true) {
(std::tie(a, b)) = makeStringPair(std::move(a), std::move(b));
(std::tie(a, b)) = makeStringPair(std::move(a), std::move(b));
}
}
```
```
clang-tools-extra/test/clang-tidy/checkers/bugprone/use-after-move.cpp:1885:49: warning: 'a' used after it was moved [bugprone-use-after-move]
1885 | (std::tie(a, b)) = makeStringPair(std::move(a), std::move(b));
| ^
clang-tools-extra/test/clang-tidy/checkers/bugprone/use-after-move.cpp:1886:39: note: move occurred here
1886 | (std::tie(a, b)) = makeStringPair(std::move(a), std::move(b));
| ^
clang-tools-extra/test/clang-tidy/checkers/bugprone/use-after-move.cpp:1885:49: note: the use happens in a later loop iteration than the move
1885 | (std::tie(a, b)) = makeStringPair(std::move(a), std::move(b));
| ^
clang-tools-extra/test/clang-tidy/checkers/bugprone/use-after-move.cpp:1885:63: warning: 'b' used after it was moved [bugprone-use-after-move]
1885 | (std::tie(a, b)) = makeStringPair(std::move(a), std::move(b));
| ^
clang-tools-extra/test/clang-tidy/checkers/bugprone/use-after-move.cpp:1886:53: note: move occurred here
1886 | (std::tie(a, b)) = makeStringPair(std::move(a), std::move(b));
| ^
clang-tools-extra/test/clang-tidy/checkers/bugprone/use-after-move.cpp:1885:63: note: the use happens in a later loop iteration than the move
1885 | (std::tie(a, b)) = makeStringPair(std::move(a), std::move(b));
| ^
clang-tools-extra/test/clang-tidy/checkers/bugprone/use-after-move.cpp:1886:49: warning: 'a' used after it was moved [bugprone-use-after-move]
1886 | (std::tie(a, b)) = makeStringPair(std::move(a), std::move(b));
| ^
clang-tools-extra/test/clang-tidy/checkers/bugprone/use-after-move.cpp:1885:39: note: move occurred here
1885 | (std::tie(a, b)) = makeStringPair(std::move(a), std::move(b));
| ^
clang-tools-extra/test/clang-tidy/checkers/bugprone/use-after-move.cpp:1886:63: warning: 'b' used after it was moved [bugprone-use-after-move]
1886 | (std::tie(a, b)) = makeStringPair(std::move(a), std::move(b));
| ^
clang-tools-extra/test/clang-tidy/checkers/bugprone/use-after-move.cpp:1885:53: note: move occurred here
1885 | (std::tie(a, b)) = makeStringPair(std::move(a), std::move(b));
| ^
```
-----
Could we do an `ignoringParenImpCasts` again? Similar to:
```cpp
binaryOperation(
hasOperatorName("="),
hasLHS(ignoringImplicit(ignoringParenImpCasts(
callExpr(callee(functionDecl(hasName("::std::tie"))),
hasAnyArgument(ignoringParenImpCasts(DeclRefMatcher))))))),
```
https://github.com/llvm/llvm-project/pull/192895
More information about the cfe-commits
mailing list