https://github.com/ziqingluo-90 updated 
https://github.com/llvm/llvm-project/pull/195746

>From ae5a3eed7eee53e507f6e4208c2072cbeac7141b Mon Sep 17 00:00:00 2001
From: Ziqing Luo <[email protected]>
Date: Tue, 28 Apr 2026 18:48:13 -0700
Subject: [PATCH 1/2] [SSAF] Add CLI option --ssaf-apply-source-pass for
 SourcePassAnalysis

The '--ssaf-apply-source-pass' option takes a list of
SourcePassAnalysis names.  The option expects the user to provide a WPA
result using '--ssaf-load-wpa-result'.

Provided SourcePassAnalysis passes will be run by clang on each AST
with the WPA result.
---
 .../clang/Basic/DiagnosticFrontendKinds.td    | 10 +++
 .../include/clang/Frontend/FrontendOptions.h  |  6 ++
 clang/include/clang/Options/Options.td        | 14 +++
 .../SourcePassAnalysisFrontendAction.h        | 33 +++++++
 .../ExecuteCompilerInvocation.cpp             |  4 +
 .../Frontend/CMakeLists.txt                   |  1 +
 .../SourcePassAnalysisFrontendAction.cpp      | 88 +++++++++++++++++++
 .../Scalable/command-line-interface.cpp       |  6 ++
 clang/test/Analysis/Scalable/help.cpp         |  6 +-
 9 files changed, 167 insertions(+), 1 deletion(-)
 create mode 100644 
clang/include/clang/ScalableStaticAnalysisFramework/Frontend/SourcePassAnalysisFrontendAction.h
 create mode 100644 
clang/lib/ScalableStaticAnalysisFramework/Frontend/SourcePassAnalysisFrontendAction.cpp

diff --git a/clang/include/clang/Basic/DiagnosticFrontendKinds.td 
b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
index f384a97b6825e..1647c869d2253 100644
--- a/clang/include/clang/Basic/DiagnosticFrontendKinds.td
+++ b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -400,6 +400,16 @@ def warn_profile_data_misexpect : Warning<
   BackendInfo, InGroup<MisExpect>;
 } // end of instrumentation issue category
 
+def warn_ssaf_load_wpa_result_unknown_file_path_format :
+  Warning<"failed to parse the value of '--ssaf-load-wpa-result=%0' "
+  "the value must follow the '<path>.<format>' pattern">,
+  InGroup<ScalableStaticAnalysisFramework>, DefaultError;
+
+def warn_ssaf_load_wpa_result_unknown_file_data_format :
+  Warning<"unknown WPA file format '%0' "
+  "specified by '--ssaf-load-wpa-result=%1'">,
+  InGroup<ScalableStaticAnalysisFramework>, DefaultError;
+
 def warn_ssaf_extract_tu_summary_file_unknown_output_format :
   Warning<"unknown output summary file format '%0' "
   "specified by '--ssaf-tu-summary-file=%1'">,
