aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Analysis/ReachableCode.cpp
diff options
context:
space:
mode:
authoryronglin <yronglin777@gmail.com>2025-02-01 16:58:05 +0800
committerGitHub <noreply@github.com>2025-02-01 16:58:05 +0800
commit44aa618ef67d302f5ab77cc591fb3434fe967a2e (patch)
treee7e8c4e46bfa1057f18786047748292b832072e0 /clang/lib/Analysis/ReachableCode.cpp
parent69905810c483811abff5f9971799bc8a32eb4514 (diff)
downloadllvm-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.cpp37
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) {