================ @@ -453,70 +455,35 @@ 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) { - // The coroutine statement, co_return, co_await, or co_yield. - const Stmt *CoroStmt = 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; - ++I) - if (std::optional<CFGStmt> CS = I->getAs<CFGStmt>()) { - 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; - break; - } - } - if (!CoroStmt) - 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 VisitStmt(Stmt *S) override { - if (S == DeadStmt) - CoroutineSubStmt = true; - return true; - } - }; - Checker checker(DeadStmt); - checker.TraverseStmt(const_cast<Stmt *>(CoroStmt)); - return checker.CoroutineSubStmt; -} - -static bool isValidDeadStmt(const Stmt *S, const clang::CFGBlock *Block) { +static bool isValidDeadStmt(ParentMap &PM, const Stmt *S, const clang::CFGBlock *Block) { if (S->getBeginLoc().isInvalid()) return false; if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(S)) return BO->getOpcode() != BO_Comma; // 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); + return !PM.getInnerMostAncestor<CoreturnStmt, CoroutineSuspendExpr>(S); } const Stmt *DeadCodeScan::findDeadCode(const clang::CFGBlock *Block) { + auto &PM = AC.getParentMap(); + for (CFGBlock::const_iterator I = Block->begin(), E = Block->end(); I!=E; ++I) if (std::optional<CFGStmt> CS = I->getAs<CFGStmt>()) { const Stmt *S = CS->getStmt(); - if (isValidDeadStmt(S, Block)) + auto *RewrittenParent = + PM.getOuterMostAncestor<CXXDefaultArgExpr, CXXDefaultInitExpr>(S); ---------------- yronglin wrote:
I try to fix Nico's example(https://github.com/llvm/llvm-project/issues/128195) about the wrong unrachable code location. The root cause of this issue is that this PR introduce "rewritten" expressions in `CFGBlock`. When we are finding the real dead code, we should try to ignore the "rewritten" sub-expression nodes in `CXXDefaultInitExpr`/`CXXDefaultArgExpr`, but I'm not sure this option is make sense. What do you think? https://github.com/llvm/llvm-project/pull/146281 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits