[clang-tools-extra] [clang-tidy] let UseAfterMoveFinder::find() return an optional<UseAfterMove> (PR #98100)
Kefu Chai via cfe-commits
cfe-commits at lists.llvm.org
Mon Jul 8 17:15:26 PDT 2024
https://github.com/tchaikov updated https://github.com/llvm/llvm-project/pull/98100
>From 1a2d88917db32253514fc7a533f5cb39d465a9c7 Mon Sep 17 00:00:00 2001
From: Kefu Chai <kefu.chai at scylladb.com>
Date: Tue, 9 Jul 2024 07:58:23 +0800
Subject: [PATCH] [clang-tidy] let UseAfterMoveFinder::find() return an
optional<UseAfterMove>
before this change, we use an output parameter so
`UseAfterMoveFinder::find()` can return the found `UseAfterMove`, and
addition to it, `UseAfterMoveFinder::find()` return a bool, so we can
tell if a use-after-free is identified. this arrangement could be
confusing when one needs to understand when the each member variable of
the returned `UseAfterMove` instance is initialized.
in this change, we return an `std::optional<UseAfterMove>` instead of
a bool, so that it's more obvious on when/where the returned
`UseAfterMove` is initialized.
this change is a cleanup. so it does not change the behavior of this
check.
Signed-off-by: Kefu Chai <kefu.chai at scylladb.com>
---
.../clang-tidy/bugprone/UseAfterMoveCheck.cpp | 56 ++++++++++---------
1 file changed, 29 insertions(+), 27 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.cpp
index c90c92b5f660a..8f4b5e8092dda 100644
--- a/clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.cpp
@@ -54,13 +54,13 @@ class UseAfterMoveFinder {
// occurs after 'MovingCall' (the expression that performs the move). If a
// use-after-move is found, writes information about it to 'TheUseAfterMove'.
// Returns whether a use-after-move was found.
- bool find(Stmt *CodeBlock, const Expr *MovingCall,
- const DeclRefExpr *MovedVariable, UseAfterMove *TheUseAfterMove);
+ std::optional<UseAfterMove> find(Stmt *CodeBlock, const Expr *MovingCall,
+ const DeclRefExpr *MovedVariable);
private:
- bool findInternal(const CFGBlock *Block, const Expr *MovingCall,
- const ValueDecl *MovedVariable,
- UseAfterMove *TheUseAfterMove);
+ std::optional<UseAfterMove> findInternal(const CFGBlock *Block,
+ const Expr *MovingCall,
+ const ValueDecl *MovedVariable);
void getUsesAndReinits(const CFGBlock *Block, const ValueDecl *MovedVariable,
llvm::SmallVectorImpl<const DeclRefExpr *> *Uses,
llvm::SmallPtrSetImpl<const Stmt *> *Reinits);
@@ -95,9 +95,9 @@ static StatementMatcher inDecltypeOrTemplateArg() {
UseAfterMoveFinder::UseAfterMoveFinder(ASTContext *TheContext)
: Context(TheContext) {}
-bool UseAfterMoveFinder::find(Stmt *CodeBlock, const Expr *MovingCall,
- const DeclRefExpr *MovedVariable,
- UseAfterMove *TheUseAfterMove) {
+std::optional<UseAfterMove>
+UseAfterMoveFinder::find(Stmt *CodeBlock, const Expr *MovingCall,
+ const DeclRefExpr *MovedVariable) {
// Generate the CFG manually instead of through an AnalysisDeclContext because
// it seems the latter can't be used to generate a CFG for the body of a
// lambda.
@@ -111,7 +111,7 @@ bool UseAfterMoveFinder::find(Stmt *CodeBlock, const Expr *MovingCall,
std::unique_ptr<CFG> TheCFG =
CFG::buildCFG(nullptr, CodeBlock, Context, Options);
if (!TheCFG)
- return false;
+ return std::nullopt;
Sequence = std::make_unique<ExprSequence>(TheCFG.get(), CodeBlock, Context);
BlockMap = std::make_unique<StmtToBlockMap>(TheCFG.get(), Context);
@@ -125,10 +125,10 @@ bool UseAfterMoveFinder::find(Stmt *CodeBlock, const Expr *MovingCall,
MoveBlock = &TheCFG->getEntry();
}
- bool Found = findInternal(MoveBlock, MovingCall, MovedVariable->getDecl(),
- TheUseAfterMove);
+ auto TheUseAfterMove =
+ findInternal(MoveBlock, MovingCall, MovedVariable->getDecl());
- if (Found) {
+ if (TheUseAfterMove) {
if (const CFGBlock *UseBlock =
BlockMap->blockContainingStmt(TheUseAfterMove->DeclRef)) {
// Does the use happen in a later loop iteration than the move?
@@ -142,15 +142,14 @@ bool UseAfterMoveFinder::find(Stmt *CodeBlock, const Expr *MovingCall,
: CFA.isReachable(UseBlock, MoveBlock);
}
}
- return Found;
+ return TheUseAfterMove;
}
-bool UseAfterMoveFinder::findInternal(const CFGBlock *Block,
- const Expr *MovingCall,
- const ValueDecl *MovedVariable,
- UseAfterMove *TheUseAfterMove) {
+std::optional<UseAfterMove>
+UseAfterMoveFinder::findInternal(const CFGBlock *Block, const Expr *MovingCall,
+ const ValueDecl *MovedVariable) {
if (Visited.count(Block))
- return false;
+ return std::nullopt;
// Mark the block as visited (except if this is the block containing the
// std::move() and it's being visited the first time).
@@ -189,17 +188,18 @@ bool UseAfterMoveFinder::findInternal(const CFGBlock *Block,
}
if (!HaveSavingReinit) {
- TheUseAfterMove->DeclRef = Use;
+ UseAfterMove TheUseAfterMove;
+ TheUseAfterMove.DeclRef = Use;
// Is this a use-after-move that depends on order of evaluation?
// This is the case if the move potentially comes after the use (and we
// already know that use potentially comes after the move, which taken
// together tells us that the ordering is unclear).
- TheUseAfterMove->EvaluationOrderUndefined =
+ TheUseAfterMove.EvaluationOrderUndefined =
MovingCall != nullptr &&
Sequence->potentiallyAfter(MovingCall, Use);
- return true;
+ return TheUseAfterMove;
}
}
}
@@ -208,12 +208,15 @@ bool UseAfterMoveFinder::findInternal(const CFGBlock *Block,
// successors.
if (Reinits.empty()) {
for (const auto &Succ : Block->succs()) {
- if (Succ && findInternal(Succ, nullptr, MovedVariable, TheUseAfterMove))
- return true;
+ if (Succ) {
+ if (auto Found = findInternal(Succ, nullptr, MovedVariable)) {
+ return Found;
+ }
+ }
}
}
- return false;
+ return std::nullopt;
}
void UseAfterMoveFinder::getUsesAndReinits(
@@ -518,9 +521,8 @@ void UseAfterMoveCheck::check(const MatchFinder::MatchResult &Result) {
for (Stmt *CodeBlock : CodeBlocks) {
UseAfterMoveFinder Finder(Result.Context);
- UseAfterMove Use;
- if (Finder.find(CodeBlock, MovingCall, Arg, &Use))
- emitDiagnostic(MovingCall, Arg, Use, this, Result.Context,
+ if (auto Use = Finder.find(CodeBlock, MovingCall, Arg))
+ emitDiagnostic(MovingCall, Arg, *Use, this, Result.Context,
determineMoveType(MoveDecl));
}
}
More information about the cfe-commits
mailing list