[clang] [clang][ssaf] Add SerializationFormatRegistry [1/2] (PR #179516)
Balázs Benics via cfe-commits
cfe-commits at lists.llvm.org
Thu Feb 5 01:02:45 PST 2026
https://github.com/steakhal updated https://github.com/llvm/llvm-project/pull/179516
>From f51136e476c265424f263493cf664b4eab8c3252 Mon Sep 17 00:00:00 2001
From: Balazs Benics <benicsbalazs at gmail.com>
Date: Tue, 3 Feb 2026 17:49:12 +0100
Subject: [PATCH 1/2] [clang][ssaf] Add SerializationFormatRegistry [2/3]
Add a registry infrastructure for SerializationFormat implementations,
enabling registration and instantiation of different serialization formats.
For example:
```c++
static SerializationFormatRegistry::Add<MyFormat>
RegisterFormat("MyFormat", "Description");
```
Formats can then be instantiated by name using `makeFormat()`.
The patch also updates the SerializationFormat base class to accept
FileSystem and OutputBackend parameters for virtualizing I/O
operations.
Assisted-by: claude
---
.../Serialization/SerializationFormat.h | 7 ++
.../SerializationFormatRegistry.h | 70 +++++++++++++++++++
clang/lib/Analysis/Scalable/CMakeLists.txt | 1 +
.../Serialization/SerializationFormat.cpp | 4 ++
.../SerializationFormatRegistry.cpp | 36 ++++++++++
.../Analysis/Scalable/CMakeLists.txt | 2 +
.../Registries/MockSerializationFormat.cpp | 38 ++++++++++
.../Registries/MockSerializationFormat.h | 29 ++++++++
.../SerializationFormatRegistryTest.cpp | 29 ++++++++
9 files changed, 216 insertions(+)
create mode 100644 clang/include/clang/Analysis/Scalable/Serialization/SerializationFormatRegistry.h
create mode 100644 clang/lib/Analysis/Scalable/Serialization/SerializationFormatRegistry.cpp
create mode 100644 clang/unittests/Analysis/Scalable/Registries/MockSerializationFormat.cpp
create mode 100644 clang/unittests/Analysis/Scalable/Registries/MockSerializationFormat.h
create mode 100644 clang/unittests/Analysis/Scalable/Registries/SerializationFormatRegistryTest.cpp
diff --git a/clang/include/clang/Analysis/Scalable/Serialization/SerializationFormat.h b/clang/include/clang/Analysis/Scalable/Serialization/SerializationFormat.h
index a53a315f461df..36efc6c273bd5 100644
--- a/clang/include/clang/Analysis/Scalable/Serialization/SerializationFormat.h
+++ b/clang/include/clang/Analysis/Scalable/Serialization/SerializationFormat.h
@@ -15,8 +15,10 @@
#define CLANG_ANALYSIS_SCALABLE_SERIALIZATION_SERIALIZATION_FORMAT_H
#include "clang/Analysis/Scalable/Model/BuildNamespace.h"
+#include "clang/Analysis/Scalable/TUSummary/TUSummary.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/VirtualFileSystem.h"
#include <vector>
namespace clang::ssaf {
@@ -48,12 +50,17 @@ class SerializationFormat {
getEntityNameNamespace(const EntityName &EN);
public:
+ explicit SerializationFormat(
+ llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS);
virtual ~SerializationFormat() = default;
virtual TUSummary readTUSummary(llvm::StringRef Path) = 0;
virtual void writeTUSummary(const TUSummary &Summary,
llvm::StringRef OutputDir) = 0;
+
+protected:
+ llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS;
};
} // namespace clang::ssaf
diff --git a/clang/include/clang/Analysis/Scalable/Serialization/SerializationFormatRegistry.h b/clang/include/clang/Analysis/Scalable/Serialization/SerializationFormatRegistry.h
new file mode 100644
index 0000000000000..17f2610380266
--- /dev/null
+++ b/clang/include/clang/Analysis/Scalable/Serialization/SerializationFormatRegistry.h
@@ -0,0 +1,70 @@
+//===- SerializationFormatRegistry.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
+//
+//===----------------------------------------------------------------------===//
+//
+// Registry for SerializationFormats, and some helper functions.
+// To register some custom serialization format, insert this code:
+//
+// static SerializationFormatRegistry::Add<MyFormat>
+// RegisterFormat("MyFormat", "My awesome serialization format");
+//
+// Then implement the formatter for the specific analysis and register the
+// format info for it:
+//
+// namespace {
+// struct MyAnalysisFormatInfo : FormatInfo {
+// MyAnalysisFormatInfo() : FormatInfo{
+// SummaryName("MyAnalysis"),
+// serializeMyAnalysis,
+// deserializeMyAnalysis,
+// } {}
+// };
+// } // namespace
+//
+// static llvm::Registry<FormatInfo>::Add<MyAnalysisFormatInfo>
+// RegisterFormatInfo(
+// "MyAnalysisFormatInfo",
+// "The MyFormat format info implementation for MyAnalysis"
+// );
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_ANALYSIS_SCALABLE_SERIALIZATION_SERIALIZATION_FORMAT_REGISTRY_H
+#define CLANG_ANALYSIS_SCALABLE_SERIALIZATION_SERIALIZATION_FORMAT_REGISTRY_H
+
+#include "clang/Analysis/Scalable/Serialization/SerializationFormat.h"
+#include "clang/Support/Compiler.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Registry.h"
+
+namespace clang::ssaf {
+
+/// Check if a SerializationFormat was registered with a given name.
+bool isFormatRegistered(llvm::StringRef FormatName);
+
+/// Try to instantiate a SerializationFormat with a given name.
+/// This might return null if the construction of the desired
+/// SerializationFormat failed.
+/// It's a fatal error if there is no format registered with the name.
+std::unique_ptr<SerializationFormat>
+makeFormat(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS,
+ llvm::StringRef FormatName);
+
+// Registry for adding new SerializationFormat implementations.
+using SerializationFormatRegistry =
+ llvm::Registry<SerializationFormat,
+ llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>>;
+
+} // namespace clang::ssaf
+
+namespace llvm {
+extern template class CLANG_TEMPLATE_ABI
+ Registry<clang::ssaf::SerializationFormat,
+ llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>>;
+} // namespace llvm
+
+#endif // CLANG_ANALYSIS_SCALABLE_SERIALIZATION_SERIALIZATION_FORMAT_REGISTRY_H
diff --git a/clang/lib/Analysis/Scalable/CMakeLists.txt b/clang/lib/Analysis/Scalable/CMakeLists.txt
index 36365b1fb87e1..c8f959e274c6d 100644
--- a/clang/lib/Analysis/Scalable/CMakeLists.txt
+++ b/clang/lib/Analysis/Scalable/CMakeLists.txt
@@ -8,6 +8,7 @@ add_clang_library(clangAnalysisScalable
Model/EntityIdTable.cpp
Model/EntityName.cpp
Serialization/SerializationFormat.cpp
+ Serialization/SerializationFormatRegistry.cpp
TUSummary/ExtractorRegistry.cpp
LINK_LIBS
diff --git a/clang/lib/Analysis/Scalable/Serialization/SerializationFormat.cpp b/clang/lib/Analysis/Scalable/Serialization/SerializationFormat.cpp
index ee155d22afa9b..6bb05747058fa 100644
--- a/clang/lib/Analysis/Scalable/Serialization/SerializationFormat.cpp
+++ b/clang/lib/Analysis/Scalable/Serialization/SerializationFormat.cpp
@@ -14,6 +14,10 @@
using namespace clang::ssaf;
+SerializationFormat::SerializationFormat(
+ llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS)
+ : FS(FS) {}
+
EntityIdTable &SerializationFormat::getIdTableForDeserialization(TUSummary &S) {
return S.IdTable;
}
diff --git a/clang/lib/Analysis/Scalable/Serialization/SerializationFormatRegistry.cpp b/clang/lib/Analysis/Scalable/Serialization/SerializationFormatRegistry.cpp
new file mode 100644
index 0000000000000..f31a154866238
--- /dev/null
+++ b/clang/lib/Analysis/Scalable/Serialization/SerializationFormatRegistry.cpp
@@ -0,0 +1,36 @@
+//===- SerializationFormatRegistry.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/Serialization/SerializationFormatRegistry.h"
+#include <memory>
+
+using namespace clang;
+using namespace ssaf;
+
+// FIXME: LLVM_INSTANTIATE_REGISTRY can't be used here because it drops extra
+// type parameters.
+template class CLANG_EXPORT_TEMPLATE
+ llvm::Registry<clang::ssaf::SerializationFormat,
+ llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>>;
+
+bool ssaf::isFormatRegistered(llvm::StringRef FormatName) {
+ for (const auto &Entry : SerializationFormatRegistry::entries())
+ if (Entry.getName() == FormatName)
+ return true;
+ return false;
+}
+
+std::unique_ptr<SerializationFormat>
+ssaf::makeFormat(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS,
+ llvm::StringRef FormatName) {
+ for (const auto &Entry : SerializationFormatRegistry::entries())
+ if (Entry.getName() == FormatName)
+ return Entry.instantiate(std::move(FS));
+ assert(false && "Unknown SerializationFormat name");
+ return nullptr;
+}
diff --git a/clang/unittests/Analysis/Scalable/CMakeLists.txt b/clang/unittests/Analysis/Scalable/CMakeLists.txt
index a21002e313ead..33e1dcc87deba 100644
--- a/clang/unittests/Analysis/Scalable/CMakeLists.txt
+++ b/clang/unittests/Analysis/Scalable/CMakeLists.txt
@@ -4,8 +4,10 @@ add_distinct_clang_unittest(ClangScalableAnalysisTests
EntityIdTest.cpp
EntityIdTableTest.cpp
EntityNameTest.cpp
+ Registries/MockSerializationFormat.cpp
Registries/MockSummaryExtractor1.cpp
Registries/MockSummaryExtractor2.cpp
+ Registries/SerializationFormatRegistryTest.cpp
Registries/SummaryExtractorRegistryTest.cpp
SummaryNameTest.cpp
diff --git a/clang/unittests/Analysis/Scalable/Registries/MockSerializationFormat.cpp b/clang/unittests/Analysis/Scalable/Registries/MockSerializationFormat.cpp
new file mode 100644
index 0000000000000..d9f5eebce1f0e
--- /dev/null
+++ b/clang/unittests/Analysis/Scalable/Registries/MockSerializationFormat.cpp
@@ -0,0 +1,38 @@
+//===- MockSerializationFormat.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 "Registries/MockSerializationFormat.h"
+#include "clang/Analysis/Scalable/Model/BuildNamespace.h"
+#include "clang/Analysis/Scalable/Serialization/SerializationFormat.h"
+#include "clang/Analysis/Scalable/Serialization/SerializationFormatRegistry.h"
+#include "clang/Analysis/Scalable/TUSummary/TUSummary.h"
+#include "llvm/ADT/StringRef.h"
+#include <cassert>
+
+using namespace clang;
+using namespace ssaf;
+
+MockSerializationFormat::MockSerializationFormat(
+ llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS)
+ : SerializationFormat(FS) {}
+
+TUSummary MockSerializationFormat::readTUSummary(llvm::StringRef Path) {
+ // TODO: Implement this.
+ BuildNamespace NS(BuildNamespaceKind::CompilationUnit, "Mock.cpp");
+ TUSummary Summary(NS);
+ return Summary;
+}
+
+void MockSerializationFormat::writeTUSummary(const TUSummary &Summary,
+ llvm::StringRef OutputDir) {
+ // TODO: Implement this.
+}
+
+static SerializationFormatRegistry::Add<MockSerializationFormat>
+ RegisterFormat("MockSerializationFormat",
+ "A serialization format for testing");
diff --git a/clang/unittests/Analysis/Scalable/Registries/MockSerializationFormat.h b/clang/unittests/Analysis/Scalable/Registries/MockSerializationFormat.h
new file mode 100644
index 0000000000000..318c8ac26502d
--- /dev/null
+++ b/clang/unittests/Analysis/Scalable/Registries/MockSerializationFormat.h
@@ -0,0 +1,29 @@
+//===- MockSerializationFormat.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_UNITTESTS_ANALYSIS_SCALABLE_REGISTRIES_MOCKSERIALIZATIONFORMAT_H
+#define LLVM_CLANG_UNITTESTS_ANALYSIS_SCALABLE_REGISTRIES_MOCKSERIALIZATIONFORMAT_H
+
+#include "clang/Analysis/Scalable/Serialization/SerializationFormat.h"
+
+namespace clang::ssaf {
+
+class MockSerializationFormat final : public SerializationFormat {
+public:
+ explicit MockSerializationFormat(
+ llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS);
+
+ TUSummary readTUSummary(llvm::StringRef Path) override;
+
+ void writeTUSummary(const TUSummary &Summary,
+ llvm::StringRef OutputDir) override;
+};
+
+} // namespace clang::ssaf
+
+#endif // LLVM_CLANG_UNITTESTS_ANALYSIS_SCALABLE_REGISTRIES_MOCKSERIALIZATIONFORMAT_H
diff --git a/clang/unittests/Analysis/Scalable/Registries/SerializationFormatRegistryTest.cpp b/clang/unittests/Analysis/Scalable/Registries/SerializationFormatRegistryTest.cpp
new file mode 100644
index 0000000000000..261d1dae21893
--- /dev/null
+++ b/clang/unittests/Analysis/Scalable/Registries/SerializationFormatRegistryTest.cpp
@@ -0,0 +1,29 @@
+//===- SummaryExtractorRegistryTest.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/Serialization/SerializationFormatRegistry.h"
+#include "llvm/ADT/StringRef.h"
+#include "gtest/gtest.h"
+
+using namespace clang;
+using namespace ssaf;
+
+namespace {
+
+TEST(SerializationFormatRegistryTest, isFormatRegistered) {
+ EXPECT_FALSE(isFormatRegistered("Non-existent-format"));
+ EXPECT_TRUE(isFormatRegistered("MockSerializationFormat"));
+}
+
+TEST(SerializationFormatRegistryTest, EnumeratingRegistryEntries) {
+ auto Formats = SerializationFormatRegistry::entries();
+ ASSERT_EQ(std::distance(Formats.begin(), Formats.end()), 1U);
+ EXPECT_EQ(Formats.begin()->getName(), "MockSerializationFormat");
+}
+
+} // namespace
>From 0c75c1554e8aed06f0a3ea269138b8c8be6af023 Mon Sep 17 00:00:00 2001
From: Balazs Benics <benicsbalazs at gmail.com>
Date: Wed, 4 Feb 2026 13:36:01 +0100
Subject: [PATCH 2/2] Satisfy clang-format
---
.../Analysis/Scalable/Registries/MockSerializationFormat.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/unittests/Analysis/Scalable/Registries/MockSerializationFormat.cpp b/clang/unittests/Analysis/Scalable/Registries/MockSerializationFormat.cpp
index d9f5eebce1f0e..69afa0fc439f0 100644
--- a/clang/unittests/Analysis/Scalable/Registries/MockSerializationFormat.cpp
+++ b/clang/unittests/Analysis/Scalable/Registries/MockSerializationFormat.cpp
@@ -30,7 +30,7 @@ TUSummary MockSerializationFormat::readTUSummary(llvm::StringRef Path) {
void MockSerializationFormat::writeTUSummary(const TUSummary &Summary,
llvm::StringRef OutputDir) {
- // TODO: Implement this.
+ // TODO: Implement this.
}
static SerializationFormatRegistry::Add<MockSerializationFormat>
More information about the cfe-commits
mailing list