Skip to content

Commit 77ec20c

Browse files
authored
[clang-tidy] let UseAfterMoveFinder::find() return an optional<UseAfterMove> (#98100)
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 <[email protected]>
1 parent 0fa20c5 commit 77ec20c

File tree

1 file changed

+29
-27
lines changed

1 file changed

+29
-27
lines changed

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

Lines changed: 29 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -54,13 +54,13 @@ class UseAfterMoveFinder {
5454
// occurs after 'MovingCall' (the expression that performs the move). If a
5555
// use-after-move is found, writes information about it to 'TheUseAfterMove'.
5656
// Returns whether a use-after-move was found.
57-
bool find(Stmt *CodeBlock, const Expr *MovingCall,
58-
const DeclRefExpr *MovedVariable, UseAfterMove *TheUseAfterMove);
57+
std::optional<UseAfterMove> find(Stmt *CodeBlock, const Expr *MovingCall,
58+
const DeclRefExpr *MovedVariable);
5959

6060
private:
61-
bool findInternal(const CFGBlock *Block, const Expr *MovingCall,
62-
const ValueDecl *MovedVariable,
63-
UseAfterMove *TheUseAfterMove);
61+
std::optional<UseAfterMove> findInternal(const CFGBlock *Block,
62+
const Expr *MovingCall,
63+
const ValueDecl *MovedVariable);
6464
void getUsesAndReinits(const CFGBlock *Block, const ValueDecl *MovedVariable,
6565
llvm::SmallVectorImpl<const DeclRefExpr *> *Uses,
6666
llvm::SmallPtrSetImpl<const Stmt *> *Reinits);
@@ -95,9 +95,9 @@ static StatementMatcher inDecltypeOrTemplateArg() {
9595
UseAfterMoveFinder::UseAfterMoveFinder(ASTContext *TheContext)
9696
: Context(TheContext) {}
9797

98-
bool UseAfterMoveFinder::find(Stmt *CodeBlock, const Expr *MovingCall,
99-
const DeclRefExpr *MovedVariable,
100-
UseAfterMove *TheUseAfterMove) {
98+
std::optional<UseAfterMove>
99+
UseAfterMoveFinder::find(Stmt *CodeBlock, const Expr *MovingCall,
100+
const DeclRefExpr *MovedVariable) {
101101
// Generate the CFG manually instead of through an AnalysisDeclContext because
102102
// it seems the latter can't be used to generate a CFG for the body of a
103103
// lambda.
@@ -111,7 +111,7 @@ bool UseAfterMoveFinder::find(Stmt *CodeBlock, const Expr *MovingCall,
111111
std::unique_ptr<CFG> TheCFG =
112112
CFG::buildCFG(nullptr, CodeBlock, Context, Options);
113113
if (!TheCFG)
114-
return false;
114+
return std::nullopt;
115115

116116
Sequence = std::make_unique<ExprSequence>(TheCFG.get(), CodeBlock, Context);
117117
BlockMap = std::make_unique<StmtToBlockMap>(TheCFG.get(), Context);
@@ -125,10 +125,10 @@ bool UseAfterMoveFinder::find(Stmt *CodeBlock, const Expr *MovingCall,
125125
MoveBlock = &TheCFG->getEntry();
126126
}
127127

128-
bool Found = findInternal(MoveBlock, MovingCall, MovedVariable->getDecl(),
129-
TheUseAfterMove);
128+
auto TheUseAfterMove =
129+
findInternal(MoveBlock, MovingCall, MovedVariable->getDecl());
130130

131-
if (Found) {
131+
if (TheUseAfterMove) {
132132
if (const CFGBlock *UseBlock =
133133
BlockMap->blockContainingStmt(TheUseAfterMove->DeclRef)) {
134134
// Does the use happen in a later loop iteration than the move?
@@ -142,15 +142,14 @@ bool UseAfterMoveFinder::find(Stmt *CodeBlock, const Expr *MovingCall,
142142
: CFA.isReachable(UseBlock, MoveBlock);
143143
}
144144
}
145-
return Found;
145+
return TheUseAfterMove;
146146
}
147147

148-
bool UseAfterMoveFinder::findInternal(const CFGBlock *Block,
149-
const Expr *MovingCall,
150-
const ValueDecl *MovedVariable,
151-
UseAfterMove *TheUseAfterMove) {
148+
std::optional<UseAfterMove>
149+
UseAfterMoveFinder::findInternal(const CFGBlock *Block, const Expr *MovingCall,
150+
const ValueDecl *MovedVariable) {
152151
if (Visited.count(Block))
153-
return false;
152+
return std::nullopt;
154153

155154
// Mark the block as visited (except if this is the block containing the
156155
// std::move() and it's being visited the first time).
@@ -189,17 +188,18 @@ bool UseAfterMoveFinder::findInternal(const CFGBlock *Block,
189188
}
190189

191190
if (!HaveSavingReinit) {
192-
TheUseAfterMove->DeclRef = Use;
191+
UseAfterMove TheUseAfterMove;
192+
TheUseAfterMove.DeclRef = Use;
193193

194194
// Is this a use-after-move that depends on order of evaluation?
195195
// This is the case if the move potentially comes after the use (and we
196196
// already know that use potentially comes after the move, which taken
197197
// together tells us that the ordering is unclear).
198-
TheUseAfterMove->EvaluationOrderUndefined =
198+
TheUseAfterMove.EvaluationOrderUndefined =
199199
MovingCall != nullptr &&
200200
Sequence->potentiallyAfter(MovingCall, Use);
201201

202-
return true;
202+
return TheUseAfterMove;
203203
}
204204
}
205205
}
@@ -208,12 +208,15 @@ bool UseAfterMoveFinder::findInternal(const CFGBlock *Block,
208208
// successors.
209209
if (Reinits.empty()) {
210210
for (const auto &Succ : Block->succs()) {
211-
if (Succ && findInternal(Succ, nullptr, MovedVariable, TheUseAfterMove))
212-
return true;
211+
if (Succ) {
212+
if (auto Found = findInternal(Succ, nullptr, MovedVariable)) {
213+
return Found;
214+
}
215+
}
213216
}
214217
}
215218

216-
return false;
219+
return std::nullopt;
217220
}
218221

219222
void UseAfterMoveFinder::getUsesAndReinits(
@@ -518,9 +521,8 @@ void UseAfterMoveCheck::check(const MatchFinder::MatchResult &Result) {
518521

519522
for (Stmt *CodeBlock : CodeBlocks) {
520523
UseAfterMoveFinder Finder(Result.Context);
521-
UseAfterMove Use;
522-
if (Finder.find(CodeBlock, MovingCall, Arg, &Use))
523-
emitDiagnostic(MovingCall, Arg, Use, this, Result.Context,
524+
if (auto Use = Finder.find(CodeBlock, MovingCall, Arg))
525+
emitDiagnostic(MovingCall, Arg, *Use, this, Result.Context,
524526
determineMoveType(MoveDecl));
525527
}
526528
}

0 commit comments

Comments
 (0)