diff options
author | yronglin <yronglin777@gmail.com> | 2025-02-01 16:58:05 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-02-01 16:58:05 +0800 |
commit | 44aa618ef67d302f5ab77cc591fb3434fe967a2e (patch) | |
tree | e7e8c4e46bfa1057f18786047748292b832072e0 /clang/lib/Analysis/ReachableCode.cpp | |
parent | 69905810c483811abff5f9971799bc8a32eb4514 (diff) | |
download | llvm-44aa618ef67d302f5ab77cc591fb3434fe967a2e.zip llvm-44aa618ef67d302f5ab77cc591fb3434fe967a2e.tar.gz llvm-44aa618ef67d302f5ab77cc591fb3434fe967a2e.tar.bz2 |
[Analyzer][CFG] Correctly handle rebuilt default arg and default init expression (#117437)
Clang currently support extending lifetime of object bound to reference
members of aggregates, that are created from default member initializer.
This PR address this change and updaye CFG and ExprEngine.
This PR reapply https://github.com/llvm/llvm-project/pull/91879.
Fixes https://github.com/llvm/llvm-project/issues/93725.
---------
Signed-off-by: yronglin <yronglin777@gmail.com>
Diffstat (limited to 'clang/lib/Analysis/ReachableCode.cpp')
-rw-r--r-- | clang/lib/Analysis/ReachableCode.cpp | 37 |
1 files changed, 19 insertions, 18 deletions
diff --git a/clang/lib/Analysis/ReachableCode.cpp b/clang/lib/Analysis/ReachableCode.cpp index dd81c8e..3b1f716 100644 --- a/clang/lib/Analysis/ReachableCode.cpp +++ b/clang/lib/Analysis/ReachableCode.cpp @@ -454,11 +454,12 @@ bool DeadCodeScan::isDeadCodeRoot(const clang::CFGBlock *Block) { return isDeadRoot; } -// Check if the given `DeadStmt` is a coroutine statement and is a substmt of -// the coroutine statement. `Block` is the CFGBlock containing the `DeadStmt`. -static bool isInCoroutineStmt(const Stmt *DeadStmt, const CFGBlock *Block) { +// Check if the given `DeadStmt` is one of target statements or is a sub-stmt of +// them. `Block` is the CFGBlock containing the `DeadStmt`. +template <class... Ts> +static bool isDeadStmtInOneOf(const Stmt *DeadStmt, const CFGBlock *Block) { // The coroutine statement, co_return, co_await, or co_yield. - const Stmt *CoroStmt = nullptr; + const Stmt *TargetStmt = nullptr; // Find the first coroutine statement after the DeadStmt in the block. bool AfterDeadStmt = false; for (CFGBlock::const_iterator I = Block->begin(), E = Block->end(); I != E; @@ -467,32 +468,27 @@ static bool isInCoroutineStmt(const Stmt *DeadStmt, const CFGBlock *Block) { const Stmt *S = CS->getStmt(); if (S == DeadStmt) AfterDeadStmt = true; - if (AfterDeadStmt && - // For simplicity, we only check simple coroutine statements. - (llvm::isa<CoreturnStmt>(S) || llvm::isa<CoroutineSuspendExpr>(S))) { - CoroStmt = S; + if (AfterDeadStmt && llvm::isa<Ts...>(S)) { + TargetStmt = S; break; } } - if (!CoroStmt) + if (!TargetStmt) return false; struct Checker : DynamicRecursiveASTVisitor { const Stmt *DeadStmt; - bool CoroutineSubStmt = false; - Checker(const Stmt *S) : DeadStmt(S) { - // Statements captured in the CFG can be implicit. - ShouldVisitImplicitCode = true; - } + bool IsSubStmtOfTargetStmt = false; + Checker(const Stmt *S) : DeadStmt(S) { ShouldVisitImplicitCode = true; } bool VisitStmt(Stmt *S) override { if (S == DeadStmt) - CoroutineSubStmt = true; + IsSubStmtOfTargetStmt = true; return true; } }; Checker checker(DeadStmt); - checker.TraverseStmt(const_cast<Stmt *>(CoroStmt)); - return checker.CoroutineSubStmt; + checker.TraverseStmt(const_cast<Stmt *>(TargetStmt)); + return checker.IsSubStmtOfTargetStmt; } static bool isValidDeadStmt(const Stmt *S, const clang::CFGBlock *Block) { @@ -503,7 +499,12 @@ static bool isValidDeadStmt(const Stmt *S, const clang::CFGBlock *Block) { // Coroutine statements are never considered dead statements, because removing // them may change the function semantic if it is the only coroutine statement // of the coroutine. - return !isInCoroutineStmt(S, Block); + // + // If the dead stmt is a sub-stmt of CXXDefaultInitExpr and CXXDefaultArgExpr, + // we would rather expect to find CXXDefaultInitExpr and CXXDefaultArgExpr as + // a valid dead stmt. + return !isDeadStmtInOneOf<CoreturnStmt, CoroutineSuspendExpr, + CXXDefaultArgExpr, CXXDefaultInitExpr>(S, Block); } const Stmt *DeadCodeScan::findDeadCode(const clang::CFGBlock *Block) { |