[clang] [clang][ssaf] Consolidate tools and shared utilities under `clang/tools/clang-ssaf/` (PR #187439)
Aviral Goel via cfe-commits
cfe-commits at lists.llvm.org
Fri Mar 20 09:38:24 PDT 2026
https://github.com/aviralg updated https://github.com/llvm/llvm-project/pull/187439
>From 4785c4c20dfa19f83b039933a35db9f98e79cb3a Mon Sep 17 00:00:00 2001
From: Aviral Goel <agoel26 at apple.com>
Date: Wed, 18 Mar 2026 22:08:00 -0700
Subject: [PATCH 1/2] Move common code out
---
.../Tool/Utils.h | 110 +++++++++++++++
.../CMakeLists.txt | 2 +-
.../Tool/CMakeLists.txt | 11 ++
.../Tool/Utils.cpp | 129 ++++++++++++++++++
clang/tools/clang-ssaf-format/CMakeLists.txt | 1 +
clang/tools/clang-ssaf-format/SSAFFormat.cpp | 129 ++----------------
clang/tools/clang-ssaf-linker/CMakeLists.txt | 1 +
clang/tools/clang-ssaf-linker/SSAFLinker.cpp | 107 ++-------------
8 files changed, 271 insertions(+), 219 deletions(-)
create mode 100644 clang/include/clang/ScalableStaticAnalysisFramework/Tool/Utils.h
create mode 100644 clang/lib/ScalableStaticAnalysisFramework/Tool/CMakeLists.txt
create mode 100644 clang/lib/ScalableStaticAnalysisFramework/Tool/Utils.cpp
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Tool/Utils.h b/clang/include/clang/ScalableStaticAnalysisFramework/Tool/Utils.h
new file mode 100644
index 0000000000000..cf515df54e631
--- /dev/null
+++ b/clang/include/clang/ScalableStaticAnalysisFramework/Tool/Utils.h
@@ -0,0 +1,110 @@
+//===- Utils.h - Shared utilities for SSAF tools ----------------*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// Shared error-handling, format-registry cache, and summary-file abstraction
+// used by clang-ssaf-linker and clang-ssaf-format.
+//
+// All declarations live in the clang::ssaf namespace.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_TOOL_UTILS_H
+#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_TOOL_UTILS_H
+
+#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormatRegistry.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/FormatVariadic.h"
+#include <string>
+
+namespace clang::ssaf {
+
+//===----------------------------------------------------------------------===//
+// Tool Identity
+//===----------------------------------------------------------------------===//
+
+/// Returns the name of the running tool, as set by initTool().
+llvm::StringRef getToolName();
+
+//===----------------------------------------------------------------------===//
+// Error Messages
+//===----------------------------------------------------------------------===//
+
+namespace ErrorMessages {
+
+constexpr const char *CannotValidateSummary =
+ "failed to validate summary '{0}': {1}";
+
+constexpr const char *ExtensionNotSupplied = "Extension not supplied";
+
+constexpr const char *NoFormatForExtension =
+ "Format not registered for extension '{0}'";
+
+constexpr const char *OutputDirectoryMissing =
+ "Parent directory does not exist";
+
+constexpr const char *FailedToLoadPlugin = "failed to load plugin '{0}': {1}";
+
+} // namespace ErrorMessages
+
+//===----------------------------------------------------------------------===//
+// Diagnostic Utilities
+//===----------------------------------------------------------------------===//
+
+[[noreturn]] void fail(const char *Msg);
+
+template <typename... Ts>
+[[noreturn]] inline void fail(const char *Fmt, Ts &&...Args) {
+ std::string Message = llvm::formatv(Fmt, std::forward<Ts>(Args)...);
+ fail(Message.data());
+}
+
+[[noreturn]] void fail(llvm::Error Err);
+
+//===----------------------------------------------------------------------===//
+// Plugin Loading
+//===----------------------------------------------------------------------===//
+
+void loadPlugins(llvm::ArrayRef<std::string> Paths);
+
+//===----------------------------------------------------------------------===//
+// Initialization
+//===----------------------------------------------------------------------===//
+
+/// Sets ToolName, ToolVersion, and the version printer, hides unrelated
+/// command-line options, and parses arguments. Must be called after InitLLVM.
+void initTool(int argc, const char **argv, llvm::StringRef Version,
+ llvm::cl::OptionCategory &Category, llvm::StringRef ToolHeading);
+
+//===----------------------------------------------------------------------===//
+// Format Registry
+//===----------------------------------------------------------------------===//
+
+/// Returns the SerializationFormat registered for \p Extension, or nullptr if
+/// none is registered. Results are cached for the lifetime of the process.
+SerializationFormat *getFormatForExtension(llvm::StringRef Extension);
+
+//===----------------------------------------------------------------------===//
+// Data Structures
+//===----------------------------------------------------------------------===//
+
+struct SummaryFile {
+ std::string Path;
+ SerializationFormat *Format = nullptr;
+
+ /// Constructs a SummaryFile by resolving the serialization format from the
+ /// file extension. Calls fail() and exits if the extension is missing or
+ /// unregistered.
+ static SummaryFile fromPath(llvm::StringRef Path);
+};
+
+} // namespace clang::ssaf
+
+#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_TOOL_UTILS_H
diff --git a/clang/lib/ScalableStaticAnalysisFramework/CMakeLists.txt b/clang/lib/ScalableStaticAnalysisFramework/CMakeLists.txt
index 6bcb1a0038127..3da5c8899ddb6 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/CMakeLists.txt
+++ b/clang/lib/ScalableStaticAnalysisFramework/CMakeLists.txt
@@ -1,4 +1,4 @@
add_subdirectory(Analyses)
add_subdirectory(Core)
add_subdirectory(Frontend)
-
+add_subdirectory(Tool)
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Tool/CMakeLists.txt b/clang/lib/ScalableStaticAnalysisFramework/Tool/CMakeLists.txt
new file mode 100644
index 0000000000000..53b900ec8c042
--- /dev/null
+++ b/clang/lib/ScalableStaticAnalysisFramework/Tool/CMakeLists.txt
@@ -0,0 +1,11 @@
+set(LLVM_LINK_COMPONENTS
+ Support
+ )
+
+add_clang_library(clangScalableStaticAnalysisFrameworkTool
+ Utils.cpp
+
+ LINK_LIBS
+ clangBasic
+ clangScalableStaticAnalysisFrameworkCore
+ )
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Tool/Utils.cpp b/clang/lib/ScalableStaticAnalysisFramework/Tool/Utils.cpp
new file mode 100644
index 0000000000000..9eef571a71d82
--- /dev/null
+++ b/clang/lib/ScalableStaticAnalysisFramework/Tool/Utils.cpp
@@ -0,0 +1,129 @@
+//===- Utils.cpp - Shared utilities for SSAF tools -----------------------===//
+//
+// 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/ScalableStaticAnalysisFramework/Tool/Utils.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/DynamicLibrary.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/FormatVariadic.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/Process.h"
+#include "llvm/Support/WithColor.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cassert>
+#include <memory>
+#include <string>
+
+namespace clang::ssaf {
+
+namespace path = llvm::sys::path;
+
+static llvm::StringRef ToolName;
+static llvm::StringRef ToolVersion;
+
+llvm::StringRef getToolName() { return ToolName; }
+
+void printVersion(llvm::raw_ostream &OS) {
+ OS << ToolName << " " << ToolVersion << "\n";
+}
+
+[[noreturn]] void fail(const char *Msg) {
+ llvm::WithColor::error(llvm::errs(), ToolName) << Msg << "\n";
+ llvm::sys::Process::Exit(1);
+}
+
+[[noreturn]] void fail(llvm::Error Err) {
+ std::string Message = llvm::toString(std::move(Err));
+ fail(Message.data());
+}
+
+void loadPlugins(llvm::ArrayRef<std::string> Paths) {
+ for (const std::string &PluginPath : Paths) {
+ std::string ErrMsg;
+ if (llvm::sys::DynamicLibrary::LoadLibraryPermanently(PluginPath.c_str(),
+ &ErrMsg)) {
+ fail(ErrorMessages::FailedToLoadPlugin, PluginPath, ErrMsg);
+ }
+ }
+}
+
+void initTool(int argc, const char **argv, llvm::StringRef Version,
+ llvm::cl::OptionCategory &Category, llvm::StringRef ToolHeading) {
+ // path::stem strips the .exe extension on Windows so ToolName is consistent.
+ ToolName = path::stem(argv[0]);
+
+ // Set tool version for the version printer.
+ ToolVersion = Version;
+
+ // Hide options unrelated to the tool from --help output.
+ llvm::cl::HideUnrelatedOptions(Category);
+
+ // Register a custom version printer for the --version flag.
+ llvm::cl::SetVersionPrinter(printVersion);
+
+ // Parse command-line arguments and exit with an error if they are invalid.
+ std::string Overview = (ToolHeading + "\n").str();
+ llvm::cl::ParseCommandLineOptions(argc, argv, Overview);
+}
+
+// FIXME: This will be revisited after we add support for registering formats
+// with extensions.
+SerializationFormat *getFormatForExtension(llvm::StringRef Extension) {
+ // This cache is not thread-safe. SSAF tools are single-threaded CLIs, so
+ // concurrent calls to this function are not expected.
+
+ // Realistically, we don't expect to encounter more than four registered
+ // formats.
+ static llvm::SmallVector<
+ std::pair<std::string, std::unique_ptr<SerializationFormat>>, 4>
+ ExtensionFormatList;
+
+ // Most recently used format is most likely to be reused again.
+ auto ReversedList = llvm::reverse(ExtensionFormatList);
+ auto It = llvm::find_if(ReversedList, [&](const auto &Entry) {
+ return Entry.first == Extension;
+ });
+ if (It != ReversedList.end()) {
+ return It->second.get();
+ }
+
+ if (!isFormatRegistered(Extension)) {
+ return nullptr;
+ }
+
+ auto Format = makeFormat(Extension);
+ SerializationFormat *Result = Format.get();
+ assert(Result &&
+ "makeFormat must return non-null for a registered extension");
+
+ ExtensionFormatList.emplace_back(Extension, std::move(Format));
+
+ return Result;
+}
+
+SummaryFile SummaryFile::fromPath(llvm::StringRef Path) {
+ llvm::StringRef Extension = path::extension(Path);
+ if (Extension.empty()) {
+ fail(ErrorMessages::CannotValidateSummary, Path,
+ ErrorMessages::ExtensionNotSupplied);
+ }
+
+ Extension = Extension.drop_front();
+ SerializationFormat *Format = getFormatForExtension(Extension);
+ if (!Format) {
+ std::string BadExtension =
+ llvm::formatv(ErrorMessages::NoFormatForExtension, Extension);
+ fail(ErrorMessages::CannotValidateSummary, Path, BadExtension);
+ }
+
+ return {Path.str(), Format};
+}
+
+} // namespace clang::ssaf
diff --git a/clang/tools/clang-ssaf-format/CMakeLists.txt b/clang/tools/clang-ssaf-format/CMakeLists.txt
index f64d12eb3fac0..864fe5bc27aaa 100644
--- a/clang/tools/clang-ssaf-format/CMakeLists.txt
+++ b/clang/tools/clang-ssaf-format/CMakeLists.txt
@@ -11,4 +11,5 @@ clang_target_link_libraries(clang-ssaf-format
PRIVATE
clangBasic
clangScalableStaticAnalysisFrameworkCore
+ clangScalableStaticAnalysisFrameworkTool
)
diff --git a/clang/tools/clang-ssaf-format/SSAFFormat.cpp b/clang/tools/clang-ssaf-format/SSAFFormat.cpp
index d91ff9402f7ec..4f337bff89ee1 100644
--- a/clang/tools/clang-ssaf-format/SSAFFormat.cpp
+++ b/clang/tools/clang-ssaf-format/SSAFFormat.cpp
@@ -16,18 +16,16 @@
#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat.h"
#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormatRegistry.h"
#include "clang/ScalableStaticAnalysisFramework/SSAFForceLinker.h" // IWYU pragma: keep
+#include "clang/ScalableStaticAnalysisFramework/Tool/Utils.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/DynamicLibrary.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/Path.h"
-#include "llvm/Support/Process.h"
-#include "llvm/Support/WithColor.h"
#include "llvm/Support/raw_ostream.h"
#include <memory>
#include <optional>
@@ -84,87 +82,18 @@ cl::opt<bool> ListFormats("list",
"analyses, then exit"),
cl::init(false), cl::cat(SsafFormatCategory));
-llvm::StringRef ToolName;
-
-void printVersion(llvm::raw_ostream &OS) { OS << ToolName << " 0.1\n"; }
-
//===----------------------------------------------------------------------===//
// Error Messages
//===----------------------------------------------------------------------===//
-namespace ErrorMessages {
-
-constexpr const char *FailedToLoadPlugin = "failed to load plugin '{0}': {1}";
-
-constexpr const char *CannotValidateSummary =
- "failed to validate summary '{0}': {1}";
-
-constexpr const char *ExtensionNotSupplied = "Extension not supplied";
-
-constexpr const char *NoFormatForExtension =
- "Format not registered for extension '{0}'";
-
-constexpr const char *OutputDirectoryMissing =
- "Parent directory does not exist";
+namespace LocalErrorMessages {
constexpr const char *OutputFileAlreadyExists = "Output file already exists";
constexpr const char *InputOutputSamePath =
"Input and Output resolve to the same path";
-} // namespace ErrorMessages
-
-//===----------------------------------------------------------------------===//
-// Diagnostic Utilities
-//===----------------------------------------------------------------------===//
-
-[[noreturn]] void fail(const char *Msg) {
- llvm::WithColor::error(llvm::errs(), ToolName) << Msg << "\n";
- llvm::sys::Process::Exit(1);
-}
-
-template <typename... Ts>
-[[noreturn]] void fail(const char *Fmt, Ts &&...Args) {
- std::string Message = llvm::formatv(Fmt, std::forward<Ts>(Args)...);
- fail(Message.data());
-}
-
-[[noreturn]] void fail(llvm::Error Err) {
- fail(toString(std::move(Err)).data());
-}
-
-//===----------------------------------------------------------------------===//
-// Format Registry
-//===----------------------------------------------------------------------===//
-
-// FIXME: This will be revisited after we add support for registering formats
-// with extensions.
-SerializationFormat *getFormatForExtension(llvm::StringRef Extension) {
- static llvm::SmallVector<
- std::pair<std::string, std::unique_ptr<SerializationFormat>>, 4>
- ExtensionFormatList;
-
- // Most recently used format is most likely to be reused again.
- auto ReversedList = llvm::reverse(ExtensionFormatList);
- auto It = llvm::find_if(ReversedList, [&](const auto &Entry) {
- return Entry.first == Extension;
- });
- if (It != ReversedList.end()) {
- return It->second.get();
- }
-
- if (!isFormatRegistered(Extension)) {
- return nullptr;
- }
-
- auto Format = makeFormat(Extension);
- SerializationFormat *Result = Format.get();
- assert(Result);
-
- ExtensionFormatList.emplace_back(Extension, std::move(Format));
-
- return Result;
-}
+} // namespace LocalErrorMessages
//===----------------------------------------------------------------------===//
// Format Listing
@@ -295,47 +224,10 @@ void listFormats() {
printFormats(Formats, computePrintLayout(Formats));
}
-//===----------------------------------------------------------------------===//
-// Plugin Loading
-//===----------------------------------------------------------------------===//
-
-void loadPlugins() {
- for (const auto &PluginPath : LoadPlugins) {
- std::string ErrMsg;
- if (llvm::sys::DynamicLibrary::LoadLibraryPermanently(PluginPath.c_str(),
- &ErrMsg)) {
- fail(ErrorMessages::FailedToLoadPlugin, PluginPath, ErrMsg);
- }
- }
-}
-
//===----------------------------------------------------------------------===//
// Input Validation
//===----------------------------------------------------------------------===//
-struct SummaryFile {
- std::string Path;
- SerializationFormat *Format = nullptr;
-
- static SummaryFile fromPath(llvm::StringRef Path) {
- llvm::StringRef Extension = path::extension(Path);
- if (Extension.empty()) {
- fail(ErrorMessages::CannotValidateSummary, Path,
- ErrorMessages::ExtensionNotSupplied);
- }
-
- Extension = Extension.drop_front();
- SerializationFormat *Format = getFormatForExtension(Extension);
- if (!Format) {
- std::string Msg =
- llvm::formatv(ErrorMessages::NoFormatForExtension, Extension);
- fail(ErrorMessages::CannotValidateSummary, Path, Msg);
- }
-
- return {Path.str(), Format};
- }
-};
-
struct FormatInput {
SummaryFile InputFile;
std::optional<SummaryFile> OutputFile;
@@ -391,12 +283,12 @@ FormatInput validateInput() {
if (RealOutputPath == FI.InputFile.Path) {
fail(ErrorMessages::CannotValidateSummary, OutputPath,
- ErrorMessages::InputOutputSamePath);
+ LocalErrorMessages::InputOutputSamePath);
}
if (fs::exists(RealOutputPath)) {
fail(ErrorMessages::CannotValidateSummary, OutputPath,
- ErrorMessages::OutputFileAlreadyExists);
+ LocalErrorMessages::OutputFileAlreadyExists);
}
FI.OutputFile = SummaryFile::fromPath(RealOutputPath);
@@ -458,15 +350,12 @@ void convert(const FormatInput &FI) {
//===----------------------------------------------------------------------===//
int main(int argc, const char **argv) {
- InitLLVM X(argc, argv);
- // path::stem strips the .exe extension on Windows so ToolName is consistent.
- ToolName = path::stem(argv[0]);
+ llvm::StringRef ToolHeading = "SSAF Format";
- cl::HideUnrelatedOptions(SsafFormatCategory);
- cl::SetVersionPrinter(printVersion);
- cl::ParseCommandLineOptions(argc, argv, "SSAF Format\n");
+ InitLLVM X(argc, argv);
+ initTool(argc, argv, "0.1", SsafFormatCategory, ToolHeading);
- loadPlugins();
+ loadPlugins(LoadPlugins);
if (ListFormats) {
listFormats();
diff --git a/clang/tools/clang-ssaf-linker/CMakeLists.txt b/clang/tools/clang-ssaf-linker/CMakeLists.txt
index 0f6041fb109c9..95db5ad2d3d08 100644
--- a/clang/tools/clang-ssaf-linker/CMakeLists.txt
+++ b/clang/tools/clang-ssaf-linker/CMakeLists.txt
@@ -11,4 +11,5 @@ clang_target_link_libraries(clang-ssaf-linker
PRIVATE
clangBasic
clangScalableStaticAnalysisFrameworkCore
+ clangScalableStaticAnalysisFrameworkTool
)
diff --git a/clang/tools/clang-ssaf-linker/SSAFLinker.cpp b/clang/tools/clang-ssaf-linker/SSAFLinker.cpp
index 3c57a2fe2cf98..1f595854c508d 100644
--- a/clang/tools/clang-ssaf-linker/SSAFLinker.cpp
+++ b/clang/tools/clang-ssaf-linker/SSAFLinker.cpp
@@ -14,9 +14,9 @@
#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/EntityLinker.h"
#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/TUSummaryEncoding.h"
#include "clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormatRegistry.h"
#include "clang/ScalableStaticAnalysisFramework/Core/Support/ErrorBuilder.h"
#include "clang/ScalableStaticAnalysisFramework/SSAFForceLinker.h" // IWYU pragma: keep
+#include "clang/ScalableStaticAnalysisFramework/Tool/Utils.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/CommandLine.h"
@@ -24,7 +24,6 @@
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/Path.h"
-#include "llvm/Support/Process.h"
#include "llvm/Support/Timer.h"
#include "llvm/Support/WithColor.h"
#include "llvm/Support/raw_ostream.h"
@@ -63,25 +62,14 @@ cl::opt<bool> Time("time", cl::desc("Enable timing"), cl::init(false),
// Error Messages
//===----------------------------------------------------------------------===//
-namespace ErrorMessages {
-
-constexpr const char *CannotValidateSummary =
- "failed to validate summary '{0}': {1}";
-
-constexpr const char *OutputDirectoryMissing =
- "Parent directory does not exist";
+namespace LocalErrorMessages {
constexpr const char *OutputDirectoryNotWritable =
"Parent directory is not writable";
-constexpr const char *ExtensionNotSupplied = "Extension not supplied";
-
-constexpr const char *NoFormatForExtension =
- "Format not registered for extension '{0}'";
-
constexpr const char *LinkingSummary = "Linking summary '{0}'";
-} // namespace ErrorMessages
+} // namespace LocalErrorMessages
//===----------------------------------------------------------------------===//
// Diagnostic Utilities
@@ -89,23 +77,6 @@ constexpr const char *LinkingSummary = "Linking summary '{0}'";
constexpr unsigned IndentationWidth = 2;
-llvm::StringRef ToolName;
-
-template <typename... Ts> [[noreturn]] void fail(const char *Msg) {
- llvm::WithColor::error(llvm::errs(), ToolName) << Msg << "\n";
- llvm::sys::Process::Exit(1);
-}
-
-template <typename... Ts>
-[[noreturn]] void fail(const char *Fmt, Ts &&...Args) {
- std::string Message = llvm::formatv(Fmt, std::forward<Ts>(Args)...);
- fail(Message.data());
-}
-
-template <typename... Ts> [[noreturn]] void fail(llvm::Error Err) {
- fail(toString(std::move(Err)).data());
-}
-
template <typename... Ts>
void info(unsigned IndentationLevel, const char *Fmt, Ts &&...Args) {
if (Verbose) {
@@ -115,70 +86,16 @@ void info(unsigned IndentationLevel, const char *Fmt, Ts &&...Args) {
}
}
-//===----------------------------------------------------------------------===//
-// Format Registry
-//===----------------------------------------------------------------------===//
-
-SerializationFormat *getFormatForExtension(llvm::StringRef Extension) {
- static llvm::SmallVector<
- std::pair<std::string, std::unique_ptr<SerializationFormat>>, 4>
- ExtensionFormatList;
-
- // Most recently used format is most likely to be reused again.
- auto ReversedList = llvm::reverse(ExtensionFormatList);
- auto It = llvm::find_if(ReversedList, [&](const auto &Entry) {
- return Entry.first == Extension;
- });
- if (It != ReversedList.end()) {
- return It->second.get();
- }
-
- if (!isFormatRegistered(Extension)) {
- return nullptr;
- }
-
- auto Format = makeFormat(Extension);
- SerializationFormat *Result = Format.get();
- assert(Result);
-
- ExtensionFormatList.emplace_back(Extension, std::move(Format));
-
- return Result;
-}
-
//===----------------------------------------------------------------------===//
// Data Structures
//===----------------------------------------------------------------------===//
-struct SummaryFile {
- std::string Path;
- SerializationFormat *Format = nullptr;
-
- static SummaryFile fromPath(llvm::StringRef Path) {
- llvm::StringRef Extension = path::extension(Path);
- if (Extension.empty()) {
- fail(ErrorMessages::CannotValidateSummary, Path,
- ErrorMessages::ExtensionNotSupplied);
- }
- Extension = Extension.drop_front();
- SerializationFormat *Format = getFormatForExtension(Extension);
- if (!Format) {
- std::string BadExtension =
- llvm::formatv(ErrorMessages::NoFormatForExtension, Extension);
- fail(ErrorMessages::CannotValidateSummary, Path, BadExtension);
- }
- return {Path.str(), Format};
- }
-};
-
struct LinkerInput {
std::vector<SummaryFile> InputFiles;
SummaryFile OutputFile;
std::string LinkUnitName;
};
-static void printVersion(llvm::raw_ostream &OS) { OS << ToolName << " 0.1\n"; }
-
//===----------------------------------------------------------------------===//
// Pipeline
//===----------------------------------------------------------------------===//
@@ -199,7 +116,7 @@ LinkerInput validate(llvm::TimerGroup &TG) {
if (fs::access(DirToCheck, fs::AccessMode::Write)) {
fail(ErrorMessages::CannotValidateSummary, OutputPath,
- ErrorMessages::OutputDirectoryNotWritable);
+ LocalErrorMessages::OutputDirectoryNotWritable);
}
LI.OutputFile = SummaryFile::fromPath(OutputPath);
@@ -264,7 +181,7 @@ void link(const LinkerInput &LI, llvm::TimerGroup &TG) {
if (auto Err = EL.link(std::move(Summary))) {
fail(ErrorBuilder::wrap(std::move(Err))
- .context(ErrorMessages::LinkingSummary, InputFile.Path)
+ .context(LocalErrorMessages::LinkingSummary, InputFile.Path)
.build());
}
}
@@ -290,18 +207,12 @@ void link(const LinkerInput &LI, llvm::TimerGroup &TG) {
//===----------------------------------------------------------------------===//
int main(int argc, const char **argv) {
- InitLLVM X(argc, argv);
- // path::stem strips the .exe extension on Windows so ToolName is consistent.
- ToolName = llvm::sys::path::stem(argv[0]);
+ llvm::StringRef ToolHeading = "SSAF Linker";
- // Hide options unrelated to clang-ssaf-linker from --help output.
- cl::HideUnrelatedOptions(SsafLinkerCategory);
- // Register a custom version printer for the --version flag.
- cl::SetVersionPrinter(printVersion);
- // Parse command-line arguments and exit with an error if they are invalid.
- cl::ParseCommandLineOptions(argc, argv, "SSAF Linker\n");
+ InitLLVM X(argc, argv);
+ initTool(argc, argv, "0.1", SsafLinkerCategory, ToolHeading);
- llvm::TimerGroup LinkerTimers(ToolName, "SSAF Linker");
+ llvm::TimerGroup LinkerTimers(getToolName(), ToolHeading);
LinkerInput LI;
{
>From 54feeae6ba52dc99e9d33227edfea1bf717b9137 Mon Sep 17 00:00:00 2001
From: Aviral Goel <agoel26 at apple.com>
Date: Fri, 20 Mar 2026 09:38:01 -0700
Subject: [PATCH 2/2] Namespace
---
.../Tool/Utils.h | 8 --
.../Tool/Utils.cpp | 96 ++++++++++---------
2 files changed, 51 insertions(+), 53 deletions(-)
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Tool/Utils.h b/clang/include/clang/ScalableStaticAnalysisFramework/Tool/Utils.h
index cf515df54e631..790920d2bf711 100644
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Tool/Utils.h
+++ b/clang/include/clang/ScalableStaticAnalysisFramework/Tool/Utils.h
@@ -83,14 +83,6 @@ void loadPlugins(llvm::ArrayRef<std::string> Paths);
void initTool(int argc, const char **argv, llvm::StringRef Version,
llvm::cl::OptionCategory &Category, llvm::StringRef ToolHeading);
-//===----------------------------------------------------------------------===//
-// Format Registry
-//===----------------------------------------------------------------------===//
-
-/// Returns the SerializationFormat registered for \p Extension, or nullptr if
-/// none is registered. Results are cached for the lifetime of the process.
-SerializationFormat *getFormatForExtension(llvm::StringRef Extension);
-
//===----------------------------------------------------------------------===//
// Data Structures
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Tool/Utils.cpp b/clang/lib/ScalableStaticAnalysisFramework/Tool/Utils.cpp
index 9eef571a71d82..2d7fa09250e7b 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Tool/Utils.cpp
+++ b/clang/lib/ScalableStaticAnalysisFramework/Tool/Utils.cpp
@@ -21,58 +21,22 @@
#include <memory>
#include <string>
-namespace clang::ssaf {
+using namespace clang;
+using namespace ssaf;
namespace path = llvm::sys::path;
-static llvm::StringRef ToolName;
-static llvm::StringRef ToolVersion;
+namespace {
-llvm::StringRef getToolName() { return ToolName; }
+llvm::StringRef ToolName;
+llvm::StringRef ToolVersion;
void printVersion(llvm::raw_ostream &OS) {
OS << ToolName << " " << ToolVersion << "\n";
}
-[[noreturn]] void fail(const char *Msg) {
- llvm::WithColor::error(llvm::errs(), ToolName) << Msg << "\n";
- llvm::sys::Process::Exit(1);
-}
-
-[[noreturn]] void fail(llvm::Error Err) {
- std::string Message = llvm::toString(std::move(Err));
- fail(Message.data());
-}
-
-void loadPlugins(llvm::ArrayRef<std::string> Paths) {
- for (const std::string &PluginPath : Paths) {
- std::string ErrMsg;
- if (llvm::sys::DynamicLibrary::LoadLibraryPermanently(PluginPath.c_str(),
- &ErrMsg)) {
- fail(ErrorMessages::FailedToLoadPlugin, PluginPath, ErrMsg);
- }
- }
-}
-
-void initTool(int argc, const char **argv, llvm::StringRef Version,
- llvm::cl::OptionCategory &Category, llvm::StringRef ToolHeading) {
- // path::stem strips the .exe extension on Windows so ToolName is consistent.
- ToolName = path::stem(argv[0]);
-
- // Set tool version for the version printer.
- ToolVersion = Version;
-
- // Hide options unrelated to the tool from --help output.
- llvm::cl::HideUnrelatedOptions(Category);
-
- // Register a custom version printer for the --version flag.
- llvm::cl::SetVersionPrinter(printVersion);
-
- // Parse command-line arguments and exit with an error if they are invalid.
- std::string Overview = (ToolHeading + "\n").str();
- llvm::cl::ParseCommandLineOptions(argc, argv, Overview);
-}
-
+// Returns the SerializationFormat registered for \p Extension, or nullptr if
+// none is registered. Results are cached for the lifetime of the process.
// FIXME: This will be revisited after we add support for registering formats
// with extensions.
SerializationFormat *getFormatForExtension(llvm::StringRef Extension) {
@@ -108,6 +72,50 @@ SerializationFormat *getFormatForExtension(llvm::StringRef Extension) {
return Result;
}
+} // namespace
+
+llvm::StringRef ssaf::getToolName() { return ToolName; }
+
+[[noreturn]] void ssaf::fail(const char *Msg) {
+ llvm::WithColor::error(llvm::errs(), ToolName) << Msg << "\n";
+ llvm::sys::Process::Exit(1);
+}
+
+[[noreturn]] void ssaf::fail(llvm::Error Err) {
+ std::string Message = llvm::toString(std::move(Err));
+ ssaf::fail(Message.data());
+}
+
+void ssaf::loadPlugins(llvm::ArrayRef<std::string> Paths) {
+ for (const std::string &PluginPath : Paths) {
+ std::string ErrMsg;
+ if (llvm::sys::DynamicLibrary::LoadLibraryPermanently(PluginPath.c_str(),
+ &ErrMsg)) {
+ fail(ErrorMessages::FailedToLoadPlugin, PluginPath, ErrMsg);
+ }
+ }
+}
+
+void ssaf::initTool(int argc, const char **argv, llvm::StringRef Version,
+ llvm::cl::OptionCategory &Category,
+ llvm::StringRef ToolHeading) {
+ // path::stem strips the .exe extension on Windows so ToolName is consistent.
+ ToolName = path::stem(argv[0]);
+
+ // Set tool version for the version printer.
+ ToolVersion = Version;
+
+ // Hide options unrelated to the tool from --help output.
+ llvm::cl::HideUnrelatedOptions(Category);
+
+ // Register a custom version printer for the --version flag.
+ llvm::cl::SetVersionPrinter(printVersion);
+
+ // Parse command-line arguments and exit with an error if they are invalid.
+ std::string Overview = (ToolHeading + "\n").str();
+ llvm::cl::ParseCommandLineOptions(argc, argv, Overview);
+}
+
SummaryFile SummaryFile::fromPath(llvm::StringRef Path) {
llvm::StringRef Extension = path::extension(Path);
if (Extension.empty()) {
@@ -125,5 +133,3 @@ SummaryFile SummaryFile::fromPath(llvm::StringRef Path) {
return {Path.str(), Format};
}
-
-} // namespace clang::ssaf
More information about the cfe-commits
mailing list