https://github.com/yronglin updated https://github.com/llvm/llvm-project/pull/91879
>From 6969f06f39363deda92d473ec14a08663c71f3b1 Mon Sep 17 00:00:00 2001 From: yronglin <yronglin...@gmail.com> Date: Sun, 12 May 2024 14:42:09 +0800 Subject: [PATCH] [Analyzer][CFG] Correctly handle rebuilted default arg and default init expression Signed-off-by: yronglin <yronglin...@gmail.com> --- clang/lib/AST/ParentMap.cpp | 16 +++++++++ clang/lib/Analysis/CFG.cpp | 38 +++++++++++++++----- clang/lib/StaticAnalyzer/Core/ExprEngine.cpp | 35 ++++++------------ 3 files changed, 56 insertions(+), 33 deletions(-) diff --git a/clang/lib/AST/ParentMap.cpp b/clang/lib/AST/ParentMap.cpp index 3d6a1cc84c7b1..534793b837bbb 100644 --- a/clang/lib/AST/ParentMap.cpp +++ b/clang/lib/AST/ParentMap.cpp @@ -97,6 +97,22 @@ static void BuildParentMap(MapTy& M, Stmt* S, BuildParentMap(M, SubStmt, OVMode); } break; + case Stmt::CXXDefaultArgExprClass: + if (auto *Arg = dyn_cast<CXXDefaultArgExpr>(S)) { + if (Arg->hasRewrittenInit()) { + M[Arg->getExpr()] = S; + BuildParentMap(M, Arg->getExpr(), OVMode); + } + } + break; + case Stmt::CXXDefaultInitExprClass: + if (auto *Init = dyn_cast<CXXDefaultInitExpr>(S)) { + if (Init->hasRewrittenInit()) { + M[Init->getExpr()] = S; + BuildParentMap(M, Init->getExpr(), OVMode); + } + } + break; default: for (Stmt *SubStmt : S->children()) { if (SubStmt) { diff --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp index 64e6155de090c..2f3f3e92516ba 100644 --- a/clang/lib/Analysis/CFG.cpp +++ b/clang/lib/Analysis/CFG.cpp @@ -556,6 +556,8 @@ class CFGBuilder { private: // Visitors to walk an AST and construct the CFG. + CFGBlock *VisitCXXDefaultArgExpr(CXXDefaultArgExpr *Default, AddStmtChoice asc); + CFGBlock *VisitCXXDefaultInitExpr(CXXDefaultInitExpr *Default, AddStmtChoice asc); CFGBlock *VisitInitListExpr(InitListExpr *ILE, AddStmtChoice asc); CFGBlock *VisitAddrLabelExpr(AddrLabelExpr *A, AddStmtChoice asc); CFGBlock *VisitAttributedStmt(AttributedStmt *A, AddStmtChoice asc); @@ -2254,16 +2256,10 @@ CFGBlock *CFGBuilder::Visit(Stmt * S, AddStmtChoice asc, asc, ExternallyDestructed); case Stmt::CXXDefaultArgExprClass: + return VisitCXXDefaultArgExpr(cast<CXXDefaultArgExpr>(S), asc); + case Stmt::CXXDefaultInitExprClass: - // FIXME: The expression inside a CXXDefaultArgExpr is owned by the - // called function's declaration, not by the caller. If we simply add - // this expression to the CFG, we could end up with the same Expr - // appearing multiple times (PR13385). - // - // It's likewise possible for multiple CXXDefaultInitExprs for the same - // expression to be used in the same function (through aggregate - // initialization). - return VisitStmt(S, asc); + return VisitCXXDefaultInitExpr(cast<CXXDefaultInitExpr>(S), asc); case Stmt::CXXBindTemporaryExprClass: return VisitCXXBindTemporaryExpr(cast<CXXBindTemporaryExpr>(S), asc); @@ -2433,6 +2429,30 @@ CFGBlock *CFGBuilder::VisitChildren(Stmt *S) { return B; } +CFGBlock *CFGBuilder::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *Arg, + AddStmtChoice asc) { + if (Arg->hasRewrittenInit()) { + if (asc.alwaysAdd(*this, Arg)) { + autoCreateBlock(); + appendStmt(Block, Arg); + } + return VisitStmt(Arg->getExpr(), asc); + } + return VisitStmt(Arg, asc); +} + +CFGBlock *CFGBuilder::VisitCXXDefaultInitExpr(CXXDefaultInitExpr *Init, + AddStmtChoice asc) { + if (Init->hasRewrittenInit()) { + if (asc.alwaysAdd(*this, Init)) { + autoCreateBlock(); + appendStmt(Block, Init); + } + return VisitStmt(Init->getExpr(), asc); + } + return VisitStmt(Init, asc); +} + CFGBlock *CFGBuilder::VisitInitListExpr(InitListExpr *ILE, AddStmtChoice asc) { if (asc.alwaysAdd(*this, ILE)) { autoCreateBlock(); diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp index 0b1edf3e5c96b..41cb4293a8451 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -1964,11 +1964,8 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, case Stmt::CXXDefaultArgExprClass: case Stmt::CXXDefaultInitExprClass: { Bldr.takeNodes(Pred); - ExplodedNodeSet PreVisit; - getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this); - - ExplodedNodeSet Tmp; - StmtNodeBuilder Bldr2(PreVisit, Tmp, *currBldrCtx); + ExplodedNodeSet CheckedSet; + getCheckerManager().runCheckersForPreStmt(CheckedSet, Pred, S, *this); const Expr *ArgE; if (const auto *DefE = dyn_cast<CXXDefaultArgExpr>(S)) @@ -1978,25 +1975,15 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, else llvm_unreachable("unknown constant wrapper kind"); - bool IsTemporary = false; - if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(ArgE)) { - ArgE = MTE->getSubExpr(); - IsTemporary = true; - } - - std::optional<SVal> ConstantVal = svalBuilder.getConstantVal(ArgE); - if (!ConstantVal) - ConstantVal = UnknownVal(); - - const LocationContext *LCtx = Pred->getLocationContext(); - for (const auto I : PreVisit) { - ProgramStateRef State = I->getState(); - State = State->BindExpr(S, LCtx, *ConstantVal); - if (IsTemporary) - State = createTemporaryRegionIfNeeded(State, LCtx, - cast<Expr>(S), - cast<Expr>(S)); - Bldr2.generateNode(S, I, State); + ExplodedNodeSet Tmp; + StmtNodeBuilder Bldr2(CheckedSet, Tmp, *currBldrCtx); + + for (auto *I : CheckedSet) { + ProgramStateRef state = (*I).getState(); + const LocationContext *LCtx = (*I).getLocationContext(); + SVal Val = state->getSVal(ArgE, LCtx); + state = state->BindExpr(S, LCtx, Val); + Bldr2.generateNode(S, I, state); } getCheckerManager().runCheckersForPostStmt(Dst, Tmp, S, *this); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits