https://github.com/steakhal created https://github.com/llvm/llvm-project/pull/205312
Third attempt of #204686 Previous attempt was: #204798 This was last reverted in #205279 This class will help keeping SSAF options apart from generic FrontendOptions. It is inspired by AnalyzerOptions. This way all of these SSAF (and future) options will be at a centralized place. In preparation of rdar://179151023 --- The previous attempt had issues on Windows with `/permissive` configs. The issue was that `GENERATE_OPTION_WITH_MARSHALLING` had a generic lambda capture and that does not constitute as an ODR-use of the captured name - because that name was only used in an unevaluated context. This meant that MSVC refused to find the function parameter. My speculative solution is to follow the established pattern of passing a pointer to the Opts structure instead of passing it directly as a reference - similar to how `AnalyzerOptions` are passed around that macro. From 68fbfcb445a037cf995feda12fed0e26438d209d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20Benics?= <[email protected]> Date: Tue, 23 Jun 2026 08:24:53 +0200 Subject: [PATCH 1/2] Reland "[clang][ssaf][NFC] Move SSAF flags from FrontendOptions to a dedicated SSAFOptions" (#204798) Second attempt of #204686 This class will help keeping SSAF options apart from generic FrontendOptions. It is inspired by AnalyzerOptions. This way all of these SSAF (and future) options will be at a centralized place. In preparation of rdar://179151023 --- .../include/clang/Frontend/CompilerInstance.h | 5 ++ .../clang/Frontend/CompilerInvocation.h | 25 ++++++--- .../include/clang/Frontend/FrontendOptions.h | 24 +-------- clang/include/clang/Frontend/SSAFOptions.h | 52 ++++++++++++++++++ clang/include/clang/Options/Options.td | 12 +++-- clang/lib/Frontend/CompilerInvocation.cpp | 32 ++++++++++- .../ExecuteCompilerInvocation.cpp | 3 +- .../TUSummaryExtractorFrontendAction.cpp | 25 ++++----- .../TUSummaryExtractorFrontendActionTest.cpp | 53 ++++++++++--------- 9 files changed, 156 insertions(+), 75 deletions(-) create mode 100644 clang/include/clang/Frontend/SSAFOptions.h diff --git a/clang/include/clang/Frontend/CompilerInstance.h b/clang/include/clang/Frontend/CompilerInstance.h index bb0eddb918623..24488e053c628 100644 --- a/clang/include/clang/Frontend/CompilerInstance.h +++ b/clang/include/clang/Frontend/CompilerInstance.h @@ -317,6 +317,11 @@ class CompilerInstance : public ModuleLoader { return Invocation->getFrontendOpts(); } + ssaf::SSAFOptions &getSSAFOpts() { return Invocation->getSSAFOpts(); } + const ssaf::SSAFOptions &getSSAFOpts() const { + return Invocation->getSSAFOpts(); + } + HeaderSearchOptions &getHeaderSearchOpts() { return Invocation->getHeaderSearchOpts(); } diff --git a/clang/include/clang/Frontend/CompilerInvocation.h b/clang/include/clang/Frontend/CompilerInvocation.h index 6fa6cd5d95534..03097aefacf50 100644 --- a/clang/include/clang/Frontend/CompilerInvocation.h +++ b/clang/include/clang/Frontend/CompilerInvocation.h @@ -51,6 +51,10 @@ class HeaderSearchOptions; class PreprocessorOptions; class TargetOptions; +namespace ssaf { +class SSAFOptions; +} // namespace ssaf + // This lets us create the DiagnosticsEngine with a properly-filled-out // DiagnosticOptions instance. std::unique_ptr<DiagnosticOptions> @@ -116,6 +120,9 @@ class CompilerInvocationBase { /// Options controlling preprocessed output. std::shared_ptr<PreprocessorOutputOptions> PreprocessorOutputOpts; + /// Options controlling the Scalable Static Analysis Framework (SSAF). + std::shared_ptr<ssaf::SSAFOptions> SSAFOpts; + /// Dummy tag type whose instance can be passed into the constructor to /// prevent creation of the reference-counted option objects. struct EmptyConstructor {}; @@ -150,6 +157,7 @@ class CompilerInvocationBase { const PreprocessorOutputOptions &getPreprocessorOutputOpts() const { return *PreprocessorOutputOpts; } + const ssaf::SSAFOptions &getSSAFOpts() const { return *SSAFOpts; } /// @} /// Visitation. @@ -247,19 +255,20 @@ class CompilerInvocation : public CompilerInvocationBase { /// @{ // Note: These need to be pulled in manually. Otherwise, they get hidden by // the mutable getters with the same names. - using CompilerInvocationBase::getLangOpts; - using CompilerInvocationBase::getTargetOpts; - using CompilerInvocationBase::getDiagnosticOpts; - using CompilerInvocationBase::getHeaderSearchOpts; - using CompilerInvocationBase::getPreprocessorOpts; using CompilerInvocationBase::getAnalyzerOpts; - using CompilerInvocationBase::getMigratorOpts; using CompilerInvocationBase::getAPINotesOpts; using CompilerInvocationBase::getCodeGenOpts; + using CompilerInvocationBase::getDependencyOutputOpts; + using CompilerInvocationBase::getDiagnosticOpts; using CompilerInvocationBase::getFileSystemOpts; using CompilerInvocationBase::getFrontendOpts; - using CompilerInvocationBase::getDependencyOutputOpts; + using CompilerInvocationBase::getHeaderSearchOpts; + using CompilerInvocationBase::getLangOpts; + using CompilerInvocationBase::getMigratorOpts; + using CompilerInvocationBase::getPreprocessorOpts; using CompilerInvocationBase::getPreprocessorOutputOpts; + using CompilerInvocationBase::getSSAFOpts; + using CompilerInvocationBase::getTargetOpts; /// @} /// Mutable getters. @@ -281,6 +290,7 @@ class CompilerInvocation : public CompilerInvocationBase { PreprocessorOutputOptions &getPreprocessorOutputOpts() { return *PreprocessorOutputOpts; } + ssaf::SSAFOptions &getSSAFOpts() { return *SSAFOpts; } /// @} /// Create a compiler invocation from a list of input options. @@ -392,6 +402,7 @@ class CowCompilerInvocation : public CompilerInvocationBase { FrontendOptions &getMutFrontendOpts(); DependencyOutputOptions &getMutDependencyOutputOpts(); PreprocessorOutputOptions &getMutPreprocessorOutputOpts(); + ssaf::SSAFOptions &getMutSSAFOpts(); /// @} }; diff --git a/clang/include/clang/Frontend/FrontendOptions.h b/clang/include/clang/Frontend/FrontendOptions.h index 7c242f6e94fe0..a8627ea5d47a4 100644 --- a/clang/include/clang/Frontend/FrontendOptions.h +++ b/clang/include/clang/Frontend/FrontendOptions.h @@ -543,27 +543,6 @@ class FrontendOptions { /// minimization hints. std::string DumpMinimizationHintsPath; - /// List of SSAF extractors to enable. - std::vector<std::string> SSAFExtractSummaries; - - /// The TU summary output file with the file extension representing the file - /// format. - std::string SSAFTUSummaryFile; - - /// Stable identifier for this translation unit, used as the name of the - /// `CompilationUnit` `BuildNamespace` of every produced TU summary. The - /// caller (typically the build system) supplies a value that is constant - /// across stages of the SSAF pipeline. - std::string SSAFCompilationUnitId; - - /// 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), @@ -581,8 +560,7 @@ class FrontendOptions { EmitPrettySymbolGraphs(false), GenReducedBMI(false), UseClangIRPipeline(false), ClangIRDisablePasses(false), ClangIRDisableCIRVerifier(false), ClangIREnableIdiomRecognizer(false), - TimeTraceGranularity(500), TimeTraceVerbose(false), - SSAFShowExtractors(false), SSAFShowFormats(false) {} + TimeTraceGranularity(500), TimeTraceVerbose(false) {} /// getInputKindForExtension - Return the appropriate input kind for a file /// extension. For example, "c" would return Language::C. diff --git a/clang/include/clang/Frontend/SSAFOptions.h b/clang/include/clang/Frontend/SSAFOptions.h new file mode 100644 index 0000000000000..738262cc4a713 --- /dev/null +++ b/clang/include/clang/Frontend/SSAFOptions.h @@ -0,0 +1,52 @@ +//===- SSAFOptions.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_FRONTEND_SSAFOPTIONS_H +#define LLVM_CLANG_FRONTEND_SSAFOPTIONS_H + +#include "llvm/Support/Compiler.h" +#include <string> +#include <vector> + +namespace clang::ssaf { + +class SSAFOptions { +public: + /// List of SSAF extractors to enable. + /// Controlled by: --ssaf-extract-summaries + std::vector<std::string> ExtractSummaries; + + /// The TU summary output file with the file extension representing the + /// serialization format. + /// Controlled by: --ssaf-tu-summary-file + std::string TUSummaryFile; + + /// Stable identifier used as the name of the `CompilationUnit` + /// `BuildNamespace` of every produced TU summary. + /// Controlled by: --ssaf-compilation-unit-id + std::string CompilationUnitId; + + /// Show the list of available SSAF summary extractors and exit. + /// Controlled by: --ssaf-list-extractors + LLVM_PREFERRED_TYPE(bool) + unsigned ShowExtractors : 1; + + /// Show the list of available SSAF serialization formats and exit. + /// Controlled by: --ssaf-list-formats + LLVM_PREFERRED_TYPE(bool) + unsigned ShowFormats : 1; + + SSAFOptions() { + ShowExtractors = false; + ShowFormats = false; + }; +}; + +} // namespace clang::ssaf + +#endif // LLVM_CLANG_FRONTEND_SSAFOPTIONS_H diff --git a/clang/include/clang/Options/Options.td b/clang/include/clang/Options/Options.td index 377897a15f746..fd13d0556083a 100644 --- a/clang/include/clang/Options/Options.td +++ b/clang/include/clang/Options/Options.td @@ -345,6 +345,8 @@ class FileSystemOpts<string base> : KeyPathAndMacro<"FileSystemOpts.", base, "FILE_SYSTEM_"> {} class AnalyzerOpts<string base> : KeyPathAndMacro<"AnalyzerOpts->", base, "ANALYZER_"> {} +class SSAFOpts<string base> + : KeyPathAndMacro<"SSAFOpts.", base, "SSAF_"> {} class MigratorOpts<string base> : KeyPathAndMacro<"MigratorOpts.", base, "MIGRATOR_"> {} @@ -947,7 +949,7 @@ def _ssaf_extract_summaries : Group<SSAF_Group>, Visibility<[ClangOption, CC1Option]>, HelpText<"Comma-separated list of summary names to extract">, - MarshallingInfoStringVector<FrontendOpts<"SSAFExtractSummaries">>; + MarshallingInfoStringVector<SSAFOpts<"ExtractSummaries">>; def _ssaf_tu_summary_file : Joined<["--"], "ssaf-tu-summary-file=">, MetaVarName<"<path>.<format>">, @@ -956,19 +958,19 @@ def _ssaf_tu_summary_file : HelpText< "The output file for the extracted summaries. " "The extension selects which file format to use.">, - MarshallingInfoString<FrontendOpts<"SSAFTUSummaryFile">>; + MarshallingInfoString<SSAFOpts<"TUSummaryFile">>; 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">>; + MarshallingInfoFlag<SSAFOpts<"ShowExtractors">>; 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">>; + MarshallingInfoFlag<SSAFOpts<"ShowFormats">>; def _ssaf_compilation_unit_id : Joined<["--"], "ssaf-compilation-unit-id=">, MetaVarName<"<id>">, @@ -978,7 +980,7 @@ def _ssaf_compilation_unit_id : "Stable identifier used as the CompilationUnit namespace name of every " "produced SSAF TU summary. Required when '--ssaf-tu-summary-file=' is " "set.">, - MarshallingInfoString<FrontendOpts<"SSAFCompilationUnitId">>; + MarshallingInfoString<SSAFOpts<"CompilationUnitId">>; def Xarch__ : JoinedAndSeparate<["-"], "Xarch_">, Flags<[NoXarchOption]>, diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index ca2d02c7dbd97..94ca546a5bcb6 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -32,6 +32,7 @@ #include "clang/Frontend/FrontendOptions.h" #include "clang/Frontend/MigratorOptions.h" #include "clang/Frontend/PreprocessorOutputOptions.h" +#include "clang/Frontend/SSAFOptions.h" #include "clang/Frontend/TextDiagnosticBuffer.h" #include "clang/Frontend/Utils.h" #include "clang/Lex/HeaderSearchOptions.h" @@ -133,7 +134,8 @@ CompilerInvocationBase::CompilerInvocationBase() FSOpts(std::make_shared<FileSystemOptions>()), FrontendOpts(std::make_shared<FrontendOptions>()), DependencyOutputOpts(std::make_shared<DependencyOutputOptions>()), - PreprocessorOutputOpts(std::make_shared<PreprocessorOutputOptions>()) {} + PreprocessorOutputOpts(std::make_shared<PreprocessorOutputOptions>()), + SSAFOpts(std::make_shared<ssaf::SSAFOptions>()) {} CompilerInvocationBase & CompilerInvocationBase::deep_copy_assign(const CompilerInvocationBase &X) { @@ -151,6 +153,7 @@ CompilerInvocationBase::deep_copy_assign(const CompilerInvocationBase &X) { FrontendOpts = make_shared_copy(X.getFrontendOpts()); DependencyOutputOpts = make_shared_copy(X.getDependencyOutputOpts()); PreprocessorOutputOpts = make_shared_copy(X.getPreprocessorOutputOpts()); + SSAFOpts = make_shared_copy(X.getSSAFOpts()); } return *this; } @@ -171,6 +174,7 @@ CompilerInvocationBase::shallow_copy_assign(const CompilerInvocationBase &X) { FrontendOpts = X.FrontendOpts; DependencyOutputOpts = X.DependencyOutputOpts; PreprocessorOutputOpts = X.PreprocessorOutputOpts; + SSAFOpts = X.SSAFOpts; } return *this; } @@ -237,6 +241,10 @@ FrontendOptions &CowCompilerInvocation::getMutFrontendOpts() { return ensureOwned(FrontendOpts); } +ssaf::SSAFOptions &CowCompilerInvocation::getMutSSAFOpts() { + return ensureOwned(SSAFOpts); +} + DependencyOutputOptions &CowCompilerInvocation::getMutDependencyOutputOpts() { return ensureOwned(DependencyOutputOpts); } @@ -1034,6 +1042,26 @@ static void GenerateAnalyzerArgs(const AnalyzerOptions &Opts, // Nothing to generate for FullCompilerInvocation. } +static void GenerateSSAFArgs(const ssaf::SSAFOptions &SSAFOpts, + ArgumentConsumer Consumer) { +#define SSAF_OPTION_WITH_MARSHALLING(...) \ + GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__) +#include "clang/Options/Options.inc" +#undef SSAF_OPTION_WITH_MARSHALLING +} + +static bool ParseSSAFArgs(ssaf::SSAFOptions &SSAFOpts, ArgList &Args, + DiagnosticsEngine &Diags) { + unsigned NumErrorsBefore = Diags.getNumErrors(); + +#define SSAF_OPTION_WITH_MARSHALLING(...) \ + PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__) +#include "clang/Options/Options.inc" +#undef SSAF_OPTION_WITH_MARSHALLING + + return Diags.getNumErrors() == NumErrorsBefore; +} + static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args, DiagnosticsEngine &Diags) { unsigned NumErrorsBefore = Diags.getNumErrors(); @@ -5083,6 +5111,7 @@ bool CompilerInvocation::CreateFromArgsImpl( ParseFileSystemArgs(Res.getFileSystemOpts(), Args, Diags); ParseMigratorArgs(Res.getMigratorOpts(), Args, Diags); ParseAnalyzerArgs(Res.getAnalyzerOpts(), Args, Diags); + ParseSSAFArgs(Res.getSSAFOpts(), Args, Diags); ParseDiagnosticArgs(Res.getDiagnosticOpts(), Args, &Diags, /*DefaultDiagColor=*/false); ParseFrontendArgs(Res.getFrontendOpts(), Args, Diags, LangOpts.IsHeaderFile); @@ -5435,6 +5464,7 @@ void CompilerInvocationBase::generateCC1CommandLine( GenerateFileSystemArgs(getFileSystemOpts(), Consumer); GenerateMigratorArgs(getMigratorOpts(), Consumer); GenerateAnalyzerArgs(getAnalyzerOpts(), Consumer); + GenerateSSAFArgs(getSSAFOpts(), Consumer); GenerateDiagnosticArgs(getDiagnosticOpts(), Consumer, /*DefaultDiagColor=*/false); GenerateFrontendArgs(getFrontendOpts(), Consumer, getLangOpts().IsHeaderFile); diff --git a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp index e4622496758ac..997200619e599 100644 --- a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp +++ b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp @@ -19,6 +19,7 @@ #include "clang/Frontend/CompilerInvocation.h" #include "clang/Frontend/FrontendActions.h" #include "clang/Frontend/FrontendPluginRegistry.h" +#include "clang/Frontend/SSAFOptions.h" #include "clang/Frontend/Utils.h" #include "clang/FrontendTool/Utils.h" #include "clang/Options/Options.h" @@ -209,7 +210,7 @@ CreateFrontendAction(CompilerInstance &CI) { Act = std::make_unique<ASTMergeAction>(std::move(Act), FEOpts.ASTMergeFiles); - if (!FEOpts.SSAFTUSummaryFile.empty()) { + if (!CI.getSSAFOpts().TUSummaryFile.empty()) { Act = std::make_unique<ssaf::TUSummaryExtractorFrontendAction>( std::move(Act)); } diff --git a/clang/lib/ScalableStaticAnalysisFramework/Frontend/TUSummaryExtractorFrontendAction.cpp b/clang/lib/ScalableStaticAnalysisFramework/Frontend/TUSummaryExtractorFrontendAction.cpp index fe900f383ae31..b4b3e85386428 100644 --- a/clang/lib/ScalableStaticAnalysisFramework/Frontend/TUSummaryExtractorFrontendAction.cpp +++ b/clang/lib/ScalableStaticAnalysisFramework/Frontend/TUSummaryExtractorFrontendAction.cpp @@ -11,6 +11,7 @@ #include "clang/Basic/DiagnosticFrontend.h" #include "clang/Basic/TargetInfo.h" #include "clang/Frontend/MultiplexConsumer.h" +#include "clang/Frontend/SSAFOptions.h" #include "clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormatRegistry.h" #include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.h" #include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummary.h" @@ -100,33 +101,33 @@ class TUSummaryRunner final : public MultiplexConsumer { private: TUSummaryRunner(llvm::Triple TargetTriple, std::unique_ptr<SerializationFormat> Format, - const FrontendOptions &Opts); + const SSAFOptions &Opts); void HandleTranslationUnit(ASTContext &Ctx) override; TUSummary Summary; TUSummaryBuilder Builder = TUSummaryBuilder(Summary); std::unique_ptr<SerializationFormat> Format; - const FrontendOptions &Opts; + const SSAFOptions &Opts; }; } // namespace std::unique_ptr<TUSummaryRunner> TUSummaryRunner::create(CompilerInstance &CI) { - const FrontendOptions &Opts = CI.getFrontendOpts(); + const SSAFOptions &Opts = CI.getSSAFOpts(); DiagnosticsEngine &Diags = CI.getDiagnostics(); - if (Opts.SSAFCompilationUnitId.empty()) { + if (Opts.CompilationUnitId.empty()) { Diags.Report(diag::warn_ssaf_tu_summary_requires_compilation_unit_id); return nullptr; } auto MaybePair = - parseOutputFileFormatAndPathOrReportError(Diags, Opts.SSAFTUSummaryFile); + parseOutputFileFormatAndPathOrReportError(Diags, Opts.TUSummaryFile); if (!MaybePair.has_value()) return nullptr; auto [FormatName, OutputPath] = MaybePair.value(); - if (reportUnrecognizedExtractorNames(Diags, Opts.SSAFExtractSummaries)) + if (reportUnrecognizedExtractorNames(Diags, Opts.ExtractSummaries)) return nullptr; return std::unique_ptr<TUSummaryRunner>{new TUSummaryRunner{ @@ -135,18 +136,18 @@ std::unique_ptr<TUSummaryRunner> TUSummaryRunner::create(CompilerInstance &CI) { TUSummaryRunner::TUSummaryRunner(llvm::Triple TargetTriple, std::unique_ptr<SerializationFormat> Format, - const FrontendOptions &Opts) + const SSAFOptions &Opts) : MultiplexConsumer(std::vector<std::unique_ptr<ASTConsumer>>{}), Summary(std::move(TargetTriple), BuildNamespace(BuildNamespaceKind::CompilationUnit, - Opts.SSAFCompilationUnitId)), + Opts.CompilationUnitId)), Format(std::move(Format)), Opts(Opts) { assert(this->Format); - assert(!Opts.SSAFCompilationUnitId.empty()); + assert(!Opts.CompilationUnitId.empty()); // Now the Summary and the builders are constructed, we can also construct the // extractors. - auto Extractors = makeTUSummaryExtractors(Builder, Opts.SSAFExtractSummaries); + auto Extractors = makeTUSummaryExtractors(Builder, Opts.ExtractSummaries); assert(!Extractors.empty()); // We must initialize the Consumers here because our extractors need a @@ -164,9 +165,9 @@ void TUSummaryRunner::HandleTranslationUnit(ASTContext &Ctx) { llvm::sys::sandbox::ScopedSetting Guard = llvm::sys::sandbox::scopedDisable(); // Then serialize the result. - if (auto Err = Format->writeTUSummary(Summary, Opts.SSAFTUSummaryFile)) { + if (auto Err = Format->writeTUSummary(Summary, Opts.TUSummaryFile)) { Ctx.getDiagnostics().Report(diag::warn_ssaf_write_tu_summary_failed) - << Opts.SSAFTUSummaryFile << llvm::toString(std::move(Err)); + << Opts.TUSummaryFile << llvm::toString(std::move(Err)); } } diff --git a/clang/unittests/ScalableStaticAnalysisFramework/Frontend/TUSummaryExtractorFrontendActionTest.cpp b/clang/unittests/ScalableStaticAnalysisFramework/Frontend/TUSummaryExtractorFrontendActionTest.cpp index 18d9e1735061d..cb5448e4860bc 100644 --- a/clang/unittests/ScalableStaticAnalysisFramework/Frontend/TUSummaryExtractorFrontendActionTest.cpp +++ b/clang/unittests/ScalableStaticAnalysisFramework/Frontend/TUSummaryExtractorFrontendActionTest.cpp @@ -11,6 +11,7 @@ #include "clang/AST/ASTContext.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/FrontendOptions.h" +#include "clang/Frontend/SSAFOptions.h" #include "clang/Frontend/TextDiagnosticBuffer.h" #include "clang/Lex/PreprocessorOptions.h" #include "clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormat.h" @@ -299,9 +300,9 @@ TEST_F(TUSummaryExtractorFrontendActionTest, // Configure valid SSAF options so the failure is purely from the wrapped // action, not from runner creation. std::string Output = makePath("output.MockSerializationFormat"); - Compiler->getFrontendOpts().SSAFTUSummaryFile = Output; - Compiler->getFrontendOpts().SSAFExtractSummaries = {"NoOpExtractor"}; - Compiler->getFrontendOpts().SSAFCompilationUnitId = "test-cu"; + Compiler->getSSAFOpts().TUSummaryFile = Output; + Compiler->getSSAFOpts().ExtractSummaries = {"NoOpExtractor"}; + Compiler->getSSAFOpts().CompilationUnitId = "test-cu"; TUSummaryExtractorFrontendAction ExtractorAction( std::make_unique<FailingAction>()); @@ -315,9 +316,9 @@ TEST_F(TUSummaryExtractorFrontendActionTest, RunnerFailsWithInvalidFormat_WrappedConsumerStillRuns) { // Use an unregistered format extension so TUSummaryRunner::create fails. std::string Output = makePath("output.xyz"); - Compiler->getFrontendOpts().SSAFTUSummaryFile = Output; - Compiler->getFrontendOpts().SSAFExtractSummaries = {"NoOpExtractor"}; - Compiler->getFrontendOpts().SSAFCompilationUnitId = "test-cu"; + Compiler->getSSAFOpts().TUSummaryFile = Output; + Compiler->getSSAFOpts().ExtractSummaries = {"NoOpExtractor"}; + Compiler->getSSAFOpts().CompilationUnitId = "test-cu"; auto Wrapped = std::make_unique<RecordingAction>(); const EventLog &Log = Wrapped->getLog(); @@ -345,9 +346,9 @@ TEST_F(TUSummaryExtractorFrontendActionTest, TEST_F(TUSummaryExtractorFrontendActionTest, RunnerFailsWithUnknownExtractor_WrappedConsumerStillRuns) { std::string Output = makePath("output.MockSerializationFormat"); - Compiler->getFrontendOpts().SSAFTUSummaryFile = Output; - Compiler->getFrontendOpts().SSAFExtractSummaries = {"NonExistentExtractor"}; - Compiler->getFrontendOpts().SSAFCompilationUnitId = "test-cu"; + Compiler->getSSAFOpts().TUSummaryFile = Output; + Compiler->getSSAFOpts().ExtractSummaries = {"NonExistentExtractor"}; + Compiler->getSSAFOpts().CompilationUnitId = "test-cu"; auto Wrapped = std::make_unique<RecordingAction>(); const EventLog &Log = Wrapped->getLog(); @@ -370,9 +371,9 @@ TEST_F(TUSummaryExtractorFrontendActionTest, TEST_F(TUSummaryExtractorFrontendActionTest, RunnerSucceeds_ASTConsumerCallbacksPropagate) { std::string Output = makePath("output.MockSerializationFormat"); - Compiler->getFrontendOpts().SSAFTUSummaryFile = Output; - Compiler->getFrontendOpts().SSAFExtractSummaries = {"NoOpExtractor"}; - Compiler->getFrontendOpts().SSAFCompilationUnitId = "test-cu"; + Compiler->getSSAFOpts().TUSummaryFile = Output; + Compiler->getSSAFOpts().ExtractSummaries = {"NoOpExtractor"}; + Compiler->getSSAFOpts().CompilationUnitId = "test-cu"; auto Wrapped = std::make_unique<RecordingAction>(); const EventLog &Log = Wrapped->getLog(); @@ -425,9 +426,9 @@ struct OrderCheckingAction : public ASTFrontendAction { TEST_F(TUSummaryExtractorFrontendActionTest, RunnerSucceeds_WrappedRunsBeforeRunner) { std::string Output = makePath("output.MockSerializationFormat"); - Compiler->getFrontendOpts().SSAFTUSummaryFile = Output; - Compiler->getFrontendOpts().SSAFExtractSummaries = {"NoOpExtractor"}; - Compiler->getFrontendOpts().SSAFCompilationUnitId = "test-cu"; + Compiler->getSSAFOpts().TUSummaryFile = Output; + Compiler->getSSAFOpts().ExtractSummaries = {"NoOpExtractor"}; + Compiler->getSSAFOpts().CompilationUnitId = "test-cu"; auto Wrapped = std::make_unique<OrderCheckingAction>(); Wrapped->OutputPath = Output; @@ -447,9 +448,9 @@ TEST_F(TUSummaryExtractorFrontendActionTest, TEST_F(TUSummaryExtractorFrontendActionTest, RunnerFailsToWrite) { std::string Output = makePath("output.FailingSerializationFormat"); - Compiler->getFrontendOpts().SSAFTUSummaryFile = Output; - Compiler->getFrontendOpts().SSAFExtractSummaries = {"NoOpExtractor"}; - Compiler->getFrontendOpts().SSAFCompilationUnitId = "test-cu"; + Compiler->getSSAFOpts().TUSummaryFile = Output; + Compiler->getSSAFOpts().ExtractSummaries = {"NoOpExtractor"}; + Compiler->getSSAFOpts().CompilationUnitId = "test-cu"; TUSummaryExtractorFrontendAction Action(std::make_unique<RecordingAction>()); @@ -469,8 +470,8 @@ TEST_F(TUSummaryExtractorFrontendActionTest, RunnerFailsToWrite) { TEST_F(TUSummaryExtractorFrontendActionTest, MissingCompilationUnitIdDiagnoses) { std::string Output = makePath("output.MockSerializationFormat"); - Compiler->getFrontendOpts().SSAFTUSummaryFile = Output; - Compiler->getFrontendOpts().SSAFExtractSummaries = {"NoOpExtractor"}; + Compiler->getSSAFOpts().TUSummaryFile = Output; + Compiler->getSSAFOpts().ExtractSummaries = {"NoOpExtractor"}; // SSAFCompilationUnitId left empty. auto Wrapped = std::make_unique<RecordingAction>(); @@ -493,9 +494,9 @@ TEST_F(TUSummaryExtractorFrontendActionTest, TEST_F(TUSummaryExtractorFrontendActionTest, EmptyCompilationUnitIdDiagnoses) { std::string Output = makePath("output.MockSerializationFormat"); - Compiler->getFrontendOpts().SSAFTUSummaryFile = Output; - Compiler->getFrontendOpts().SSAFExtractSummaries = {"NoOpExtractor"}; - Compiler->getFrontendOpts().SSAFCompilationUnitId = ""; + Compiler->getSSAFOpts().TUSummaryFile = Output; + Compiler->getSSAFOpts().ExtractSummaries = {"NoOpExtractor"}; + Compiler->getSSAFOpts().CompilationUnitId = ""; auto Wrapped = std::make_unique<RecordingAction>(); const EventLog &Log = Wrapped->getLog(); @@ -520,9 +521,9 @@ TEST_F(TUSummaryExtractorFrontendActionTest, const std::string CUId = "cu-X-test"; std::string Output = makePath("output.CapturingSerializationFormat"); - Compiler->getFrontendOpts().SSAFTUSummaryFile = Output; - Compiler->getFrontendOpts().SSAFExtractSummaries = {"NoOpExtractor"}; - Compiler->getFrontendOpts().SSAFCompilationUnitId = CUId; + Compiler->getSSAFOpts().TUSummaryFile = Output; + Compiler->getSSAFOpts().ExtractSummaries = {"NoOpExtractor"}; + Compiler->getSSAFOpts().CompilationUnitId = CUId; TUSummaryExtractorFrontendAction Action(std::make_unique<RecordingAction>()); EXPECT_TRUE(Compiler->ExecuteAction(Action)); From ca6ad8fc5c9cbe3091645fc9dbac2a1c15e2511c Mon Sep 17 00:00:00 2001 From: Balazs Benics <[email protected]> Date: Tue, 23 Jun 2026 10:43:12 +0100 Subject: [PATCH 2/2] fixup Reland "[clang][ssaf][NFC] Move SSAF flags from FrontendOptions to a dedicated SSAFOptions" [clang][ssaf] Fix MSVC build break in GenerateSSAFArgs/ParseSSAFArgs The GENERATE_OPTION_WITH_MARSHALLING macro emits a generic lambda '[&](const auto &Extracted) { ... decltype(KEYPATH) ... }(EXTRACTOR(KEYPATH))'. Inside the lambda body, the keypath identifier appears only in decltype(...) -- an unevaluated operand. Names used solely in unevaluated operands are not odr-used, so '[&]' does not implicitly capture them, and the lambda's templated operator() must find the name via ordinary lookup in the enclosing scope. MSVC under /permissive- (used by the sanitizer-windows builder) refuses to find a function parameter through this path, producing: error C2065: 'SSAFOpts': undeclared identifier note: see reference to function template instantiation 'GenerateSSAFArgs::<lambda_...>::operator ()<T>(const T &) const' Clang and GCC are more lenient and accept it. The existing AnalyzerOpts and MigratorOpts helpers work around this by taking the options as 'Opts' and declaring a local variable that matches the keypath name. Mirror that pattern for SSAF: switch the keypath to 'SSAFOpts->' and introduce a local pointer 'SSAFOpts = &Opts' in both GenerateSSAFArgs and ParseSSAFArgs. Assisted-By: claude --- clang/include/clang/Options/Options.td | 2 +- clang/lib/Frontend/CompilerInvocation.cpp | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/clang/include/clang/Options/Options.td b/clang/include/clang/Options/Options.td index fd13d0556083a..4fc9f4d4c3472 100644 --- a/clang/include/clang/Options/Options.td +++ b/clang/include/clang/Options/Options.td @@ -346,7 +346,7 @@ class FileSystemOpts<string base> class AnalyzerOpts<string base> : KeyPathAndMacro<"AnalyzerOpts->", base, "ANALYZER_"> {} class SSAFOpts<string base> - : KeyPathAndMacro<"SSAFOpts.", base, "SSAF_"> {} + : KeyPathAndMacro<"SSAFOpts->", base, "SSAF_"> {} class MigratorOpts<string base> : KeyPathAndMacro<"MigratorOpts.", base, "MIGRATOR_"> {} diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 94ca546a5bcb6..55b344fc2da26 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -1042,18 +1042,22 @@ static void GenerateAnalyzerArgs(const AnalyzerOptions &Opts, // Nothing to generate for FullCompilerInvocation. } -static void GenerateSSAFArgs(const ssaf::SSAFOptions &SSAFOpts, +static void GenerateSSAFArgs(const ssaf::SSAFOptions &Opts, ArgumentConsumer Consumer) { + const ssaf::SSAFOptions *SSAFOpts = &Opts; + #define SSAF_OPTION_WITH_MARSHALLING(...) \ GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__) #include "clang/Options/Options.inc" #undef SSAF_OPTION_WITH_MARSHALLING } -static bool ParseSSAFArgs(ssaf::SSAFOptions &SSAFOpts, ArgList &Args, +static bool ParseSSAFArgs(ssaf::SSAFOptions &Opts, ArgList &Args, DiagnosticsEngine &Diags) { unsigned NumErrorsBefore = Diags.getNumErrors(); + ssaf::SSAFOptions *SSAFOpts = &Opts; + #define SSAF_OPTION_WITH_MARSHALLING(...) \ PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__) #include "clang/Options/Options.inc" _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
