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
