https://github.com/NagyDonat created 
https://github.com/llvm/llvm-project/pull/204371

Part of my commit series to gradually eliminate the class `NodeBuilder`. 
Admittedly this is one of the few places where the implementation with the 
`NodeBuilder` is more concise than the new code.

This is caused by two factors:
1. This is an optional step in the analysis, so the "put source nodes in 
destination unless we generate a child node from them" behavior of 
`NodeBuilder` -- which is often completely useless -- was helpful on two 
branches.
2. Making nodes with tags is very rare, so I intentionally did not include 
support for tagging in `makeNodeWithBinding` -- but this is one of the few 
places where tags are applied.

From 14b74b4c8e31bfaeade554220068ae052847cacb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Don=C3=A1t=20Nagy?= <[email protected]>
Date: Wed, 17 Jun 2026 16:01:09 +0200
Subject: [PATCH 1/2] Introduce name for Pred->getStackFrame()

---
 clang/lib/StaticAnalyzer/Core/ExprEngine.cpp | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp 
b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
index 32da5e097c76e..7996b7ff96d1c 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -3722,6 +3722,7 @@ void 
ExprEngine::evalEagerlyAssumeBifurcation(ExplodedNodeSet &Dst,
   NodeBuilder Bldr(Src, Dst, *currBldrCtx);
 
   for (ExplodedNode *Pred : Src) {
+    const StackFrame *SF = Pred->getStackFrame();
     // Test if the previous node was as the same expression.  This can happen
     // when the expression fails to evaluate to anything meaningful and
     // (as an optimization) we don't generate a node.
@@ -3732,7 +3733,7 @@ void 
ExprEngine::evalEagerlyAssumeBifurcation(ExplodedNodeSet &Dst,
 
     ProgramStateRef State = Pred->getState();
     State = State->set<LastEagerlyAssumeExprIfSuccessful>(nullptr);
-    SVal V = State->getSVal(Ex, Pred->getStackFrame());
+    SVal V = State->getSVal(Ex, SF);
     std::optional<nonloc::SymbolVal> SEV = V.getAs<nonloc::SymbolVal>();
     if (SEV && SEV->isExpression()) {
       const auto &[TrueTag, FalseTag] = getEagerlyAssumeBifurcationTags();
@@ -3747,14 +3748,14 @@ void 
ExprEngine::evalEagerlyAssumeBifurcation(ExplodedNodeSet &Dst,
       // First assume that the condition is true.
       if (StateTrue) {
         SVal Val = svalBuilder.makeIntVal(1U, Ex->getType());
-        StateTrue = StateTrue->BindExpr(Ex, Pred->getStackFrame(), Val);
+        StateTrue = StateTrue->BindExpr(Ex, SF, Val);
         Bldr.generateNode(Ex, Pred, StateTrue, TrueTag);
       }
 
       // Next, assume that the condition is false.
       if (StateFalse) {
         SVal Val = svalBuilder.makeIntVal(0U, Ex->getType());
-        StateFalse = StateFalse->BindExpr(Ex, Pred->getStackFrame(), Val);
+        StateFalse = StateFalse->BindExpr(Ex, SF, Val);
         Bldr.generateNode(Ex, Pred, StateFalse, FalseTag);
       }
     }

From 3a1fe88b1a540f93f885e81d651c40f6794c77f0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Don=C3=A1t=20Nagy?= <[email protected]>
Date: Wed, 17 Jun 2026 16:06:09 +0200
Subject: [PATCH 2/2] Remove NodeBuilder from eagerly assume logic

Admittedly this is one of the few places where the implementation with
the `NodeBuilder` is more concise than the new code.

This is caused by two factors:
1. This is an optional step in the analysis, so the "put source nodes in
   destination unless we generate a child node from them" behavior of
   `NodeBuilder` -- which is often completely useless -- was helpful on
   two branches.
2. Making nodes with tags is very rare, so I intentionally did not
   include support for tagging in `makeNodeWithBinding` -- but this is
   one of the few places where tags are applied.
---
 clang/lib/StaticAnalyzer/Core/ExprEngine.cpp | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp 
b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
index 7996b7ff96d1c..e820f9c12612f 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -3719,8 +3719,6 @@ 
REGISTER_TRAIT_WITH_PROGRAMSTATE(LastEagerlyAssumeExprIfSuccessful,
 void ExprEngine::evalEagerlyAssumeBifurcation(ExplodedNodeSet &Dst,
                                               ExplodedNodeSet &Src,
                                               const Expr *Ex) {
-  NodeBuilder Bldr(Src, Dst, *currBldrCtx);
-
   for (ExplodedNode *Pred : Src) {
     const StackFrame *SF = Pred->getStackFrame();
     // Test if the previous node was as the same expression.  This can happen
@@ -3728,6 +3726,7 @@ void 
ExprEngine::evalEagerlyAssumeBifurcation(ExplodedNodeSet &Dst,
     // (as an optimization) we don't generate a node.
     ProgramPoint P = Pred->getLocation();
     if (!P.getAs<PostStmt>() || P.castAs<PostStmt>().getStmt() != Ex) {
+      Dst.insert(Pred);
       continue;
     }
 
@@ -3749,15 +3748,19 @@ void 
ExprEngine::evalEagerlyAssumeBifurcation(ExplodedNodeSet &Dst,
       if (StateTrue) {
         SVal Val = svalBuilder.makeIntVal(1U, Ex->getType());
         StateTrue = StateTrue->BindExpr(Ex, SF, Val);
-        Bldr.generateNode(Ex, Pred, StateTrue, TrueTag);
+        PostStmt PostStmtTrue(Ex, SF, TrueTag);
+        Dst.insert(Engine.makeNode(PostStmtTrue, StateTrue, Pred));
       }
 
       // Next, assume that the condition is false.
       if (StateFalse) {
         SVal Val = svalBuilder.makeIntVal(0U, Ex->getType());
         StateFalse = StateFalse->BindExpr(Ex, SF, Val);
-        Bldr.generateNode(Ex, Pred, StateFalse, FalseTag);
+        PostStmt PostStmtFalse(Ex, SF, FalseTag);
+        Dst.insert(Engine.makeNode(PostStmtFalse, StateFalse, Pred));
       }
+    } else {
+      Dst.insert(Pred);
     }
   }
 }

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

Reply via email to