https://github.com/NagyDonat updated 
https://github.com/llvm/llvm-project/pull/139939

From 8a33087fcd94d326cac602a6be83a1b34b43e1ab Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Don=C3=A1t=20Nagy?= <donat.n...@ericsson.com>
Date: Wed, 14 May 2025 19:24:37 +0200
Subject: [PATCH 01/10] [WIP][analyzer] Refactor `ExplodedGraph::trim()`

...because its implementation was using a complicated two-pass graph
traversal while in fact one pass is sufficient for performing that
trimming operation.

Note that this commit changes the interface of `trim`: it no longer
accepts nullpointers within the array `Sinks` and `BugReporter.cpp` (the
single non-debug caller) was modified accordingly. This also affects the
interface of `DumpGraph` (which calls `trim` under the hood), but that's
a debug helper which is only called if some developer compiles a tweaked
version of the analyzer for local debugging and it is unlikely that a
developer would pass nullpointers to it.

WORK IN PROGRESS -- DO NOT MERGE!

After this commit the analyzer will pick different representants from
the bug report equivalence classes (because some iteration order
changes), which breaks lots of testcases.
---
 clang/lib/StaticAnalyzer/Core/BugReporter.cpp |   3 +-
 .../lib/StaticAnalyzer/Core/ExplodedGraph.cpp | 110 ++++++------------
 2 files changed, 35 insertions(+), 78 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp 
b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
index d5bc3ac2962d5..709fb18f14789 100644
--- a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
+++ b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
@@ -2633,7 +2633,8 @@ BugPathGetter::BugPathGetter(const ExplodedGraph 
*OriginalGraph,
     assert(I->isValid() &&
            "We only allow BugReporterVisitors and BugReporter itself to "
            "invalidate reports!");
-    Nodes.emplace_back(I->getErrorNode());
+    if (const ExplodedNode *ErrNode = I->getErrorNode())
+      Nodes.emplace_back(ErrNode);
   }
 
   // The trimmed graph is created in the body of the constructor to ensure
