llvmorg-github-actions[bot] wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang-static-analyzer-1

Author: Jan Korous (jkorous-apple)

<details>
<summary>Changes</summary>

Adds the four `--ssaf-*` driver flags
(`--ssaf-source-transformation=`, `--ssaf-global-scope-analysis-result=`, 
`--ssaf-src-edit-file=`, `--ssaf-transformation-report-file=`) under 
`SSAF_Group`, marshalled into `FrontendOptions`. The compilation-unit 
identifier flag introduced earlier is reused. The driver forwards all four 
flags to `cc1`.

Adds twelve `warn_ssaf_*` diagnostics under
`-Wscalable-static-analysis-framework` (`DefaultError`) covering the 
orphan-flag matrix, unknown transformation names, unknown output formats, 
WPA-suite read failures, and edit/report write failures.

Adds `clang::ssaf::SourceTransformationFrontendAction` — a 
`WrapperFrontendAction` that, when any source-edit flag is set, validates the 
CLI as a group, loads the WPASuite from the configured path, instantiates the 
named transformation, and serializes the accumulated edits and findings through 
the configured formats. The action is wrapped in `ExecuteCompilerInvocation` 
after the existing TU-summary wrap so both pipelines stack as independent 
`ASTConsumer`s on the same translation unit; they exchange no data.

Assisted-By: Claude Opus 4.7

---

Patch is 44.67 KiB, truncated to 20.00 KiB below, full version: 
https://github.com/llvm/llvm-project/pull/208590.diff


23 Files Affected:

- (added) clang/docs/ScalableStaticAnalysis/user-docs/SourceEditGeneration.rst 
(+63) 
- (modified) clang/include/clang/Basic/DiagnosticFrontendKinds.td (+46) 
- (modified) clang/include/clang/Basic/DiagnosticIDs.h (+1-1) 
- (modified) clang/include/clang/Frontend/SSAFOptions.h (+21) 
- (modified) clang/include/clang/Options/Options.td (+38) 
- (added) 
clang/include/clang/ScalableStaticAnalysis/Frontend/SourceTransformationFrontendAction.h
 (+34) 
- (modified) clang/lib/Driver/ToolChains/Clang.cpp (+4) 
- (modified) clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp (+7) 
- (modified) clang/lib/ScalableStaticAnalysis/Frontend/CMakeLists.txt (+3) 
- (added) 
clang/lib/ScalableStaticAnalysis/Frontend/SourceTransformationFrontendAction.cpp
 (+234) 
- (modified) clang/test/Analysis/Scalable/help.cpp (+8) 
- (added) 
clang/test/Analysis/Scalable/source-edit-generation/Inputs/empty-suite.json 
(+5) 
- (added) 
clang/test/Analysis/Scalable/source-edit-generation/Inputs/two-function-suite.json
 (+26) 
- (added) 
clang/test/Analysis/Scalable/source-edit-generation/Plugins/CMakeLists.txt (+3) 
- (added) 
clang/test/Analysis/Scalable/source-edit-generation/Plugins/TestTransformationPlugin/CMakeLists.txt
 (+16) 
- (added) 
clang/test/Analysis/Scalable/source-edit-generation/Plugins/TestTransformationPlugin/TestTransformation.cpp
 (+101) 
- (added) 
clang/test/Analysis/Scalable/source-edit-generation/Plugins/lit.local.cfg (+2) 
- (added) clang/test/Analysis/Scalable/source-edit-generation/cli-errors.cpp 
(+51) 
- (added) clang/test/Analysis/Scalable/source-edit-generation/coexistence.cpp 
(+33) 
- (added) 
clang/test/Analysis/Scalable/source-edit-generation/downgradable-errors.cpp 
(+35) 
- (added) clang/test/Analysis/Scalable/source-edit-generation/happy-path.cpp 
(+37) 
- (added) clang/test/Analysis/Scalable/source-edit-generation/write-failure.cpp 
(+41) 
- (modified) clang/test/CMakeLists.txt (+2) 