diff --git a/clang/include/clang/Frontend/FrontendOptions.h 
b/clang/include/clang/Frontend/FrontendOptions.h
index f7f51bc37c98d..88ea5f4bf3bff 100644
--- a/clang/include/clang/Frontend/FrontendOptions.h
+++ b/clang/include/clang/Frontend/FrontendOptions.h
@@ -558,6 +558,12 @@ class FrontendOptions {
   LLVM_PREFERRED_TYPE(bool)
   unsigned SSAFShowFormats : 1;
 
+  /// List of SSAF source-pass analysis names to apply.
+  std::vector<std::string> SSAFApplySourcePass;
+
+  /// The WPA result file to load, with file extension selecting the format.
+  std::string SSAFLoadWPAResult;
+
 public:
   FrontendOptions()
       : DisableFree(false), RelocatablePCH(false), ShowHelp(false),
diff --git a/clang/include/clang/Options/Options.td 
b/clang/include/clang/Options/Options.td
index c64ebba6f3dbf..610860de74b49 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -969,6 +969,20 @@ def _ssaf_list_formats :
   Visibility<[ClangOption, CC1Option]>,
   HelpText<"Display the list of available SSAF serialization formats">,
   MarshallingInfoFlag<FrontendOpts<"SSAFShowFormats">>;
+def _ssaf_apply_source_pass :
+  CommaJoined<["--"], "ssaf-apply-source-pass=">,
+  MetaVarName<"<analysis-names>">,
+  Group<SSAF_Group>,
+  Visibility<[ClangOption, CC1Option]>,
+  HelpText<"Comma-separated list of source-pass analysis names to apply">,
+  MarshallingInfoStringVector<FrontendOpts<"SSAFApplySourcePass">>;
+def _ssaf_load_wpa_result :
+  Joined<["--"], "ssaf-load-wpa-result=">,
+  MetaVarName<"<path>.<format>">,
+  Group<SSAF_Group>,
+  Visibility<[ClangOption, CC1Option]>,
+  HelpText<"The WPA result file to load. The extension selects which file 
format to use.">,
+  MarshallingInfoString<FrontendOpts<"SSAFLoadWPAResult">>;
 def Xarch__
     : JoinedAndSeparate<["-"], "Xarch_">,
       Flags<[NoXarchOption]>,
diff --git 
a/clang/include/clang/ScalableStaticAnalysisFramework/Frontend/SourcePassAnalysisFrontendAction.h
 
b/clang/include/clang/ScalableStaticAnalysisFramework/Frontend/SourcePassAnalysisFrontendAction.h
new file mode 100644
index 0000000000000..53d17576ca1e0
--- /dev/null
+++ 
b/clang/include/clang/ScalableStaticAnalysisFramework/Frontend/SourcePassAnalysisFrontendAction.h
@@ -0,0 +1,33 @@
+//===- SourcePassAnalysisFrontendAction.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_SCALABLESTATICANALYSISFRAMEWORK_FRONTEND_SOURCEPASSANALYSISFRONTENDACTION_H
+#define 
LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_FRONTEND_SOURCEPASSANALYSISFRONTENDACTION_H
+
+#include "clang/Frontend/FrontendAction.h"
+#include <memory>
+
+namespace clang::ssaf {
+
+/// Wraps the existing \c FrontendAction and injects the source-pass analysis
+/// \c ASTConsumers into the pipeline after the ASTConsumers of the wrapped
+/// action.
+class SourcePassAnalysisFrontendAction final : public WrapperFrontendAction {
+public:
+  explicit SourcePassAnalysisFrontendAction(
+      std::unique_ptr<FrontendAction> WrappedAction);
+  ~SourcePassAnalysisFrontendAction();
+
+protected:
+  std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
+                                                 StringRef InFile) override;
+};
+
+} // namespace clang::ssaf
+
+#endif // 
LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_FRONTEND_SOURCEPASSANALYSISFRONTENDACTION_H
diff --git a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp 
b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
index e4622496758ac..536ad2686a84a 100644
--- a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
+++ b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
@@ -23,6 +23,7 @@
 #include "clang/FrontendTool/Utils.h"
 #include "clang/Options/Options.h"
 #include "clang/Rewrite/Frontend/FrontendActions.h"
+#include 
"clang/ScalableStaticAnalysisFramework/Frontend/SourcePassAnalysisFrontendAction.h"
 #include 
"clang/ScalableStaticAnalysisFramework/Frontend/TUSummaryExtractorFrontendAction.h"
 #include "clang/ScalableStaticAnalysisFramework/SSAFForceLinker.h" // IWYU 
pragma: keep
 #include "clang/StaticAnalyzer/Frontend/AnalyzerHelpFlags.h"
@@ -213,6 +214,9 @@ CreateFrontendAction(CompilerInstance &CI) {
     Act = std::make_unique<ssaf::TUSummaryExtractorFrontendAction>(
         std::move(Act));
   }
