[clang] [clang][ssaf] Add --ssaf-list-{extractor, format} flags (PR #185428)
Balázs Benics via cfe-commits
cfe-commits at lists.llvm.org
Mon Mar 9 07:23:13 PDT 2026
https://github.com/steakhal created https://github.com/llvm/llvm-project/pull/185428
These flags only work with the `clang` driver.
The `cc1` driver would ignore these flags.
Probably it could be implemented differently, but it's already better than having nothing.
>From 1882b71e904e67e410cb7b53c36c0f2690713394 Mon Sep 17 00:00:00 2001
From: Balazs Benics <benicsbalazs at gmail.com>
Date: Thu, 5 Mar 2026 17:09:26 +0000
Subject: [PATCH] [clang][ssaf] Add --ssaf-list-{extractor,format} flags
These flags only work with the `clang` driver.
The `cc1` driver would ignore these flags.
Probably it could be implemented differently, but it's already better
than having nothing.
---
.../user-docs/SummaryExtraction.rst | 4 +++
.../SerializationFormatRegistry.h | 4 +++
.../Scalable/TUSummary/ExtractorRegistry.h | 4 +++
.../include/clang/Frontend/FrontendOptions.h | 11 +++++++-
clang/include/clang/Options/Options.td | 12 +++++++++
.../SerializationFormatRegistry.cpp | 6 +++++
.../Scalable/TUSummary/ExtractorRegistry.cpp | 6 +++++
clang/lib/Driver/CMakeLists.txt | 1 +
clang/lib/Driver/Driver.cpp | 19 ++++++++++++++
clang/test/Analysis/SSAF/help.cpp | 26 ++++++++++++++-----
10 files changed, 86 insertions(+), 7 deletions(-)
diff --git a/clang/docs/ScalableStaticAnalysisFramework/user-docs/SummaryExtraction.rst b/clang/docs/ScalableStaticAnalysisFramework/user-docs/SummaryExtraction.rst
index f7472bfd8643a..96892cfa5fdea 100644
--- a/clang/docs/ScalableStaticAnalysisFramework/user-docs/SummaryExtraction.rst
+++ b/clang/docs/ScalableStaticAnalysisFramework/user-docs/SummaryExtraction.rst
@@ -13,6 +13,8 @@ Two flags control summary extraction:
- ``--ssaf-extract-summaries=<name1>,<name2>,...``: Comma-separated list of summary extractor names to enable.
- ``--ssaf-tu-summary-file=<path>.<format>``: Output file for the extracted summaries. The file extension selects the serialization format (e.g. ``.json``).
+- ``--ssaf-list-extractors``: List the available summary extractors.
+- ``--ssaf-list-formats``: List the available serialization formats.
Example invocation:
@@ -22,6 +24,8 @@ Example invocation:
--ssaf-tu-summary-file=my-tu-summary.json \
-c input.cpp -o input.o
+ clang --ssaf-list-extractors --ssaf-list-formats
+
Diagnostics
***********
diff --git a/clang/include/clang/Analysis/Scalable/Serialization/SerializationFormatRegistry.h b/clang/include/clang/Analysis/Scalable/Serialization/SerializationFormatRegistry.h
index 7edd7b5b561d9..6e8ebabc1b742 100644
--- a/clang/include/clang/Analysis/Scalable/Serialization/SerializationFormatRegistry.h
+++ b/clang/include/clang/Analysis/Scalable/Serialization/SerializationFormatRegistry.h
@@ -68,6 +68,7 @@
#include "clang/Support/Compiler.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Registry.h"
+#include "llvm/Support/raw_ostream.h"
namespace clang::ssaf {
@@ -80,6 +81,9 @@ bool isFormatRegistered(llvm::StringRef FormatName);
/// It's a fatal error if there is no format registered with the name.
std::unique_ptr<SerializationFormat> makeFormat(llvm::StringRef FormatName);
+/// Print the list of available serialization formats.
+void printAvailableFormats(llvm::raw_ostream &OS);
+
// Registry for adding new SerializationFormat implementations.
using SerializationFormatRegistry = llvm::Registry<SerializationFormat>;
diff --git a/clang/include/clang/Analysis/Scalable/TUSummary/ExtractorRegistry.h b/clang/include/clang/Analysis/Scalable/TUSummary/ExtractorRegistry.h
index d9147871a5101..c02f956ebc73d 100644
--- a/clang/include/clang/Analysis/Scalable/TUSummary/ExtractorRegistry.h
+++ b/clang/include/clang/Analysis/Scalable/TUSummary/ExtractorRegistry.h
@@ -30,6 +30,7 @@
#include "clang/Support/Compiler.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Registry.h"
+#include "llvm/Support/raw_ostream.h"
namespace clang::ssaf {
@@ -43,6 +44,9 @@ bool isTUSummaryExtractorRegistered(llvm::StringRef SummaryName);
std::unique_ptr<ASTConsumer> makeTUSummaryExtractor(llvm::StringRef SummaryName,
TUSummaryBuilder &Builder);
+/// Print the list of available TUSummaryExtractors.
+void printAvailableTUSummaryExtractors(llvm::raw_ostream &OS);
+
// Registry for adding new TUSummaryExtractor implementations.
using TUSummaryExtractorRegistry =
llvm::Registry<TUSummaryExtractor, TUSummaryBuilder &>;
diff --git a/clang/include/clang/Frontend/FrontendOptions.h b/clang/include/clang/Frontend/FrontendOptions.h
index 0d8eb6a1b7379..f7f51bc37c98d 100644
--- a/clang/include/clang/Frontend/FrontendOptions.h
+++ b/clang/include/clang/Frontend/FrontendOptions.h
@@ -550,6 +550,14 @@ class FrontendOptions {
/// format.
std::string SSAFTUSummaryFile;
+ /// Show available SSAF summary extractors.
+ LLVM_PREFERRED_TYPE(bool)
+ unsigned SSAFShowExtractors : 1;
+
+ /// Show available SSAF serialization formats.
+ LLVM_PREFERRED_TYPE(bool)
+ unsigned SSAFShowFormats : 1;
+
public:
FrontendOptions()
: DisableFree(false), RelocatablePCH(false), ShowHelp(false),
@@ -567,7 +575,8 @@ class FrontendOptions {
EmitPrettySymbolGraphs(false), GenReducedBMI(false),
UseClangIRPipeline(false), ClangIRDisablePasses(false),
ClangIRDisableCIRVerifier(false), ClangIREnableIdiomRecognizer(false),
- TimeTraceGranularity(500), TimeTraceVerbose(false) {}
+ TimeTraceGranularity(500), TimeTraceVerbose(false),
+ SSAFShowExtractors(false), SSAFShowFormats(false) {}
/// getInputKindForExtension - Return the appropriate input kind for a file
/// extension. For example, "c" would return Language::C.
diff --git a/clang/include/clang/Options/Options.td b/clang/include/clang/Options/Options.td
index 011ed4bf95675..a5ab6d88bbd86 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -961,6 +961,18 @@ def _ssaf_tu_summary_file :
"The output file for the extracted summaries. "
"The extension selects which file format to use.">,
MarshallingInfoString<FrontendOpts<"SSAFTUSummaryFile">>;
+def _ssaf_list_extractors :
+ Flag<["--"], "ssaf-list-extractors">,
+ Group<SSAF_Group>,
+ Visibility<[ClangOption, CC1Option]>,
+ HelpText<"Display the list of available SSAF summary extractors">,
+ MarshallingInfoFlag<FrontendOpts<"SSAFShowExtractors">>;
+def _ssaf_list_formats :
+ Flag<["--"], "ssaf-list-formats">,
+ Group<SSAF_Group>,
+ Visibility<[ClangOption, CC1Option]>,
+ HelpText<"Display the list of available SSAF serialization formats">,
+ MarshallingInfoFlag<FrontendOpts<"SSAFShowFormats">>;
def Xarch__
: JoinedAndSeparate<["-"], "Xarch_">,
Flags<[NoXarchOption]>,
diff --git a/clang/lib/Analysis/Scalable/Serialization/SerializationFormatRegistry.cpp b/clang/lib/Analysis/Scalable/Serialization/SerializationFormatRegistry.cpp
index 7cfa4370aa9ed..6c0ece351856b 100644
--- a/clang/lib/Analysis/Scalable/Serialization/SerializationFormatRegistry.cpp
+++ b/clang/lib/Analysis/Scalable/Serialization/SerializationFormatRegistry.cpp
@@ -29,3 +29,9 @@ ssaf::makeFormat(llvm::StringRef FormatName) {
assert(false && "Unknown SerializationFormat name");
return nullptr;
}
+
+void ssaf::printAvailableFormats(llvm::raw_ostream &OS) {
+ OS << "OVERVIEW: Available SSAF serialization formats:\n\n";
+ for (const auto &Entry : SerializationFormatRegistry::entries())
+ OS << " " << Entry.getName() << " - " << Entry.getDesc() << "\n";
+}
diff --git a/clang/lib/Analysis/Scalable/TUSummary/ExtractorRegistry.cpp b/clang/lib/Analysis/Scalable/TUSummary/ExtractorRegistry.cpp
index 8e3871126a2b3..1849ef753106d 100644
--- a/clang/lib/Analysis/Scalable/TUSummary/ExtractorRegistry.cpp
+++ b/clang/lib/Analysis/Scalable/TUSummary/ExtractorRegistry.cpp
@@ -33,3 +33,9 @@ ssaf::makeTUSummaryExtractor(llvm::StringRef SummaryName,
assert(false && "Unknown SummaryExtractor name");
return nullptr;
}
+
+void ssaf::printAvailableTUSummaryExtractors(llvm::raw_ostream &OS) {
+ OS << "OVERVIEW: Available SSAF summary extractors:\n\n";
+ for (const auto &Entry : TUSummaryExtractorRegistry::entries())
+ OS << " " << Entry.getName() << " - " << Entry.getDesc() << "\n";
+}
diff --git a/clang/lib/Driver/CMakeLists.txt b/clang/lib/Driver/CMakeLists.txt
index f5440a01a5932..e945db961256f 100644
--- a/clang/lib/Driver/CMakeLists.txt
+++ b/clang/lib/Driver/CMakeLists.txt
@@ -99,6 +99,7 @@ add_clang_library(clangDriver
target_parser_gen
LINK_LIBS
+ clangAnalysisScalable
clangBasic
clangFrontend
clangSerialization
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index 420340aaab885..ff2a74ef49ab5 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -53,6 +53,9 @@
#include "ToolChains/WebAssembly.h"
#include "ToolChains/XCore.h"
#include "ToolChains/ZOS.h"
+#include "clang/Analysis/Scalable/SSAFForceLinker.h" // IWYU pragma: keep
+#include "clang/Analysis/Scalable/Serialization/SerializationFormatRegistry.h"
+#include "clang/Analysis/Scalable/TUSummary/ExtractorRegistry.h"
#include "clang/Basic/DiagnosticDriver.h"
#include "clang/Basic/TargetID.h"
#include "clang/Basic/Version.h"
@@ -2555,6 +2558,22 @@ bool Driver::HandleImmediateArgs(Compilation &C) {
return false;
}
+ // Honor --ssaf-list-extractors, --ssaf-list-formats and their combinations.
+ bool ListExtractors = C.getArgs().hasArg(options::OPT__ssaf_list_extractors);
+ bool ListFormats = C.getArgs().hasArg(options::OPT__ssaf_list_formats);
+ if (ListExtractors || ListFormats) {
+ if (ListExtractors)
+ ssaf::printAvailableTUSummaryExtractors(llvm::outs());
+ if (ListFormats)
+ ssaf::printAvailableFormats(llvm::outs());
+ return false;
+ }
+
+ if (C.getArgs().hasArg(options::OPT__ssaf_list_formats)) {
+ ssaf::printAvailableFormats(llvm::outs());
+ return false;
+ }
+
if (C.getArgs().hasArg(options::OPT_v) ||
C.getArgs().hasArg(options::OPT__HASH_HASH_HASH) ||
C.getArgs().hasArg(options::OPT_print_supported_cpus) ||
diff --git a/clang/test/Analysis/SSAF/help.cpp b/clang/test/Analysis/SSAF/help.cpp
index 3755b96e3ce4f..a2e72cd198af7 100644
--- a/clang/test/Analysis/SSAF/help.cpp
+++ b/clang/test/Analysis/SSAF/help.cpp
@@ -1,7 +1,21 @@
-// RUN: %clang --help 2>&1 | FileCheck %s
-// RUN: %clang_cc1 --help 2>&1 | FileCheck %s
+// DEFINE: %{filecheck} = FileCheck %s --match-full-lines --check-prefix
-// CHECK: --ssaf-extract-summaries=<summary-names>
-// CHECK-NEXT: Comma-separated list of summary names to extract
-// CHECK-NEXT: --ssaf-tu-summary-file=<path>.<format>
-// CHECK-NEXT: The output file for the extracted summaries. The extension selects which file format to use.
+// RUN: %clang --help 2>&1 | %{filecheck}=HELP
+// RUN: %clang_cc1 --help 2>&1 | %{filecheck}=HELP
+
+// HELP: --ssaf-extract-summaries=<summary-names>
+// HELP-NEXT: Comma-separated list of summary names to extract
+// HELP-NEXT: --ssaf-list-extractors Display the list of available SSAF summary extractors
+// HELP-NEXT: --ssaf-list-formats Display the list of available SSAF serialization formats
+// HELP-NEXT: --ssaf-tu-summary-file=<path>.<format>
+// HELP-NEXT: The output file for the extracted summaries. The extension selects which file format to use.
+
+// FIXME: --ssaf-list-{extractors,formats} only work with the `clang` driver.
+// RUN: %clang --ssaf-list-extractors 2>&1 | %{filecheck}=LIST-EXTRACTORS
+// LIST-EXTRACTORS: OVERVIEW: Available SSAF summary extractors:
+
+// RUN: %clang --ssaf-list-formats 2>&1 | %{filecheck}=LIST-FORMATS
+// LIST-FORMATS: OVERVIEW: Available SSAF serialization formats:
+// LIST-FORMATS: json - JSON serialization format
+
+// RUN: %clang --ssaf-list-extractors --ssaf-list-formats 2>&1 | %{filecheck}=LIST-EXTRACTORS,LIST-FORMATS
More information about the cfe-commits
mailing list