``````````diff
diff --git 
a/clang/docs/ScalableStaticAnalysis/user-docs/SourceEditGeneration.rst 
b/clang/docs/ScalableStaticAnalysis/user-docs/SourceEditGeneration.rst
new file mode 100644
index 0000000000000..25839c6f32c7f
--- /dev/null
+++ b/clang/docs/ScalableStaticAnalysis/user-docs/SourceEditGeneration.rst
@@ -0,0 +1,63 @@
+==============================
+Source Edit Generation
+==============================
+
+Source edit generation relies on a ``WPASuite`` result produced by an
+earlier whole-program analysis. It runs alongside the normal compile
+and emits two per-translation-unit artifacts:
+
+- a *source-edit file* (``--ssaf-src-edit-file=``) containing
+  ``clang::tooling::Replacement`` records ready for
+  ``clang-apply-replacements``,
+- a *transformation-report file* (``--ssaf-transformation-report-file=``)
+  containing diagnostic-style findings.
+
+Driver flags
+============
+
+Four flags control the pipeline; they are all both ``--ssaf-…`` driver
+flags and ``cc1`` flags. The compilation-unit identifier is shared
+with the summary extraction step. A given compilation unit needs to
+receive the same identifier for both summary extraction and source
+edit generation.
+
+.. list-table::
+   :header-rows: 1
+
+   * - Flag
+     - Purpose
+   * - ``--ssaf-source-transformation=<name>``
+     - Name of the transformation to run.
+   * - ``--ssaf-global-scope-analysis-result=<path>.<format>``
+     - WPASuite input. The extension selects the serialization format.
+   * - ``--ssaf-src-edit-file=<path>``
+     - Source-edit output. Always written as a
+       ``clang-apply-replacements``-compatible YAML document; the
+       file extension is not interpreted.
+   * - ``--ssaf-transformation-report-file=<path>``
+     - Transformation-report output. Always written as a SARIF JSON
+       document; the file extension is not interpreted.
+   * - ``--ssaf-compilation-unit-id=<id>``
+     - Stable identifier for this translation unit (also required by
+       the summary extraction).
+
+When ``--ssaf-source-transformation=`` is non-empty the framework wraps
+the active ``FrontendAction`` in a ``SourceTransformationFrontendAction``;
+otherwise the compile is byte-for-byte unchanged.
+
+Examples
+========
+
+Apply the source edits with ``clang-apply-replacements``:
+
+.. code-block:: console
+
+   $ clang -c foo.cpp \
+       --ssaf-source-transformation=my-transformation \
+       --ssaf-global-scope-analysis-result=wpa.json \
+       --ssaf-src-edit-file=foo.yaml \
+       --ssaf-transformation-report-file=foo.sarif \
+       --ssaf-compilation-unit-id=cu-foo
+   $ clang-apply-replacements --remove-change-desc-files <dir-with-yaml>
+
+The transformation report can be consumed by any SARIF viewer.
diff --git a/clang/include/clang/Basic/DiagnosticFrontendKinds.td 
b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
index cef2fc32a1642..4677af8400e26 100644
--- a/clang/include/clang/Basic/DiagnosticFrontendKinds.td
+++ b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -435,6 +435,52 @@ def warn_ssaf_tu_summary_requires_compilation_unit_id :
           "'--ssaf-compilation-unit-id=' to be set">,
   InGroup<ScalableStaticAnalysis>, DefaultError;
 
+def warn_ssaf_source_transformation_unknown_name :
+  Warning<"no source transformation registered with name: %0">,
+  InGroup<ScalableStaticAnalysis>, DefaultError;
+
+def warn_ssaf_source_transformation_requires_wpa_file :
+  Warning<"option '--ssaf-source-transformation=' requires "
+          "'--ssaf-global-scope-analysis-result=' to be set">,
+  InGroup<ScalableStaticAnalysis>, DefaultError;
+
+def warn_ssaf_source_transformation_requires_edit_file :
+  Warning<"option '--ssaf-source-transformation=' requires "
+          "'--ssaf-src-edit-file=' to be set">,
+  InGroup<ScalableStaticAnalysis>, DefaultError;
+
+def warn_ssaf_source_transformation_requires_report_file :
+  Warning<"option '--ssaf-source-transformation=' requires "
+          "'--ssaf-transformation-report-file=' to be set">,
+  InGroup<ScalableStaticAnalysis>, DefaultError;
+
+def warn_ssaf_source_transformation_requires_compilation_unit_id :
+  Warning<"option '--ssaf-source-transformation=' requires "
+          "'--ssaf-compilation-unit-id=' to be set">,
+  InGroup<ScalableStaticAnalysis>, DefaultError;
+
+def warn_ssaf_read_wpa_suite_failed :
+  Warning<"failed to read whole-program analysis result from '%0': %1">,
+  InGroup<ScalableStaticAnalysis>, DefaultError;
+
+def warn_ssaf_src_edit_file_requires_transformation :
+  Warning<"option '--ssaf-src-edit-file=' requires "
+          "'--ssaf-source-transformation=' to be set">,
+  InGroup<ScalableStaticAnalysis>, DefaultError;
+
+def warn_ssaf_write_src_edit_failed :
+  Warning<"failed to write source edits to '%0': %1">,
+  InGroup<ScalableStaticAnalysis>, DefaultError;
+
+def warn_ssaf_transformation_report_file_requires_transformation :
+  Warning<"option '--ssaf-transformation-report-file=' requires "
+          "'--ssaf-source-transformation=' to be set">,
+  InGroup<ScalableStaticAnalysis>, DefaultError;
+
+def warn_ssaf_write_transformation_report_failed :
+  Warning<"failed to write transformation report to '%0': %1">,
+  InGroup<ScalableStaticAnalysis>, DefaultError;
+
 def err_extract_api_ignores_file_not_found :
   Error<"file '%0' specified by '--extract-api-ignores=' not found">, 
