[clang] 1c424bf - [NFC][analyzer] Clarify current LocationContext and CFGBlock (#185107)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Mar 11 07:08:30 PDT 2026
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.
More information about the cfe-commits
mailing list