Skip to content

Commit fa31ace

Browse files
authored
[NFCI][analyzer] Simplify NodeBuilder constructors (llvm#181875)
This commit simplifies the construction of `NodeBuilder` and its subclasses in three ways: - It removes an assertion that only appeared in one of the two constructors of `NodeBuilder`. While the asserted "no sinks in the `Frontier`" invariant apparently holds, this assertion was not the right place for expressing it. (In the future I might re-add a similar assertion in a more reasonable location.) - It adds a new constructor for `NodeBuilder` that doesn't take a "source node(s)" argument, because this argument was often irrelevant. - It removes the "source node(s)" arguments from the subclasses of `NodeBuilder` because it was always completely irrelevant in those situations. Before this commit, constructors of `NodeBuilder` took three arguments: - the source node or nodes, - the destination node set where the freshly built nodes are placed, - the `NodeBuilderContext` that provides access to the exploded graph. Among these, the latter two were saved in data members, but the only use of the source node(s) was that the constructor inserted them into the destination node set (= the data member `Frontier`). However, adding the source node(s) to the `Frontier` is usually irrelevant, because later set operations almost always remove them from the `Frontier`. This is especially clear in the subclasses derived from `NodeBuilder` whose constructor immediately remove the source node(s) from the `Frontier`. (In other situations, the source node(s) are usually removed from the `Frontier` by the calls to `generateNode()`.) This commit introduces a new constructor for `NodeBuilder` that doesn't have a "source node(s)" parameter, then uses this constructor to implement the constructors of the subclasses without pointless insertion and then removal of nodes from the destination set. Note that if a node `N` was already present in the destination set, then its insertion+removal would remove it from the set; but I verified that the destination set passed to constructors of subclasses of `NodeBuilder` is always an empty set (at this point). The new constructor of `NodeBuiler` is public because later it will be also useful for simplifying other code that uses `NodeBuilder` directly.
1 parent 0786f2d commit fa31ace

3 files changed

Lines changed: 19 additions & 45 deletions

File tree

clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h

Lines changed: 13 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -245,30 +245,25 @@ class NodeBuilder {
245245
/// the builder dies.
246246
ExplodedNodeSet &Frontier;
247247

248-
bool hasNoSinksInFrontier() {
249-
for (const auto I : Frontier)
250-
if (I->isSink())
251-
return false;
252-
return true;
253-
}
254-
255248
ExplodedNode *generateNodeImpl(const ProgramPoint &PP,
256249
ProgramStateRef State,
257250
ExplodedNode *Pred,
258251
bool MarkAsSink = false);
259252

260253
public:
254+
NodeBuilder(ExplodedNodeSet &DstSet, const NodeBuilderContext &Ctx)
255+
: C(Ctx), Frontier(DstSet) {}
256+
261257
NodeBuilder(ExplodedNode *SrcNode, ExplodedNodeSet &DstSet,
262258
const NodeBuilderContext &Ctx)
263-
: C(Ctx), Frontier(DstSet) {
259+
: NodeBuilder(DstSet, Ctx) {
264260
Frontier.Add(SrcNode);
265261
}
266262

267263
NodeBuilder(const ExplodedNodeSet &SrcSet, ExplodedNodeSet &DstSet,
268264
const NodeBuilderContext &Ctx)
269-
: C(Ctx), Frontier(DstSet) {
265+
: NodeBuilder(DstSet, Ctx) {
270266
Frontier.insert(SrcSet);
271-
assert(hasNoSinksInFrontier());
272267
}
273268

274269
/// Generates a node in the ExplodedGraph.
@@ -333,21 +328,9 @@ class BranchNodeBuilder : public NodeBuilder {
333328
const CFGBlock *DstF;
334329

335330
public:
336-
BranchNodeBuilder(ExplodedNode *SrcNode, ExplodedNodeSet &DstSet,
337-
const NodeBuilderContext &C, const CFGBlock *DT,
338-
const CFGBlock *DF)
339-
: NodeBuilder(SrcNode, DstSet, C), DstT(DT), DstF(DF) {
340-
// The branch node builder does not generate autotransitions.
341-
// If there are no successors it means that both branches are infeasible.
342-
takeNodes(SrcNode);
343-
}
344-
345-
BranchNodeBuilder(const ExplodedNodeSet &SrcSet, ExplodedNodeSet &DstSet,
346-
const NodeBuilderContext &C, const CFGBlock *DT,
347-
const CFGBlock *DF)
348-
: NodeBuilder(SrcSet, DstSet, C), DstT(DT), DstF(DF) {
349-
takeNodes(SrcSet);
350-
}
331+
BranchNodeBuilder(ExplodedNodeSet &DstSet, const NodeBuilderContext &C,
332+
const CFGBlock *DT, const CFGBlock *DF)
333+
: NodeBuilder(DstSet, C), DstT(DT), DstF(DF) {}
351334

352335
ExplodedNode *generateNode(ProgramStateRef State, bool branch,
353336
ExplodedNode *Pred);
@@ -358,14 +341,9 @@ class IndirectGotoNodeBuilder : public NodeBuilder {
358341
const Expr *Target;
359342

360343
public:
361-
IndirectGotoNodeBuilder(ExplodedNode *SrcNode, ExplodedNodeSet &DstSet,
362-
NodeBuilderContext &Ctx, const Expr *Tgt,
363-
const CFGBlock *Dispatch)
364-
: NodeBuilder(SrcNode, DstSet, Ctx), DispatchBlock(*Dispatch),
365-
Target(Tgt) {
366-
// The indirect goto node builder does not generate autotransitions.
367-
takeNodes(SrcNode);
368-
}
344+
IndirectGotoNodeBuilder(ExplodedNodeSet &DstSet, NodeBuilderContext &Ctx,
345+
const Expr *Tgt, const CFGBlock *Dispatch)
346+
: NodeBuilder(DstSet, Ctx), DispatchBlock(*Dispatch), Target(Tgt) {}
369347

370348
using iterator = CFGBlock::const_succ_iterator;
371349

@@ -386,12 +364,8 @@ class IndirectGotoNodeBuilder : public NodeBuilder {
386364

387365
class SwitchNodeBuilder : public NodeBuilder {
388366
public:
389-
SwitchNodeBuilder(ExplodedNode *SrcNode, ExplodedNodeSet &DstSet,
390-
const NodeBuilderContext &Ctx)
391-
: NodeBuilder(SrcNode, DstSet, Ctx) {
392-
// The switch node builder does not generate autotransitions.
393-
takeNodes(SrcNode);
394-
}
367+
SwitchNodeBuilder(ExplodedNodeSet &DstSet, const NodeBuilderContext &Ctx)
368+
: NodeBuilder(DstSet, Ctx) {}
395369

396370
using iterator = CFGBlock::const_succ_reverse_iterator;
397371

clang/lib/StaticAnalyzer/Core/CoreEngine.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -428,7 +428,7 @@ void CoreEngine::HandleBlockExit(const CFGBlock * B, ExplodedNode *Pred) {
428428
NodeBuilderContext Ctx(*this, B, Pred);
429429
ExplodedNodeSet Dst;
430430
IndirectGotoNodeBuilder Builder(
431-
Pred, Dst, Ctx, cast<IndirectGotoStmt>(Term)->getTarget(),
431+
Dst, Ctx, cast<IndirectGotoStmt>(Term)->getTarget(),
432432
*(B->succ_begin()));
433433

434434
ExprEng.processIndirectGoto(Builder, Pred);

clang/lib/StaticAnalyzer/Core/ExprEngine.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1650,7 +1650,7 @@ void ExprEngine::processCleanupTemporaryBranch(const CXXBindTemporaryExpr *BTE,
16501650
ExplodedNodeSet &Dst,
16511651
const CFGBlock *DstT,
16521652
const CFGBlock *DstF) {
1653-
BranchNodeBuilder TempDtorBuilder(Pred, Dst, BldCtx, DstT, DstF);
1653+
BranchNodeBuilder TempDtorBuilder(Dst, BldCtx, DstT, DstF);
16541654
ProgramStateRef State = Pred->getState();
16551655
const LocationContext *LC = Pred->getLocationContext();
16561656
if (getObjectUnderConstruction(State, BTE, LC)) {
@@ -2850,7 +2850,7 @@ void ExprEngine::processBranch(
28502850

28512851
// Check for NULL conditions; e.g. "for(;;)"
28522852
if (!Condition) {
2853-
BranchNodeBuilder NullCondBldr(Pred, Dst, BldCtx, DstT, DstF);
2853+
BranchNodeBuilder NullCondBldr(Dst, BldCtx, DstT, DstF);
28542854
NullCondBldr.generateNode(Pred->getState(), true, Pred);
28552855
return;
28562856
}
@@ -2870,7 +2870,7 @@ void ExprEngine::processBranch(
28702870
if (CheckersOutSet.empty())
28712871
return;
28722872

2873-
BranchNodeBuilder Builder(CheckersOutSet, Dst, BldCtx, DstT, DstF);
2873+
BranchNodeBuilder Builder(Dst, BldCtx, DstT, DstF);
28742874
for (ExplodedNode *PredN : CheckersOutSet) {
28752875
if (PredN->isSink())
28762876
continue;
@@ -2979,7 +2979,7 @@ void ExprEngine::processStaticInitializer(
29792979
const auto *VD = cast<VarDecl>(DS->getSingleDecl());
29802980
ProgramStateRef state = Pred->getState();
29812981
bool initHasRun = state->contains<InitializedGlobalsSet>(VD);
2982-
BranchNodeBuilder Builder(Pred, Dst, BuilderCtx, DstT, DstF);
2982+
BranchNodeBuilder Builder(Dst, BuilderCtx, DstT, DstF);
29832983

29842984
if (!initHasRun) {
29852985
state = state->add<InitializedGlobalsSet>(VD);
@@ -3108,7 +3108,7 @@ void ExprEngine::processSwitch(NodeBuilderContext &BC, const SwitchStmt *Switch,
31083108
ExplodedNode *Pred, ExplodedNodeSet &Dst) {
31093109
const Expr *Condition = Switch->getCond();
31103110

3111-
SwitchNodeBuilder Builder(Pred, Dst, BC);
3111+
SwitchNodeBuilder Builder(Dst, BC);
31123112

31133113
ProgramStateRef State = Pred->getState();
31143114
SVal CondV = State->getSVal(Condition, Pred->getLocationContext());

0 commit comments

Comments
 (0)