Author: Ziqing Luo
Date: 2026-08-29T22:04:15-07:00
New Revision: 0f3ffcd6d5f307133848b396a70d29918960edba

URL: 
https://github.com/llvm/llvm-project/commit/0f3ffcd6d5f307133848b396a70d29918960edba
DIFF: 
https://github.com/llvm/llvm-project/commit/0f3ffcd6d5f307133848b396a70d29918960edba.diff

LOG: [SSAF][SourceTransform] Add '--ssaf-link-unit-id=' for specifying link 
unit IDs (#218823)

The source-transformation pass takes WPA results as input, where
entities are named under link-unit and compilation-unit namespaces. To
associate ASTNodes with entities, the source-transformation pass needs
to know both link-unit and compilation-unit IDs. Such information is
provided by the caller.

rdar://185818153

Added: 
    

Modified: 
    clang/docs/ScalableStaticAnalysis/user-docs/SourceEditGeneration.md
    clang/include/clang/Basic/DiagnosticFrontendKinds.td
    clang/include/clang/Frontend/SSAFOptions.h
    clang/include/clang/Options/Options.td
    clang/lib/Driver/ToolChains/Clang.cpp
    
clang/lib/ScalableStaticAnalysis/Frontend/SourceTransformationFrontendAction.cpp
    clang/test/Analysis/Scalable/help.cpp
    clang/test/Analysis/Scalable/source-edit-generation/cli-errors.cpp
    clang/test/Analysis/Scalable/source-edit-generation/coexistence.cpp
    clang/test/Analysis/Scalable/source-edit-generation/downgradable-errors.cpp
    clang/test/Analysis/Scalable/source-edit-generation/happy-path.cpp
    clang/test/Analysis/Scalable/source-edit-generation/write-failure.cpp

Removed: 
    


################################################################################
diff  --git 
a/clang/docs/ScalableStaticAnalysis/user-docs/SourceEditGeneration.md 
b/clang/docs/ScalableStaticAnalysis/user-docs/SourceEditGeneration.md
index ad7d93d02fcf9..af7fc7f56aa8c 100644
--- a/clang/docs/ScalableStaticAnalysis/user-docs/SourceEditGeneration.md
+++ b/clang/docs/ScalableStaticAnalysis/user-docs/SourceEditGeneration.md
@@ -12,11 +12,12 @@ and emits two per-translation-unit artifacts:
 
 ## Driver options
 
-Four options control the pipeline; they are all both `--ssaf-…` driver
+Five options control the pipeline; they are all both `--ssaf-…` driver
 options and `cc1` options. 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.
+edit generation. The link-unit identifier must match the identifier
+of the link unit that this compilation unit was linked into.
 
 ```{eval-rst}
 .. list-table::
@@ -38,6 +39,9 @@ edit generation.
    * - ``--ssaf-compilation-unit-id=<id>``
      - Stable identifier for this translation unit (also required by
        the summary extraction).
+   * - ``--ssaf-link-unit-id=<id>``
+     - Stable identifier of the link unit this translation unit was
+       linked into.
 ```
 
 When `--ssaf-source-transformation=` is non-empty the framework wraps
@@ -54,7 +58,8 @@ $ clang -c foo.cpp \
     --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
+    --ssaf-compilation-unit-id=cu-foo \
+    --ssaf-link-unit-id=lu-foo
 $ clang-apply-replacements --remove-change-desc-files <dir-with-yaml>
 ```
 

diff  --git a/clang/include/clang/Basic/DiagnosticFrontendKinds.td 
b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
index be321ca83da12..a10f10502a702 100644
--- a/clang/include/clang/Basic/DiagnosticFrontendKinds.td
+++ b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -446,7 +446,8 @@ def warn_ssaf_source_transformation_unknown_name :
 def warn_ssaf_source_transformation_requires :
   Warning<"option '--ssaf-source-transformation=' requires "
           
"'%select{--ssaf-global-scope-analysis-result=|--ssaf-src-edit-file=|"
-          "--ssaf-transformation-report-file=|--ssaf-compilation-unit-id=}0' "
+          "--ssaf-transformation-report-file=|--ssaf-compilation-unit-id=|"
+          "--ssaf-link-unit-id=}0' "
           "to be set">,
   InGroup<ScalableStaticAnalysis>, DefaultError;
 

diff  --git a/clang/include/clang/Frontend/SSAFOptions.h 
b/clang/include/clang/Frontend/SSAFOptions.h
index 189bf3b383c46..cfdc019395d2a 100644
--- a/clang/include/clang/Frontend/SSAFOptions.h
+++ b/clang/include/clang/Frontend/SSAFOptions.h
@@ -42,6 +42,10 @@ class SSAFOptions {
   /// Controlled by: --ssaf-global-scope-analysis-result
   std::string GlobalScopeAnalysisResult;
 
+  /// Stable identifier of the link unit that this compilation unit was
+  /// linked into. Controlled by: --ssaf-link-unit-id
+  std::string LinkUnitId;
+
   /// Path of the source-edit output file produced by the source
   /// transformation.
   /// Controlled by: --ssaf-src-edit-file

diff  --git a/clang/include/clang/Options/Options.td 
b/clang/include/clang/Options/Options.td
index 5c99efc6f58b7..3b88dce9c822b 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -1021,6 +1021,15 @@ def _ssaf_global_scope_analysis_result :
     "consumed by the source transformation. The extension selects which file "
     "format to use.">,
   MarshallingInfoString<SSAFOpts<"GlobalScopeAnalysisResult">>;
+def _ssaf_link_unit_id :
+  Joined<["--"], "ssaf-link-unit-id=">,
+  MetaVarName<"<id>">,
+  Group<SSAF_Group>,
+  Visibility<[ClangOption, CC1Option]>,
+  HelpText<
+    "Stable identifier of the link unit that this compilation unit was "
+    "linked into.">,
+  MarshallingInfoString<SSAFOpts<"LinkUnitId">>;
 def _ssaf_src_edit_file :
   Joined<["--"], "ssaf-src-edit-file=">,
   MetaVarName<"<path>">,

diff  --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index b86f15918a554..072664e6040f3 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -8138,6 +8138,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction 
&JA,
   Args.AddLastArg(CmdArgs, options::OPT__ssaf_no_extract_from_system_headers);
   Args.AddLastArg(CmdArgs, options::OPT__ssaf_source_transformation);
   Args.AddLastArg(CmdArgs, options::OPT__ssaf_global_scope_analysis_result);
+  Args.AddLastArg(CmdArgs, options::OPT__ssaf_link_unit_id);
   Args.AddLastArg(CmdArgs, options::OPT__ssaf_src_edit_file);
   Args.AddLastArg(CmdArgs, options::OPT__ssaf_transformation_report_file);
 

diff  --git 
a/clang/lib/ScalableStaticAnalysis/Frontend/SourceTransformationFrontendAction.cpp
 
b/clang/lib/ScalableStaticAnalysis/Frontend/SourceTransformationFrontendAction.cpp
index 6ae7518e0ed56..4983d5e241e0f 100644
--- 
a/clang/lib/ScalableStaticAnalysis/Frontend/SourceTransformationFrontendAction.cpp
+++ 
b/clang/lib/ScalableStaticAnalysis/Frontend/SourceTransformationFrontendAction.cpp
@@ -98,6 +98,7 @@ enum SourceTransformationCompanion {
   STCompanion_EditFile,          // --ssaf-src-edit-file=
   STCompanion_ReportFile,        // --ssaf-transformation-report-file=
   STCompanion_CompilationUnitId, // --ssaf-compilation-unit-id=
+  STCompanion_LinkUnitId,        // --ssaf-link-unit-id=
 };
 
 /// Options that depend on `--ssaf-source-transformation=` being set. Values
@@ -136,6 +137,11 @@ static bool reportOrphanOptionMisuse(DiagnosticsEngine 
&Diags,
           << STCompanion_CompilationUnitId;
       Reported = true;
     }
+    if (Opts.LinkUnitId.empty()) {
+      Diags.Report(diag::warn_ssaf_source_transformation_requires)
+          << STCompanion_LinkUnitId;
+      Reported = true;
+    }
   } else {
     if (!Opts.SrcEditFile.empty()) {
       
Diags.Report(diag::warn_ssaf_option_ignored_without_source_transformation)

diff  --git a/clang/test/Analysis/Scalable/help.cpp 
b/clang/test/Analysis/Scalable/help.cpp
index 3aee63d7ceaf5..73041823d27cd 100644
--- a/clang/test/Analysis/Scalable/help.cpp
+++ b/clang/test/Analysis/Scalable/help.cpp
@@ -11,6 +11,8 @@
 // HELP-NEXT:    Path to the WPASuite file containing the whole-program 
analysis result consumed by the source transformation. The extension selects 
which file format to use.
 // HELP-NEXT:  --ssaf-include-local-entities
 // HELP-NEXT:    Include block-scope (function-local) declarations in 
extracted SSAF summaries. By default they are omitted.
+// HELP-NEXT:  --ssaf-link-unit-id=<id>
+// HELP-NEXT:    Stable identifier of the link unit that this compilation unit 
was linked into.
 // 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-no-extract-from-system-headers

diff  --git 
a/clang/test/Analysis/Scalable/source-edit-generation/cli-errors.cpp 
b/clang/test/Analysis/Scalable/source-edit-generation/cli-errors.cpp
index bc1ea22039525..2c746222363ae 100644
--- a/clang/test/Analysis/Scalable/source-edit-generation/cli-errors.cpp
+++ b/clang/test/Analysis/Scalable/source-edit-generation/cli-errors.cpp
@@ -1,15 +1,21 @@
 // CLI errors for the source-edit-generation pipeline. Every misuse of the
-// four `--ssaf-{source-transformation,global-scope-analysis-result,
-// src-edit-file,transformation-report-file}=` options emits a default-error
-// diagnostic under `-Wscalable-static-analysis-framework`. The runner
-// produces no edit/report files and the rest of the compile pipeline is
-// untouched.
+// six `--ssaf-{source-transformation,global-scope-analysis-result,
+// src-edit-file,transformation-report-file,compilation-unit-id,
+// link-unit-id}=` options emits a default-error diagnostic under
+// `-Wscalable-static-analysis-framework`. The runner produces no edit/report
+// files and the rest of the compile pipeline is untouched.
 
 // DEFINE: %{filecheck} = FileCheck %s --match-full-lines --check-prefix
 // DEFINE: %{base} = --ssaf-source-transformation=does-not-exist \
 // DEFINE:   --ssaf-global-scope-analysis-result=%S/Inputs/empty-suite.json \
 // DEFINE:   --ssaf-src-edit-file=%t/edits.yaml \
 // DEFINE:   --ssaf-transformation-report-file=%t/report.sarif \
+// DEFINE:   --ssaf-compilation-unit-id=cu \
+// DEFINE:   --ssaf-link-unit-id=lu
+// DEFINE: %{base-no-link-unit-id} = 
--ssaf-source-transformation=does-not-exist \
+// DEFINE:   --ssaf-global-scope-analysis-result=%S/Inputs/empty-suite.json \
+// DEFINE:   --ssaf-src-edit-file=%t/edits.yaml \
+// DEFINE:   --ssaf-transformation-report-file=%t/report.sarif \
 // DEFINE:   --ssaf-compilation-unit-id=cu
 
 // 
=============================================================================
@@ -33,6 +39,7 @@
 // ORPHAN-COMPANIONS-DAG: error: option '--ssaf-source-transformation=' 
requires '--ssaf-src-edit-file=' to be set 
[-Wscalable-static-analysis-framework]
 // ORPHAN-COMPANIONS-DAG: error: option '--ssaf-source-transformation=' 
requires '--ssaf-transformation-report-file=' to be set 
[-Wscalable-static-analysis-framework]
 // ORPHAN-COMPANIONS-DAG: error: option '--ssaf-source-transformation=' 
requires '--ssaf-compilation-unit-id=' to be set 
[-Wscalable-static-analysis-framework]
+// ORPHAN-COMPANIONS-DAG: error: option '--ssaf-source-transformation=' 
requires '--ssaf-link-unit-id=' to be set [-Wscalable-static-analysis-framework]
 
 // 
=============================================================================
 // 3. Reverse orphans: edit/report file set without transformation option.
@@ -48,4 +55,22 @@
 // ORPHAN-REPORT: error: option '--ssaf-transformation-report-file=' is 
ignored without '--ssaf-source-transformation=' 
[-Wscalable-static-analysis-framework]
 // RUN: not test -e %t/r.sarif
 
+// 
=============================================================================
+// 4. Missing or empty --ssaf-link-unit-id= alone (all other companions set).
+// 
=============================================================================
+
+// RUN: rm -rf %t && mkdir -p %t
+// RUN: not %clang     -c %s -o %t/test.o %{base-no-link-unit-id} 2>&1 | 
%{filecheck}=MISSING-LINK-UNIT-ID
+// RUN: not %clang_cc1    %s              %{base-no-link-unit-id} 2>&1 | 
%{filecheck}=MISSING-LINK-UNIT-ID
+// RUN: not test -e %t/edits.yaml
+// RUN: not test -e %t/report.sarif
+
+// RUN: rm -rf %t && mkdir -p %t
+// RUN: not %clang     -c %s -o %t/test.o %{base-no-link-unit-id} 
--ssaf-link-unit-id= 2>&1 | %{filecheck}=MISSING-LINK-UNIT-ID
+// RUN: not %clang_cc1    %s              %{base-no-link-unit-id} 
--ssaf-link-unit-id= 2>&1 | %{filecheck}=MISSING-LINK-UNIT-ID
+// RUN: not test -e %t/edits.yaml
+// RUN: not test -e %t/report.sarif
+
+// MISSING-LINK-UNIT-ID: error: option '--ssaf-source-transformation=' 
requires '--ssaf-link-unit-id=' to be set [-Wscalable-static-analysis-framework]
+
 void foo() {}

diff  --git 
a/clang/test/Analysis/Scalable/source-edit-generation/coexistence.cpp 
b/clang/test/Analysis/Scalable/source-edit-generation/coexistence.cpp
index f93eafa9e3ab1..89e41ef708e31 100644
--- a/clang/test/Analysis/Scalable/source-edit-generation/coexistence.cpp
+++ b/clang/test/Analysis/Scalable/source-edit-generation/coexistence.cpp
@@ -15,6 +15,7 @@
 // RUN:   --ssaf-src-edit-file=%t/edits.yaml \
 // RUN:   --ssaf-transformation-report-file=%t/report.sarif \
 // RUN:   --ssaf-compilation-unit-id=cu \
+// RUN:   --ssaf-link-unit-id=lu \
 // RUN:   -emit-obj -o %t/test.o %s
 
 // All four artifacts must be present.

diff  --git 
a/clang/test/Analysis/Scalable/source-edit-generation/downgradable-errors.cpp 
b/clang/test/Analysis/Scalable/source-edit-generation/downgradable-errors.cpp
index b2c79bc91cd51..008ef47f828dc 100644
--- 
a/clang/test/Analysis/Scalable/source-edit-generation/downgradable-errors.cpp
+++ 
b/clang/test/Analysis/Scalable/source-edit-generation/downgradable-errors.cpp
@@ -9,7 +9,8 @@
 // DEFINE:   --ssaf-global-scope-analysis-result=%S/Inputs/empty-suite.json \
 // DEFINE:   --ssaf-src-edit-file=%t/edits.yaml \
 // DEFINE:   --ssaf-transformation-report-file=%t/report.sarif \
-// DEFINE:   --ssaf-compilation-unit-id=cu
+// DEFINE:   --ssaf-compilation-unit-id=cu \
+// DEFINE:   --ssaf-link-unit-id=lu
 
 // 
=============================================================================
 // 1. -Wno-error=scalable-static-analysis-framework downgrades to a warning.

diff  --git 
a/clang/test/Analysis/Scalable/source-edit-generation/happy-path.cpp 
b/clang/test/Analysis/Scalable/source-edit-generation/happy-path.cpp
index d22c901217c31..aadb260ac11f5 100644
--- a/clang/test/Analysis/Scalable/source-edit-generation/happy-path.cpp
+++ b/clang/test/Analysis/Scalable/source-edit-generation/happy-path.cpp
@@ -14,6 +14,7 @@
 // RUN:   --ssaf-src-edit-file=%t/edits.yaml \
 // RUN:   --ssaf-transformation-report-file=%t/report.sarif \
 // RUN:   --ssaf-compilation-unit-id=cu \
+// RUN:   --ssaf-link-unit-id=lu \
 // RUN:   -emit-obj -o %t/test.o %s
 
 // RUN: FileCheck --check-prefix=EDITS --input-file=%t/edits.yaml %s

diff  --git 
a/clang/test/Analysis/Scalable/source-edit-generation/write-failure.cpp 
b/clang/test/Analysis/Scalable/source-edit-generation/write-failure.cpp
index 74ef0421045a8..f884fbc0ca343 100644
--- a/clang/test/Analysis/Scalable/source-edit-generation/write-failure.cpp
+++ b/clang/test/Analysis/Scalable/source-edit-generation/write-failure.cpp
@@ -18,6 +18,7 @@
 // RUN:   --ssaf-src-edit-file=%t/missing-dir/edits.yaml \
 // RUN:   --ssaf-transformation-report-file=%t/report.sarif \
 // RUN:   --ssaf-compilation-unit-id=cu \
+// RUN:   --ssaf-link-unit-id=lu \
 // RUN:   -emit-obj -o %t/test.o %s 2>&1 | FileCheck --check-prefix=EDIT-FAIL 
%s
 // EDIT-FAIL: warning: failed to write source edits to 
'{{.*}}/missing-dir/edits.yaml'{{.*}}[-Wscalable-static-analysis-framework]
 // RUN: test -e %t/test.o
@@ -34,6 +35,7 @@
 // RUN:   --ssaf-src-edit-file=%t/edits.yaml \
 // RUN:   --ssaf-transformation-report-file=%t/missing-dir/report.sarif \
 // RUN:   --ssaf-compilation-unit-id=cu \
+// RUN:   --ssaf-link-unit-id=lu \
 // RUN:   -emit-obj -o %t/test.o %s 2>&1 | FileCheck 
--check-prefix=REPORT-FAIL %s
 // REPORT-FAIL: warning: failed to write transformation report to 
'{{.*}}/missing-dir/report.sarif'{{.*}}[-Wscalable-static-analysis-framework]
 // RUN: test -e %t/test.o


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

Reply via email to