[llvm-branch-commits] [clang] [Draft][NFC][SSAF] Rename PointerFlowReachableAnalysis to UnsafeBufferReachableAnalysis (PR #195204)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Thu Apr 30 18:06:29 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang-ssaf

Author: Ziqing Luo (ziqingluo-90)

<details>
<summary>Changes</summary>

The previous-named PointerFlowReachableAnalysis is essentially
propagating unsafe buffers on a pointer flow graph.  The pointer flow
analysis is a dependency, instead of the subject.  So do the rename
and move.

---

Patch is 31.15 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/195204.diff


5 Files Affected:

- (modified) clang/include/clang/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowAnalysis.h (-14) 
- (modified) clang/include/clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageAnalysis.h (+21-2) 
- (modified) clang/lib/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowAnalysis.cpp (-110) 
- (modified) clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageAnalysis.cpp (+108) 
- (added) clang/unittests/ScalableStaticAnalysisFramework/WholeProgramAnalysis/PointerFlowReachableAnalysisTest.cpp (+434) 


``````````diff
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowAnalysis.h b/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowAnalysis.h
index 5b2e534368f98..f0d5c779a3298 100644
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowAnalysis.h
+++ b/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowAnalysis.h
@@ -9,16 +9,12 @@
 // Defines
 // - PointerFlowAnalysisResult
 //     - the plain PointerFlow info collected from the whole program.
-// - PointerFlowReachableAnalysisResult
-//     - the set of reachable pointers in the pointer flow graph from a provided
-//       starting set.
 //
 //===----------------------------------------------------------------------===//
 
 #ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_POINTERFLOW_POINTERFLOWANALYSIS_H
 #define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_POINTERFLOW_POINTERFLOWANALYSIS_H
 
-#include "clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.h"
 #include "clang/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlow.h"
 #include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
 #include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisName.h"
@@ -30,8 +26,6 @@ namespace clang::ssaf {
 
 constexpr llvm::StringLiteral PointerFlowAnalysisResultName =
     "PointerFlowAnalysisResult";
-constexpr llvm::StringLiteral UnsafeBufferReachableAnalysisResultName =
-    "UnsafeBufferReachableAnalysisResult";
 
 /// A PointerFlowAnalysisResult is a set of pointer-flow edges, i.e.,
 /// a pointer-flow graph. A directed edge src -> dest corresponds to an
@@ -51,14 +45,6 @@ struct PointerFlowAnalysisResult final : AnalysisResult {
   std::map<EntityId, EdgeSet> Edges;
 };
 
-struct UnsafeBufferReachableAnalysisResult final : AnalysisResult {
-  static AnalysisName analysisName() {
-    return AnalysisName(UnsafeBufferReachableAnalysisResultName.str());
-  }
-
-  std::map<EntityId, EntityPointerLevelSet> Reachables;
-};
-
 } // namespace clang::ssaf
 
 #endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_POINTERFLOW_POINTERFLOWANALYSIS_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageAnalysis.h b/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageAnalysis.h
index 9cfd59e5c0333..da9115679bb2c 100644
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageAnalysis.h
+++ b/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageAnalysis.h
@@ -6,8 +6,17 @@
 //
 //===----------------------------------------------------------------------===//
 //
-// Defines UnsafeBufferUsageAnalysisResult, the whole-program analysis result
-// type for UnsafeBufferUsageAnalysis.
+// Defines:
+// - UnsafeBufferUsageAnalysisResult
+//     - the whole-program analysis result
+//       type for UnsafeBufferUsageAnalysis. It collects unsafe buffer usages
+//       throughout the whole program.
+//
+// - UnsafeBufferReachableAnalysisResult
+//     - the whole-program analysis result
+//       type for UnsafeBufferReachableAnalysis. It propagates unsafe buffer
+//       usages through the pointer flow graph, starting from the initial set
+//       collected by UnsafeBufferUsageAnalysis.
 //
 //===----------------------------------------------------------------------===//
 
@@ -25,6 +34,8 @@ namespace clang::ssaf {
 
 constexpr llvm::StringLiteral UnsafeBufferUsageAnalysisResultName =
     "UnsafeBufferUsageAnalysisResult";
+constexpr llvm::StringLiteral UnsafeBufferReachableAnalysisResultName =
+    "UnsafeBufferReachableAnalysisResult";
 
 struct UnsafeBufferUsageAnalysisResult final : AnalysisResult {
   static AnalysisName analysisName() {
@@ -38,6 +49,14 @@ struct UnsafeBufferUsageAnalysisResult final : AnalysisResult {
   auto end() const { return UnsafeBuffers.end(); }
 };
 
+struct UnsafeBufferReachableAnalysisResult final : AnalysisResult {
+  static AnalysisName analysisName() {
+    return AnalysisName(UnsafeBufferReachableAnalysisResultName.str());
+  }
+
+  std::map<EntityId, EntityPointerLevelSet> Reachables;
+};
+
 } // namespace clang::ssaf
 
 #endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_UNSAFEBUFFERUSAGE_UNSAFEBUFFERUSAGEANALYSIS_H
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowAnalysis.cpp b/clang/lib/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowAnalysis.cpp
index c3916b38ae7ff..cf606a76bbe0a 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowAnalysis.cpp
+++ b/clang/lib/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowAnalysis.cpp
@@ -8,11 +8,8 @@
 
 #include "clang/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowAnalysis.h"
 #include "SSAFAnalysesCommon.h"
-#include "clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.h"
-#include "clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevelFormat.h"
 #include "clang/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlow.h"
 #include "clang/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowFormat.h"
-#include "clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageAnalysis.h"
 #include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
 #include "clang/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat.h"
 #include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisRegistry.h"
@@ -117,113 +114,6 @@ class PointerFlowAnalysis final
 AnalysisRegistry::Add<PointerFlowAnalysis>
     RegisterPointerFlowAnalysis("Whole-program pointer flow analysis");
 
-//===----------------------------------------------------------------------===//
-// PointerFlowReachableAnalysis---computes reachable node
-//===----------------------------------------------------------------------===//
-
-json::Object serializePointerFlowReachableAnalysisResult(
-    const UnsafeBufferReachableAnalysisResult &R,
-    JSONFormat::EntityIdToJSONFn IdToJSON) {
-  json::Object Result;
-
-  Result[UnsafeBufferReachableAnalysisResultName] =
-      entityPointerLevelMapToJSON(R.Reachables, IdToJSON);
-  return Result;
-}
-
-Expected<std::unique_ptr<AnalysisResult>>
-deserializePointerFlowReachableAnalysisResult(
-    const json::Object &Obj, JSONFormat::EntityIdFromJSONFn IdFromJSON) {
-  const json::Array *Content =
-      Obj.getArray(UnsafeBufferReachableAnalysisResultName);
-
-  if (!Content)
-    return makeSawButExpectedError(
-        Obj, "an object with a key %s",
-        UnsafeBufferReachableAnalysisResultName.data());
-
-  auto Reachables = entityPointerLevelMapFromJSON(*Content, IdFromJSON);
-
-  if (!Reachables)
-    return Reachables.takeError();
-
-  auto Ret = std::make_unique<UnsafeBufferReachableAnalysisResult>();
-
-  Ret->Reachables = std::move(*Reachables);
-  return Ret;
-}
-
-JSONFormat::AnalysisResultRegistry::Add<UnsafeBufferReachableAnalysisResult>
-    RegisterPointerFlowReachableResultForJSON(
-        serializePointerFlowReachableAnalysisResult,
-        deserializePointerFlowReachableAnalysisResult);
-
-/// Computes all the reachable "nodes" (pointers) in a pointer flow graph from a
-/// provided starter node set.  Specifically, the starter set is the unsafe
-/// pointers found by `UnsafeBufferUsageAnalysis`.
-class UnsafeBufferReachableAnalysis
-    : public DerivedAnalysis<UnsafeBufferReachableAnalysisResult,
-                             PointerFlowAnalysisResult,
-                             UnsafeBufferUsageAnalysisResult> {
-  using GraphT = std::map<EntityId, EdgeSet>;
-  const GraphT *Graph = nullptr;
-
-  // Use pointers for efficiency. Both `Graph` and `Reachables` in the result
-  // are tree-based containers that only grow. So pointers to them are stable.
-  using EPLPtr = const EntityPointerLevel *;
-
-  // Find all outgoing edges from `EPL` in the `Graph`, insert their
-  // destination nodes into `Reachables`, and add newly discovered nodes to
-  // `Worklist`:
-  void updateReachablesWithOutgoings(EPLPtr EPL,
-                                     std::vector<EPLPtr> &WorkList) {
-    for (auto &[Id, SubGraph] : *Graph) {
-      auto I = SubGraph.find(*EPL);
-
-      if (I != SubGraph.end()) {
-        for (const auto &EPL : I->second) {
-          auto [Ignored, Inserted] = getResult().Reachables[Id].insert(EPL);
-          if (Inserted)
-            WorkList.push_back(&EPL);
-        }
-      }
-    }
-  }
-
-public:
-  llvm::Error
-  initialize(const PointerFlowAnalysisResult &Graph,
-             const UnsafeBufferUsageAnalysisResult &Starter) override {
-    this->Graph = &Graph.Edges;
-    assert(getResult().Reachables.empty());
-    getResult().Reachables.insert(Starter.begin(), Starter.end());
-    return llvm::Error::success();
-  }
-
-  llvm::Expected<bool> step() override {
-    auto &Reachables = getResult().Reachables;
-    // Simple DFS:
-    std::vector<EPLPtr> Worklist;
-
-    for (auto &[Id, EPLs] : Reachables)
-      for (auto &EPL : EPLs)
-        Worklist.push_back(&EPL);
-
-    while (!Worklist.empty()) {
-      EPLPtr Node = Worklist.back();
-      Worklist.pop_back();
-
-      updateReachablesWithOutgoings(Node, Worklist);
-    }
-    // This is not an iterative algorithm so stop iteration by retruning false:
-    return false;
-  }
-};
-
-AnalysisRegistry::Add<UnsafeBufferReachableAnalysis>
-    RegisterPointerFlowReachableAnalysis(
-        "Reachable pointers from unsafe buffer usage in pointer flow graph");
-
 } // namespace
 
 // NOLINTNEXTLINE(misc-use-internal-linkage)
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageAnalysis.cpp b/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageAnalysis.cpp
index 0a7b62f207864..abafacbbad608 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageAnalysis.cpp
+++ b/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageAnalysis.cpp
@@ -15,6 +15,7 @@
 #include "SSAFAnalysesCommon.h"
 #include "clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.h"
 #include "clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevelFormat.h"
+#include "clang/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowAnalysis.h"
 #include "clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h"
 #include "clang/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat.h"
 #include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisRegistry.h"
@@ -82,6 +83,113 @@ AnalysisRegistry::Add<UnsafeBufferUsageAnalysis>
     RegisterUnsafeBufferUsageAnalysis(
         "Whole-program unsafe buffer usage analysis");
 
+//===----------------------------------------------------------------------===//
+// UnsafeBufferReachableAnalysis---computes reachable unsafe buffer nodes
+//===----------------------------------------------------------------------===//
+
+json::Object serializeUnsafeBufferReachableAnalysisResult(
+    const UnsafeBufferReachableAnalysisResult &R,
+    JSONFormat::EntityIdToJSONFn IdToJSON) {
+  json::Object Result;
+
+  Result[UnsafeBufferReachableAnalysisResultName] =
+      entityPointerLevelMapToJSON(R.Reachables, IdToJSON);
+  return Result;
+}
+
+Expected<std::unique_ptr<AnalysisResult>>
+deserializeUnsafeBufferReachableAnalysisResult(
+    const json::Object &Obj, JSONFormat::EntityIdFromJSONFn IdFromJSON) {
+  const json::Array *Content =
+      Obj.getArray(UnsafeBufferReachableAnalysisResultName);
+
+  if (!Content)
+    return makeSawButExpectedError(
+        Obj, "an object with a key %s",
+        UnsafeBufferReachableAnalysisResultName.data());
+
+  auto Reachables = entityPointerLevelMapFromJSON(*Content, IdFromJSON);
+
+  if (!Reachables)
+    return Reachables.takeError();
+
+  auto Ret = std::make_unique<UnsafeBufferReachableAnalysisResult>();
+
+  Ret->Reachables = std::move(*Reachables);
+  return Ret;
+}
+
+JSONFormat::AnalysisResultRegistry::Add<UnsafeBufferReachableAnalysisResult>
+    RegisterPointerFlowReachableResultForJSON(
+        serializeUnsafeBufferReachableAnalysisResult,
+        deserializeUnsafeBufferReachableAnalysisResult);
+
+/// Computes all the reachable "nodes" (pointers) in a pointer flow graph from a
+/// provided starter node set.  Specifically, the starter set is the unsafe
+/// pointers found by `UnsafeBufferUsageAnalysis`.
+class UnsafeBufferReachableAnalysis
+    : public DerivedAnalysis<UnsafeBufferReachableAnalysisResult,
+                             PointerFlowAnalysisResult,
+                             UnsafeBufferUsageAnalysisResult> {
+  using GraphT = std::map<EntityId, EdgeSet>;
+  const GraphT *Graph = nullptr;
+
+  // Use pointers for efficiency. Both `Graph` and `Reachables` in the result
+  // are tree-based containers that only grow. So pointers to them are stable.
+  using EPLPtr = const EntityPointerLevel *;
+
+  // Find all outgoing edges from `EPL` in the `Graph`, insert their
+  // destination nodes into `Reachables`, and add newly discovered nodes to
+  // `Worklist`:
+  void updateReachablesWithOutgoings(EPLPtr EPL,
+                                     std::vector<EPLPtr> &WorkList) {
+    for (auto &[Id, SubGraph] : *Graph) {
+      auto I = SubGraph.find(*EPL);
+
+      if (I != SubGraph.end()) {
+        for (const auto &EPL : I->second) {
+          auto [Ignored, Inserted] = getResult().Reachables[Id].insert(EPL);
+          if (Inserted)
+            WorkList.push_back(&EPL);
+        }
+      }
+    }
+  }
+
+public:
+  llvm::Error
+  initialize(const PointerFlowAnalysisResult &Graph,
+             const UnsafeBufferUsageAnalysisResult &Starter) override {
+    this->Graph = &Graph.Edges;
+    assert(getResult().Reachables.empty());
+    getResult().Reachables.insert(Starter.begin(), Starter.end());
+    return llvm::Error::success();
+  }
+
+  llvm::Expected<bool> step() override {
+    auto &Reachables = getResult().Reachables;
+    // Simple DFS:
+    std::vector<EPLPtr> Worklist;
+
+    for (auto &[Id, EPLs] : Reachables)
+      for (auto &EPL : EPLs)
+        Worklist.push_back(&EPL);
+
+    while (!Worklist.empty()) {
+      EPLPtr Node = Worklist.back();
+      Worklist.pop_back();
+
+      updateReachablesWithOutgoings(Node, Worklist);
+    }
+    // This is not an iterative algorithm so stop iteration by retruning false:
+    return false;
+  }
+};
+
+AnalysisRegistry::Add<UnsafeBufferReachableAnalysis>
+    RegisterUnsafeBufferReachableAnalysis(
+        "Reachable pointers from unsafe buffer usage in pointer flow graph");
+
 } // namespace
 
 // NOLINTNEXTLINE(misc-use-internal-linkage)
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/WholeProgramAnalysis/PointerFlowReachableAnalysisTest.cpp b/clang/unittests/ScalableStaticAnalysisFramework/WholeProgramAnalysis/PointerFlowReachableAnalysisTest.cpp
new file mode 100644
index 0000000000000..cc303faf09254
--- /dev/null
+++ b/clang/unittests/ScalableStaticAnalysisFramework/WholeProgramAnalysis/PointerFlowReachableAnalysisTest.cpp
@@ -0,0 +1,434 @@
+//===- UnsafeBufferReachableAnalysisTest.cpp
+//-------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "../TestFixture.h"
+#include "clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.h"
+#include "clang/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlow.h"
+#include "clang/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowAnalysis.h"
+#include "clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h"
+#include "clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageAnalysis.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummary.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisDriver.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/WPASuite.h"
+#include "llvm/ADT/Sequence.h"
+#include "gtest/gtest.h"
+#include <map>
+#include <memory>
+#include <optional>
+
+using namespace clang;
+using namespace ssaf;
+
+namespace clang::ssaf {
+extern PointerFlowEntitySummary buildPointerFlowEntitySummary(EdgeSet Edges);
+extern UnsafeBufferUsageEntitySummary
+    buildUnsafeBufferUsageEntitySummary(EntityPointerLevelSet);
+} // namespace clang::ssaf
+
+namespace {
+
+/// Enumerate all possible partitions of `N` nodes into `NumGrps` groups.
+/// Both nodes and groups are unlabeled. For each partition, a non-increasing
+/// order is enforced to avoid equivalent permutations.
+///
+/// \return all possible partitions, each represented as an array of unsigned
+/// integers denoting the number of nodes in each group.
+/// \param N the number of nodes
+/// \param NumGrps the number of groups
+/// \param MaxPerGrp an upper bound on the number of nodes per group, used to
+/// enforce non-increasing order and prevent duplicate partitions.
+using PartitionT = std::vector<unsigned>;
+static std::vector<PartitionT> enumeratePartition(unsigned N, unsigned NumGrps,
+                                                  unsigned MaxPerGrp) {
+  if (NumGrps == 0) {
+    if (N == 0)
+      return {{}};
+    return {}; // Due to the non-increasing order enforcement, equivalent
+               // permutations become invalid partitions.
+  }
+
+  std::vector<PartitionT> Partitions;
+
+  MaxPerGrp = std::min(N, MaxPerGrp);
+  // Try to distribute `J` nodes to the current group:
+  for (unsigned J = MaxPerGrp;; --J) {
+    std::vector<PartitionT> PrefixPartitions =
+        enumeratePartition(N - J, NumGrps - 1, J);
+
+    for (auto &Partition : PrefixPartitions) {
+      Partition.push_back(J);
+      Partitions.push_back(std::move(Partition));
+    }
+    if (J == 0)
+      break;
+  }
+  return Partitions;
+}
+
+class UnsafeBufferReachableAnalysisTest : public TestFixture {
+protected:
+  using EPLEdge = std::pair<EntityPointerLevel, EntityPointerLevel>;
+
+  static constexpr EntityLinkage ExternalLinkage =
+      EntityLinkage(EntityLinkageType::External);
+
+  std::unique_ptr<LUSummary> makeLUSummary() {
+    NestedBuildNamespace NS(
+        {BuildNamespace(BuildNamespaceKind::LinkUnit, "TestLU")});
+    return std::make_unique<LUSummary>(std::move(NS));
+  }
+
+  EntityId addEntity(LUSummary &LU, llvm::StringRef USR) {
+    NestedBuildNamespace NS(
+        {BuildNamespace(BuildNamespaceKind::LinkUnit, "TestLU")});
+    EntityName Name(USR.str(), "", NS);
+    EntityId Id = getIdTable(LU).getId(Name);
+    getLinkageTable(LU).insert({Id, ExternalLinkage});
+    return Id;
+  }
+
+  /// Insert a PointerFlowEntitySummary for an entity.
+  void insertPointerFlowSummary(LUSummary &LU, EntityId Id, EdgeSet Edges) {
+    getData(LU)[PointerFlowEntitySummary::summaryName()][Id] =
+        std::make_unique<PointerFlowEntitySummary>(
+            buildPointerFlowEntitySummary(std::move(Edges)));
+  }
+
+  /// Insert an UnsafeBufferUsageEntitySummary for an entity.
+  void insertUnsafeBufferUsageSummary(LUSummary &LU, EntityId Id,
+                                      EntityPointerLevelSet UnsafeBuffers) {
+    getData(LU)[UnsafeBufferUsageEntitySummary::summaryName()][Id] =
+        std::make_unique<UnsafeBufferUsageEntitySummary>(
+            buildUnsafeBufferUsageEntitySummary(std::move(UnsafeBuffers)));
+  }
+
+  /// Create \p N entities in \p LU and return their EntityIds.
+  std::vector<EntityId> createEntities(LU...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/195204


More information about the llvm-branch-commits mailing list