+  if (!FEOpts.SSAFApplySourcePass.empty()) {
+    Act = 
std::make_unique<ssaf::SourcePassAnalysisFrontendAction>(std::move(Act));
+  }
   return Act;
 }
 
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Frontend/CMakeLists.txt 
b/clang/lib/ScalableStaticAnalysisFramework/Frontend/CMakeLists.txt
index 3da1558810572..409e7841c3f3d 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Frontend/CMakeLists.txt
+++ b/clang/lib/ScalableStaticAnalysisFramework/Frontend/CMakeLists.txt
@@ -3,6 +3,7 @@ set(LLVM_LINK_COMPONENTS
   )
 
 add_clang_library(clangScalableStaticAnalysisFrameworkFrontend
+  SourcePassAnalysisFrontendAction.cpp
   TUSummaryExtractorFrontendAction.cpp
 
   LINK_LIBS
diff --git 
a/clang/lib/ScalableStaticAnalysisFramework/Frontend/SourcePassAnalysisFrontendAction.cpp
 
b/clang/lib/ScalableStaticAnalysisFramework/Frontend/SourcePassAnalysisFrontendAction.cpp
new file mode 100644
index 0000000000000..173b2f7134f29
--- /dev/null
+++ 
b/clang/lib/ScalableStaticAnalysisFramework/Frontend/SourcePassAnalysisFrontendAction.cpp
@@ -0,0 +1,88 @@
+//===- SourcePassAnalysisFrontendAction.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/ScalableStaticAnalysisFramework/Frontend/SourcePassAnalysisFrontendAction.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/Basic/DiagnosticFrontend.h"
+#include "clang/Frontend/MultiplexConsumer.h"
+#include 
"clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormatRegistry.h"
+#include 
"clang/ScalableStaticAnalysisFramework/Core/SourcePassAnalysis/SourcePassAnalysisRegistry.h"
+#include 
"clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/WPASuite.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/IOSandbox.h"
+#include "llvm/Support/Path.h"
+#include <memory>
+
+using namespace clang;
+using namespace ssaf;
+
+SourcePassAnalysisFrontendAction::~SourcePassAnalysisFrontendAction() = 
default;
+
+SourcePassAnalysisFrontendAction::SourcePassAnalysisFrontendAction(
+    std::unique_ptr<FrontendAction> WrappedAction)
+    : WrapperFrontendAction(std::move(WrappedAction)) {}
+
+std::unique_ptr<ASTConsumer>
+SourcePassAnalysisFrontendAction::CreateASTConsumer(CompilerInstance &CI,
+                                                    StringRef InFile) {
+  auto WrappedConsumer = WrapperFrontendAction::CreateASTConsumer(CI, InFile);
+  if (!WrappedConsumer)
+    return nullptr;
+
+  const FrontendOptions &Opts = CI.getFrontendOpts();
+
+  // Parse format from file extension.
+  StringRef File = Opts.SSAFLoadWPAResult;
+  StringRef Ext = llvm::sys::path::extension(File);
+
+  if (!Ext.consume_front(".") || File.empty()) {
+    CI.getDiagnostics().Report(
+        diag::warn_ssaf_load_wpa_result_unknown_file_path_format)
+        << File;
+    return WrappedConsumer;
+  }
+
+  if (!isFormatRegistered(Ext)) {
+    CI.getDiagnostics().Report(
+        diag::warn_ssaf_load_wpa_result_unknown_file_data_format)
+        << Ext << File;
+    return WrappedConsumer;
+  }
+
+  // Load WPA results.
+  auto Format = makeFormat(Ext);
+
+  // FIXME(sandboxing): Remove this by adopting `llvm::vfs::OutputBackend`.
+  llvm::sys::sandbox::ScopedSetting Guard = 
llvm::sys::sandbox::scopedDisable();
+
+  CI.getCodeGenOpts().ClearASTBeforeBackend = false;
+
+  // Instantiate each requested source-pass analysis.
+  // FIXME: WPASuite is not copyable. For now, each analysis gets a fresh read.
+  // Consider shared ownership if multiple analyses need the same suite.
+  std::vector<std::unique_ptr<ASTConsumer>> Consumers;
+  Consumers.push_back(std::move(WrappedConsumer));
+
+  for (const auto &Name : Opts.SSAFApplySourcePass) {
+    auto SuiteOrErr = Format->readWPASuite(File);
+    if (!SuiteOrErr) {
+      llvm::report_fatal_error(SuiteOrErr.takeError());
+      continue;
+    }
+    auto AnalysisOrErr = SourcePassAnalysisRegistry::instantiate(
+        AnalysisName(Name), 
std::make_unique<WPASuite>(std::move(*SuiteOrErr)));
+    if (!AnalysisOrErr) {
+      llvm::report_fatal_error(AnalysisOrErr.takeError());
+      continue;
+    }
+    Consumers.push_back(std::move(*AnalysisOrErr));
+  }
+
+  return std::make_unique<MultiplexConsumer>(std::move(Consumers));
+}
diff --git a/clang/test/Analysis/Scalable/command-line-interface.cpp 
b/clang/test/Analysis/Scalable/command-line-interface.cpp
index a632f487f2bb7..ea215fe4cd4b5 100644
--- a/clang/test/Analysis/Scalable/command-line-interface.cpp
+++ b/clang/test/Analysis/Scalable/command-line-interface.cpp
@@ -20,3 +20,9 @@ void empty() {}
 // NO-EXTRACTORS-ENABLED:    error: must enable some summary extractors using 
the '--ssaf-extract-summaries=' option [-Wscalable-static-analysis-framework]
 // NO-EXTRACTOR-WITH-NAME:   error: no summary extractor was registered with 
name: extractor1 [-Wscalable-static-analysis-framework]
 // NO-EXTRACTORS-WITH-NAME:  error: no summary extractors were registered with 
name: extractor1, extractor2 [-Wscalable-static-analysis-framework]
+
+// RUN: not %clang_cc1 -fsyntax-only %s --ssaf-apply-source-pass=X 
--ssaf-load-wpa-result=foo.unknownfmt 2>&1 | 
%{filecheck}=UNKNOWN-WPA-INPUT-FORMAT
+// RUN: not %clang_cc1 -fsyntax-only %s --ssaf-apply-source-pass=SomeAnalysis  
                          2>&1 | %{filecheck}=NO-WPA-FILE
+
+// UNKNOWN-WPA-INPUT-FORMAT: error: unknown WPA file format 'unknownfmt' 
specified by '--ssaf-load-wpa-result=foo.unknownfmt' 
[-Wscalable-static-analysis-framework]
+// NO-WPA-FILE:              error: failed to parse the value of 
'--ssaf-load-wpa-result=' the value must follow the '<path>.<format>' pattern 
[-Wscalable-static-analysis-framework]
diff --git a/clang/test/Analysis/Scalable/help.cpp 
b/clang/test/Analysis/Scalable/help.cpp
index a2e72cd198af7..274ef923a6e84 100644
--- a/clang/test/Analysis/Scalable/help.cpp
+++ b/clang/test/Analysis/Scalable/help.cpp
@@ -3,10 +3,14 @@
 // RUN: %clang     --help 2>&1 | %{filecheck}=HELP
 // RUN: %clang_cc1 --help 2>&1 | %{filecheck}=HELP
 
-// HELP:       --ssaf-extract-summaries=<summary-names>
+// HELP:       --ssaf-apply-source-pass=<analysis-names>
+// HELP-NEXT:    Comma-separated list of source-pass analysis names to apply
+// HELP-NEXT:  --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-load-wpa-result=<path>.<format>
+// HELP-NEXT:    The WPA result file to load. The extension selects which file 
format to use.
 // 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.
 

>From dc924524e9e00169b6eadd46bf083227a1879925 Mon Sep 17 00:00:00 2001
From: Ziqing Luo <[email protected]>
Date: Mon, 4 May 2026 16:35:59 -0700
Subject: [PATCH 2/2] fix clang-format

---
 clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp 
b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
index 536ad2686a84a..9bfec61bfdcb1 100644
--- a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
+++ b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
@@ -215,7 +215,8 @@ CreateFrontendAction(CompilerInstance &CI) {
         std::move(Act));
   }
   if (!FEOpts.SSAFApplySourcePass.empty()) {
-    Act = 
std::make_unique<ssaf::SourcePassAnalysisFrontendAction>(std::move(Act));
+    Act = std::make_unique<ssaf::SourcePassAnalysisFrontendAction>(
+        std::move(Act));
   }
   return Act;
 }

_______________________________________________
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits

Reply via email to