[clang] [clang][ssaf] Add EntityLinkage data structure (PR #181718)

Aviral Goel via cfe-commits cfe-commits at lists.llvm.org
Mon Feb 16 12:10:51 PST 2026


https://github.com/aviralg updated https://github.com/llvm/llvm-project/pull/181718

>From 981d4e23acaf6ec2135d52c2f7eb2d52f7833065 Mon Sep 17 00:00:00 2001
From: Aviral Goel <agoel26 at apple.com>
Date: Mon, 16 Feb 2026 10:21:09 -0800
Subject: [PATCH 1/3] Add EntityLinkage data structure and update TUSummary

---
 .../Analysis/Scalable/Model/EntityLinkage.h   | 50 +++++++++++++++++++
 .../Scalable/Model/PrivateFieldNames.def      |  2 +
 .../Analysis/Scalable/TUSummary/TUSummary.h   |  4 ++
 .../Analysis/Scalable/CMakeLists.txt          |  1 +
 .../Analysis/Scalable/EntityLinkageTest.cpp   | 48 ++++++++++++++++++
 5 files changed, 105 insertions(+)
 create mode 100644 clang/include/clang/Analysis/Scalable/Model/EntityLinkage.h
 create mode 100644 clang/unittests/Analysis/Scalable/EntityLinkageTest.cpp

diff --git a/clang/include/clang/Analysis/Scalable/Model/EntityLinkage.h b/clang/include/clang/Analysis/Scalable/Model/EntityLinkage.h
new file mode 100644
index 0000000000000..8ac51007afc65
--- /dev/null
+++ b/clang/include/clang/Analysis/Scalable/Model/EntityLinkage.h
@@ -0,0 +1,50 @@
+//===- EntityLinkage.h ------------------------------------------*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_SCALABLE_MODEL_ENTITYLINKAGE_H
+#define LLVM_CLANG_ANALYSIS_SCALABLE_MODEL_ENTITYLINKAGE_H
+
+namespace clang::ssaf {
+
+/// Represents the linkage properties of an entity in the program model.
+///
+/// EntityLinkage captures whether an entity has no linkage, internal linkage,
+/// or external linkage, which determines its visibility and accessibility
+/// across translation units.
+class EntityLinkage {
+  friend class SerializationFormat;
+
+public:
+  /// Specifies the type of linkage an entity has.
+  enum class LinkageType {
+    None,     ///< No linkage (e.g., local variables, function parameters)
+    Internal, ///< Internal linkage (static functions/variables, anonymous
+              ///< namespace)
+    External  ///< External linkage (globally visible across translation units)
+  };
+
+  /// Constructs an EntityLinkage with no linkage (default).
+  EntityLinkage() : Linkage(LinkageType::None) {}
+
+  /// Constructs an EntityLinkage with the specified linkage type.
+  ///
+  /// \param L The linkage type to assign to this entity.
+  explicit EntityLinkage(LinkageType L) : Linkage(L) {}
+
+  /// Returns the linkage type of this entity.
+  ///
+  /// \return The LinkageType indicating the entity's linkage.
+  LinkageType getLinkage() const { return Linkage; }
+
+private:
+  LinkageType Linkage;
+};
+
+} // namespace clang::ssaf
+
+#endif // LLVM_CLANG_ANALYSIS_SCALABLE_MODEL_ENTITYLINKAGE_H
diff --git a/clang/include/clang/Analysis/Scalable/Model/PrivateFieldNames.def b/clang/include/clang/Analysis/Scalable/Model/PrivateFieldNames.def
index 59064659996b4..961994f4ae455 100644
--- a/clang/include/clang/Analysis/Scalable/Model/PrivateFieldNames.def
+++ b/clang/include/clang/Analysis/Scalable/Model/PrivateFieldNames.def
@@ -19,12 +19,14 @@
 
 FIELD(BuildNamespace, Kind)
 FIELD(BuildNamespace, Name)
+FIELD(EntityLinkage, Linkage)
 FIELD(EntityName, Namespace)
 FIELD(EntityName, Suffix)
 FIELD(EntityName, USR)
 FIELD(NestedBuildNamespace, Namespaces)
 FIELD(TUSummary, Data)
 FIELD(TUSummary, IdTable)
+FIELD(TUSummary, LinkageTable)
 FIELD(TUSummary, TUNamespace)
 
 #undef FIELD
diff --git a/clang/include/clang/Analysis/Scalable/TUSummary/TUSummary.h b/clang/include/clang/Analysis/Scalable/TUSummary/TUSummary.h
index 4af1c70e1a488..2520ce87f3959 100644
--- a/clang/include/clang/Analysis/Scalable/TUSummary/TUSummary.h
+++ b/clang/include/clang/Analysis/Scalable/TUSummary/TUSummary.h
@@ -12,6 +12,7 @@
 #include "clang/Analysis/Scalable/Model/BuildNamespace.h"
 #include "clang/Analysis/Scalable/Model/EntityId.h"
 #include "clang/Analysis/Scalable/Model/EntityIdTable.h"
+#include "clang/Analysis/Scalable/Model/EntityLinkage.h"
 #include "clang/Analysis/Scalable/Model/SummaryName.h"
 #include "clang/Analysis/Scalable/TUSummary/EntitySummary.h"
 #include <map>
@@ -23,8 +24,11 @@ namespace clang::ssaf {
 class TUSummary {
   /// Identifies the translation unit.
   BuildNamespace TUNamespace;
+
   EntityIdTable IdTable;
 
+  std::map<EntityId, EntityLinkage> LinkageTable;
+
   std::map<SummaryName, std::map<EntityId, std::unique_ptr<EntitySummary>>>
       Data;
 
diff --git a/clang/unittests/Analysis/Scalable/CMakeLists.txt b/clang/unittests/Analysis/Scalable/CMakeLists.txt
index 601845b4ab77a..692fb0fa58b99 100644
--- a/clang/unittests/Analysis/Scalable/CMakeLists.txt
+++ b/clang/unittests/Analysis/Scalable/CMakeLists.txt
@@ -3,6 +3,7 @@ add_distinct_clang_unittest(ClangScalableAnalysisTests
   BuildNamespaceTest.cpp
   EntityIdTest.cpp
   EntityIdTableTest.cpp
+  EntityLinkageTest.cpp
   EntityNameTest.cpp
   Registries/FancyAnalysisData.cpp
   Registries/MockSerializationFormat.cpp
diff --git a/clang/unittests/Analysis/Scalable/EntityLinkageTest.cpp b/clang/unittests/Analysis/Scalable/EntityLinkageTest.cpp
new file mode 100644
index 0000000000000..d71cf0597d80f
--- /dev/null
+++ b/clang/unittests/Analysis/Scalable/EntityLinkageTest.cpp
@@ -0,0 +1,48 @@
+//===- unittests/Analysis/Scalable/EntityLinkageTest.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 "clang/Analysis/Scalable/Model/EntityLinkage.h"
+#include "gtest/gtest.h"
+
+namespace clang::ssaf {
+
+namespace {
+
+TEST(EntityLinkageTest, GetLinkageReturnsCorrectValue) {
+  EntityLinkage Linkage;
+  EntityLinkage NoneLinkage(EntityLinkage::LinkageType::None);
+  EntityLinkage InternalLinkage(EntityLinkage::LinkageType::Internal);
+  EntityLinkage ExternalLinkage(EntityLinkage::LinkageType::External);
+
+  EXPECT_EQ(Linkage.getLinkage(), EntityLinkage::LinkageType::None);
+  EXPECT_EQ(NoneLinkage.getLinkage(), EntityLinkage::LinkageType::None);
+  EXPECT_EQ(InternalLinkage.getLinkage(), EntityLinkage::LinkageType::Internal);
+  EXPECT_EQ(ExternalLinkage.getLinkage(), EntityLinkage::LinkageType::External);
+}
+
+TEST(EntityLinkageTest, CopyConstructor) {
+  EntityLinkage Original(EntityLinkage::LinkageType::External);
+  EntityLinkage Copy = Original;
+
+  EXPECT_EQ(Copy.getLinkage(), EntityLinkage::LinkageType::External);
+  EXPECT_EQ(Copy.getLinkage(), Original.getLinkage());
+}
+
+TEST(EntityLinkageTest, AssignmentOperator) {
+  EntityLinkage Linkage1(EntityLinkage::LinkageType::None);
+  EntityLinkage Linkage2(EntityLinkage::LinkageType::External);
+
+  Linkage1 = Linkage2;
+
+  EXPECT_EQ(Linkage1.getLinkage(), EntityLinkage::LinkageType::External);
+  EXPECT_EQ(Linkage1.getLinkage(), Linkage2.getLinkage());
+}
+
+} // namespace
+
+} // namespace clang::ssaf

>From a97a70dc745963eec91b03c864da43603805aea4 Mon Sep 17 00:00:00 2001
From: Aviral Goel <agoel26 at apple.com>
Date: Mon, 16 Feb 2026 11:24:09 -0800
Subject: [PATCH 2/3] Balazs

---
 .../Analysis/Scalable/Model/EntityLinkage.h   | 12 +++----
 .../Analysis/Scalable/EntityLinkageTest.cpp   | 34 ++++++++++---------
 2 files changed, 22 insertions(+), 24 deletions(-)

diff --git a/clang/include/clang/Analysis/Scalable/Model/EntityLinkage.h b/clang/include/clang/Analysis/Scalable/Model/EntityLinkage.h
index 8ac51007afc65..4aa5d597e1066 100644
--- a/clang/include/clang/Analysis/Scalable/Model/EntityLinkage.h
+++ b/clang/include/clang/Analysis/Scalable/Model/EntityLinkage.h
@@ -22,15 +22,11 @@ class EntityLinkage {
 public:
   /// Specifies the type of linkage an entity has.
   enum class LinkageType {
-    None,     ///< No linkage (e.g., local variables, function parameters)
-    Internal, ///< Internal linkage (static functions/variables, anonymous
-              ///< namespace)
-    External  ///< External linkage (globally visible across translation units)
+    None,     ///< local variables, function parameters
+    Internal, ///< static functions/variables, anonymous namespace
+    External  ///< globally visible across translation units
   };
 
-  /// Constructs an EntityLinkage with no linkage (default).
-  EntityLinkage() : Linkage(LinkageType::None) {}
-
   /// Constructs an EntityLinkage with the specified linkage type.
   ///
   /// \param L The linkage type to assign to this entity.
@@ -42,7 +38,7 @@ class EntityLinkage {
   LinkageType getLinkage() const { return Linkage; }
 
 private:
-  LinkageType Linkage;
+  LinkageType Linkage = LinkageType::None;
 };
 
 } // namespace clang::ssaf
diff --git a/clang/unittests/Analysis/Scalable/EntityLinkageTest.cpp b/clang/unittests/Analysis/Scalable/EntityLinkageTest.cpp
index d71cf0597d80f..0eb8ecd4fc97a 100644
--- a/clang/unittests/Analysis/Scalable/EntityLinkageTest.cpp
+++ b/clang/unittests/Analysis/Scalable/EntityLinkageTest.cpp
@@ -9,40 +9,42 @@
 #include "clang/Analysis/Scalable/Model/EntityLinkage.h"
 #include "gtest/gtest.h"
 
-namespace clang::ssaf {
+using clang::ssaf::EntityLinkage;
 
 namespace {
 
+constexpr inline auto None = EntityLinkage::LinkageType::None;
+constexpr inline auto Internal = EntityLinkage::LinkageType::Internal;
+constexpr inline auto External = EntityLinkage::LinkageType::External;
+
 TEST(EntityLinkageTest, GetLinkageReturnsCorrectValue) {
   EntityLinkage Linkage;
-  EntityLinkage NoneLinkage(EntityLinkage::LinkageType::None);
-  EntityLinkage InternalLinkage(EntityLinkage::LinkageType::Internal);
-  EntityLinkage ExternalLinkage(EntityLinkage::LinkageType::External);
-
-  EXPECT_EQ(Linkage.getLinkage(), EntityLinkage::LinkageType::None);
-  EXPECT_EQ(NoneLinkage.getLinkage(), EntityLinkage::LinkageType::None);
-  EXPECT_EQ(InternalLinkage.getLinkage(), EntityLinkage::LinkageType::Internal);
-  EXPECT_EQ(ExternalLinkage.getLinkage(), EntityLinkage::LinkageType::External);
+  EntityLinkage NoneLinkage(None);
+  EntityLinkage InternalLinkage(Internal);
+  EntityLinkage ExternalLinkage(External);
+
+  EXPECT_EQ(Linkage.getLinkage(), None);
+  EXPECT_EQ(NoneLinkage.getLinkage(), None);
+  EXPECT_EQ(InternalLinkage.getLinkage(), Internal);
+  EXPECT_EQ(ExternalLinkage.getLinkage(), External);
 }
 
 TEST(EntityLinkageTest, CopyConstructor) {
-  EntityLinkage Original(EntityLinkage::LinkageType::External);
+  EntityLinkage Original(External);
   EntityLinkage Copy = Original;
 
-  EXPECT_EQ(Copy.getLinkage(), EntityLinkage::LinkageType::External);
+  EXPECT_EQ(Copy.getLinkage(), External);
   EXPECT_EQ(Copy.getLinkage(), Original.getLinkage());
 }
 
 TEST(EntityLinkageTest, AssignmentOperator) {
-  EntityLinkage Linkage1(EntityLinkage::LinkageType::None);
-  EntityLinkage Linkage2(EntityLinkage::LinkageType::External);
+  EntityLinkage Linkage1(None);
+  EntityLinkage Linkage2(External);
 
   Linkage1 = Linkage2;
 
-  EXPECT_EQ(Linkage1.getLinkage(), EntityLinkage::LinkageType::External);
+  EXPECT_EQ(Linkage1.getLinkage(), External);
   EXPECT_EQ(Linkage1.getLinkage(), Linkage2.getLinkage());
 }
 
 } // namespace
-
-} // namespace clang::ssaf

>From 39c958d1990475d8db61746a6626f7b29a1c40a6 Mon Sep 17 00:00:00 2001
From: Aviral Goel <agoel26 at apple.com>
Date: Mon, 16 Feb 2026 12:09:04 -0800
Subject: [PATCH 3/3] More fixes

---
 .../clang/Analysis/Scalable/Model/EntityLinkage.h        | 9 +--------
 clang/unittests/Analysis/Scalable/EntityLinkageTest.cpp  | 4 +---
 2 files changed, 2 insertions(+), 11 deletions(-)

diff --git a/clang/include/clang/Analysis/Scalable/Model/EntityLinkage.h b/clang/include/clang/Analysis/Scalable/Model/EntityLinkage.h
index 4aa5d597e1066..ba5f7d3073a30 100644
--- a/clang/include/clang/Analysis/Scalable/Model/EntityLinkage.h
+++ b/clang/include/clang/Analysis/Scalable/Model/EntityLinkage.h
@@ -20,25 +20,18 @@ class EntityLinkage {
   friend class SerializationFormat;
 
 public:
-  /// Specifies the type of linkage an entity has.
   enum class LinkageType {
     None,     ///< local variables, function parameters
     Internal, ///< static functions/variables, anonymous namespace
     External  ///< globally visible across translation units
   };
 
-  /// Constructs an EntityLinkage with the specified linkage type.
-  ///
-  /// \param L The linkage type to assign to this entity.
   explicit EntityLinkage(LinkageType L) : Linkage(L) {}
 
-  /// Returns the linkage type of this entity.
-  ///
-  /// \return The LinkageType indicating the entity's linkage.
   LinkageType getLinkage() const { return Linkage; }
 
 private:
-  LinkageType Linkage = LinkageType::None;
+  LinkageType Linkage;
 };
 
 } // namespace clang::ssaf
diff --git a/clang/unittests/Analysis/Scalable/EntityLinkageTest.cpp b/clang/unittests/Analysis/Scalable/EntityLinkageTest.cpp
index 0eb8ecd4fc97a..efd804de0af5f 100644
--- a/clang/unittests/Analysis/Scalable/EntityLinkageTest.cpp
+++ b/clang/unittests/Analysis/Scalable/EntityLinkageTest.cpp
@@ -17,13 +17,11 @@ constexpr inline auto None = EntityLinkage::LinkageType::None;
 constexpr inline auto Internal = EntityLinkage::LinkageType::Internal;
 constexpr inline auto External = EntityLinkage::LinkageType::External;
 
-TEST(EntityLinkageTest, GetLinkageReturnsCorrectValue) {
-  EntityLinkage Linkage;
+TEST(EntityLinkageTest, Constructor) {
   EntityLinkage NoneLinkage(None);
   EntityLinkage InternalLinkage(Internal);
   EntityLinkage ExternalLinkage(External);
 
-  EXPECT_EQ(Linkage.getLinkage(), None);
   EXPECT_EQ(NoneLinkage.getLinkage(), None);
   EXPECT_EQ(InternalLinkage.getLinkage(), Internal);
   EXPECT_EQ(ExternalLinkage.getLinkage(), External);



More information about the cfe-commits mailing list