diff --git a/clang/lib/StaticAnalyzer/Core/ExplodedGraph.cpp 
b/clang/lib/StaticAnalyzer/Core/ExplodedGraph.cpp
index 098922d94061f..85f84af4167e0 100644
--- a/clang/lib/StaticAnalyzer/Core/ExplodedGraph.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExplodedGraph.cpp
@@ -442,60 +442,21 @@ std::unique_ptr<ExplodedGraph>
 ExplodedGraph::trim(ArrayRef<const NodeTy *> Sinks,
                     InterExplodedGraphMap *ForwardMap,
                     InterExplodedGraphMap *InverseMap) const {
-  // FIXME: The two-pass algorithm of this function (which was introduced in
-  // 2008) is terribly overcomplicated and should be replaced by a single
-  // (backward) pass.
-
-  if (Nodes.empty())
+  if (Sinks.empty())
     return nullptr;
 
-  using Pass1Ty = llvm::DenseSet<const ExplodedNode *>;
-  Pass1Ty Pass1;
-
-  using Pass2Ty = InterExplodedGraphMap;
-  InterExplodedGraphMap Pass2Scratch;
-  Pass2Ty &Pass2 = ForwardMap ? *ForwardMap : Pass2Scratch;
-
-  SmallVector<const ExplodedNode*, 10> WL1, WL2;
-
-  // ===- Pass 1 (reverse DFS) -===
-  for (const auto Sink : Sinks)
-    if (Sink)
-      WL1.push_back(Sink);
-
-  // Process the first worklist until it is empty.
-  while (!WL1.empty()) {
-    const ExplodedNode *N = WL1.pop_back_val();
-
-    // Have we already visited this node?  If so, continue to the next one.
-    if (!Pass1.insert(N).second)
-      continue;
-
-    // If this is the root enqueue it to the second worklist.
-    if (N->Preds.empty()) {
-      assert(N == getRoot() && "Found non-root node with no predecessors!");
-      WL2.push_back(N);
-      continue;
-    }
-
-    // Visit our predecessors and enqueue them.
-    WL1.append(N->Preds.begin(), N->Preds.end());
-  }
+  std::unique_ptr<ExplodedGraph> Trimmed = std::make_unique<ExplodedGraph>();
 
-  // We didn't hit the root? Return with a null pointer for the new graph.
-  if (WL2.empty())
-    return nullptr;
+  SmallVector<const ExplodedNode*, 32> Worklist{Sinks};
 
-  assert(WL2.size() == 1 && "There must be only one root!");
+  InterExplodedGraphMap Scratch;
+  if (!ForwardMap)
+    ForwardMap = &Scratch;
 
-  // Create an empty graph.
-  std::unique_ptr<ExplodedGraph> G = std::make_unique<ExplodedGraph>();
+  while (!Worklist.empty()) {
+    const ExplodedNode *N = Worklist.pop_back_val();
 
-  // ===- Pass 2 (forward DFS to construct the new graph) -===
-  while (!WL2.empty()) {
-    const ExplodedNode *N = WL2.pop_back_val();
-
-    auto [Place, Inserted] = Pass2.try_emplace(N);
+    auto [Place, Inserted] = ForwardMap->try_emplace(N);
 
     // Skip this node if we have already processed it.
     if (!Inserted)
@@ -503,48 +464,43 @@ ExplodedGraph::trim(ArrayRef<const NodeTy *> Sinks,
 
     // Create the corresponding node in the new graph and record the mapping
     // from the old node to the new node.
-    ExplodedNode *NewN = G->createUncachedNode(N->getLocation(), N->State,
+    ExplodedNode *NewN = Trimmed->createUncachedNode(N->getLocation(), 
N->State,
                                                N->getID(), N->isSink());
     Place->second = NewN;
 
     // Also record the reverse mapping from the new node to the old node.
     if (InverseMap) (*InverseMap)[NewN] = N;
 
-    // If this node is the root, designate it as such in the graph.
-    if (N->Preds.empty()) {
-      assert(N == getRoot());
-      G->designateAsRoot(NewN);
-    }
-
-    // In the case that some of the intended predecessors of NewN have already
-    // been created, we should hook them up as predecessors.
+    // If this is the root node, designate is as the root in the trimmed graph 
as well.
+    if (N == getRoot())
+      Trimmed->designateAsRoot(NewN);
 
-    // Walk through the predecessors of 'N' and hook up their corresponding
-    // nodes in the new graph (if any) to the freshly created node.
+    // Iterate over the predecessors of the node: if they are already present
+    // in the trimmed graph, then add the corresponding edges with
+    // `addPredecessor()`, otherwise add them to the worklist.
     for (const ExplodedNode *Pred : N->Preds) {
-      Pass2Ty::iterator PI = Pass2.find(Pred);
-      if (PI == Pass2.end())
-        continue;
-
-      NewN->addPredecessor(const_cast<ExplodedNode *>(PI->second), *G);
+      auto Iterator = ForwardMap->find(Pred);
+      if (Iterator != ForwardMap->end()) {
+        NewN->addPredecessor(const_cast<ExplodedNode *>(Iterator->second), 
*Trimmed);
+      } else {
+        Worklist.push_back(Pred);
+      }
     }
 
-    // In the case that some of the intended successors of NewN have already
-    // been created, we should hook them up as successors.  Otherwise, enqueue
-    // the new nodes from the original graph that should have nodes created
-    // in the new graph.
+    // Iterate over the successors of the node: if they are present in the
+    // trimmed graph, then add the corresponding edges with `addPredecessor()`.
+    // (If they are not present in the trimmed graph, we don't add them to the
+    // worklist. Maybe we'll reach them through a different direction, maybe
+    // they will be omitted from the trimmed graph.)
     for (const ExplodedNode *Succ : N->Succs) {
-      Pass2Ty::iterator PI = Pass2.find(Succ);
-      if (PI != Pass2.end()) {
-        const_cast<ExplodedNode *>(PI->second)->addPredecessor(NewN, *G);
-        continue;
+      auto Iterator = ForwardMap->find(Succ);
+      if (Iterator != ForwardMap->end()) {
+        const_cast<ExplodedNode *>(Iterator->second)->addPredecessor(NewN, 
*Trimmed);
       }
-
-      // Enqueue nodes to the worklist that were marked during pass 1.
-      if (Pass1.count(Succ))
-        WL2.push_back(Succ);
     }
   }
 
-  return G;
+  assert(Trimmed->getRoot() && "The root must be reachable from any nonempty 
set of sinks!");
+
+  return Trimmed;
 }

From 348e740362e6f2bd9e747affa26e3a5bf826c4d9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Don=C3=A1t=20Nagy?= <donat.n...@ericsson.com>
Date: Thu, 15 May 2025 13:57:48 +0200
Subject: [PATCH 02/10] Simplify map lookup; unbrace

---
 clang/lib/StaticAnalyzer/Core/ExplodedGraph.cpp | 17 ++++++-----------
 1 file changed, 6 insertions(+), 11 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Core/ExplodedGraph.cpp 
b/clang/lib/StaticAnalyzer/Core/ExplodedGraph.cpp
index 85f84af4167e0..121f1a5eadbe4 100644
--- a/clang/lib/StaticAnalyzer/Core/ExplodedGraph.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExplodedGraph.cpp
@@ -479,12 +479,10 @@ ExplodedGraph::trim(ArrayRef<const NodeTy *> Sinks,
     // in the trimmed graph, then add the corresponding edges with
     // `addPredecessor()`, otherwise add them to the worklist.
     for (const ExplodedNode *Pred : N->Preds) {
-      auto Iterator = ForwardMap->find(Pred);
-      if (Iterator != ForwardMap->end()) {
-        NewN->addPredecessor(const_cast<ExplodedNode *>(Iterator->second), 
*Trimmed);
-      } else {
+      if (const ExplodedNode *Mapped = ForwardMap->lookup(Pred))
+        NewN->addPredecessor(const_cast<ExplodedNode *>(Mapped), *Trimmed);
+      else
         Worklist.push_back(Pred);
-      }
     }
 
     // Iterate over the successors of the node: if they are present in the
@@ -492,12 +490,9 @@ ExplodedGraph::trim(ArrayRef<const NodeTy *> Sinks,
     // (If they are not present in the trimmed graph, we don't add them to the
     // worklist. Maybe we'll reach them through a different direction, maybe
     // they will be omitted from the trimmed graph.)
-    for (const ExplodedNode *Succ : N->Succs) {
-      auto Iterator = ForwardMap->find(Succ);
-      if (Iterator != ForwardMap->end()) {
-        const_cast<ExplodedNode *>(Iterator->second)->addPredecessor(NewN, 
*Trimmed);
-      }
-    }
+    for (const ExplodedNode *Succ : N->Succs)
+      if (const ExplodedNode *Mapped = ForwardMap->lookup(Succ))
+        const_cast<ExplodedNode *>(Mapped)->addPredecessor(NewN, *Trimmed);
   }
 
   assert(Trimmed->getRoot() && "The root must be reachable from any nonempty 
set of sinks!");

From 300b7ce25a45ca1cd95a000de6c0568c6393e6c2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Don=C3=A1t=20Nagy?= <donat.n...@ericsson.com>
Date: Thu, 15 May 2025 14:03:35 +0200
Subject: [PATCH 03/10] Get rid of InverseMap because it was unused

---
 .../Core/PathSensitive/ExplodedGraph.h           |  7 ++-----
 clang/lib/StaticAnalyzer/Core/BugReporter.cpp    |  6 +++---
 clang/lib/StaticAnalyzer/Core/ExplodedGraph.cpp  | 16 ++++++----------
 3 files changed, 11 insertions(+), 18 deletions(-)

diff --git 
a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h 
b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
index e995151927c96..cf913c064933e 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
@@ -413,15 +413,12 @@ class ExplodedGraph {
   ///
   /// \param Nodes The nodes which must appear in the final graph. Presumably
   ///              these are end-of-path nodes (i.e. they have no successors).
-  /// \param[out] ForwardMap An optional map from nodes in this graph to nodes
+  /// \param[out] NodeMap An optional map from nodes in this graph to nodes
   ///                        in the returned graph.
-  /// \param[out] InverseMap An optional map from nodes in the returned graph 
to
-  ///                        nodes in this graph.
   /// \returns The trimmed graph
   std::unique_ptr<ExplodedGraph>
   trim(ArrayRef<const NodeTy *> Nodes,
-       InterExplodedGraphMap *ForwardMap = nullptr,
-       InterExplodedGraphMap *InverseMap = nullptr) const;
+       InterExplodedGraphMap *NodeMap = nullptr) const;
 
   /// Enable tracking of recently allocated nodes for potential reclamation
   /// when calling reclaimRecentlyAllocatedNodes().
diff --git a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp 
b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
index 709fb18f14789..188de7da50c62 100644
--- a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
+++ b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
@@ -2639,8 +2639,8 @@ BugPathGetter::BugPathGetter(const ExplodedGraph 
*OriginalGraph,
 
   // The trimmed graph is created in the body of the constructor to ensure
   // that the DenseMaps have been initialized already.
-  InterExplodedGraphMap ForwardMap;
-  TrimmedGraph = OriginalGraph->trim(Nodes, &ForwardMap);
+  InterExplodedGraphMap NodeMap;
+  TrimmedGraph = OriginalGraph->trim(Nodes, &NodeMap);
 
   // Find the (first) error node in the trimmed graph.  We just need to consult
   // the node map which maps from nodes in the original graph to nodes
@@ -2648,7 +2648,7 @@ BugPathGetter::BugPathGetter(const ExplodedGraph 
*OriginalGraph,
   llvm::SmallPtrSet<const ExplodedNode *, 32> RemainingNodes;
 
   for (PathSensitiveBugReport *Report : bugReports) {
-    const ExplodedNode *NewNode = ForwardMap.lookup(Report->getErrorNode());
+    const ExplodedNode *NewNode = NodeMap.lookup(Report->getErrorNode());
     assert(NewNode &&
            "Failed to construct a trimmed graph that contains this error "
            "node!");
diff --git a/clang/lib/StaticAnalyzer/Core/ExplodedGraph.cpp 
b/clang/lib/StaticAnalyzer/Core/ExplodedGraph.cpp
index 121f1a5eadbe4..7a13dbe5961b8 100644
--- a/clang/lib/StaticAnalyzer/Core/ExplodedGraph.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExplodedGraph.cpp
@@ -440,8 +440,7 @@ ExplodedNode *ExplodedGraph::createUncachedNode(const 
ProgramPoint &L,
 
 std::unique_ptr<ExplodedGraph>
 ExplodedGraph::trim(ArrayRef<const NodeTy *> Sinks,
-                    InterExplodedGraphMap *ForwardMap,
-                    InterExplodedGraphMap *InverseMap) const {
+                    InterExplodedGraphMap *NodeMap) const {
   if (Sinks.empty())
     return nullptr;
 
@@ -450,13 +449,13 @@ ExplodedGraph::trim(ArrayRef<const NodeTy *> Sinks,
   SmallVector<const ExplodedNode*, 32> Worklist{Sinks};
 
   InterExplodedGraphMap Scratch;
-  if (!ForwardMap)
-    ForwardMap = &Scratch;
+  if (!NodeMap)
+    NodeMap = &Scratch;
 
   while (!Worklist.empty()) {
     const ExplodedNode *N = Worklist.pop_back_val();
 
-    auto [Place, Inserted] = ForwardMap->try_emplace(N);
+    auto [Place, Inserted] = NodeMap->try_emplace(N);
 
     // Skip this node if we have already processed it.
     if (!Inserted)
@@ -468,9 +467,6 @@ ExplodedGraph::trim(ArrayRef<const NodeTy *> Sinks,
                                                N->getID(), N->isSink());
     Place->second = NewN;
 
-    // Also record the reverse mapping from the new node to the old node.
-    if (InverseMap) (*InverseMap)[NewN] = N;
-
     // If this is the root node, designate is as the root in the trimmed graph 
as well.
     if (N == getRoot())
       Trimmed->designateAsRoot(NewN);
@@ -479,7 +475,7 @@ ExplodedGraph::trim(ArrayRef<const NodeTy *> Sinks,
     // in the trimmed graph, then add the corresponding edges with
     // `addPredecessor()`, otherwise add them to the worklist.
     for (const ExplodedNode *Pred : N->Preds) {
-      if (const ExplodedNode *Mapped = ForwardMap->lookup(Pred))
+      if (const ExplodedNode *Mapped = NodeMap->lookup(Pred))
         NewN->addPredecessor(const_cast<ExplodedNode *>(Mapped), *Trimmed);
       else
         Worklist.push_back(Pred);
@@ -491,7 +487,7 @@ ExplodedGraph::trim(ArrayRef<const NodeTy *> Sinks,
     // worklist. Maybe we'll reach them through a different direction, maybe
     // they will be omitted from the trimmed graph.)
     for (const ExplodedNode *Succ : N->Succs)
-      if (const ExplodedNode *Mapped = ForwardMap->lookup(Succ))
+      if (const ExplodedNode *Mapped = NodeMap->lookup(Succ))
         const_cast<ExplodedNode *>(Mapped)->addPredecessor(NewN, *Trimmed);
   }
 

From 7ea7d8330e4ac8b8d637336395342deb574e4f6f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Don=C3=A1t=20Nagy?= <donat.n...@ericsson.com>
Date: Thu, 15 May 2025 14:07:07 +0200
Subject: [PATCH 04/10] Eliminate const_cast by using the proper type

---
 .../StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h     | 2 +-
 clang/lib/StaticAnalyzer/Core/ExplodedGraph.cpp           | 8 ++++----
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git 
a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h 
b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
index cf913c064933e..7fb1b8dc45bfd 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
@@ -298,7 +298,7 @@ class ExplodedNode : public llvm::FoldingSetNode {
 };
 
 using InterExplodedGraphMap =
-    llvm::DenseMap<const ExplodedNode *, const ExplodedNode *>;
+    llvm::DenseMap<const ExplodedNode *, ExplodedNode *>;
 
 class ExplodedGraph {
 protected:
diff --git a/clang/lib/StaticAnalyzer/Core/ExplodedGraph.cpp 
b/clang/lib/StaticAnalyzer/Core/ExplodedGraph.cpp
index 7a13dbe5961b8..ee76271e2eb5d 100644
--- a/clang/lib/StaticAnalyzer/Core/ExplodedGraph.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExplodedGraph.cpp
@@ -475,8 +475,8 @@ ExplodedGraph::trim(ArrayRef<const NodeTy *> Sinks,
     // in the trimmed graph, then add the corresponding edges with
     // `addPredecessor()`, otherwise add them to the worklist.
     for (const ExplodedNode *Pred : N->Preds) {
-      if (const ExplodedNode *Mapped = NodeMap->lookup(Pred))
-        NewN->addPredecessor(const_cast<ExplodedNode *>(Mapped), *Trimmed);
+      if (ExplodedNode *Mapped = NodeMap->lookup(Pred))
+        NewN->addPredecessor(Mapped, *Trimmed);
       else
         Worklist.push_back(Pred);
     }
@@ -487,8 +487,8 @@ ExplodedGraph::trim(ArrayRef<const NodeTy *> Sinks,
     // worklist. Maybe we'll reach them through a different direction, maybe
     // they will be omitted from the trimmed graph.)
     for (const ExplodedNode *Succ : N->Succs)
-      if (const ExplodedNode *Mapped = NodeMap->lookup(Succ))
-        const_cast<ExplodedNode *>(Mapped)->addPredecessor(NewN, *Trimmed);
+      if (ExplodedNode *Mapped = NodeMap->lookup(Succ))
+        Mapped->addPredecessor(NewN, *Trimmed);
   }
 
   assert(Trimmed->getRoot() && "The root must be reachable from any nonempty 
set of sinks!");

From c2a6891a417c854b2679236707a6a49f3a487b1a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Don=C3=A1t=20Nagy?= <donat.n...@ericsson.com>
Date: Thu, 15 May 2025 14:59:50 +0200
Subject: [PATCH 05/10] Avoid copying a vector of node pointers

---
 .../Core/PathSensitive/ExplodedGraph.h          | 17 ++++++++++++-----
 clang/lib/StaticAnalyzer/Core/BugReporter.cpp   |  6 +++---
 clang/lib/StaticAnalyzer/Core/ExplodedGraph.cpp |  6 ++----
 clang/lib/StaticAnalyzer/Core/ExprEngine.cpp    |  3 ++-
 4 files changed, 19 insertions(+), 13 deletions(-)

diff --git 
a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h 
b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
index 7fb1b8dc45bfd..911d9d350acab 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
@@ -300,6 +300,9 @@ class ExplodedNode : public llvm::FoldingSetNode {
 using InterExplodedGraphMap =
     llvm::DenseMap<const ExplodedNode *, ExplodedNode *>;
 
+using TrimGraphWorklist =
+    SmallVector<const ExplodedNode*, 32>;
+
 class ExplodedGraph {
 protected:
   friend class CoreEngine;
@@ -411,13 +414,17 @@ class ExplodedGraph {
   /// Creates a trimmed version of the graph that only contains paths leading
   /// to the given nodes.
   ///
-  /// \param Nodes The nodes which must appear in the final graph. Presumably
-  ///              these are end-of-path nodes (i.e. they have no successors).
-  /// \param[out] NodeMap An optional map from nodes in this graph to nodes
-  ///                        in the returned graph.
+  /// \param[in,out] Worklist Vector of nodes which must appear in the final
+  ///                         graph. Presumably these are end-of-path nodes
+  ///                         (i.e. they have no successors). This argument is
+  ///                         consumed and emptied by the trimming algorithm.
+  ///
+  /// \param[out] NodeMap If specified, this will be filled to map nodes from
+  ///                     this map to nodes in the returned graph.
+  ///
   /// \returns The trimmed graph
   std::unique_ptr<ExplodedGraph>
-  trim(ArrayRef<const NodeTy *> Nodes,
+  trim(TrimGraphWorklist &Worklist,
        InterExplodedGraphMap *NodeMap = nullptr) const;
 
   /// Enable tracking of recently allocated nodes for potential reclamation
diff --git a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp 
b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
index 188de7da50c62..67972b2e8ec2c 100644
--- a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
+++ b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
@@ -2628,19 +2628,19 @@ class BugPathGetter {
 
 BugPathGetter::BugPathGetter(const ExplodedGraph *OriginalGraph,
                              ArrayRef<PathSensitiveBugReport *> &bugReports) {
-  SmallVector<const ExplodedNode *, 32> Nodes;
+  TrimGraphWorklist Worklist;
   for (const auto I : bugReports) {
     assert(I->isValid() &&
            "We only allow BugReporterVisitors and BugReporter itself to "
            "invalidate reports!");
     if (const ExplodedNode *ErrNode = I->getErrorNode())
-      Nodes.emplace_back(ErrNode);
+      Worklist.emplace_back(ErrNode);
   }
 
   // The trimmed graph is created in the body of the constructor to ensure
   // that the DenseMaps have been initialized already.
   InterExplodedGraphMap NodeMap;
-  TrimmedGraph = OriginalGraph->trim(Nodes, &NodeMap);
+  TrimmedGraph = OriginalGraph->trim(Worklist, &NodeMap);
 
   // Find the (first) error node in the trimmed graph.  We just need to consult
   // the node map which maps from nodes in the original graph to nodes
diff --git a/clang/lib/StaticAnalyzer/Core/ExplodedGraph.cpp 
b/clang/lib/StaticAnalyzer/Core/ExplodedGraph.cpp
index ee76271e2eb5d..cbf160a83ab2a 100644
--- a/clang/lib/StaticAnalyzer/Core/ExplodedGraph.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExplodedGraph.cpp
@@ -439,15 +439,13 @@ ExplodedNode *ExplodedGraph::createUncachedNode(const 
ProgramPoint &L,
 }
 
 std::unique_ptr<ExplodedGraph>
-ExplodedGraph::trim(ArrayRef<const NodeTy *> Sinks,
+ExplodedGraph::trim(TrimGraphWorklist &Worklist,
                     InterExplodedGraphMap *NodeMap) const {
-  if (Sinks.empty())
+  if (Worklist.empty())
     return nullptr;
 
   std::unique_ptr<ExplodedGraph> Trimmed = std::make_unique<ExplodedGraph>();
 
-  SmallVector<const ExplodedNode*, 32> Worklist{Sinks};
-
   InterExplodedGraphMap Scratch;
   if (!NodeMap)
     NodeMap = &Scratch;
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp 
b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
index ebad83dad0c8f..6a7069954c731 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -4096,7 +4096,8 @@ std::string ExprEngine::DumpGraph(bool trim, StringRef 
Filename) {
 
 std::string ExprEngine::DumpGraph(ArrayRef<const ExplodedNode *> Nodes,
                                   StringRef Filename) {
-  std::unique_ptr<ExplodedGraph> TrimmedG(G.trim(Nodes));
+  TrimGraphWorklist Worklist{Nodes};
+  std::unique_ptr<ExplodedGraph> TrimmedG(G.trim(Worklist));
 
   if (!TrimmedG) {
     llvm::errs() << "warning: Trimmed ExplodedGraph is empty.\n";

From a8ced536abc7d31bf4479246e87e2a9f550d9f9a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Don=C3=A1t=20Nagy?= <donat.n...@ericsson.com>
Date: Thu, 15 May 2025 15:03:09 +0200
Subject: [PATCH 06/10] Delete an unused type alias

---
 .../clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h     | 2 --
 1 file changed, 2 deletions(-)

diff --git 
a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h 
b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
index 911d9d350acab..0e30a42800422 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
@@ -409,8 +409,6 @@ class ExplodedGraph {
   llvm::BumpPtrAllocator & getAllocator() { return BVC.getAllocator(); }
   BumpVectorContext &getNodeAllocator() { return BVC; }
 
-  using NodeMap = llvm::DenseMap<const ExplodedNode *, ExplodedNode *>;
-
   /// Creates a trimmed version of the graph that only contains paths leading
   /// to the given nodes.
   ///

From 42d30762c3dbb18914eaed9398eb28d28cedde7e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Don=C3=A1t=20Nagy?= <donat.n...@ericsson.com>
Date: Thu, 15 May 2025 15:16:18 +0200
Subject: [PATCH 07/10] Capitalize the parameter 'bugReports'

---
 clang/lib/StaticAnalyzer/Core/BugReporter.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp 
b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
index 67972b2e8ec2c..f080516574db8 100644
--- a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
+++ b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
@@ -2627,9 +2627,9 @@ class BugPathGetter {
 } // namespace
 
 BugPathGetter::BugPathGetter(const ExplodedGraph *OriginalGraph,
-                             ArrayRef<PathSensitiveBugReport *> &bugReports) {
+                             ArrayRef<PathSensitiveBugReport *> &BugReports) {
   TrimGraphWorklist Worklist;
-  for (const auto I : bugReports) {
+  for (const auto I : BugReports) {
     assert(I->isValid() &&
            "We only allow BugReporterVisitors and BugReporter itself to "
            "invalidate reports!");
@@ -2647,7 +2647,7 @@ BugPathGetter::BugPathGetter(const ExplodedGraph 
*OriginalGraph,
   // in the new graph.
   llvm::SmallPtrSet<const ExplodedNode *, 32> RemainingNodes;
 
-  for (PathSensitiveBugReport *Report : bugReports) {
+  for (PathSensitiveBugReport *Report : BugReports) {
     const ExplodedNode *NewNode = NodeMap.lookup(Report->getErrorNode());
     assert(NewNode &&
            "Failed to construct a trimmed graph that contains this error "

From f6b4ef520af22f8437b8b6423e68dcfae81c8690 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Don=C3=A1t=20Nagy?= <donat.n...@ericsson.com>
Date: Thu, 15 May 2025 15:23:30 +0200
Subject: [PATCH 08/10] Clarify that PathSensitiveBugReport::ErrorNode is never
 null

The declaration of this data member was specifying `nullptr` as an
initializer, but each constructor of the class initializes it to a
non-null value (which is taken as an argument) and nothing changes its
value later.
---
 .../clang/StaticAnalyzer/Core/BugReporter/BugReporter.h      | 5 +++--
 clang/lib/StaticAnalyzer/Core/BugReporter.cpp                | 4 ++--
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h 
b/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
index 8e1d25b3eefa1..7152a76d8649c 100644
--- a/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
+++ b/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
@@ -294,8 +294,9 @@ class PathSensitiveBugReport : public BugReport {
 
 protected:
   /// The ExplodedGraph node against which the report was thrown. It 
corresponds
-  /// to the end of the execution path that demonstrates the bug.
-  const ExplodedNode *ErrorNode = nullptr;
+  /// to the end of the execution path that demonstrates the bug. This is never
+  /// a nullpointer.
+  const ExplodedNode *ErrorNode;
 
   /// The range that corresponds to ErrorNode's program point. It is usually
   /// highlighted in the report.
diff --git a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp 
b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
index f080516574db8..ef2bcdb79561c 100644
--- a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
+++ b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
@@ -2171,6 +2171,7 @@ PathSensitiveBugReport::PathSensitiveBugReport(
     : BugReport(Kind::PathSensitive, bt, shortDesc, desc), 
ErrorNode(errorNode),
       ErrorNodeRange(getStmt() ? getStmt()->getSourceRange() : SourceRange()),
       UniqueingLocation(LocationToUnique), UniqueingDecl(DeclToUnique) {
+  assert(ErrorNode && "The error node must not be null!");
   assert(!isDependency(ErrorNode->getState()
                            ->getAnalysisManager()
                            .getCheckerManager()
@@ -2633,8 +2634,7 @@ BugPathGetter::BugPathGetter(const ExplodedGraph 
*OriginalGraph,
     assert(I->isValid() &&
            "We only allow BugReporterVisitors and BugReporter itself to "
            "invalidate reports!");
-    if (const ExplodedNode *ErrNode = I->getErrorNode())
-      Worklist.emplace_back(ErrNode);
+    Worklist.emplace_back(I->getErrorNode());
   }
 
   // The trimmed graph is created in the body of the constructor to ensure

From fde270e59862924f2ce282323ce93e83d9cd4ff6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Don=C3=A1t=20Nagy?= <donat.n...@ericsson.com>
Date: Thu, 15 May 2025 15:28:25 +0200
Subject: [PATCH 09/10] Fix misleading declaration of a loop variable

It looks like an iterator, let's clarify its type and use a better name.
---
 clang/lib/StaticAnalyzer/Core/BugReporter.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp 
b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
index ef2bcdb79561c..3b22b22be741d 100644
--- a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
+++ b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
@@ -2630,11 +2630,11 @@ class BugPathGetter {
 BugPathGetter::BugPathGetter(const ExplodedGraph *OriginalGraph,
                              ArrayRef<PathSensitiveBugReport *> &BugReports) {
   TrimGraphWorklist Worklist;
-  for (const auto I : BugReports) {
-    assert(I->isValid() &&
+  for (PathSensitiveBugReport *BR : BugReports) {
+    assert(BR->isValid() &&
            "We only allow BugReporterVisitors and BugReporter itself to "
            "invalidate reports!");
-    Worklist.emplace_back(I->getErrorNode());
+    Worklist.emplace_back(BR->getErrorNode());
   }
 
   // The trimmed graph is created in the body of the constructor to ensure

From 64b117aa17e4546e58edd49d139073939a080c5c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Don=C3=A1t=20Nagy?= <donat.n...@ericsson.com>
Date: Thu, 15 May 2025 15:30:06 +0200
Subject: [PATCH 10/10] Satisfy git-clang-format

---
 .../clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h    | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git 
a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h 
b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
index 0e30a42800422..235afa468692c 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
@@ -300,8 +300,7 @@ class ExplodedNode : public llvm::FoldingSetNode {
 using InterExplodedGraphMap =
     llvm::DenseMap<const ExplodedNode *, ExplodedNode *>;
 
-using TrimGraphWorklist =
-    SmallVector<const ExplodedNode*, 32>;
+using TrimGraphWorklist = SmallVector<const ExplodedNode *, 32>;
 
 class ExplodedGraph {
 protected:

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to