Author: DonĂ¡t Nagy Date: 2026-03-11T15:08:25+01:00 New Revision: 1c424bfb03d6dd4b994a0d549e1f3e23852f1e16
URL: https://github.com/llvm/llvm-project/commit/1c424bfb03d6dd4b994a0d549e1f3e23852f1e16 DIFF: https://github.com/llvm/llvm-project/commit/1c424bfb03d6dd4b994a0d549e1f3e23852f1e16.diff LOG: [NFC][analyzer] Clarify current LocationContext and CFGBlock (#185107) The analyzer often uses the current `LocationContext` and `CFGBlock`, for example to assign unique identifiers to conjured symbols. This information is currently handled in a haphazard way: - Logic that determines this is often duplicated in several redundant locations. - It is stored in `NodeBuilderContext` objects, despite the fact that it is not actually used for building (exploded) nodes. - Many methods pass it around in arguments, while many others use it through the field `NodeBuilderContext *currBldrCtx` of `ExprEngine`. - This `currBldrCtx` points to local variables in random stack frames, e.g. there is an early return in `ExprEngine::processBranch` where it becomes stale (but AFAIK it is never dereferenced after that point). This commit starts a transition to a more principled system, where there is a single canonical source for accessing this information (methods of `ExprEngine`), which is populated once per `dispatchWorkItem` call, as close to the beginning of `dispatchWorkItem` as possible. As the transition is not yet complete, this commit keeps `currBldrCtx` to retain compatiblity with the old way of working -- but builds a nice interface around it that will be able to switch to a different, more natural data representation in the future. I intend to follow this up with additional commits that performs analogous transitions in the remaining parts of the codebase. Added: Modified: clang/include/clang/StaticAnalyzer/Core/CheckerManager.h clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h clang/lib/StaticAnalyzer/Core/CheckerManager.cpp clang/lib/StaticAnalyzer/Core/CoreEngine.cpp clang/lib/StaticAnalyzer/Core/ExprEngine.cpp clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp clang/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp Removed: ################################################################################ diff --git a/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h b/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h index bf33ce616d954..348c7eff09161 100644 --- a/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h +++ b/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h @@ -360,11 +360,8 @@ class CheckerManager { ExprEngine &Eng); /// Run checkers on end of function. - void runCheckersForEndFunction(NodeBuilderContext &BC, - ExplodedNodeSet &Dst, - ExplodedNode *Pred, - ExprEngine &Eng, - const ReturnStmt *RS); + void runCheckersForEndFunction(ExplodedNodeSet &Dst, ExplodedNode *Pred, + ExprEngine &Eng, const ReturnStmt *RS); /// Run checkers for branch condition. void runCheckersForBranchCondition(const Stmt *condition, diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h index 21749b0f42b2b..6b70fda42819c 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h @@ -339,8 +339,9 @@ class IndirectGotoNodeBuilder : public NodeBuilder { const Expr *Target; public: - IndirectGotoNodeBuilder(ExplodedNodeSet &DstSet, NodeBuilderContext &Ctx, - const Expr *Tgt, const CFGBlock *Dispatch) + IndirectGotoNodeBuilder(ExplodedNodeSet &DstSet, + const NodeBuilderContext &Ctx, const Expr *Tgt, + const CFGBlock *Dispatch) : NodeBuilder(DstSet, Ctx), DispatchBlock(*Dispatch), Target(Tgt) {} using iterator = CFGBlock::const_succ_iterator; diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h index 2ca03174fbdc9..2023a7a5b1ac8 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h @@ -159,7 +159,29 @@ class ExprEngine { SValBuilder &svalBuilder; unsigned int currStmtIdx = 0; + + /// Pointer to a (so-called, somewhat misnamed) NodeBuilderContext object + /// which has three independent roles: + /// - It holds a pointer to the CFGBlock that is currently under analysis. + /// (This is the primary way to get the current block.) + /// - It holds a pointer to the current LocationContext. (This is rarely + /// used, the location context is usually queried from a recent + /// ExplodedNode. Unfortunately it seems that these two sources of truth + /// are not always consistent.) + /// - It can be used for constructing `NodeBuilder`s. Practically all + /// `NodeBuilder` objects are useless complications in the code, so I + /// intend to replace them with direct use of `CoreEngine::makeNode`. + /// TODO: Eventually `currBldrCtx` should be replaced by two separate fields: + /// `const CFGBlock *CurrBlock` & `const LocationContext *CurrLocationContext` + /// that are kept up-to-date and are almost always non-null during the + /// analysis. I will switch to this more natural representation when + /// `NodeBuilder`s are eliminated from the code. const NodeBuilderContext *currBldrCtx = nullptr; + /// Historically `currBldrCtx` pointed to a local variable in some stack + /// frame. This field is introduced as a temporary measure to allow a gradual + /// transition. Only use this in {re,}setLocationContextAndBlock! + /// TODO: Remove this temporary hack. + std::optional<NodeBuilderContext> OwnedCurrBldrCtx; /// Helper object to determine if an Objective-C message expression /// implicitly never returns. @@ -216,7 +238,28 @@ class ExprEngine { return &CTU; } - const NodeBuilderContext &getBuilderContext() { + // FIXME: Ideally the body of this method should look like + // CurrLocationContext = LC; + // CurrBlock = B; + // where CurrLocationContext and CurrBlock are new member variables that + // fulfill the roles of `currBldrCtx` in a more natural way. + // This implementation is a temporary measure to allow a gradual transition. + void setCurrLocationContextAndBlock(const LocationContext *LC, + const CFGBlock *B) { + // Note that there is a call to resetCurrLocationContextAndBlock at the + // beginning of dispatchWorkItem. + assert(!currBldrCtx && !OwnedCurrBldrCtx && + "This should be called at most once per call to dispatchWorkItem"); + OwnedCurrBldrCtx.emplace(Engine, B, LC); + currBldrCtx = &*OwnedCurrBldrCtx; + } + + void resetCurrLocationContextAndBlock() { + currBldrCtx = nullptr; + OwnedCurrBldrCtx = std::nullopt; + } + + const NodeBuilderContext &getBuilderContext() const { assert(currBldrCtx); return *currBldrCtx; } @@ -226,9 +269,35 @@ class ExprEngine { return G.getRoot()->getLocation().getLocationContext(); } + /// Get the 'current' location context corresponding to the current work item + /// (elementary analysis step handled by `dispatchWorkItem`). + /// FIXME: This sometimes (e.g. in some `BeginFunction` callbacks) diff ers + /// from the `LocationContext` that can be obtained from diff erent sources + /// (e.g. a recent `ExplodedNode`). Traditionally this location context is + /// only used for block count calculations (`getNumVisited`); it is probably + /// wise to follow this tradition until the discrepancies are resolved. + const LocationContext *getCurrLocationContext() const { + return currBldrCtx ? currBldrCtx->getLocationContext() : nullptr; + } + + /// Get the 'current' CFGBlock corresponding to the current work item + /// (elementary analysis step handled by `dispatchWorkItem`). + const CFGBlock *getCurrBlock() const { + return currBldrCtx ? currBldrCtx->getBlock() : nullptr; + } + ConstCFGElementRef getCFGElementRef() const { - const CFGBlock *blockPtr = currBldrCtx ? currBldrCtx->getBlock() : nullptr; - return {blockPtr, currStmtIdx}; + return {getCurrBlock(), currStmtIdx}; + } + + unsigned getNumVisited(const LocationContext *LC, + const CFGBlock *Block) const { + return Engine.WList->getBlockCounter().getNumVisited(LC->getStackFrame(), + Block->getBlockID()); + } + + unsigned getNumVisitedCurrent() const { + return getNumVisited(getCurrLocationContext(), getCurrBlock()); } /// Dump graph to the specified filename. @@ -293,7 +362,7 @@ class ExprEngine { /// processCFGElement - Called by CoreEngine. Used to generate new successor /// nodes by processing the 'effects' of a CFG element. void processCFGElement(const CFGElement E, ExplodedNode *Pred, - unsigned StmtIdx, NodeBuilderContext *Ctx); + unsigned StmtIdx); void ProcessStmt(const Stmt *S, ExplodedNode *Pred); @@ -320,35 +389,30 @@ class ExprEngine { void processCFGBlockEntrance(const BlockEdge &L, const BlockEntrance &BE, NodeBuilder &Builder, ExplodedNode *Pred); - void runCheckersForBlockEntrance(const NodeBuilderContext &BldCtx, - const BlockEntrance &Entrance, + void runCheckersForBlockEntrance(const BlockEntrance &Entrance, ExplodedNode *Pred, ExplodedNodeSet &Dst); /// ProcessBranch - Called by CoreEngine. Used to generate successor nodes by /// processing the 'effects' of a branch condition. If the branch condition /// is a loop condition, IterationsCompletedInLoop is the number of completed /// iterations (otherwise it's std::nullopt). - void processBranch(const Stmt *Condition, NodeBuilderContext &BuilderCtx, - ExplodedNode *Pred, ExplodedNodeSet &Dst, - const CFGBlock *DstT, const CFGBlock *DstF, + void processBranch(const Stmt *Condition, ExplodedNode *Pred, + ExplodedNodeSet &Dst, const CFGBlock *DstT, + const CFGBlock *DstF, std::optional<unsigned> IterationsCompletedInLoop); /// Called by CoreEngine. /// Used to generate successor nodes for temporary destructors depending /// on whether the corresponding constructor was visited. void processCleanupTemporaryBranch(const CXXBindTemporaryExpr *BTE, - NodeBuilderContext &BldCtx, ExplodedNode *Pred, ExplodedNodeSet &Dst, const CFGBlock *DstT, const CFGBlock *DstF); /// Called by CoreEngine. Used to processing branching behavior /// at static initializers. - void processStaticInitializer(const DeclStmt *DS, - NodeBuilderContext& BuilderCtx, - ExplodedNode *Pred, - ExplodedNodeSet &Dst, - const CFGBlock *DstT, + void processStaticInitializer(const DeclStmt *DS, ExplodedNode *Pred, + ExplodedNodeSet &Dst, const CFGBlock *DstT, const CFGBlock *DstF); /// processIndirectGoto - Called by CoreEngine. Used to generate successor @@ -358,29 +422,23 @@ class ExprEngine { /// ProcessSwitch - Called by CoreEngine. Used to generate successor /// nodes by processing the 'effects' of a switch statement. - void processSwitch(NodeBuilderContext &BC, const SwitchStmt *Switch, - ExplodedNode *Pred, ExplodedNodeSet &Dst); + void processSwitch(const SwitchStmt *Switch, ExplodedNode *Pred, + ExplodedNodeSet &Dst); /// Called by CoreEngine. Used to notify checkers that processing a /// function has begun. Called for both inlined and top-level functions. - void processBeginOfFunction(NodeBuilderContext &BC, - ExplodedNode *Pred, ExplodedNodeSet &Dst, + void processBeginOfFunction(ExplodedNode *Pred, ExplodedNodeSet &Dst, const BlockEdge &L); /// Called by CoreEngine. Used to notify checkers that processing a /// function has ended. Called for both inlined and top-level functions. - void processEndOfFunction(NodeBuilderContext& BC, - ExplodedNode *Pred, - const ReturnStmt *RS = nullptr); + void processEndOfFunction(ExplodedNode *Pred, const ReturnStmt *RS = nullptr); /// Remove dead bindings/symbols before exiting a function. - void removeDeadOnEndOfFunction(NodeBuilderContext& BC, - ExplodedNode *Pred, - ExplodedNodeSet &Dst); + void removeDeadOnEndOfFunction(ExplodedNode *Pred, ExplodedNodeSet &Dst); /// Generate the entry node of the callee. - void processCallEnter(NodeBuilderContext& BC, CallEnter CE, - ExplodedNode *Pred); + void processCallEnter(CallEnter CE, ExplodedNode *Pred); /// Generate the sequence of nodes that simulate the call exit and the post /// visit for CallExpr. @@ -706,9 +764,7 @@ class ExprEngine { /// Return the CFG element corresponding to the worklist element /// that is currently being processed by ExprEngine. - CFGElement getCurrentCFGElement() { - return (*currBldrCtx->getBlock())[currStmtIdx]; - } + CFGElement getCurrentCFGElement() { return (*getCurrBlock())[currStmtIdx]; } /// Create a new state in which the call return value is binded to the /// call origin expression. diff --git a/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp b/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp index 8ee4832643b91..20a906dde38b1 100644 --- a/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp +++ b/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp @@ -505,15 +505,14 @@ void CheckerManager::runCheckersForBeginFunction(ExplodedNodeSet &Dst, /// Run checkers for end of path. // Note, We do not chain the checker output (like in expandGraphWithCheckers) // for this callback since end of path nodes are expected to be final. -void CheckerManager::runCheckersForEndFunction(NodeBuilderContext &BC, - ExplodedNodeSet &Dst, +void CheckerManager::runCheckersForEndFunction(ExplodedNodeSet &Dst, ExplodedNode *Pred, ExprEngine &Eng, const ReturnStmt *RS) { // We define the builder outside of the loop because if at least one checker // creates a successor for Pred, we do not need to generate an // autotransition for it. - NodeBuilder Bldr(Pred, Dst, BC); + NodeBuilder Bldr(Pred, Dst, Eng.getBuilderContext()); for (const auto &checkFn : EndFunctionCheckers) { const ProgramPoint &L = FunctionExitPoint(RS, Pred->getLocationContext(), checkFn.Checker); diff --git a/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp b/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp index d32db1669e1fe..3dc9c53bd30d7 100644 --- a/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp +++ b/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp @@ -119,9 +119,10 @@ bool CoreEngine::ExecuteWorkList(const LocationContext *L, unsigned MaxSteps, assert(IsNew); G.designateAsRoot(Node); - NodeBuilderContext BuilderCtx(*this, StartLoc.getDst(), Node); + ExprEng.setCurrLocationContextAndBlock(Node->getLocationContext(), Succ); + ExplodedNodeSet DstBegin; - ExprEng.processBeginOfFunction(BuilderCtx, Node, DstBegin, StartLoc); + ExprEng.processBeginOfFunction(Node, DstBegin, StartLoc); enqueue(DstBegin); } @@ -216,6 +217,14 @@ void CoreEngine::dispatchWorkItem(ExplodedNode *Pred, ProgramPoint Loc, return timeTraceMetadata(Pred, Loc); }}; PrettyStackTraceLocationContext CrashInfo(Pred->getLocationContext()); + + // This work item is not necessarily related to the previous one, so + // the old current LocationContext and Block is no longer relevant. + // The new current LocationContext and Block should be set soon, but this + // guarantees that buggy access before that will trigger loud crashes instead + // of silently using stale data. + ExprEng.resetCurrLocationContextAndBlock(); + // Dispatch on the location type. switch (Loc.getKind()) { case ProgramPoint::BlockEdgeKind: @@ -259,7 +268,7 @@ void CoreEngine::dispatchWorkItem(ExplodedNode *Pred, ProgramPoint Loc, void CoreEngine::HandleBlockEdge(const BlockEdge &L, ExplodedNode *Pred) { const CFGBlock *Blk = L.getDst(); - NodeBuilderContext BuilderCtx(*this, Blk, Pred); + ExprEng.setCurrLocationContextAndBlock(Pred->getLocationContext(), Blk); // Mark this block as visited. const LocationContext *LC = Pred->getLocationContext(); @@ -280,17 +289,15 @@ void CoreEngine::HandleBlockEdge(const BlockEdge &L, ExplodedNode *Pred) { }, /*IsPrunable=*/true)); // Perform the transition. - ExplodedNodeSet Dst; - NodeBuilder Bldr(Pred, Dst, BuilderCtx); - Pred = Bldr.generateNode(P, Pred->getState(), Pred); + Pred = makeNode(P, Pred->getState(), Pred); if (!Pred) return; } // Check if we are entering the EXIT block. - if (Blk == &(L.getLocationContext()->getCFG()->getExit())) { - assert(L.getLocationContext()->getCFG()->getExit().empty() && - "EXIT block cannot contain Stmts."); + const CFGBlock &ExitBlk = L.getLocationContext()->getCFG()->getExit(); + if (Blk == &ExitBlk) { + assert(ExitBlk.empty() && "EXIT block cannot contain Stmts."); // Get return statement.. const ReturnStmt *RS = nullptr; @@ -306,11 +313,11 @@ void CoreEngine::HandleBlockEdge(const BlockEdge &L, ExplodedNode *Pred) { ExplodedNodeSet CheckerNodes; BlockEntrance BE(L.getSrc(), L.getDst(), Pred->getLocationContext()); - ExprEng.runCheckersForBlockEntrance(BuilderCtx, BE, Pred, CheckerNodes); + ExprEng.runCheckersForBlockEntrance(BE, Pred, CheckerNodes); // Process the final state transition. for (ExplodedNode *P : CheckerNodes) { - ExprEng.processEndOfFunction(BuilderCtx, P, RS); + ExprEng.processEndOfFunction(P, RS); } // This path is done. Don't enqueue any more nodes. @@ -320,7 +327,7 @@ void CoreEngine::HandleBlockEdge(const BlockEdge &L, ExplodedNode *Pred) { // Call into the ExprEngine to process entering the CFGBlock. BlockEntrance BE(L.getSrc(), L.getDst(), Pred->getLocationContext()); ExplodedNodeSet DstNodes; - NodeBuilder Builder(Pred, DstNodes, BuilderCtx); + NodeBuilder Builder(Pred, DstNodes, ExprEng.getBuilderContext()); ExprEng.processCFGBlockEntrance(L, BE, Builder, Pred); // Auto-generate a node. @@ -330,7 +337,7 @@ void CoreEngine::HandleBlockEdge(const BlockEdge &L, ExplodedNode *Pred) { ExplodedNodeSet CheckerNodes; for (auto *N : DstNodes) { - ExprEng.runCheckersForBlockEntrance(BuilderCtx, BE, N, CheckerNodes); + ExprEng.runCheckersForBlockEntrance(BE, N, CheckerNodes); } // Enqueue nodes onto the worklist. @@ -349,14 +356,17 @@ void CoreEngine::HandleBlockEntrance(const BlockEntrance &L, // Process the entrance of the block. if (std::optional<CFGElement> E = L.getFirstElement()) { - NodeBuilderContext Ctx(*this, L.getBlock(), Pred); - ExprEng.processCFGElement(*E, Pred, 0, &Ctx); + ExprEng.setCurrLocationContextAndBlock(Pred->getLocationContext(), + L.getBlock()); + ExprEng.processCFGElement(*E, Pred, 0); } else HandleBlockExit(L.getBlock(), Pred); } void CoreEngine::HandleBlockExit(const CFGBlock * B, ExplodedNode *Pred) { if (const Stmt *Term = B->getTerminatorStmt()) { + ExprEng.setCurrLocationContextAndBlock(Pred->getLocationContext(), B); + switch (Term->getStmtClass()) { default: llvm_unreachable("Analysis for this terminator not implemented."); @@ -425,11 +435,10 @@ void CoreEngine::HandleBlockExit(const CFGBlock * B, ExplodedNode *Pred) { case Stmt::IndirectGotoStmtClass: { // Only 1 successor: the indirect goto dispatch block. assert(B->succ_size() == 1); - NodeBuilderContext Ctx(*this, B, Pred); ExplodedNodeSet Dst; IndirectGotoNodeBuilder Builder( - Dst, Ctx, cast<IndirectGotoStmt>(Term)->getTarget(), - *(B->succ_begin())); + Dst, ExprEng.getBuilderContext(), + cast<IndirectGotoStmt>(Term)->getTarget(), *(B->succ_begin())); ExprEng.processIndirectGoto(Builder, Pred); // Enqueue the new frontier onto the worklist. @@ -452,9 +461,8 @@ void CoreEngine::HandleBlockExit(const CFGBlock * B, ExplodedNode *Pred) { return; case Stmt::SwitchStmtClass: { - NodeBuilderContext Ctx(*this, B, Pred); ExplodedNodeSet Dst; - ExprEng.processSwitch(Ctx, cast<SwitchStmt>(Term), Pred, Dst); + ExprEng.processSwitch(cast<SwitchStmt>(Term), Pred, Dst); // Enqueue the new frontier onto the worklist. enqueue(Dst); return; @@ -485,16 +493,16 @@ void CoreEngine::HandleBlockExit(const CFGBlock * B, ExplodedNode *Pred) { } void CoreEngine::HandleCallEnter(const CallEnter &CE, ExplodedNode *Pred) { - NodeBuilderContext BuilderCtx(*this, CE.getEntry(), Pred); - ExprEng.processCallEnter(BuilderCtx, CE, Pred); + ExprEng.setCurrLocationContextAndBlock(Pred->getLocationContext(), + CE.getEntry()); + ExprEng.processCallEnter(CE, Pred); } void CoreEngine::HandleBranch(const Stmt *Cond, const Stmt *Term, const CFGBlock * B, ExplodedNode *Pred) { assert(B->succ_size() == 2); - NodeBuilderContext Ctx(*this, B, Pred); ExplodedNodeSet Dst; - ExprEng.processBranch(Cond, Ctx, Pred, Dst, *(B->succ_begin()), + ExprEng.processBranch(Cond, Pred, Dst, *(B->succ_begin()), *(B->succ_begin() + 1), getCompletedIterationCount(B, Pred)); // Enqueue the new frontier onto the worklist. @@ -505,10 +513,9 @@ void CoreEngine::HandleCleanupTemporaryBranch(const CXXBindTemporaryExpr *BTE, const CFGBlock *B, ExplodedNode *Pred) { assert(B->succ_size() == 2); - NodeBuilderContext Ctx(*this, B, Pred); ExplodedNodeSet Dst; - ExprEng.processCleanupTemporaryBranch(BTE, Ctx, Pred, Dst, *(B->succ_begin()), - *(B->succ_begin() + 1)); + ExprEng.processCleanupTemporaryBranch(BTE, Pred, Dst, *(B->succ_begin()), + *(B->succ_begin() + 1)); // Enqueue the new frontier onto the worklist. enqueue(Dst); } @@ -516,10 +523,9 @@ void CoreEngine::HandleCleanupTemporaryBranch(const CXXBindTemporaryExpr *BTE, void CoreEngine::HandleStaticInit(const DeclStmt *DS, const CFGBlock *B, ExplodedNode *Pred) { assert(B->succ_size() == 2); - NodeBuilderContext Ctx(*this, B, Pred); ExplodedNodeSet Dst; - ExprEng.processStaticInitializer(DS, Ctx, Pred, Dst, - *(B->succ_begin()), *(B->succ_begin()+1)); + ExprEng.processStaticInitializer(DS, Pred, Dst, *(B->succ_begin()), + *(B->succ_begin() + 1)); // Enqueue the new frontier onto the worklist. enqueue(Dst); } @@ -538,8 +544,8 @@ void CoreEngine::HandlePostStmt(const CFGBlock *B, unsigned StmtIdx, if (StmtIdx == B->size()) HandleBlockExit(B, Pred); else { - NodeBuilderContext Ctx(*this, B, Pred); - ExprEng.processCFGElement((*B)[StmtIdx], Pred, StmtIdx, &Ctx); + ExprEng.setCurrLocationContextAndBlock(Pred->getLocationContext(), B); + ExprEng.processCFGElement((*B)[StmtIdx], Pred, StmtIdx); } } diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp index bc8e9040444c9..ad419bbca50e6 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -422,7 +422,7 @@ ProgramStateRef ExprEngine::createTemporaryRegionIfNeeded( case SubobjectAdjustment::MemberPointerAdjustment: // FIXME: Unimplemented. State = State->invalidateRegions(Reg, getCFGElementRef(), - currBldrCtx->blockCount(), LC, true, + getNumVisitedCurrent(), LC, true, nullptr, nullptr, nullptr); return State; } @@ -439,7 +439,7 @@ ProgramStateRef ExprEngine::createTemporaryRegionIfNeeded( SVal InitVal = State->getSVal(Init, LC); if (InitVal.isUnknown()) { InitVal = getSValBuilder().conjureSymbolVal( - getCFGElementRef(), LC, Init->getType(), currBldrCtx->blockCount()); + getCFGElementRef(), LC, Init->getType(), getNumVisitedCurrent()); State = State->bindLoc(BaseReg.castAs<Loc>(), InitVal, LC, false); // Then we'd need to take the value that certainly exists and bind it @@ -449,7 +449,7 @@ ProgramStateRef ExprEngine::createTemporaryRegionIfNeeded( // compute the value. InitValWithAdjustments = getSValBuilder().conjureSymbolVal( getCFGElementRef(), LC, InitWithAdjustments->getType(), - currBldrCtx->blockCount()); + getNumVisitedCurrent()); } State = State->bindLoc(Reg.castAs<Loc>(), InitValWithAdjustments, LC, false); @@ -966,9 +966,8 @@ void ExprEngine::processEndWorklist() { } void ExprEngine::processCFGElement(const CFGElement E, ExplodedNode *Pred, - unsigned StmtIdx, NodeBuilderContext *Ctx) { + unsigned StmtIdx) { currStmtIdx = StmtIdx; - currBldrCtx = Ctx; switch (E.getKind()) { case CFGElement::Statement: @@ -1144,7 +1143,7 @@ void ExprEngine::ProcessStmt(const Stmt *currStmt, ExplodedNode *Pred) { } // Enqueue the new nodes onto the work list. - Engine.enqueueStmtNodes(Dst, currBldrCtx->getBlock(), currStmtIdx); + Engine.enqueueStmtNodes(Dst, getCurrBlock(), currStmtIdx); } void ExprEngine::ProcessLoopExit(const Stmt* S, ExplodedNode *Pred) { @@ -1159,7 +1158,7 @@ void ExprEngine::ProcessLoopExit(const Stmt* S, ExplodedNode *Pred) { LoopExit PP(S, Pred->getLocationContext()); ExplodedNode *N = Engine.makeNode(PP, NewState, Pred); if (N && !N->isSink()) - Engine.enqueueStmtNode(N, currBldrCtx->getBlock(), currStmtIdx); + Engine.enqueueStmtNode(N, getCurrBlock(), currStmtIdx); } void ExprEngine::ProcessInitializer(const CFGInitializer CFGInit, @@ -1217,7 +1216,7 @@ void ExprEngine::ProcessInitializer(const CFGInitializer CFGInit, SValBuilder &SVB = getSValBuilder(); InitVal = SVB.conjureSymbolVal(getCFGElementRef(), stackFrame, - Field->getType(), currBldrCtx->blockCount()); + Field->getType(), getNumVisitedCurrent()); } } else { InitVal = State->getSVal(BMI->getInit(), stackFrame); @@ -1248,7 +1247,7 @@ void ExprEngine::ProcessInitializer(const CFGInitializer CFGInit, for (ExplodedNode *Pred : Tmp) Dst.Add(Engine.makeNode(PP, Pred->getState(), Pred)); // Enqueue the new nodes onto the work list. - Engine.enqueueStmtNodes(Dst, currBldrCtx->getBlock(), currStmtIdx); + Engine.enqueueStmtNodes(Dst, getCurrBlock(), currStmtIdx); } std::pair<ProgramStateRef, uint64_t> @@ -1312,7 +1311,7 @@ void ExprEngine::ProcessImplicitDtor(const CFGImplicitDtor D, } // Enqueue the new nodes onto the work list. - Engine.enqueueStmtNodes(Dst, currBldrCtx->getBlock(), currStmtIdx); + Engine.enqueueStmtNodes(Dst, getCurrBlock(), currStmtIdx); } void ExprEngine::ProcessNewAllocator(const CXXNewExpr *NE, @@ -1331,7 +1330,7 @@ void ExprEngine::ProcessNewAllocator(const CXXNewExpr *NE, getCFGElementRef()); Dst.Add(Engine.makeNode(PP, Pred->getState(), Pred)); } - Engine.enqueueStmtNodes(Dst, currBldrCtx->getBlock(), currStmtIdx); + Engine.enqueueStmtNodes(Dst, getCurrBlock(), currStmtIdx); } void ExprEngine::ProcessAutomaticObjDtor(const CFGAutomaticObjDtor Dtor, @@ -1638,12 +1637,11 @@ void ExprEngine::ProcessTemporaryDtor(const CFGTemporaryDtor D, } void ExprEngine::processCleanupTemporaryBranch(const CXXBindTemporaryExpr *BTE, - NodeBuilderContext &BldCtx, ExplodedNode *Pred, ExplodedNodeSet &Dst, const CFGBlock *DstT, const CFGBlock *DstF) { - BranchNodeBuilder TempDtorBuilder(Dst, BldCtx, DstT, DstF); + BranchNodeBuilder TempDtorBuilder(Dst, *currBldrCtx, DstT, DstF); ProgramStateRef State = Pred->getState(); const LocationContext *LC = Pred->getLocationContext(); if (getObjectUnderConstruction(State, BTE, LC)) { @@ -1844,7 +1842,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, case Stmt::OMPMetaDirectiveClass: case Stmt::HLSLOutArgExprClass: { const ExplodedNode *node = Bldr.generateSink(S, Pred, Pred->getState()); - Engine.addAbortedBlock(node, currBldrCtx->getBlock()); + Engine.addAbortedBlock(node, getCurrBlock()); break; } @@ -2052,7 +2050,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, const LocationContext *LCtx = N->getLocationContext(); SVal result = svalBuilder.conjureSymbolVal( /*symbolTag=*/nullptr, getCFGElementRef(), LCtx, resultType, - currBldrCtx->blockCount()); + getNumVisitedCurrent()); ProgramStateRef State = N->getState()->BindExpr(Ex, LCtx, result); // Escape pointers passed into the list, unless it's an ObjC boxed @@ -2120,7 +2118,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, Bldr.addNodes(Dst); } else { const ExplodedNode *node = Bldr.generateSink(S, Pred, Pred->getState()); - Engine.addAbortedBlock(node, currBldrCtx->getBlock()); + Engine.addAbortedBlock(node, getCurrBlock()); } break; @@ -2640,17 +2638,14 @@ void ExprEngine::processCFGBlockEntrance(const BlockEdge &L, } } -void ExprEngine::runCheckersForBlockEntrance(const NodeBuilderContext &BldCtx, - const BlockEntrance &Entrance, +void ExprEngine::runCheckersForBlockEntrance(const BlockEntrance &Entrance, ExplodedNode *Pred, ExplodedNodeSet &Dst) { llvm::PrettyStackTraceFormat CrashInfo( "Processing block entrance B%d -> B%d", Entrance.getPreviousBlock()->getBlockID(), Entrance.getBlock()->getBlockID()); - currBldrCtx = &BldCtx; getCheckerManager().runCheckersForBlockEntrance(Dst, Pred, Entrance, *this); - currBldrCtx = nullptr; } //===----------------------------------------------------------------------===// @@ -2835,16 +2830,15 @@ assumeCondition(const Stmt *Condition, ExplodedNode *N) { } void ExprEngine::processBranch( - const Stmt *Condition, NodeBuilderContext &BldCtx, ExplodedNode *Pred, - ExplodedNodeSet &Dst, const CFGBlock *DstT, const CFGBlock *DstF, + const Stmt *Condition, ExplodedNode *Pred, ExplodedNodeSet &Dst, + const CFGBlock *DstT, const CFGBlock *DstF, std::optional<unsigned> IterationsCompletedInLoop) { assert((!Condition || !isa<CXXBindTemporaryExpr>(Condition)) && "CXXBindTemporaryExprs are handled by processBindTemporary."); - currBldrCtx = &BldCtx; // Check for NULL conditions; e.g. "for(;;)" if (!Condition) { - BranchNodeBuilder NullCondBldr(Dst, BldCtx, DstT, DstF); + BranchNodeBuilder NullCondBldr(Dst, *currBldrCtx, DstT, DstF); NullCondBldr.generateNode(Pred->getState(), true, Pred); return; } @@ -2852,7 +2846,7 @@ void ExprEngine::processBranch( if (const auto *Ex = dyn_cast<Expr>(Condition)) Condition = Ex->IgnoreParens(); - Condition = ResolveCondition(Condition, BldCtx.getBlock()); + Condition = ResolveCondition(Condition, getCurrBlock()); PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(), Condition->getBeginLoc(), "Error evaluating branch"); @@ -2864,7 +2858,7 @@ void ExprEngine::processBranch( if (CheckersOutSet.empty()) return; - BranchNodeBuilder Builder(Dst, BldCtx, DstT, DstF); + BranchNodeBuilder Builder(Dst, *currBldrCtx, DstT, DstF); for (ExplodedNode *PredN : CheckersOutSet) { ProgramStateRef PrevState = PredN->getState(); @@ -2954,7 +2948,6 @@ void ExprEngine::processBranch( Builder.generateNode(StFalse, false, PredN); } } - currBldrCtx = nullptr; } /// The GDM component containing the set of global variables which have been @@ -2962,23 +2955,21 @@ void ExprEngine::processBranch( REGISTER_TRAIT_WITH_PROGRAMSTATE(InitializedGlobalsSet, llvm::ImmutableSet<const VarDecl *>) -void ExprEngine::processStaticInitializer( - const DeclStmt *DS, NodeBuilderContext &BuilderCtx, ExplodedNode *Pred, - ExplodedNodeSet &Dst, const CFGBlock *DstT, const CFGBlock *DstF) { - currBldrCtx = &BuilderCtx; - +void ExprEngine::processStaticInitializer(const DeclStmt *DS, + ExplodedNode *Pred, + ExplodedNodeSet &Dst, + const CFGBlock *DstT, + const CFGBlock *DstF) { const auto *VD = cast<VarDecl>(DS->getSingleDecl()); ProgramStateRef state = Pred->getState(); bool initHasRun = state->contains<InitializedGlobalsSet>(VD); - BranchNodeBuilder Builder(Dst, BuilderCtx, DstT, DstF); + BranchNodeBuilder Builder(Dst, *currBldrCtx, DstT, DstF); if (!initHasRun) { state = state->add<InitializedGlobalsSet>(VD); } Builder.generateNode(state, initHasRun, Pred); - - currBldrCtx = nullptr; } /// processIndirectGoto - Called by CoreEngine. Used to generate successor @@ -3014,18 +3005,15 @@ void ExprEngine::processIndirectGoto(IndirectGotoNodeBuilder &Builder, Builder.generateNode(Succ, State, Pred); } -void ExprEngine::processBeginOfFunction(NodeBuilderContext &BC, - ExplodedNode *Pred, +void ExprEngine::processBeginOfFunction(ExplodedNode *Pred, ExplodedNodeSet &Dst, const BlockEdge &L) { - SaveAndRestore<const NodeBuilderContext *> NodeContextRAII(currBldrCtx, &BC); getCheckerManager().runCheckersForBeginFunction(Dst, L, Pred, *this); } /// ProcessEndPath - Called by CoreEngine. Used to generate end-of-path /// nodes when the control reaches the end of a function. -void ExprEngine::processEndOfFunction(NodeBuilderContext& BC, - ExplodedNode *Pred, +void ExprEngine::processEndOfFunction(ExplodedNode *Pred, const ReturnStmt *RS) { ProgramStateRef State = Pred->getState(); @@ -3064,9 +3052,7 @@ void ExprEngine::processEndOfFunction(NodeBuilderContext& BC, // Perform the transition with cleanups. if (State != Pred->getState()) { - ExplodedNodeSet PostCleanup; - NodeBuilder Bldr(Pred, PostCleanup, BC); - Pred = Bldr.generateNode(Pred->getLocation(), State, Pred); + Pred = Engine.makeNode(Pred->getLocation(), State, Pred); if (!Pred) { // The node with clean temporaries already exists. We might have reached // it on a path on which we initialize diff erent temporaries. @@ -3081,13 +3067,13 @@ void ExprEngine::processEndOfFunction(NodeBuilderContext& BC, if (Pred->getLocationContext()->inTopFrame()) { // Remove dead symbols. ExplodedNodeSet AfterRemovedDead; - removeDeadOnEndOfFunction(BC, Pred, AfterRemovedDead); + removeDeadOnEndOfFunction(Pred, AfterRemovedDead); // Notify checkers. for (const auto I : AfterRemovedDead) - getCheckerManager().runCheckersForEndFunction(BC, Dst, I, *this, RS); + getCheckerManager().runCheckersForEndFunction(Dst, I, *this, RS); } else { - getCheckerManager().runCheckersForEndFunction(BC, Dst, Pred, *this, RS); + getCheckerManager().runCheckersForEndFunction(Dst, Pred, *this, RS); } Engine.enqueueEndOfFunction(Dst, RS); @@ -3095,12 +3081,11 @@ void ExprEngine::processEndOfFunction(NodeBuilderContext& BC, /// ProcessSwitch - Called by CoreEngine. Used to generate successor /// nodes by processing the 'effects' of a switch statement. -void ExprEngine::processSwitch(NodeBuilderContext &BC, const SwitchStmt *Switch, - ExplodedNode *Pred, ExplodedNodeSet &Dst) { - currBldrCtx = &BC; +void ExprEngine::processSwitch(const SwitchStmt *Switch, ExplodedNode *Pred, + ExplodedNodeSet &Dst) { const Expr *Condition = Switch->getCond(); - SwitchNodeBuilder Builder(Dst, BC); + SwitchNodeBuilder Builder(Dst, *currBldrCtx); ExplodedNodeSet CheckersOutSet; getCheckerManager().runCheckersForBranchCondition( @@ -3172,8 +3157,6 @@ void ExprEngine::processSwitch(NodeBuilderContext &BC, const SwitchStmt *Switch, Builder.generateDefaultCaseNode(State, Node); } - - currBldrCtx = nullptr; } //===----------------------------------------------------------------------===// @@ -3601,7 +3584,7 @@ void ExprEngine::VisitAtomicExpr(const AtomicExpr *AE, ExplodedNode *Pred, } State = State->invalidateRegions(ValuesToInvalidate, getCFGElementRef(), - currBldrCtx->blockCount(), LCtx, + getNumVisitedCurrent(), LCtx, /*CausedByPointerEscape*/ true, /*Symbols=*/nullptr); @@ -3950,7 +3933,7 @@ void ExprEngine::VisitGCCAsmStmt(const GCCAsmStmt *A, ExplodedNode *Pred, if (std::optional<Loc> LV = X.getAs<Loc>()) state = state->invalidateRegions(*LV, getCFGElementRef(), - currBldrCtx->blockCount(), + getNumVisitedCurrent(), Pred->getLocationContext(), /*CausedByPointerEscape=*/true); } @@ -3961,7 +3944,7 @@ void ExprEngine::VisitGCCAsmStmt(const GCCAsmStmt *A, ExplodedNode *Pred, if (std::optional<Loc> LV = X.getAs<Loc>()) state = state->invalidateRegions(*LV, getCFGElementRef(), - currBldrCtx->blockCount(), + getNumVisitedCurrent(), Pred->getLocationContext(), /*CausedByPointerEscape=*/true); } diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp index b7fac30500d26..67beed5dbb6fb 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp @@ -65,7 +65,7 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B, // EXPERIMENTAL: "Conjured" symbols. // FIXME: Handle structs. if (RightV.isUnknown()) { - unsigned Count = currBldrCtx->blockCount(); + unsigned Count = getNumVisitedCurrent(); RightV = svalBuilder.conjureSymbolVal(nullptr, getCFGElementRef(), LCtx, Count); } @@ -83,7 +83,7 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B, if (B->isAdditiveOp()) { // TODO: This can be removed after we enable history tracking with // SymSymExpr. - unsigned Count = currBldrCtx->blockCount(); + unsigned Count = getNumVisitedCurrent(); RightV = conjureOffsetSymbolOnLocation( RightV, LeftV, getCFGElementRef(), RHS->getType(), svalBuilder, Count, LCtx); @@ -170,7 +170,7 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B, // LValue on the LHS will bind to. LHSVal = svalBuilder.conjureSymbolVal(/*symbolTag=*/nullptr, getCFGElementRef(), LCtx, LTy, - currBldrCtx->blockCount()); + getNumVisitedCurrent()); // However, we need to convert the symbol to the computation type. Result = svalBuilder.evalCast(LHSVal, CTy, LTy); } else { @@ -201,9 +201,8 @@ void ExprEngine::VisitBlockExpr(const BlockExpr *BE, ExplodedNode *Pred, const BlockDecl *BD = BE->getBlockDecl(); // Get the value of the block itself. - SVal V = svalBuilder.getBlockPointer(BD, T, - Pred->getLocationContext(), - currBldrCtx->blockCount()); + SVal V = svalBuilder.getBlockPointer(BD, T, Pred->getLocationContext(), + getNumVisitedCurrent()); ProgramStateRef State = Pred->getState(); @@ -498,7 +497,7 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex, if (val.isUnknown()) { DefinedOrUnknownSVal NewSym = svalBuilder.conjureSymbolVal( /*symbolTag=*/nullptr, getCFGElementRef(), LCtx, resultType, - currBldrCtx->blockCount()); + getNumVisitedCurrent()); state = state->BindExpr(CastE, LCtx, NewSym); } else // Else, bind to the derived region value. @@ -522,7 +521,7 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex, if (val.isUnknown()) { val = svalBuilder.conjureSymbolVal( /*symbolTag=*/nullptr, getCFGElementRef(), LCtx, resultType, - currBldrCtx->blockCount()); + getNumVisitedCurrent()); } state = state->BindExpr(CastE, LCtx, val); Bldr.generateNode(CastE, Pred, state); @@ -568,7 +567,7 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex, resultType = getContext().getPointerType(resultType); SVal result = svalBuilder.conjureSymbolVal( /*symbolTag=*/nullptr, getCFGElementRef(), LCtx, resultType, - currBldrCtx->blockCount()); + getNumVisitedCurrent()); state = state->BindExpr(CastE, LCtx, result); Bldr.generateNode(CastE, Pred, state); continue; @@ -661,7 +660,7 @@ void ExprEngine::VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred, InitVal = svalBuilder.conjureSymbolVal( /*symbolTag=*/nullptr, getCFGElementRef(), LC, Ty, - currBldrCtx->blockCount()); + getNumVisitedCurrent()); } @@ -831,7 +830,7 @@ void ExprEngine::VisitGuardedExpr(const Expr *Ex, if (!hasValue) V = svalBuilder.conjureSymbolVal(nullptr, getCFGElementRef(), LCtx, - currBldrCtx->blockCount()); + getNumVisitedCurrent()); // Generate a new node with the binding from the appropriate path. B.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V, true)); @@ -1115,7 +1114,7 @@ void ExprEngine::VisitIncrementDecrementOperator(const UnaryOperator* U, if (Result.isUnknown()){ DefinedOrUnknownSVal SymVal = svalBuilder.conjureSymbolVal( /*symbolTag=*/nullptr, getCFGElementRef(), LCtx, - currBldrCtx->blockCount()); + getNumVisitedCurrent()); Result = SymVal; // If the value is a location, ++/-- should always preserve diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp index 07852984e4ee3..0866dda766667 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp @@ -254,7 +254,7 @@ SVal ExprEngine::computeObjectUnderConstruction( QualType ReturnTy = RetE->getType(); QualType RegionTy = ACtx.getPointerType(ReturnTy); return SVB.conjureSymbolVal(&TopLevelSymRegionTag, getCFGElementRef(), - SFC, RegionTy, currBldrCtx->blockCount()); + SFC, RegionTy, getNumVisitedCurrent()); } llvm_unreachable("Unhandled return value construction context!"); } @@ -975,7 +975,7 @@ void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred, // really part of the CXXNewExpr because they happen BEFORE the // CXXConstructExpr subexpression. See PR12014 for some discussion. - unsigned blockCount = currBldrCtx->blockCount(); + unsigned blockCount = getNumVisitedCurrent(); const LocationContext *LCtx = Pred->getLocationContext(); SVal symVal = UnknownVal(); FunctionDecl *FD = CNE->getOperatorNew(); @@ -1138,7 +1138,7 @@ void ExprEngine::VisitCXXCatchStmt(const CXXCatchStmt *CS, ExplodedNode *Pred, const LocationContext *LCtx = Pred->getLocationContext(); SVal V = svalBuilder.conjureSymbolVal(getCFGElementRef(), LCtx, VD->getType(), - currBldrCtx->blockCount()); + getNumVisitedCurrent()); ProgramStateRef state = Pred->getState(); state = state->bindLoc(state->getLValue(VD, LCtx), V, LCtx); diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp index a407a923d7d0f..a4a22ce10952c 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp @@ -39,8 +39,7 @@ STAT_COUNTER(NumInlinedCalls, "The # of times we inlined a call"); STAT_COUNTER(NumReachedInlineCountMax, "The # of times we reached inline count maximum"); -void ExprEngine::processCallEnter(NodeBuilderContext& BC, CallEnter CE, - ExplodedNode *Pred) { +void ExprEngine::processCallEnter(CallEnter CE, ExplodedNode *Pred) { // Get the entry block in the CFG of the callee. const CFGBlock *Entry = CE.getEntry(); @@ -62,8 +61,13 @@ void ExprEngine::processCallEnter(NodeBuilderContext& BC, CallEnter CE, ExplodedNode *Node = G.getNode(Loc, state, false, &isNew); Node->addPredecessor(Pred, G); if (isNew) { + // FIXME: In the `processBeginOfFunction` callback + // `ExprEngine::getCurrLocationContext()` can be diff erent from the + // `LocationContext` queried from e.g. the `ExplodedNode`s. I'm not + // touching this now because this commit is NFC; but in the future it would + // be nice to avoid this inconsistency. ExplodedNodeSet DstBegin; - processBeginOfFunction(BC, Node, DstBegin, Loc); + processBeginOfFunction(Node, DstBegin, Loc); Engine.enqueue(DstBegin); } } @@ -158,8 +162,7 @@ static SVal adjustReturnValue(SVal V, QualType ExpectedTy, QualType ActualTy, return UnknownVal(); } -void ExprEngine::removeDeadOnEndOfFunction(NodeBuilderContext& BC, - ExplodedNode *Pred, +void ExprEngine::removeDeadOnEndOfFunction(ExplodedNode *Pred, ExplodedNodeSet &Dst) { // Find the last statement in the function and the corresponding basic block. const Stmt *LastSt = nullptr; @@ -175,7 +178,6 @@ void ExprEngine::removeDeadOnEndOfFunction(NodeBuilderContext& BC, // point will be associated. However, we only want to use LastStmt as a // reference for what to clean up if it's a ReturnStmt; otherwise, everything // is dead. - SaveAndRestore<const NodeBuilderContext *> NodeContextRAII(currBldrCtx, &BC); const LocationContext *LCtx = Pred->getLocationContext(); removeDead(Pred, Dst, dyn_cast<ReturnStmt>(LastSt), LCtx, LCtx->getAnalysisDeclContext()->getBody(), @@ -551,8 +553,8 @@ void ExprEngine::inlineCall(WorkList *WList, const CallEvent &Call, // Construct a new stack frame for the callee. AnalysisDeclContext *CalleeADC = AMgr.getAnalysisDeclContext(D); const StackFrameContext *CalleeSFC = - CalleeADC->getStackFrame(ParentOfCallee, CallE, currBldrCtx->getBlock(), - currBldrCtx->blockCount(), currStmtIdx); + CalleeADC->getStackFrame(ParentOfCallee, CallE, getCurrBlock(), + getNumVisitedCurrent(), currStmtIdx); CallEnter Loc(CallE, CalleeSFC, CurLC); @@ -768,7 +770,7 @@ ProgramStateRef ExprEngine::bindReturnValue(const CallEvent &Call, SVal R; QualType ResultTy = Call.getResultType(); - unsigned Count = currBldrCtx->blockCount(); + unsigned Count = getNumVisitedCurrent(); if (auto RTC = getCurrentCFGElement().getAs<CFGCXXRecordTypedCall>()) { // Conjure a temporary if the function returns an object by value. SVal Target; @@ -833,7 +835,7 @@ ProgramStateRef ExprEngine::bindReturnValue(const CallEvent &Call, // a conjured return value. void ExprEngine::conservativeEvalCall(const CallEvent &Call, NodeBuilder &Bldr, ExplodedNode *Pred, ProgramStateRef State) { - State = Call.invalidateRegions(currBldrCtx->blockCount(), State); + State = Call.invalidateRegions(getNumVisitedCurrent(), State); State = bindReturnValue(Call, Pred->getLocationContext(), State); // And make the result node. diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp index bb0fd6ded2def..07703bdf38239 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp @@ -48,7 +48,7 @@ static void populateObjCForDestinationSet(ExplodedNodeSet &dstLocation, const ObjCForCollectionStmt *S, ConstCFGElementRef elem, SVal elementV, SymbolManager &SymMgr, - const NodeBuilderContext *currBldrCtx, + unsigned NumVisitedCurrent, NodeBuilder &Bldr, bool hasElements) { for (ExplodedNode *Pred : dstLocation) { @@ -69,7 +69,7 @@ static void populateObjCForDestinationSet(ExplodedNodeSet &dstLocation, SVal V; if (hasElements) { SymbolRef Sym = - SymMgr.conjureSymbol(elem, LCtx, T, currBldrCtx->blockCount()); + SymMgr.conjureSymbol(elem, LCtx, T, NumVisitedCurrent); V = svalBuilder.makeLoc(Sym); } else { V = svalBuilder.makeIntVal(0, T); @@ -136,12 +136,13 @@ void ExprEngine::VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S, if (!isContainerNull) populateObjCForDestinationSet(DstLocationSingleton, svalBuilder, S, - elemRef, elementV, SymMgr, currBldrCtx, - Bldr, + elemRef, elementV, SymMgr, + getNumVisitedCurrent(), Bldr, /*hasElements=*/true); populateObjCForDestinationSet(DstLocationSingleton, svalBuilder, S, elemRef, - elementV, SymMgr, currBldrCtx, Bldr, + elementV, SymMgr, getNumVisitedCurrent(), + Bldr, /*hasElements=*/false); // Finally, run any custom checkers. _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
