[clang] [analyzer] Remove irrelevant transitions in processCFGBlockEntrance (PR #216008)

DonĂ¡t Nagy via cfe-commits cfe-commits at lists.llvm.org
Thu Aug 13 04:03:36 PDT 2026


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

My recent commit c76a617524fa62f85c1ff825b5d47885599c6482 cleaned up the logic of `ExprEngine::processCFGBlockEntrance`, highlighting the fact that it sometimes creates an extra transition that has no relevant purpose. This commit removes this extra transition to simplify the code.

This is not an NFC change, because changing the number of exploded nodes can theoretically perturb the graph creation and traversal algorithms; but I'm confident that there was no logic that concretely looked for these particular nodes.

Also note that this commit is a no-op if loop unrolling is disabled (the default) and unless loop widening is also enabled, it can only remove a node that is directly followed by a sink as its only child.

----

I will evaluate the effects of this PR by analyzing our set of open source projects with loop unrolling and loop widening both enabled.

>From 3f9a2ab47fa28d1f6657b5cebe5fa9fc3523d086 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Don=C3=A1t=20Nagy?= <donat.nagy at ericsson.com>
Date: Thu, 13 Aug 2026 12:56:19 +0200
Subject: [PATCH] [analyzer] Remove irrelevant transitions in
 processCFGBlockEntrance

My recent commit c76a617524fa62f85c1ff825b5d47885599c6482 cleaned up the
logic of `ExprEngine::processCFGBlockEntrance`, highlighting the fact
that it sometimes creates an extra transition that has no relevant
purpose. This commit removes this extra transition to simplify the code.

This is not an NFC change, because changing the number of exploded nodes
can theoretically perturb the graph creation and traversal algorithms;
but I'm confident that there was no logic that concretely looked for
these particular nodes.

Also note that this commit is a no-op if loop unrolling is disabled (the
default) and unless loop widening is also enabled, it can only remove a
node that is directly followed by a sink as its only child.
---
 clang/lib/StaticAnalyzer/Core/ExprEngine.cpp | 17 -----------------
 1 file changed, 17 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
index 328ed5b23dd83..f9a1fdd233bd9 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -2415,14 +2415,6 @@ ExplodedNode *ExprEngine::processCFGBlockEntrance(const BlockEntrance &BE,
     if (!isa_and_nonnull<ForStmt, WhileStmt, DoStmt, CXXForRangeStmt>(Term))
       return Engine.makeNode(BE, State, Pred);
 
-    if (State != Pred->getState()) {
-      // TODO: This intermediate transition is very likely to be irrelevant,
-      // remove it in a follow-up change.
-      Pred = Engine.makeNode(BE, State, Pred);
-      if (!Pred)
-        return nullptr;
-    }
-
     // FIXME:
     // We cannot use the CFG element from the via `ExprEngine::getCFGElementRef`
     // since we are currently at the block entrance and the current reference
@@ -2439,15 +2431,6 @@ ExplodedNode *ExprEngine::processCFGBlockEntrance(const BlockEntrance &BE,
     return Engine.makeNode(BE, State, Pred);
 
   // ... otherwise, discard this execution path.
-
-  if (State != Pred->getState()) {
-    // TODO: This intermediate transition is very likely to be irrelevant,
-    // remove it in a follow-up change.
-    Pred = Engine.makeNode(BE, State, Pred);
-    if (!Pred)
-      return nullptr;
-  }
-
   static SimpleProgramPointTag Tag(TagProviderName, "Block count exceeded");
   const ExplodedNode *Sink =
       Engine.makeNode(BE.withTag(&Tag), State, Pred, /*MarkAsSink=*/true);



More information about the cfe-commits mailing list