Author: DonĂ¡t Nagy
Date: 2026-02-18T10:37:28+01:00
New Revision: fa31acedc547481feebe6fb1cf920a1e3e45c6b6

URL: 
https://github.com/llvm/llvm-project/commit/fa31acedc547481feebe6fb1cf920a1e3e45c6b6
DIFF: 
https://github.com/llvm/llvm-project/commit/fa31acedc547481feebe6fb1cf920a1e3e45c6b6.diff

LOG: [NFCI][analyzer] Simplify NodeBuilder constructors (#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.

Added: 
    

Modified: 
    clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
    clang/lib/StaticAnalyzer/Core/CoreEngine.cpp
    clang/lib/StaticAnalyzer/Core/ExprEngine.cpp

Removed: 
    


################################################################################
diff  --git 
a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h 
b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
index a7fe34b425d5d..d4669fd2d1720 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
@@ -245,30 +245,25 @@ class NodeBuilder {
   /// the builder dies.
   ExplodedNodeSet &Frontier;
 
-  bool hasNoSinksInFrontier() {
-    for (const auto  I : Frontier)
-      if (I->isSink())
-        return false;
-    return true;
-  }
-
   ExplodedNode *generateNodeImpl(const ProgramPoint &PP,
                                  ProgramStateRef State,
                                  ExplodedNode *Pred,
                                  bool MarkAsSink = false);
 
 public:
+  NodeBuilder(ExplodedNodeSet &DstSet, const NodeBuilderContext &Ctx)
+      : C(Ctx), Frontier(DstSet) {}
+
   NodeBuilder(ExplodedNode *SrcNode, ExplodedNodeSet &DstSet,
               const NodeBuilderContext &Ctx)
-      : C(Ctx), Frontier(DstSet) {
+      : NodeBuilder(DstSet, Ctx) {
     Frontier.Add(SrcNode);
   }
 
   NodeBuilder(const ExplodedNodeSet &SrcSet, ExplodedNodeSet &DstSet,
               const NodeBuilderContext &Ctx)
-      : C(Ctx), Frontier(DstSet) {
+      : NodeBuilder(DstSet, Ctx) {
     Frontier.insert(SrcSet);
-    assert(hasNoSinksInFrontier());
   }
 
   /// Generates a node in the ExplodedGraph.
@@ -333,21 +328,9 @@ class BranchNodeBuilder : public NodeBuilder {
   const CFGBlock *DstF;
 
 public:
-  BranchNodeBuilder(ExplodedNode *SrcNode, ExplodedNodeSet &DstSet,
-                    const NodeBuilderContext &C, const CFGBlock *DT,
-                    const CFGBlock *DF)
-      : NodeBuilder(SrcNode, DstSet, C), DstT(DT), DstF(DF) {
-    // The branch node builder does not generate autotransitions.
-    // If there are no successors it means that both branches are infeasible.
-    takeNodes(SrcNode);
-  }
-
-  BranchNodeBuilder(const ExplodedNodeSet &SrcSet, ExplodedNodeSet &DstSet,
-                    const NodeBuilderContext &C, const CFGBlock *DT,
-                    const CFGBlock *DF)
-      : NodeBuilder(SrcSet, DstSet, C), DstT(DT), DstF(DF) {
-    takeNodes(SrcSet);
-  }
+  BranchNodeBuilder(ExplodedNodeSet &DstSet, const NodeBuilderContext &C,
+                    const CFGBlock *DT, const CFGBlock *DF)
+      : NodeBuilder(DstSet, C), DstT(DT), DstF(DF) {}
 
   ExplodedNode *generateNode(ProgramStateRef State, bool branch,
                              ExplodedNode *Pred);
@@ -358,14 +341,9 @@ class IndirectGotoNodeBuilder : public NodeBuilder {
   const Expr *Target;
 
 public:
-  IndirectGotoNodeBuilder(ExplodedNode *SrcNode, ExplodedNodeSet &DstSet,
-                          NodeBuilderContext &Ctx, const Expr *Tgt,
-                          const CFGBlock *Dispatch)
-      : NodeBuilder(SrcNode, DstSet, Ctx), DispatchBlock(*Dispatch),
-        Target(Tgt) {
-    // The indirect goto node builder does not generate autotransitions.
-    takeNodes(SrcNode);
-  }
+  IndirectGotoNodeBuilder(ExplodedNodeSet &DstSet, NodeBuilderContext &Ctx,
+                          const Expr *Tgt, const CFGBlock *Dispatch)
+      : NodeBuilder(DstSet, Ctx), DispatchBlock(*Dispatch), Target(Tgt) {}
 
   using iterator = CFGBlock::const_succ_iterator;
 
@@ -386,12 +364,8 @@ class IndirectGotoNodeBuilder : public NodeBuilder {
 
 class SwitchNodeBuilder : public NodeBuilder {
 public:
-  SwitchNodeBuilder(ExplodedNode *SrcNode, ExplodedNodeSet &DstSet,
-                    const NodeBuilderContext &Ctx)
-      : NodeBuilder(SrcNode, DstSet, Ctx) {
-    // The switch node builder does not generate autotransitions.
-    takeNodes(SrcNode);
-  }
+  SwitchNodeBuilder(ExplodedNodeSet &DstSet, const NodeBuilderContext &Ctx)
+      : NodeBuilder(DstSet, Ctx) {}
 
   using iterator = CFGBlock::const_succ_reverse_iterator;
 

diff  --git a/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp 
b/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp
index 1e5a04b8efbe4..9f0fcc4c3e3a5 100644
--- a/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp
+++ b/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp
@@ -428,7 +428,7 @@ void CoreEngine::HandleBlockExit(const CFGBlock * B, 
ExplodedNode *Pred) {
         NodeBuilderContext Ctx(*this, B, Pred);
         ExplodedNodeSet Dst;
         IndirectGotoNodeBuilder Builder(
-            Pred, Dst, Ctx, cast<IndirectGotoStmt>(Term)->getTarget(),
+            Dst, Ctx, cast<IndirectGotoStmt>(Term)->getTarget(),
             *(B->succ_begin()));
 
         ExprEng.processIndirectGoto(Builder, Pred);

diff  --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp 
b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
index e0bc083f6b978..8c9265ae55311 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -1650,7 +1650,7 @@ void ExprEngine::processCleanupTemporaryBranch(const 
CXXBindTemporaryExpr *BTE,
                                                ExplodedNodeSet &Dst,
                                                const CFGBlock *DstT,
                                                const CFGBlock *DstF) {
-  BranchNodeBuilder TempDtorBuilder(Pred, Dst, BldCtx, DstT, DstF);
+  BranchNodeBuilder TempDtorBuilder(Dst, BldCtx, DstT, DstF);
   ProgramStateRef State = Pred->getState();
   const LocationContext *LC = Pred->getLocationContext();
   if (getObjectUnderConstruction(State, BTE, LC)) {
@@ -2850,7 +2850,7 @@ void ExprEngine::processBranch(
 
   // Check for NULL conditions; e.g. "for(;;)"
   if (!Condition) {
-    BranchNodeBuilder NullCondBldr(Pred, Dst, BldCtx, DstT, DstF);
+    BranchNodeBuilder NullCondBldr(Dst, BldCtx, DstT, DstF);
     NullCondBldr.generateNode(Pred->getState(), true, Pred);
     return;
   }
@@ -2870,7 +2870,7 @@ void ExprEngine::processBranch(
   if (CheckersOutSet.empty())
     return;
 
-  BranchNodeBuilder Builder(CheckersOutSet, Dst, BldCtx, DstT, DstF);
+  BranchNodeBuilder Builder(Dst, BldCtx, DstT, DstF);
   for (ExplodedNode *PredN : CheckersOutSet) {
     if (PredN->isSink())
       continue;
@@ -2979,7 +2979,7 @@ void ExprEngine::processStaticInitializer(
   const auto *VD = cast<VarDecl>(DS->getSingleDecl());
   ProgramStateRef state = Pred->getState();
   bool initHasRun = state->contains<InitializedGlobalsSet>(VD);
-  BranchNodeBuilder Builder(Pred, Dst, BuilderCtx, DstT, DstF);
+  BranchNodeBuilder Builder(Dst, BuilderCtx, DstT, DstF);
 
   if (!initHasRun) {
     state = state->add<InitializedGlobalsSet>(VD);
@@ -3108,7 +3108,7 @@ void ExprEngine::processSwitch(NodeBuilderContext &BC, 
const SwitchStmt *Switch,
                                ExplodedNode *Pred, ExplodedNodeSet &Dst) {
   const Expr *Condition = Switch->getCond();
 
-  SwitchNodeBuilder Builder(Pred, Dst, BC);
+  SwitchNodeBuilder Builder(Dst, BC);
 
   ProgramStateRef State = Pred->getState();
   SVal CondV = State->getSVal(Condition, Pred->getLocationContext());


        
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to