DefaultFatal;
 
diff --git a/clang/include/clang/Basic/DiagnosticIDs.h 
b/clang/include/clang/Basic/DiagnosticIDs.h
index 63b5e6a28aac0..2d7e32579b608 100644
--- a/clang/include/clang/Basic/DiagnosticIDs.h
+++ b/clang/include/clang/Basic/DiagnosticIDs.h
@@ -36,7 +36,7 @@ enum class Group;
 enum {
   DIAG_SIZE_COMMON = 300,
   DIAG_SIZE_DRIVER = 400,
-  DIAG_SIZE_FRONTEND = 200,
+  DIAG_SIZE_FRONTEND = 250,
   DIAG_SIZE_SERIALIZATION = 120,
   DIAG_SIZE_LEX = 500,
   DIAG_SIZE_PARSE = 800,
diff --git a/clang/include/clang/Frontend/SSAFOptions.h 
b/clang/include/clang/Frontend/SSAFOptions.h
index 738262cc4a713..c042a3fff6019 100644
--- a/clang/include/clang/Frontend/SSAFOptions.h
+++ b/clang/include/clang/Frontend/SSAFOptions.h
@@ -31,6 +31,27 @@ class SSAFOptions {
   /// Controlled by: --ssaf-compilation-unit-id
   std::string CompilationUnitId;
 
+  /// Name of the SSAF source transformation to run. Exactly one transformation
+  /// per invocation; non-empty implies the source-transformation pipeline is
+  /// active.
+  /// Controlled by: --ssaf-source-transformation
+  std::string SourceTransformation;
+
+  /// Path of the WPASuite input consumed by the source transformation. The
+  /// extension selects which serialization format reads it.
+  /// Controlled by: --ssaf-global-scope-analysis-result
+  std::string GlobalScopeAnalysisResult;
+
+  /// Path of the source-edit output file produced by the source
+  /// transformation.
+  /// Controlled by: --ssaf-src-edit-file
+  std::string SrcEditFile;
+
+  /// Path of the transformation-report output file produced by the source
+  /// transformation.
+  /// Controlled by: --ssaf-transformation-report-file
+  std::string TransformationReportFile;
+
   /// Show the list of available SSAF summary extractors and exit.
   /// Controlled by: --ssaf-list-extractors
   LLVM_PREFERRED_TYPE(bool)
diff --git a/clang/include/clang/Options/Options.td 
b/clang/include/clang/Options/Options.td
index 677aaf00b5083..52711492d3cb1 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -982,6 +982,44 @@ def _ssaf_compilation_unit_id :
     "produced SSAF TU summary. Required when '--ssaf-tu-summary-file=' is "
     "set.">,
   MarshallingInfoString<SSAFOpts<"CompilationUnitId">>;
+def _ssaf_source_transformation :
+  Joined<["--"], "ssaf-source-transformation=">,
+  MetaVarName<"<name>">,
+  Group<SSAF_Group>,
+  Visibility<[ClangOption, CC1Option]>,
+  HelpText<
+    "Name of the SSAF source transformation to run. Exactly one transformation 
"
+    "per invocation.">,
+  MarshallingInfoString<SSAFOpts<"SourceTransformation">>;
+def _ssaf_global_scope_analysis_result :
+  Joined<["--"], "ssaf-global-scope-analysis-result=">,
+  MetaVarName<"<path>.<format>">,
+  Group<SSAF_Group>,
+  Visibility<[ClangOption, CC1Option]>,
+  HelpText<
+    "Path to the WPASuite file containing the whole-program analysis result "
+    "consumed by the source transformation. The extension selects which file "
+    "format to use.">,
+  MarshallingInfoString<SSAFOpts<"GlobalScopeAnalysisResult">>;
+def _ssaf_src_edit_file :
+  Joined<["--"], "ssaf-src-edit-file=">,
+  MetaVarName<"<path>">,
+  Group<SSAF_Group>,
+  Visibility<[ClangOption, CC1Option]>,
+  HelpText<
+    "Output file for the source edits produced by the source transformation. "
+    "The output is a YAML document compatible with "
+    "'clang-apply-replacements'.">,
+  MarshallingInfoString<SSAFOpts<"SrcEditFile">>;
+def _ssaf_transformation_report_file :
+  Joined<["--"], "ssaf-transformation-report-file=">,
+  MetaVarName<"<path>">,
+  Group<SSAF_Group>,
+  Visibility<[ClangOption, CC1Option]>,
+  HelpText<
+    "Output file for the transformation report produced by the source "
+    "transformation. The output is a SARIF 2.1.0 JSON document.">,
+  MarshallingInfoString<SSAFOpts<"TransformationReportFile">>;
 def Xarch__
     : JoinedAndSeparate<["-"], "Xarch_">,
       Flags<[NoXarchOption]>,
diff --git 
a/clang/include/clang/ScalableStaticAnalysis/Frontend/SourceTransformationFrontendAction.h
 
b/clang/include/clang/ScalableStaticAnalysis/Frontend/SourceTransformationFrontendAction.h
new file mode 100644
index 0000000000000..1d554ca8343b8
--- /dev/null
+++ 
b/clang/include/clang/ScalableStaticAnalysis/Frontend/SourceTransformationFrontendAction.h
@@ -0,0 +1,34 @@
+//===- SourceTransformationFrontendAction.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_SCALABLESTATICANALYSIS_FRONTEND_SOURCETRANSFORMATIONFRONTENDACTION_H
+#define 
LLVM_CLANG_SCALABLESTATICANALYSIS_FRONTEND_SOURCETRANSFORMATIONFRONTENDACTION_H
+
+#include "clang/Frontend/FrontendAction.h"
+#include <memory>
+
+namespace clang::ssaf {
+
+/// Wraps the existing \c FrontendAction and runs the source-transformation
+/// pipeline alongside it. The transformation consumes a \c WPASuite read from
+/// \c SSAFOptions::GlobalScopeAnalysisResult and emits source edits and a
+/// transformation report to the configured output files.
+class SourceTransformationFrontendAction final : public WrapperFrontendAction {
+public:
+  explicit SourceTransformationFrontendAction(
+      std::unique_ptr<FrontendAction> WrappedAction);
+  ~SourceTransformationFrontendAction();
+
+protected:
+  std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
+                                                 StringRef InFile) override;
+};
+
+} // namespace clang::ssaf
+
+#endif // 
LLVM_CLANG_SCALABLESTATICANALYSIS_FRONTEND_SOURCETRANSFORMATIONFRONTENDACTION_H
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index a30b01a675b99..32c8103e3556a 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -8073,6 +8073,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction 
&JA,
   Args.AddLastArg(CmdArgs, options::OPT__ssaf_extract_summaries);
   Args.AddLastArg(CmdArgs, options::OPT__ssaf_tu_summary_file);
   Args.AddLastArg(CmdArgs, options::OPT__ssaf_compilation_unit_id);
+  Args.AddLastArg(CmdArgs, options::OPT__ssaf_source_transformation);
+  Args.AddLastArg(CmdArgs, options::OPT__ssaf_global_scope_analysis_result);
+  Args.AddLastArg(CmdArgs, options::OPT__ssaf_src_edit_file);
+  Args.AddLastArg(CmdArgs, options::OPT__ssaf_transformation_report_file);
 
   // Handle serialized diagnostics.
   if (Arg *A = Args.getLastArg(options::OPT__serialize_diags)) {
diff --git a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp 
b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
index a206770c8490f..6c3a5d096c99b 100644
--- a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
+++ b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
@@ -24,6 +24,7 @@
 #include "clang/FrontendTool/Utils.h"
 #include "clang/Options/Options.h"
 #include "clang/Rewrite/Frontend/FrontendActions.h"
+#include 
"clang/ScalableStaticAnalysis/Frontend/SourceTransformationFrontendAction.h"
 #include 
"clang/ScalableStaticAnalysis/Frontend/TUSummaryExtractorFrontendAction.h"
 #include "clang/ScalableStaticAnalysis/SSAFForceLinker.h" // IWYU pragma: keep
 #include "clang/StaticAnalyzer/Frontend/AnalyzerHelpFlags.h"
@@ -214,6 +215,12 @@ CreateFrontendAction(CompilerInstance &CI) {
     Act = std::make_unique<ssaf::TUSummaryExtractorFrontendAction>(
         std::move(Act));
   }
+  if (!CI.getSSAFOpts().SourceTransformation.empty() ||
+      !CI.getSSAFOpts().SrcEditFile.empty() ||
+      !CI.getSSAFOpts().TransformationReportFile.empty()) {
+    Act = std::make_unique<ssaf::SourceTransformationFrontendAction>(
+        std::move(Act));
+  }
   return Act;
 }
 
diff --git a/clang/lib/ScalableStaticAnalysis/Frontend/CMakeLists.txt 
b/clang/lib/ScalableStaticAnalysis/Frontend/CMakeLists.txt
index 74e1d0cbe1ed0..58a4806754b45 100644
--- a/clang/lib/ScalableStaticAnalysis/Frontend/CMakeLists.txt
+++ b/clang/lib/ScalableStaticAnalysis/Frontend/CMakeLists.txt
@@ -4,6 +4,7 @@ set(LLVM_LINK_COMPONENTS
   )
 
 add_clang_library(clangScalableStaticAnalysisFrontend
+  SourceTransformationFrontendAction.cpp
   TUSummaryExtractorFrontendAction.cpp
 
   LINK_LIBS
@@ -12,5 +13,7 @@ add_clang_library(clangScalableStaticAnalysisFrontend
   clangFrontend
   clangScalableStaticAnalysisAnalyses
   clangScalableStaticAnalysisCore
+  clangScalableStaticAnalysisSourceTransformation
   clangSema
+  clangToolingCore
   )
diff --git 
a/clang/lib/ScalableStaticAnalysis/Frontend/SourceTransformationFrontendAction.cpp
 
b/clang/lib/ScalableStaticAnalysis/Frontend/SourceTransformationFrontendAction.cpp
new file mode 100644
index 0000000000000..1fdc82009f8cc
--- /dev/null
+++ 
b/clang/lib/ScalableStaticAnalysis/Frontend/SourceTransformationFrontendAction.cpp
@@ -0,0 +1,234 @@
+//===- SourceTransformationFrontendAction.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/ScalableStaticAnalysis/Frontend/SourceTransformationFrontendAction.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/Basic/DiagnosticFrontend.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/MultiplexConsumer.h"
+#include "clang/Frontend/SSAFOptions.h"
+#include 
"clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormat.h"
+#include 
"clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormatRegistry.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/WPASuite.h"
+#include 
"clang/ScalableStaticAnalysis/SourceTransformation/SARIFTransformationReportFormat.h"
+#include 
"clang/ScalableStaticAnalysis/SourceTransformation/SourceEditEmitter.h"
+#include "clang/ScalableStaticAnalysis/SourceTransformation/Transformation.h"
+#include 
"clang/ScalableStaticAnalysis/SourceTransformation/TransformationRegistry.h"
+#include 
"clang/ScalableStaticAnalysis/SourceTransformation/TransformationReportEmitter.h"
+#include 
"clang/ScalableStaticAnalysis/SourceTransformation/YAMLSourceEditFormat.h"
+#include "clang/Tooling/Core/Replacement.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/IOSandbox.h"
+#include "llvm/Support/Path.h"
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+using namespace clang;
+using namespace ssaf;
+
+namespace {
+
+/// Concrete `SourceEditEmitter` that buffers replacements until flushed.
+class AccumulatorSourceEditEmitter final : public SourceEditEmitter {
+public:
+  void addReplacement(clang::tooling::Replacement R) override {
+    Replacements.push_back(std::move(R));
+  }
+
+  std::vector<clang::tooling::Replacement> Replacements;
+};
+
+/// Concrete `TransformationReportEmitter` that buffers results until flushed.
+class AccumulatorReportEmitter final : public TransformationReportEmitter {
+public:
+  void addResult(StringRef RuleId, clang::SarifResultLevel Level,
+                 clang::CharSourceRange Range, StringRef Message) override {
+    Results.push_back({RuleId.str(), Level, Range, Message.str()});
+  }
+
+  std::vector<ReportResult> Results;
+};
+
+/// Per-TU runner: owns the loaded `WPASuite`, the accumulator emitters, and
+/// the user-supplied `Transformation`. Inherits from `MultiplexConsumer` so
+/// the transformation's `ASTConsumer` virtuals are forwarded for free;
+/// serializes both outputs after the AST walk completes.
+class SourceTransformationRunner final : public MultiplexConsumer {
+public:
+  static std::unique_ptr<SourceTransformationRunner>
+  create(CompilerInstance &CI, StringRef InFile);
+
+private:
+  SourceTransformationRunner(WPASuite Suite, const SSAFOptions &Opts,
+                             StringRef InFile);
+
+  void HandleTranslationUnit(ASTContext &Ctx) override;
+
+  WPASuite Suite;
+  AccumulatorSourceEditEmitter Edits;
+  AccumulatorReportEmitter Report;
+  const SSAFOptions &Opts;
+  std::string InFile;
+};
+
+} // namespace
+
+/// Returns the bare extension of \p Path (no leading dot), or `std::nullopt` 
if
+/// \p Path is empty or has no recognizable extension.
+static std::optional<StringRef> bareExtension(StringRef Path) {
+  StringRef Ext = llvm::sys::path::extension(Path);
+  if (!Ext.consume_front("."))
+    return std::nullopt;
+  return Ext;
+}
+
+/// Returns `true` if any orphan-flag warning was reported. Every missing
+/// companion flag fires its own diagnostic in a single pass so the user
+/// sees the full list of CLI mistakes at once.
+static bool reportOrphanFlagMisuse(DiagnosticsEngine &Diags,
+                                   const SSAFOptions &Opts) {
+  bool Reported = false;
+
+  if (!Opts.SourceTransformation.empty()) {
+    if (Opts.GlobalScopeAnalysisResult.empty()) {
+      Diags.Report(diag::warn_ssaf_source_transformation_requires_wpa_file);
+      Reported = true;
+    }
+    if (Opts.SrcEditFile.empty()) {
+      Diags.Report(diag::warn_ssaf_source_transformation_requires_edit_file);
+      Reported = true;
+    }
+    if (Opts.TransformationReportFile.empty()) {
+      Diags.Report(diag::warn_ssaf_source_transformation_requires_report_file);
+      Reported = true;
+    }
+    if (Opts.CompilationUnitId.empty()) {
+      Diags.Report(
+          diag::warn_ssaf_source_transformation_requires_compilation_unit_id);
+      Reported = true;
+    }
+  } else {
+    if (!Opts.SrcEditFile.empty()) {
+      Diags.Report(diag::warn_ssaf_src_edit_file_requires_transformation);
+      Reported = true;
+    }
+    if (!Opts.TransformationReportFile.empty()) {
+      Diags.Report(
+          diag::warn_ssaf_transformation_report_file_requires_transformation);
+      Reported = true;
+    }
+  }
+
+  return Reported;
+}
+
+std::unique_ptr<SourceTransformationRunner>
+SourceTransformationRunner::create(CompilerInstance &CI, StringRef InFile) {
+  const SSAFOptions &Opts = CI.getSSAFOpts();
+  DiagnosticsEngine &Diags = CI.getDiagnostics();
+
+  if (reportOrphanFlagMisuse(Diags, Opts))
+    return nullptr;
+  if (Opts.SourceTransformation.empty())
+    return nullptr;
+
+  if (!isTransformationRegistered(Opts.SourceTransformation)) {
+    Diags.Report(diag::warn_ssaf_source_transformation_unknown_name)
+        << Opts.SourceTransformation;
+    return nullptr;
+  }
+
+  std::optional<StringRef> WPAExt =
+      bareExtension(Opts.GlobalScopeAnalysisResult);
+  std::unique_ptr<SerializationFormat> WPAFormat =
+      WPAExt && isFormatRegistered(*WPAExt) ? makeFormat(*WPAExt) : nullptr;
+  if (!WPAFormat) {
+    Diags.Report(diag::warn_ssaf_read_wpa_suite_failed)
+        << Opts.GlobalScopeAnalysisResult << "unknown serialization format";
+    return nullptr;
+  }
+  llvm::sys::sandbox::ScopedSetting Guard = llvm::sys...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/208590
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to