[clang] [llvm] Revert the clang SSAF orchestrator/driver stack (PR #232274)

Balázs Benics via cfe-commits cfe-commits at lists.llvm.org
Thu Oct 15 04:01:48 PDT 2026


https://github.com/steakhal created https://github.com/llvm/llvm-project/pull/232274

This reverts the SSAF orchestrator/driver stack landed on 2026-10-13/14, as requested by multiple maintainers in #231999. The changes broke upstream and downstream builders (red for >1 day) and violate LLVM layering rules, with no straightforward forward fix in a reasonable timeframe.

Reasons for reverting

- GNU Make made a mandatory dependency for lit tests (previously optional per the GettingStarted requirements (https://llvm.org/docs/GettingStarted.html#software)) — broke all macOS builders, which don't ship GNU Make.
- New layering dependencies from clang/ onto clang-tools-extra and libc++ — clang/test gained a dep on clang-apply-replacements; tests assume libc++ exists, which some targets (e.g. Solaris) don't provide.
- Windows path length — a tool name pushed build paths past MAX_PATH (260).

Commits reverted (newest first)

- 6abd4709cff4 — [gn] port clang-ssaf-driver (#232118)
- 1c563eafd44e — [gn] port clang-ssaf-merge-conflict-report (#232115)
- 8a96bd506570 — [gn] port clang-ssaf-merge-transformation-report (#232114)
- 73109fa8894a — [gn] port clang-ssaf-orchestrator-make (#232113)
- a8797d63e97f — Clang ssaf driver 4 (#231999)
- ba6d822f43f0 — Merge transformation reports per link unit (#231957)
- 3e93f25d161f — Put clang-ssaf-orchestrator-make in LLVM_BINARY_DIR (#231930)
- f32ac72b4f1e — Add clang-ssaf-merge-conflict-report (#231731)
- 07195e29cdba — Add clang-ssaf-merge-transformation-report (#231664)
- 9d4c617fc399 — Interpose ld.lld (#231720)
- 9d9ad8a3dbc5 — Clang ssaf orchestrator fixes (#231678)
- 4d2bc2c3a7a4 — Interpose ar (#231618)
- 2250a9708e9e — Add a transformation pass (#231601)
- dbde204202ad — Add clang-ssaf-orchestrator-make (#231583)

Complaints referenced

- #231583 — clang tests failing (Kewen12): #231583#issuecomment-6153318133
- #231583 — breaks Solaris, libc++ not always present (rorth): #231583#issuecomment-6153866977
- #231583 — GNU Make now required, broke macOS builders, RFC expected (petrhosek): #231583#issuecomment-6182524527
- #231583 — 3 builders still failing, fix or revert (kovdan01): #231583#issuecomment-6186432153
- #231664 — Windows MAX_PATH exceeded by tool name (yueshe): #231664#issuecomment-6175672277
- #231678 — fix incomplete, 14 ssaf tests still failing (Kewen12): #231678#issuecomment-6157991885
- #231720 — still failing after fix (dyung): #231720#issuecomment-6175099823
- #231720 — still failing downstream, revert the stack (Prabhuk): #231720#issuecomment-6179425292
- #231999 — clang/ should not depend on clang-tools-extra (nico): #231999#discussion_r4277237257
- #231999 — unreviewed stack, revert all (nikic): #231999#issuecomment-6187057955
- #231999 — second reverting, layering violations (petrhosek): #231999#issuecomment-6187297359

Build-bot failures referenced

- Builder 10 (clang tests): https://lab.llvm.org/buildbot/#/builders/10/builds/37473
- Solaris/amd64 (staging 120): https://lab.llvm.org/staging/#/builders/120/builds/22263
- intel-sycl-gpu (225): https://lab.llvm.org/buildbot/#/builders/225/builds/21732
- llvm-clang-x86_64-sie-ubuntu-fast (144): https://lab.llvm.org/buildbot/#/builders/144/builds/68697
- llvm-clang-ubuntu-x-aarch64-pac-ret (229): https://lab.llvm.org/buildbot/#/builders/229
- llvm-clang-ubuntu-x-aarch64-pauthtest (227): https://lab.llvm.org/buildbot/#/builders/227
- Builder 10 after first fix (#231678): https://lab.llvm.org/buildbot/#/builders/10/builds/37490
- llvm-clang-x86_64-sie-ubuntu-fast after ld.lld fix (#231720): https://lab.llvm.org/buildbot/#/builders/144/builds/68731

Authored-By: claude

>From b20395abcf43c51eb6f9a00eca84c6f01d3132e1 Mon Sep 17 00:00:00 2001
From: Balazs Benics <benicsbalazs at gmail.com>
Date: Thu, 15 Oct 2026 11:53:29 +0100
Subject: [PATCH 01/14] Revert "[gn] port a8797d63e97f (clang-ssaf-driver)
 (#232118)"

This reverts commit 6abd4709cff4728192c95890a83196cc073c4204.
---
 llvm/utils/gn/secondary/clang/test/BUILD.gn   |  1 -
 .../clang/tools/clang-ssaf-driver/BUILD.gn    | 41 -------------------
 2 files changed, 42 deletions(-)
 delete mode 100644 llvm/utils/gn/secondary/clang/tools/clang-ssaf-driver/BUILD.gn

diff --git a/llvm/utils/gn/secondary/clang/test/BUILD.gn b/llvm/utils/gn/secondary/clang/test/BUILD.gn
index 63e0413e60abe..ebf98cca873a6 100644
--- a/llvm/utils/gn/secondary/clang/test/BUILD.gn
+++ b/llvm/utils/gn/secondary/clang/test/BUILD.gn
@@ -165,7 +165,6 @@ group("test") {
     "//clang/tools/clang-repl",
     "//clang/tools/clang-scan-deps",
     "//clang/tools/clang-ssaf-analyzer",
-    "//clang/tools/clang-ssaf-driver",
     "//clang/tools/clang-ssaf-format",
     "//clang/tools/clang-ssaf-linker",
     "//clang/tools/clang-ssaf-merge-conflict-report",
diff --git a/llvm/utils/gn/secondary/clang/tools/clang-ssaf-driver/BUILD.gn b/llvm/utils/gn/secondary/clang/tools/clang-ssaf-driver/BUILD.gn
deleted file mode 100644
index 24819c607fa1f..0000000000000
--- a/llvm/utils/gn/secondary/clang/tools/clang-ssaf-driver/BUILD.gn
+++ /dev/null
@@ -1,41 +0,0 @@
-import("//llvm/utils/gn/build/write_cmake_config.gni")
-import("//llvm/version.gni")
-
-# Python tool. Copies its scripts into the build dir, like scan-build.
-group("clang-ssaf-driver") {
-  deps = [
-    ":bin",
-    ":lib",
-    ":version",
-
-    # The driver runs the orchestrator installed beside it.
-    "//clang/tools/clang-ssaf-orchestrator-make",
-  ]
-}
-
-copy("bin") {
-  sources = [ "bin/clang-ssaf-driver" ]
-  outputs = [ "$root_build_dir/bin/{{source_file_part}}" ]
-}
-
-copy("lib") {
-  sources = [
-    "lib/clang_ssaf_driver/__init__.py",
-    "lib/clang_ssaf_driver/apply.py",
-    "lib/clang_ssaf_driver/driver.py",
-    "lib/clang_ssaf_driver/logging_diagnostics.py",
-    "lib/clang_ssaf_driver/make_orchestrator.py",
-    "lib/clang_ssaf_driver/options.py",
-    "lib/clang_ssaf_driver/patch.py",
-    "lib/clang_ssaf_driver/report.py",
-    "lib/clang_ssaf_driver/source_edits.py",
-    "lib/clang_ssaf_driver/transformations.py",
-  ]
-  outputs = [ "$root_build_dir/lib/clang_ssaf_driver/{{source_file_part}}" ]
-}
-
-write_cmake_config("version") {
-  input = "lib/clang_ssaf_driver/version.py.in"
-  output = "$root_build_dir/lib/clang_ssaf_driver/version.py"
-  values = [ "CLANG_VERSION=$llvm_version" ]
-}

>From d6ab875542fca710f92c56ea7cc1abc84ca3f052 Mon Sep 17 00:00:00 2001
From: Balazs Benics <benicsbalazs at gmail.com>
Date: Thu, 15 Oct 2026 11:53:29 +0100
Subject: [PATCH 02/14] Revert "[gn] port f32ac72b4f1e
 (clang-ssaf-merge-conflict-report) (#232115)"

This reverts commit 1c563eafd44e93dd222ca45d010c54ddb331c44e.
---
 llvm/utils/gn/secondary/clang/test/BUILD.gn               | 1 -
 .../clang/tools/clang-ssaf-merge-conflict-report/BUILD.gn | 8 --------
 2 files changed, 9 deletions(-)
 delete mode 100644 llvm/utils/gn/secondary/clang/tools/clang-ssaf-merge-conflict-report/BUILD.gn

diff --git a/llvm/utils/gn/secondary/clang/test/BUILD.gn b/llvm/utils/gn/secondary/clang/test/BUILD.gn
index ebf98cca873a6..07a3a827f9e26 100644
--- a/llvm/utils/gn/secondary/clang/test/BUILD.gn
+++ b/llvm/utils/gn/secondary/clang/test/BUILD.gn
@@ -167,7 +167,6 @@ group("test") {
     "//clang/tools/clang-ssaf-analyzer",
     "//clang/tools/clang-ssaf-format",
     "//clang/tools/clang-ssaf-linker",
-    "//clang/tools/clang-ssaf-merge-conflict-report",
     "//clang/tools/clang-ssaf-merge-transformation-report",
     "//clang/tools/clang-ssaf-orchestrator-make",
     "//clang/tools/clang-ssaf-src-edit-merge",
diff --git a/llvm/utils/gn/secondary/clang/tools/clang-ssaf-merge-conflict-report/BUILD.gn b/llvm/utils/gn/secondary/clang/tools/clang-ssaf-merge-conflict-report/BUILD.gn
deleted file mode 100644
index a8d6adc180492..0000000000000
--- a/llvm/utils/gn/secondary/clang/tools/clang-ssaf-merge-conflict-report/BUILD.gn
+++ /dev/null
@@ -1,8 +0,0 @@
-executable("clang-ssaf-merge-conflict-report") {
-  configs += [ "//llvm/utils/gn/build:clang_code" ]
-  deps = [
-    "//clang/lib/ScalableStaticAnalysis/Tool",
-    "//llvm/lib/Support",
-  ]
-  sources = [ "MergeConflictReport.cpp" ]
-}

>From 8e934c752ce29987e9b44bd454b39618f8a749e4 Mon Sep 17 00:00:00 2001
From: Balazs Benics <benicsbalazs at gmail.com>
Date: Thu, 15 Oct 2026 11:53:29 +0100
Subject: [PATCH 03/14] Revert "[gn] port 07195e29cdba
 (clang-ssaf-merge-transformation-report) (#232114)"

This reverts commit 8a96bd50657089675820ae1e3d32a5d4a48f3eaa.
---
 llvm/utils/gn/secondary/clang/test/BUILD.gn               | 1 -
 .../tools/clang-ssaf-merge-transformation-report/BUILD.gn | 8 --------
 2 files changed, 9 deletions(-)
 delete mode 100644 llvm/utils/gn/secondary/clang/tools/clang-ssaf-merge-transformation-report/BUILD.gn

diff --git a/llvm/utils/gn/secondary/clang/test/BUILD.gn b/llvm/utils/gn/secondary/clang/test/BUILD.gn
index 07a3a827f9e26..370c93f043f62 100644
--- a/llvm/utils/gn/secondary/clang/test/BUILD.gn
+++ b/llvm/utils/gn/secondary/clang/test/BUILD.gn
@@ -167,7 +167,6 @@ group("test") {
     "//clang/tools/clang-ssaf-analyzer",
     "//clang/tools/clang-ssaf-format",
     "//clang/tools/clang-ssaf-linker",
-    "//clang/tools/clang-ssaf-merge-transformation-report",
     "//clang/tools/clang-ssaf-orchestrator-make",
     "//clang/tools/clang-ssaf-src-edit-merge",
     "//clang/tools/clang-sycl-linker",
diff --git a/llvm/utils/gn/secondary/clang/tools/clang-ssaf-merge-transformation-report/BUILD.gn b/llvm/utils/gn/secondary/clang/tools/clang-ssaf-merge-transformation-report/BUILD.gn
deleted file mode 100644
index efc26d39c1be8..0000000000000
--- a/llvm/utils/gn/secondary/clang/tools/clang-ssaf-merge-transformation-report/BUILD.gn
+++ /dev/null
@@ -1,8 +0,0 @@
-executable("clang-ssaf-merge-transformation-report") {
-  configs += [ "//llvm/utils/gn/build:clang_code" ]
-  deps = [
-    "//clang/lib/ScalableStaticAnalysis/Tool",
-    "//llvm/lib/Support",
-  ]
-  sources = [ "MergeTransformationReport.cpp" ]
-}

>From c94e203f058d19e29a09dd82b1be629d9ef961b2 Mon Sep 17 00:00:00 2001
From: Balazs Benics <benicsbalazs at gmail.com>
Date: Thu, 15 Oct 2026 11:53:29 +0100
Subject: [PATCH 04/14] Revert "[gn] port dbde204202ad
 (clang-ssaf-orchestrator-make) (#232113)"

This reverts commit 73109fa8894a058f2687389df6356a9e062d66eb.
---
 llvm/utils/gn/secondary/clang/test/BUILD.gn   |  1 -
 .../clang-ssaf-orchestrator-make/BUILD.gn     | 64 -------------------
 2 files changed, 65 deletions(-)
 delete mode 100644 llvm/utils/gn/secondary/clang/tools/clang-ssaf-orchestrator-make/BUILD.gn

diff --git a/llvm/utils/gn/secondary/clang/test/BUILD.gn b/llvm/utils/gn/secondary/clang/test/BUILD.gn
index 370c93f043f62..8448649755187 100644
--- a/llvm/utils/gn/secondary/clang/test/BUILD.gn
+++ b/llvm/utils/gn/secondary/clang/test/BUILD.gn
@@ -167,7 +167,6 @@ group("test") {
     "//clang/tools/clang-ssaf-analyzer",
     "//clang/tools/clang-ssaf-format",
     "//clang/tools/clang-ssaf-linker",
-    "//clang/tools/clang-ssaf-orchestrator-make",
     "//clang/tools/clang-ssaf-src-edit-merge",
     "//clang/tools/clang-sycl-linker",
     "//clang/tools/diagtool",
diff --git a/llvm/utils/gn/secondary/clang/tools/clang-ssaf-orchestrator-make/BUILD.gn b/llvm/utils/gn/secondary/clang/tools/clang-ssaf-orchestrator-make/BUILD.gn
deleted file mode 100644
index a2a32d747f010..0000000000000
--- a/llvm/utils/gn/secondary/clang/tools/clang-ssaf-orchestrator-make/BUILD.gn
+++ /dev/null
@@ -1,64 +0,0 @@
-import("//llvm/utils/gn/build/write_cmake_config.gni")
-import("//llvm/version.gni")
-
-# Python tool. Copies its scripts into the build dir, like scan-build.
-group("clang-ssaf-orchestrator-make") {
-  deps = [
-    ":bin",
-    ":lib",
-    ":shim",
-    ":shims",
-    ":version",
-  ]
-}
-
-copy("bin") {
-  sources = [ "bin/clang-ssaf-orchestrator-make" ]
-  outputs = [ "$root_build_dir/bin/{{source_file_part}}" ]
-}
-
-copy("lib") {
-  sources = [
-    "lib/clang_ssaf_orchestrator_make/__init__.py",
-    "lib/clang_ssaf_orchestrator_make/build_graph.py",
-    "lib/clang_ssaf_orchestrator_make/config.py",
-    "lib/clang_ssaf_orchestrator_make/config_orchestrator.py",
-    "lib/clang_ssaf_orchestrator_make/config_shims.py",
-    "lib/clang_ssaf_orchestrator_make/failure_logs.py",
-    "lib/clang_ssaf_orchestrator_make/interposition.py",
-    "lib/clang_ssaf_orchestrator_make/logging_diagnostics.py",
-    "lib/clang_ssaf_orchestrator_make/options.py",
-    "lib/clang_ssaf_orchestrator_make/orchestrator.py",
-    "lib/clang_ssaf_orchestrator_make/ssaf_artifact_repository.py",
-    "lib/clang_ssaf_orchestrator_make/utils.py",
-  ]
-  outputs = [
-    "$root_build_dir/lib/clang_ssaf_orchestrator_make/{{source_file_part}}",
-  ]
-}
-
-write_cmake_config("version") {
-  input = "lib/clang_ssaf_orchestrator_make/version.py.in"
-  output = "$root_build_dir/lib/clang_ssaf_orchestrator_make/version.py"
-  values = [ "CLANG_VERSION=$llvm_version" ]
-}
-
-copy("shims") {
-  sources = [
-    "lib/clang_ssaf_orchestrator_make/shims/__init__.py",
-    "lib/clang_ssaf_orchestrator_make/shims/ar.py",
-    "lib/clang_ssaf_orchestrator_make/shims/clang.py",
-    "lib/clang_ssaf_orchestrator_make/shims/commands.py",
-    "lib/clang_ssaf_orchestrator_make/shims/driver_jobs.py",
-    "lib/clang_ssaf_orchestrator_make/shims/ld.py",
-    "lib/clang_ssaf_orchestrator_make/shims/run.py",
-    "lib/clang_ssaf_orchestrator_make/shims/shim.py",
-  ]
-  outputs = [ "$root_build_dir/lib/clang_ssaf_orchestrator_make/shims/{{source_file_part}}" ]
-}
-
-copy("shim") {
-  sources = [ "shims/shim" ]
-  outputs =
-      [ "$root_build_dir/libexec/ssaf-orchestrator-shims/{{source_file_part}}" ]
-}

>From 90851c51dcb0cdb9965c1e0d591167341e911021 Mon Sep 17 00:00:00 2001
From: Balazs Benics <benicsbalazs at gmail.com>
Date: Thu, 15 Oct 2026 11:53:30 +0100
Subject: [PATCH 05/14] Revert "Clang ssaf driver 4 (#231999)"

This reverts commit a8797d63e97f4eba871c986a2c487da5db78d358.
---
 .../user-docs/Driver.md                       | 108 --------
 .../apply-clang-apply-replacements.test       |  38 ---
 .../Analysis/Scalable/ssaf-driver/apply.test  |  86 -------
 .../ssaf-driver/archive-conflict.test         |  56 -----
 .../Scalable/ssaf-driver/bad-args.test        |  21 --
 .../Scalable/ssaf-driver/build-failure.test   |  17 --
 .../Scalable/ssaf-driver/conflicts.test       |  58 -----
 .../Analysis/Scalable/ssaf-driver/help.test   |  28 ---
 .../Scalable/ssaf-driver/lit.local.cfg        |  53 ----
 .../Analysis/Scalable/ssaf-driver/report.test |  48 ----
 .../Scalable/ssaf-driver/transformation.test  |  72 ------
 .../Scalable/ssaf-driver/unittests.test       |   8 -
 clang/test/CMakeLists.txt                     |   4 -
 clang/tools/CMakeLists.txt                    |   1 -
 clang/tools/clang-ssaf-driver/CMakeLists.txt  |  75 ------
 clang/tools/clang-ssaf-driver/README.md       |  35 ---
 .../clang-ssaf-driver/bin/clang-ssaf-driver   |  15 --
 .../lib/clang_ssaf_driver/__init__.py         |  10 -
 .../lib/clang_ssaf_driver/apply.py            |  81 ------
 .../lib/clang_ssaf_driver/driver.py           | 105 --------
 .../clang_ssaf_driver/logging_diagnostics.py  |  31 ---
 .../clang_ssaf_driver/make_orchestrator.py    |  64 -----
 .../lib/clang_ssaf_driver/options.py          | 159 ------------
 .../lib/clang_ssaf_driver/patch.py            | 129 ----------
 .../lib/clang_ssaf_driver/report.py           | 136 ----------
 .../lib/clang_ssaf_driver/source_edits.py     | 186 --------------
 .../lib/clang_ssaf_driver/transformations.py  |  18 --
 .../lib/clang_ssaf_driver/version.py.in       |   5 -
 .../tools/clang-ssaf-driver/tests/__init__.py |   3 -
 .../clang-ssaf-driver/tests/test_apply.py     | 118 ---------
 .../clang-ssaf-driver/tests/test_driver.py    | 124 ---------
 .../tests/test_make_orchestrator.py           | 137 ----------
 .../clang-ssaf-driver/tests/test_options.py   | 107 --------
 .../clang-ssaf-driver/tests/test_patch.py     | 237 ------------------
 .../clang-ssaf-driver/tests/test_report.py    | 204 ---------------
 .../tests/test_source_edits.py                | 171 -------------
 36 files changed, 2748 deletions(-)
 delete mode 100644 clang/docs/ScalableStaticAnalysis/user-docs/Driver.md
 delete mode 100644 clang/test/Analysis/Scalable/ssaf-driver/apply-clang-apply-replacements.test
 delete mode 100644 clang/test/Analysis/Scalable/ssaf-driver/apply.test
 delete mode 100644 clang/test/Analysis/Scalable/ssaf-driver/archive-conflict.test
 delete mode 100644 clang/test/Analysis/Scalable/ssaf-driver/bad-args.test
 delete mode 100644 clang/test/Analysis/Scalable/ssaf-driver/build-failure.test
 delete mode 100644 clang/test/Analysis/Scalable/ssaf-driver/conflicts.test
 delete mode 100644 clang/test/Analysis/Scalable/ssaf-driver/help.test
 delete mode 100644 clang/test/Analysis/Scalable/ssaf-driver/lit.local.cfg
 delete mode 100644 clang/test/Analysis/Scalable/ssaf-driver/report.test
 delete mode 100644 clang/test/Analysis/Scalable/ssaf-driver/transformation.test
 delete mode 100644 clang/test/Analysis/Scalable/ssaf-driver/unittests.test
 delete mode 100644 clang/tools/clang-ssaf-driver/CMakeLists.txt
 delete mode 100644 clang/tools/clang-ssaf-driver/README.md
 delete mode 100755 clang/tools/clang-ssaf-driver/bin/clang-ssaf-driver
 delete mode 100644 clang/tools/clang-ssaf-driver/lib/clang_ssaf_driver/__init__.py
 delete mode 100644 clang/tools/clang-ssaf-driver/lib/clang_ssaf_driver/apply.py
 delete mode 100644 clang/tools/clang-ssaf-driver/lib/clang_ssaf_driver/driver.py
 delete mode 100644 clang/tools/clang-ssaf-driver/lib/clang_ssaf_driver/logging_diagnostics.py
 delete mode 100644 clang/tools/clang-ssaf-driver/lib/clang_ssaf_driver/make_orchestrator.py
 delete mode 100644 clang/tools/clang-ssaf-driver/lib/clang_ssaf_driver/options.py
 delete mode 100644 clang/tools/clang-ssaf-driver/lib/clang_ssaf_driver/patch.py
 delete mode 100644 clang/tools/clang-ssaf-driver/lib/clang_ssaf_driver/report.py
 delete mode 100644 clang/tools/clang-ssaf-driver/lib/clang_ssaf_driver/source_edits.py
 delete mode 100644 clang/tools/clang-ssaf-driver/lib/clang_ssaf_driver/transformations.py
 delete mode 100644 clang/tools/clang-ssaf-driver/lib/clang_ssaf_driver/version.py.in
 delete mode 100644 clang/tools/clang-ssaf-driver/tests/__init__.py
 delete mode 100644 clang/tools/clang-ssaf-driver/tests/test_apply.py
 delete mode 100644 clang/tools/clang-ssaf-driver/tests/test_driver.py
 delete mode 100644 clang/tools/clang-ssaf-driver/tests/test_make_orchestrator.py
 delete mode 100644 clang/tools/clang-ssaf-driver/tests/test_options.py
 delete mode 100644 clang/tools/clang-ssaf-driver/tests/test_patch.py
 delete mode 100644 clang/tools/clang-ssaf-driver/tests/test_report.py
 delete mode 100644 clang/tools/clang-ssaf-driver/tests/test_source_edits.py

diff --git a/clang/docs/ScalableStaticAnalysis/user-docs/Driver.md b/clang/docs/ScalableStaticAnalysis/user-docs/Driver.md
deleted file mode 100644
index 86c892b3497c5..0000000000000
--- a/clang/docs/ScalableStaticAnalysis/user-docs/Driver.md
+++ /dev/null
@@ -1,108 +0,0 @@
-# Transforming a Project
-
-`clang-ssaf-driver` runs a source transformation over a whole project as it
-builds, and presents what it found: the source edits as a patch, the
-transformation report as diagnostics and as SARIF, and, if asked, the edits
-applied to the sources. It drives projects built with make through
-`clang-ssaf-orchestrator-make`, whose requirements it shares; see
-{doc}`MakeProjects`.
-
-## Usage
-
-Run it from the project root, with its options before the build command:
-
-```console
-$ clang-ssaf-driver --transformation=cpp-bounded-buffers -- make -j8
-```
-
-The driver knows which summaries and which whole-program analysis each
-transformation needs:
-
-```{eval-rst}
-.. list-table::
-   :header-rows: 1
-
-   * - Transformation
-     - What it does
-   * - ``cpp-bounded-buffers``
-     - Rewrites the raw pointers and arrays that need bounds into
-       ``bounded_ptr`` and ``bounded_array``.
-```
-
-## Results
-
-A run writes two files into the output directory:
-
-- `<transformation>.patch`, the source edits as one unified diff whose paths
-  are relative to the project root, for `patch -p1` from there;
-- `<transformation>.sarif`, the transformation report: the findings of every
-  translation unit, and every conflict between source edits.
-
-Both are named on stdout, after the orchestrator's own results:
-
-```text
-patch: /work/proj/ssaf-output/cpp-bounded-buffers.patch
-report: /work/proj/ssaf-output/cpp-bounded-buffers.sarif
-```
-
-The report is also printed on stderr, one line per finding the way a compiler
-prints a diagnostic, and closes with a count for each rule:
-
-```text
-src/shared.h:1:8: note: declarator of a multi-declarator group is not yet rewritten [cpp-bounded-buffers-skipped]
-src/shared.h:3:1: error: 2 overlapping replacement(s) at file:///work/proj/src/shared.h byte 20 were dropped; resolve manually. [clang-reforge-replacement-conflict]
-src/shared.h:5:1: note: candidate edit: "bounded_ptr<int> "
-src/shared.h:3:1: note: candidate edit: "bounded_ptr<long> "
-1 clang-reforge-replacement-conflict, 1 cpp-bounded-buffers-skipped reported
-```
-
-A finding is a place the transformation did not rewrite. A conflict is a place
-where translation units asked for different edits; none of them is made, and
-an edit that overlaps a conflict is left out of the patch too, with a warning.
-Both are left to be done by hand, and neither changes the exit status.
-
-## Applying the edits
-
-`--apply` also rewrites the sources, using `clang-apply-replacements` from
-clang-tools-extra. It is looked for on `PATH`, or named with
-`--clang-apply-replacements=<path>`, before anything is built. The patch is
-written either way, and the run fails if the sources do not end up the way the
-patch shows them.
-
-## Options
-
-```{eval-rst}
-.. list-table::
-   :header-rows: 1
-
-   * - Option
-     - Purpose
-   * - ``--transformation=<name>``
-     - The transformation to run. Required.
-   * - ``-o``, ``--output-dir=<dir>``
-     - Where the results and the SSAF artifacts go. Defaults to
-       ``ssaf-output``, and is the orchestrator's output directory.
-   * - ``--apply``
-     - Also apply the source edits.
-   * - ``--clang-apply-replacements=<path>``
-     - Path to ``clang-apply-replacements``. Defaults to the name on
-       ``PATH``.
-   * - ``--ssaf-clang=<path>``, ``--ssaf-linker=<path>``,
-       ``--ssaf-analyzer=<path>``, ``--ssaf-src-edit-merge=<path>``,
-       ``--ssaf-merge-transformation-report=<path>``,
-       ``--ssaf-merge-conflict-report=<path>``,
-       ``--ssaf-extra-clang-arg=<arg>``, ``-k``, ``-v``
-     - Passed to the orchestrator; see {doc}`MakeProjects`.
-   * - ``--version``
-     - The clang version this was built from.
-```
-
-## What is not supported
-
-**Edits outside the project root.** A file the project does not contain is
-left out of the patch and is not applied to; the driver names it in a warning.
-
-**Compilations that run in another directory**, as in recursive make or
-`make -C`. A source edit names its file relative to where its compilation ran,
-and is merged where the link runs, so such an edit can be lost or land on the
-wrong file. Run the build from the project root.
diff --git a/clang/test/Analysis/Scalable/ssaf-driver/apply-clang-apply-replacements.test b/clang/test/Analysis/Scalable/ssaf-driver/apply-clang-apply-replacements.test
deleted file mode 100644
index 0c1d73b67add7..0000000000000
--- a/clang/test/Analysis/Scalable/ssaf-driver/apply-clang-apply-replacements.test
+++ /dev/null
@@ -1,38 +0,0 @@
-# REQUIRES: ssaf-driver-make-build, clang-apply-replacements
-# RUN: rm -rf %t && split-file %s %t
-# RUN: mkdir -p %t/build
-
-# clang-apply-replacements writes what the patch shows; the run checks it.
-# RUN: cd %t
-# RUN: %clang-ssaf-driver --transformation=cpp-bounded-buffers --apply \
-# RUN:     --ssaf-clang=%ssaf-driver-clang -o %t/out -- make \
-# RUN:   | FileCheck %s --check-prefix=STDOUT
-# STDOUT: patch: {{[^ ]*}}/out/cpp-bounded-buffers.patch
-# RUN: FileCheck %s --check-prefix=PARSE --input-file=%t/src/parse.cpp
-# PARSE: int total(bounded_ptr<int> data, int n) {
-# RUN: FileCheck %s --check-prefix=MAIN --input-file=%t/src/main.cpp
-# MAIN: int total(bounded_ptr<int> data, int n);
-# MAIN: bounded_array<int, 4> values = {1, 2, 3, 4};
-
-#--- Makefile
-CXX = clang++
-all: build/prg
-build/%.o: src/%.cpp
-	$(CXX) -c -o $@ $<
-build/prg: build/main.o build/parse.o
-	$(CXX) -o $@ build/main.o build/parse.o
-
-#--- src/parse.cpp
-int total(int *data, int n) {
-  int t = 0;
-  for (int i = 0; i < n; ++i)
-    t += data[i];
-  return t;
-}
-
-#--- src/main.cpp
-int total(int *data, int n);
-int main() {
-  int values[4] = {1, 2, 3, 4};
-  return total(values, 4);
-}
diff --git a/clang/test/Analysis/Scalable/ssaf-driver/apply.test b/clang/test/Analysis/Scalable/ssaf-driver/apply.test
deleted file mode 100644
index 523df03914162..0000000000000
--- a/clang/test/Analysis/Scalable/ssaf-driver/apply.test
+++ /dev/null
@@ -1,86 +0,0 @@
-# REQUIRES: ssaf-driver-make-build
-# RUN: rm -rf %t && split-file %s %t
-# RUN: mkdir -p %t/build
-# RUN: chmod +x %t/lazy-tool %t/recording-tool
-# RUN: cd %t
-
-# A tool that leaves the sources as they were fails the run, because the
-# patch would not show what --apply did.
-# RUN: not %clang-ssaf-driver --transformation=cpp-bounded-buffers --apply \
-# RUN:     --clang-apply-replacements=%t/lazy-tool \
-# RUN:     --ssaf-clang=%ssaf-driver-clang -o %t/out -- make 2>&1 > /dev/null \
-# RUN:   | FileCheck %s --check-prefix=LAZY
-# LAZY:      clang-ssaf-driver: error: clang-apply-replacements did not write what the patch shows:
-# LAZY-NEXT:   src/main.cpp
-# LAZY-NEXT:   src/parse.cpp
-
-# The tool is given a directory holding the edits the patch shows, named by
-# absolute path, and nothing else.
-# RUN: %clang-ssaf-driver --transformation=cpp-bounded-buffers --apply \
-# RUN:     --clang-apply-replacements=%t/recording-tool \
-# RUN:     --ssaf-clang=%ssaf-driver-clang -o %t/out -- make \
-# RUN:   | FileCheck %s --check-prefix=STDOUT
-# STDOUT: patch: {{[^ ]*}}/out/cpp-bounded-buffers.patch
-# STDOUT: report: {{[^ ]*}}/out/cpp-bounded-buffers.sarif
-# RUN: FileCheck %s --check-prefix=ARGS -DOUT=%t/out --input-file=%t/tool.args
-# ARGS: [[OUT]]/apply
-# RUN: FileCheck %s --check-prefix=LISTING --match-full-lines \
-# RUN:   --input-file=%t/tool.listing
-# LISTING:     source-edits.yaml
-# LISTING-NOT: {{.}}
-# RUN: FileCheck %s --check-prefix=EDITS --input-file=%t/tool.yaml
-# EDITS:     FilePath:        "{{/.*}}/src/main.cpp"
-# EDITS:     FilePath:        "{{/.*}}/src/parse.cpp"
-# EDITS:     ReplacementText: "bounded_ptr<int> "
-
-# RUN: FileCheck %s --check-prefix=APPLIED --input-file=%t/src/parse.cpp
-# APPLIED: int total(bounded_ptr<int> data, int n) {
-
-#--- Makefile
-CXX = clang++
-all: build/prg
-build/%.o: src/%.cpp
-	$(CXX) -c -o $@ $<
-build/prg: build/main.o build/parse.o
-	$(CXX) -o $@ build/main.o build/parse.o
-
-#--- src/parse.cpp
-int total(int *data, int n) {
-  int t = 0;
-  for (int i = 0; i < n; ++i)
-    t += data[i];
-  return t;
-}
-
-#--- src/main.cpp
-int total(int *data, int n);
-int main() {
-  int values[4] = {1, 2, 3, 4};
-  return total(values, 4);
-}
-
-#--- expected/src/parse.cpp
-int total(bounded_ptr<int> data, int n) {
-  int t = 0;
-  for (int i = 0; i < n; ++i)
-    t += data[i];
-  return t;
-}
-
-#--- expected/src/main.cpp
-int total(bounded_ptr<int> data, int n);
-int main() {
-  bounded_array<int, 4> values = {1, 2, 3, 4};
-  return total(values, 4);
-}
-
-#--- recording-tool
-#!/bin/sh
-here=$(dirname "$0")
-echo "$@" > "$here/tool.args"
-ls "$1" > "$here/tool.listing"
-cp "$1/source-edits.yaml" "$here/tool.yaml"
-cp "$here/expected/src/main.cpp" "$here/expected/src/parse.cpp" "$here/src/"
-
-#--- lazy-tool
-#!/bin/sh
diff --git a/clang/test/Analysis/Scalable/ssaf-driver/archive-conflict.test b/clang/test/Analysis/Scalable/ssaf-driver/archive-conflict.test
deleted file mode 100644
index 4ecb37c0a20b9..0000000000000
--- a/clang/test/Analysis/Scalable/ssaf-driver/archive-conflict.test
+++ /dev/null
@@ -1,56 +0,0 @@
-# REQUIRES: ssaf-driver-make-build
-# RUN: rm -rf %t && split-file %s %t
-# RUN: mkdir -p %t/build
-
-# The two halves of the archive disagree on the header, so the archive's merge
-# drops both of their edits to it. main.cpp asks for one of them again, and
-# the link's own merge keeps it; the driver leaves it out, because it
-# overlaps a reported conflict.
-# RUN: cd %t
-# RUN: %clang-ssaf-driver --transformation=cpp-bounded-buffers \
-# RUN:     --ssaf-clang=%ssaf-driver-clang -o %t/out -- make \
-# RUN:     2> %t/stderr.txt > /dev/null
-# RUN: FileCheck %s --check-prefix=STDERR --input-file=%t/stderr.txt
-# STDERR: src/shared.h:3:1: error: 2 overlapping replacement(s) at {{.*}} were dropped; resolve manually. [clang-reforge-replacement-conflict]
-# STDERR: clang-ssaf-driver: warning: left out 1 edit(s) to src/shared.h that overlap a reported conflict
-
-# RUN: FileCheck %s --check-prefix=PATCH \
-# RUN:   --input-file=%t/out/cpp-bounded-buffers.patch
-# PATCH:     +++ b/src/a.cpp
-# PATCH:     +bounded_ptr<int> g;
-# PATCH-NOT: shared.h
-
-#--- Makefile
-CXX = clang++
-all: build/prg
-build/%.o: src/%.cpp src/shared.h
-	$(CXX) -c -o $@ $<
-build/libparts.a: build/a.o build/b.o
-	ar rcs $@ build/a.o build/b.o
-build/prg: build/main.o build/libparts.a
-	$(CXX) -o $@ build/main.o build/libparts.a
-
-#--- src/shared.h
-extern
-#if USE_LONG
-long
-#else
-int
-#endif
-*g;
-
-#--- src/a.cpp
-#include "shared.h"
-int *g;
-int a() { return g[5]; }
-
-#--- src/b.cpp
-#define USE_LONG 1
-#include "shared.h"
-long b() { return g[7]; }
-
-#--- src/main.cpp
-#include "shared.h"
-int a();
-long b();
-int main() { return a() + (int)b(); }
diff --git a/clang/test/Analysis/Scalable/ssaf-driver/bad-args.test b/clang/test/Analysis/Scalable/ssaf-driver/bad-args.test
deleted file mode 100644
index 3319215cfdcc9..0000000000000
--- a/clang/test/Analysis/Scalable/ssaf-driver/bad-args.test
+++ /dev/null
@@ -1,21 +0,0 @@
-
-# RUN: not %clang-ssaf-driver -- make 2>&1 \
-# RUN:   | FileCheck %s --check-prefix=NO-TRANSFORMATION
-# NO-TRANSFORMATION: error: the following arguments are required: --transformation
-
-# RUN: not %clang-ssaf-driver --transformation=no-such -- make 2>&1 \
-# RUN:   | FileCheck %s --check-prefix=UNKNOWN
-# UNKNOWN: error: argument --transformation: invalid choice: 'no-such' {{.*}}cpp-bounded-buffers
-
-# RUN: not %clang-ssaf-driver --transformation=cpp-bounded-buffers 2>&1 \
-# RUN:   | FileCheck %s --check-prefix=NO-BUILD
-# NO-BUILD: clang-ssaf-driver: error: no build command given
-
-# Without clang-apply-replacements, --apply stops the run before it builds.
-# RUN: rm -rf %t && mkdir -p %t
-# RUN: not %clang-ssaf-driver --transformation=cpp-bounded-buffers --apply \
-# RUN:     --clang-apply-replacements=%t/missing -o %t/out -- make 2>&1 \
-# RUN:   | FileCheck %s --check-prefix=NO-APPLY -DPATH=%t/missing
-# NO-APPLY:      clang-ssaf-driver: error: --apply needs clang-apply-replacements:
-# NO-APPLY-NEXT:   --clang-apply-replacements: not a file: [[PATH]]
-# RUN: not ls %t/out
diff --git a/clang/test/Analysis/Scalable/ssaf-driver/build-failure.test b/clang/test/Analysis/Scalable/ssaf-driver/build-failure.test
deleted file mode 100644
index 732ea9b5bf26d..0000000000000
--- a/clang/test/Analysis/Scalable/ssaf-driver/build-failure.test
+++ /dev/null
@@ -1,17 +0,0 @@
-# REQUIRES: ssaf-driver-make-build
-# RUN: rm -rf %t && split-file %s %t
-
-# A failing build fails the run with the orchestrator's status, and leaves
-# neither a patch nor a report.
-# RUN: cd %t
-# RUN: not %clang-ssaf-driver --transformation=cpp-bounded-buffers \
-# RUN:     --ssaf-clang=%ssaf-driver-clang -o %t/out -- make 2>&1 \
-# RUN:   | FileCheck %s
-# CHECK: clang-ssaf-orchestrator-make: error: build failed (exit 2)
-# CHECK: clang-ssaf-driver: error: clang-ssaf-orchestrator-make failed (exit 2)
-# RUN: not ls %t/out/cpp-bounded-buffers.patch
-# RUN: not ls %t/out/cpp-bounded-buffers.sarif
-
-#--- Makefile
-all:
-	false
diff --git a/clang/test/Analysis/Scalable/ssaf-driver/conflicts.test b/clang/test/Analysis/Scalable/ssaf-driver/conflicts.test
deleted file mode 100644
index ea98af9a386df..0000000000000
--- a/clang/test/Analysis/Scalable/ssaf-driver/conflicts.test
+++ /dev/null
@@ -1,58 +0,0 @@
-# REQUIRES: ssaf-driver-make-build
-# RUN: rm -rf %t && split-file %s %t
-# RUN: mkdir -p %t/build
-
-# The two translation units see different declarations of g in the header,
-# so their edits to it conflict and neither is applied. The conflict is
-# reported with both candidates, and the rest of the edits are still made.
-# RUN: cd %t
-# RUN: %clang-ssaf-driver --transformation=cpp-bounded-buffers \
-# RUN:     --ssaf-clang=%ssaf-driver-clang -o %t/out -- make \
-# RUN:     2> %t/stderr.txt > /dev/null
-
-# RUN: FileCheck %s --check-prefix=STDERR --input-file=%t/stderr.txt
-# STDERR:      src/shared.h:3:1: error: 2 overlapping replacement(s) at file://{{.*}}/src/shared.h byte 20 were dropped; resolve manually. [clang-reforge-replacement-conflict]
-# STDERR-DAG:  src/shared.h:3:1: note: candidate edit: "bounded_ptr<long> "
-# STDERR-DAG:  src/shared.h:5:1: note: candidate edit: "bounded_ptr<int> "
-# STDERR:      1 clang-reforge-replacement-conflict reported
-
-# RUN: FileCheck %s --check-prefix=SARIF \
-# RUN:   --input-file=%t/out/cpp-bounded-buffers.sarif
-# SARIF: "name": "clang-ssaf",
-# SARIF: "byteOffset": 20
-# SARIF: "ruleId": "clang-reforge-replacement-conflict"
-# SARIF: "name": "clang-ssaf-src-edit-merge",
-
-# RUN: FileCheck %s --check-prefix=PATCH \
-# RUN:   --input-file=%t/out/cpp-bounded-buffers.patch
-# PATCH:     +++ b/src/a.cpp
-# PATCH:     +bounded_ptr<int> g;
-# PATCH-NOT: shared.h
-
-#--- Makefile
-CXX = clang++
-all: build/prg
-build/%.o: src/%.cpp src/shared.h
-	$(CXX) -c -o $@ $<
-build/prg: build/a.o build/b.o
-	$(CXX) -o $@ build/a.o build/b.o
-
-#--- src/shared.h
-extern
-#if USE_LONG
-long
-#else
-int
-#endif
-*g;
-
-#--- src/a.cpp
-#include "shared.h"
-int *g;
-long b();
-int main() { return g[5] + (int)b(); }
-
-#--- src/b.cpp
-#define USE_LONG 1
-#include "shared.h"
-long b() { return g[7]; }
diff --git a/clang/test/Analysis/Scalable/ssaf-driver/help.test b/clang/test/Analysis/Scalable/ssaf-driver/help.test
deleted file mode 100644
index 0466fcf3d1ba7..0000000000000
--- a/clang/test/Analysis/Scalable/ssaf-driver/help.test
+++ /dev/null
@@ -1,28 +0,0 @@
-
-# RUN: %clang-ssaf-driver --help | FileCheck %s
-
-# CHECK: usage: clang-ssaf-driver [options] --transformation=<name> [--] <build command>
-# CHECK: --version
-# CHECK: --transformation <name>
-# CHECK: --output-dir
-# CHECK: --apply
-# CHECK: --clang-apply-replacements
-# CHECK: --ssaf-clang
-# CHECK: --ssaf-linker
-# CHECK: --ssaf-analyzer
-# CHECK: --ssaf-src-edit-merge
-# CHECK: --ssaf-merge-transformation-report
-# CHECK: --ssaf-merge-conflict-report
-# CHECK: --ssaf-extra-clang-arg
-# CHECK: --keep-going
-# CHECK: --verbose
-
-# RUN: %clang-ssaf-driver --version | FileCheck %s --check-prefix=VERSION
-# VERSION: clang-ssaf-driver {{[0-9]+\.[0-9]+\.[0-9]+}}
-
-# The tool imports its own package, whatever else of that name PYTHONPATH holds.
-# RUN: rm -rf %t && mkdir -p %t/clang_ssaf_driver
-# RUN: echo 'raise SystemExit("a decoy was imported")' \
-# RUN:   > %t/clang_ssaf_driver/__init__.py
-# RUN: env PYTHONPATH=%t %clang-ssaf-driver --version \
-# RUN:   | FileCheck %s --check-prefix=VERSION
diff --git a/clang/test/Analysis/Scalable/ssaf-driver/lit.local.cfg b/clang/test/Analysis/Scalable/ssaf-driver/lit.local.cfg
deleted file mode 100644
index 333c6002b8188..0000000000000
--- a/clang/test/Analysis/Scalable/ssaf-driver/lit.local.cfg
+++ /dev/null
@@ -1,53 +0,0 @@
-# -*- Python -*-
-
-import lit.util
-import os
-import platform
-
-if platform.system() == "Windows":
-    config.unsupported = True
-
-if lit.util.which("make"):
-    config.available_features.add("ssaf-driver-make-build")
-
-if lit.util.which("clang-apply-replacements", config.llvm_tools_dir):
-    config.available_features.add("clang-apply-replacements")
-
-if lit.util.which("patch"):
-    config.available_features.add("patch")
-
-config.substitutions.append(
-    (
-        "%clang-ssaf-driver",
-        '"%s" "%s"'
-        % (
-            config.python_executable,
-            os.path.join(config.llvm_tools_dir, "clang-ssaf-driver"),
-        ),
-    )
-)
-
-config.substitutions.append(
-    ("%ssaf-driver-python", '"%s"' % config.python_executable)
-)
-
-config.substitutions.append(
-    (
-        "%ssaf-driver-libs",
-        os.path.join(os.path.dirname(config.llvm_tools_dir), "lib"),
-    )
-)
-
-config.substitutions.append(
-    (
-        "%ssaf-driver-src",
-        os.path.join(config.clang_src_dir, "tools", "clang-ssaf-driver"),
-    )
-)
-
-config.substitutions.append(
-    (
-        "%ssaf-driver-clang",
-        config.clang if config.have_llvm_driver else os.path.realpath(config.clang),
-    )
-)
diff --git a/clang/test/Analysis/Scalable/ssaf-driver/report.test b/clang/test/Analysis/Scalable/ssaf-driver/report.test
deleted file mode 100644
index 979eebda5e5a4..0000000000000
--- a/clang/test/Analysis/Scalable/ssaf-driver/report.test
+++ /dev/null
@@ -1,48 +0,0 @@
-# REQUIRES: ssaf-driver-make-build
-# RUN: rm -rf %t && split-file %s %t
-# RUN: mkdir -p %t/build
-
-# Both translation units report the declaration group in the header; the
-# report has each of its declarators once, after main.cpp's own group.
-# RUN: cd %t
-# RUN: %clang-ssaf-driver --transformation=cpp-bounded-buffers \
-# RUN:     --ssaf-clang=%ssaf-driver-clang -o %t/out -- make \
-# RUN:     2> %t/stderr.txt | FileCheck %s --check-prefix=STDOUT
-# STDOUT: report: {{[^ ]*}}/out/cpp-bounded-buffers.sarif
-
-# RUN: FileCheck %s --check-prefix=STDERR --input-file=%t/stderr.txt
-# STDERR:      src/main.cpp:2:1: note: declarator of a multi-declarator group is not yet rewritten [cpp-bounded-buffers-skipped]
-# STDERR-NEXT: src/main.cpp:2:1: note: declarator of a multi-declarator group is not yet rewritten [cpp-bounded-buffers-skipped]
-# STDERR-NEXT: src/shared.h:1:8: note: declarator of a multi-declarator group is not yet rewritten [cpp-bounded-buffers-skipped]
-# STDERR-NEXT: src/shared.h:1:8: note: declarator of a multi-declarator group is not yet rewritten [cpp-bounded-buffers-skipped]
-# STDERR-NEXT: 4 cpp-bounded-buffers-skipped reported
-
-# The report holds the same findings, and the patch changes nothing.
-# RUN: FileCheck %s --check-prefix=SARIF \
-# RUN:   --input-file=%t/out/cpp-bounded-buffers.sarif
-# RUN: grep 'multi-declarator group' %t/out/cpp-bounded-buffers.sarif | count 4
-# RUN: count 0 < %t/out/cpp-bounded-buffers.patch
-# SARIF: "runs": [
-# SARIF: "name": "clang-ssaf",
-# SARIF: "name": "clang-ssaf-src-edit-merge",
-
-#--- Makefile
-CXX = clang++
-all: build/prg
-build/%.o: src/%.cpp src/shared.h
-	$(CXX) -c -o $@ $<
-build/prg: build/main.o build/use.o
-	$(CXX) -o $@ build/main.o build/use.o
-
-#--- src/shared.h
-extern int *p, *q;
-
-#--- src/use.cpp
-#include "shared.h"
-int use() { return p[1] + q[1]; }
-
-#--- src/main.cpp
-#include "shared.h"
-int *p, *q;
-int use();
-int main() { return use(); }
diff --git a/clang/test/Analysis/Scalable/ssaf-driver/transformation.test b/clang/test/Analysis/Scalable/ssaf-driver/transformation.test
deleted file mode 100644
index a51008e2335f1..0000000000000
--- a/clang/test/Analysis/Scalable/ssaf-driver/transformation.test
+++ /dev/null
@@ -1,72 +0,0 @@
-# REQUIRES: ssaf-driver-make-build
-# RUN: rm -rf %t && split-file %s %t
-# RUN: mkdir -p %t/build
-
-# RUN: cd %t
-# RUN: %clang-ssaf-driver --transformation=cpp-bounded-buffers \
-# RUN:     --ssaf-clang=%ssaf-driver-clang -o %t/out -- make \
-# RUN:   | FileCheck %s --check-prefix=STDOUT
-# STDOUT: source-edits: {{[^ ]*}}/out/ssaf-artifacts{{[^ ]*}}/build/prg.edits.yaml
-# STDOUT: patch: {{[^ ]*}}/out/cpp-bounded-buffers.patch
-# STDOUT: report: {{[^ ]*}}/out/cpp-bounded-buffers.sarif
-
-# RUN: diff %t/expected.patch %t/out/cpp-bounded-buffers.patch
-
-# The sources are left as they were.
-# RUN: FileCheck %s --check-prefix=UNCHANGED --input-file=%t/src/parse.cpp
-# UNCHANGED: int total(int *data, int n) {
-
-# A second run into the same output directory starts afresh.
-# RUN: %clang-ssaf-driver --transformation=cpp-bounded-buffers \
-# RUN:     --ssaf-clang=%ssaf-driver-clang -o %t/out -- make > %t/second.txt
-# RUN: diff %t/expected.patch %t/out/cpp-bounded-buffers.patch
-
-# The patch applies to the sources.
-# RUN: %if patch %{ rm -rf %t/copy && mkdir -p %t/copy && cp -R %t/src %t/copy %}
-# RUN: %if patch %{ patch -s -p1 -d %t/copy < %t/out/cpp-bounded-buffers.patch %}
-# RUN: %if patch %{ FileCheck %s --check-prefix=PATCHED --input-file=%t/copy/src/parse.cpp %}
-# PATCHED: int total(bounded_ptr<int> data, int n) {
-
-#--- Makefile
-CXX = clang++
-all: build/prg
-build/%.o: src/%.cpp
-	$(CXX) -c -o $@ $<
-build/prg: build/main.o build/parse.o
-	$(CXX) -o $@ build/main.o build/parse.o
-
-#--- src/parse.cpp
-int total(int *data, int n) {
-  int t = 0;
-  for (int i = 0; i < n; ++i)
-    t += data[i];
-  return t;
-}
-
-#--- src/main.cpp
-int total(int *data, int n);
-int main() {
-  int values[4] = {1, 2, 3, 4};
-  return total(values, 4);
-}
-
-#--- expected.patch
---- a/src/main.cpp
-+++ b/src/main.cpp
-@@ -1,6 +1,6 @@
--int total(int *data, int n);
-+int total(bounded_ptr<int> data, int n);
- int main() {
--  int values[4] = {1, 2, 3, 4};
-+  bounded_array<int, 4> values = {1, 2, 3, 4};
-   return total(values, 4);
- }
- 
---- a/src/parse.cpp
-+++ b/src/parse.cpp
-@@ -1,4 +1,4 @@
--int total(int *data, int n) {
-+int total(bounded_ptr<int> data, int n) {
-   int t = 0;
-   for (int i = 0; i < n; ++i)
-     t += data[i];
diff --git a/clang/test/Analysis/Scalable/ssaf-driver/unittests.test b/clang/test/Analysis/Scalable/ssaf-driver/unittests.test
deleted file mode 100644
index 60ab238f41cb1..0000000000000
--- a/clang/test/Analysis/Scalable/ssaf-driver/unittests.test
+++ /dev/null
@@ -1,8 +0,0 @@
-
-# RUN: env PYTHONDONTWRITEBYTECODE=1 PYTHONPATH=%ssaf-driver-libs \
-# RUN:     %ssaf-driver-python -m unittest discover \
-# RUN:   -s %ssaf-driver-src/tests -t %ssaf-driver-src \
-# RUN:   > %t.log 2>&1
-# RUN: FileCheck %s --input-file=%t.log --implicit-check-not=FAILED
-
-# CHECK: {{^OK}}
diff --git a/clang/test/CMakeLists.txt b/clang/test/CMakeLists.txt
index 0a595f6ba3cdf..e498ef13f71e2 100644
--- a/clang/test/CMakeLists.txt
+++ b/clang/test/CMakeLists.txt
@@ -117,12 +117,8 @@ list(APPEND CLANG_TEST_DEPS
 
 if(NOT WIN32)
   list(APPEND CLANG_TEST_DEPS
-    clang-ssaf-driver
     clang-ssaf-orchestrator-make
     )
-  if(TARGET clang-apply-replacements)
-    list(APPEND CLANG_TEST_DEPS clang-apply-replacements)
-  endif()
 endif()
 
 if(CLANG_ENABLE_CIR)
diff --git a/clang/tools/CMakeLists.txt b/clang/tools/CMakeLists.txt
index c60843e4b7eeb..f85381e65ac20 100644
--- a/clang/tools/CMakeLists.txt
+++ b/clang/tools/CMakeLists.txt
@@ -21,7 +21,6 @@ add_clang_subdirectory(clang-ssaf-linker)
 add_clang_subdirectory(clang-ssaf-merge-conflict-report)
 add_clang_subdirectory(clang-ssaf-merge-transformation-report)
 if(NOT WIN32)
-  add_clang_subdirectory(clang-ssaf-driver)
   add_clang_subdirectory(clang-ssaf-orchestrator-make)
 endif()
 add_clang_subdirectory(clang-ssaf-src-edit-merge)
diff --git a/clang/tools/clang-ssaf-driver/CMakeLists.txt b/clang/tools/clang-ssaf-driver/CMakeLists.txt
deleted file mode 100644
index 00513636edf96..0000000000000
--- a/clang/tools/clang-ssaf-driver/CMakeLists.txt
+++ /dev/null
@@ -1,75 +0,0 @@
-set(SsafDriverLib
-    "__init__.py"
-    "apply.py"
-    "driver.py"
-    "logging_diagnostics.py"
-    "make_orchestrator.py"
-    "options.py"
-    "patch.py"
-    "report.py"
-    "source_edits.py"
-    "transformations.py")
-
-set(SsafDriverPackageDir "lib/clang_ssaf_driver")
-
-# Copy one file into the build tree and install it, recording the copy so the
-# tool's target can depend on it. kind is FILES or PROGRAMS.
-function(add_ssaf_driver_file source build_dir destination kind)
-  get_filename_component(name "${source}" NAME)
-  set(copied "${LLVM_BINARY_DIR}/${build_dir}/${name}")
-  add_custom_command(OUTPUT "${copied}"
-                     COMMAND ${CMAKE_COMMAND} -E make_directory
-                       "${LLVM_BINARY_DIR}/${build_dir}"
-                     COMMAND ${CMAKE_COMMAND} -E copy
-                       "${CMAKE_CURRENT_SOURCE_DIR}/${source}" "${copied}"
-                     DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/${source}")
-  set(SSAF_DRIVER_DEPENDS ${SSAF_DRIVER_DEPENDS} "${copied}" PARENT_SCOPE)
-  install(${kind} "${source}"
-          DESTINATION "${destination}"
-          COMPONENT clang-ssaf-driver)
-endfunction()
-
-add_ssaf_driver_file("bin/clang-ssaf-driver"
-                     "bin" "${CMAKE_INSTALL_BINDIR}" PROGRAMS)
-
-foreach(lib ${SsafDriverLib})
-  add_ssaf_driver_file("${SsafDriverPackageDir}/${lib}"
-                       "${SsafDriverPackageDir}" "${SsafDriverPackageDir}" FILES)
-endforeach()
-
-# Substituted at configure time into this directory's own build area, then
-# copied like every other file, so that deleting the package from the build
-# tree leaves a rule to put it back.
-configure_file(
-  "${CMAKE_CURRENT_SOURCE_DIR}/${SsafDriverPackageDir}/version.py.in"
-  "${CMAKE_CURRENT_BINARY_DIR}/version.py")
-set(version_py "${LLVM_BINARY_DIR}/${SsafDriverPackageDir}/version.py")
-add_custom_command(OUTPUT "${version_py}"
-                   COMMAND ${CMAKE_COMMAND} -E make_directory
-                     "${LLVM_BINARY_DIR}/${SsafDriverPackageDir}"
-                   COMMAND ${CMAKE_COMMAND} -E copy
-                     "${CMAKE_CURRENT_BINARY_DIR}/version.py" "${version_py}"
-                   DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/version.py")
-list(APPEND SSAF_DRIVER_DEPENDS "${version_py}")
-install(FILES "${CMAKE_CURRENT_BINARY_DIR}/version.py"
-        DESTINATION "${SsafDriverPackageDir}"
-        COMPONENT clang-ssaf-driver)
-
-add_custom_target(clang-ssaf-driver ALL DEPENDS ${SSAF_DRIVER_DEPENDS})
-set_target_properties(clang-ssaf-driver PROPERTIES FOLDER "Clang/Tools")
-if(NOT LLVM_ENABLE_IDE)
-  add_llvm_install_targets("install-clang-ssaf-driver"
-                           DEPENDS clang-ssaf-driver
-                           COMPONENT clang-ssaf-driver)
-endif()
-
-# The driver runs the orchestrator installed beside it.
-if(CLANG_TOOL_CLANG_SSAF_ORCHESTRATOR_MAKE_BUILD)
-  add_dependencies(clang-ssaf-driver clang-ssaf-orchestrator-make)
-  if(NOT LLVM_ENABLE_IDE)
-    add_dependencies(install-clang-ssaf-driver
-                     install-clang-ssaf-orchestrator-make)
-    add_dependencies(install-clang-ssaf-driver-stripped
-                     install-clang-ssaf-orchestrator-make-stripped)
-  endif()
-endif()
diff --git a/clang/tools/clang-ssaf-driver/README.md b/clang/tools/clang-ssaf-driver/README.md
deleted file mode 100644
index 48c8592820c63..0000000000000
--- a/clang/tools/clang-ssaf-driver/README.md
+++ /dev/null
@@ -1,35 +0,0 @@
-# clang-ssaf-driver
-
-Runs a Scalable Static Analysis Framework source transformation over a project
-as it builds, and presents the result: the source edits as a patch, the
-transformation report as diagnostics and as SARIF, and optionally the edits
-applied with `clang-apply-replacements`. Projects built with make are driven
-through `clang-ssaf-orchestrator-make`, installed beside it.
-
-- Using it: [Transforming a Project](
-  ../../docs/ScalableStaticAnalysis/user-docs/Driver.md)
-
-## Layout
-
-| | |
-|---|---|
-| `bin/` | the entry script, installed to `bin/` |
-| `lib/clang_ssaf_driver/` | the package, installed to `lib/` |
-| `tests/` | the Python unit tests |
-
-## Running the tests
-
-```
-PYTHONPATH=lib python3 -m unittest discover  # from this directory
-llvm-lit clang/test/Analysis/Scalable/ssaf-driver
-```
-
-The lit suite runs the unit tests too, against the copy in the build tree, so
-`ninja check-clang` covers both. The tool is a declared dependency of
-`check-clang`.
-
-## Packaging
-
-CMake copies the Python files into the build tree and installs them under the
-`clang-ssaf-driver` component, and installing it installs the orchestrator's
-component too.
diff --git a/clang/tools/clang-ssaf-driver/bin/clang-ssaf-driver b/clang/tools/clang-ssaf-driver/bin/clang-ssaf-driver
deleted file mode 100755
index b21f4000e684d..0000000000000
--- a/clang/tools/clang-ssaf-driver/bin/clang-ssaf-driver
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/usr/bin/env python3
-# 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
-
-import os.path
-import sys
-
-this_dir = os.path.dirname(os.path.realpath(__file__))
-sys.path.insert(0, os.path.join(os.path.dirname(this_dir), "lib"))
-
-from clang_ssaf_driver import driver
-
-if __name__ == "__main__":
-    sys.exit(driver.main(sys.argv[1:]))
diff --git a/clang/tools/clang-ssaf-driver/lib/clang_ssaf_driver/__init__.py b/clang/tools/clang-ssaf-driver/lib/clang_ssaf_driver/__init__.py
deleted file mode 100644
index 5b5a2956e2697..0000000000000
--- a/clang/tools/clang-ssaf-driver/lib/clang_ssaf_driver/__init__.py
+++ /dev/null
@@ -1,10 +0,0 @@
-# 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
-
-PROGRAM = "clang-ssaf-driver"
-
-try:
-    from .version import VERSION
-except ImportError:
-    VERSION = "unknown (not built)"
diff --git a/clang/tools/clang-ssaf-driver/lib/clang_ssaf_driver/apply.py b/clang/tools/clang-ssaf-driver/lib/clang_ssaf_driver/apply.py
deleted file mode 100644
index 5ccd941f9b6b3..0000000000000
--- a/clang/tools/clang-ssaf-driver/lib/clang_ssaf_driver/apply.py
+++ /dev/null
@@ -1,81 +0,0 @@
-# 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
-
-import os
-import shutil
-import subprocess
-
-from . import logging_diagnostics, source_edits
-from .make_orchestrator import exit_status
-from .options import ENVIRONMENT_ERROR, Problem
-
-TOOL = "clang-apply-replacements"
-STAGING_DIR = "apply"
-STAGED_EDITS = "source-edits.yaml"
-
-
-def resolve_tool(cl_option_value):
-    name_or_path = TOOL if cl_option_value is None else cl_option_value
-    if os.sep in name_or_path:
-        candidate = os.path.abspath(name_or_path)
-    else:
-        candidate = shutil.which(name_or_path)
-    if not candidate:
-        error = "%s: not found on PATH" % name_or_path
-    elif not os.path.isfile(candidate):
-        error = "not a file: %s" % candidate
-    elif not os.access(candidate, os.X_OK):
-        error = "not executable: %s" % candidate
-    else:
-        return candidate, None
-    return None, Problem(
-        ENVIRONMENT_ERROR,
-        "--apply needs %s:" % TOOL,
-        ["--clang-apply-replacements: " + error],
-    )
-
-
-def apply_source_edits(tool, files, output_dir, verbose):
-    staging_dir = os.path.join(output_dir, STAGING_DIR)
-    replacements = [
-        source_edits.Replacement(each.path, offset, length, text)
-        for each in files
-        for offset, length, text in each.edits
-    ]
-    try:
-        shutil.rmtree(staging_dir, ignore_errors=True)
-        os.makedirs(staging_dir)
-        source_edits.write_source_edits(
-            os.path.join(staging_dir, STAGED_EDITS), replacements
-        )
-    except OSError as error:
-        return Problem(ENVIRONMENT_ERROR, "cannot stage the source edits: %s" % error)
-
-    command = [tool, staging_dir]
-    logging_diagnostics.report_note(verbose, "running: %s" % " ".join(command))
-    try:
-        status = exit_status(subprocess.call(command))
-    except OSError as error:
-        return Problem(127, "cannot run '%s': %s" % (tool, error))
-    except KeyboardInterrupt:
-        return Problem(130, "%s was interrupted" % TOOL)
-    if status != 0:
-        return Problem(status, "%s failed (exit %d)" % (TOOL, status))
-
-    mismatched = []
-    for each in files:
-        try:
-            with open(each.path, "rb") as handle:
-                written = handle.read()
-        except OSError:
-            written = None
-        if written != each.edited:
-            mismatched.append(each.relative_path)
-    if mismatched:
-        return Problem(
-            ENVIRONMENT_ERROR,
-            "%s did not write what the patch shows:" % TOOL,
-            mismatched,
-        )
-    return None
diff --git a/clang/tools/clang-ssaf-driver/lib/clang_ssaf_driver/driver.py b/clang/tools/clang-ssaf-driver/lib/clang_ssaf_driver/driver.py
deleted file mode 100644
index c23f81352a49a..0000000000000
--- a/clang/tools/clang-ssaf-driver/lib/clang_ssaf_driver/driver.py
+++ /dev/null
@@ -1,105 +0,0 @@
-# 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
-
-import os
-
-from . import (
-    apply,
-    logging_diagnostics,
-    make_orchestrator,
-    options,
-    patch,
-    report,
-    source_edits,
-)
-from .transformations import TRANSFORMATIONS
-
-
-def run(command_line_opts):
-    orchestrator = make_orchestrator.find_orchestrator()
-    if not os.path.isfile(orchestrator):
-        return options.Problem(
-            options.ENVIRONMENT_ERROR,
-            "cannot find %s: %s" % (make_orchestrator.ORCHESTRATOR, orchestrator),
-        )
-    tool = None
-    if command_line_opts.apply:
-        tool, problem = apply.resolve_tool(command_line_opts.clang_apply_replacements)
-        if problem is not None:
-            return problem
-
-    project_root = os.path.realpath(os.getcwd())
-    output_dir = os.path.realpath(command_line_opts.output_dir)
-    status, results = make_orchestrator.run_orchestrator(
-        make_orchestrator.orchestrator_command(
-            orchestrator,
-            TRANSFORMATIONS[command_line_opts.transformation],
-            command_line_opts,
-        ),
-        command_line_opts.verbose,
-    )
-    if status != 0:
-        return options.Problem(
-            status, "%s failed (exit %d)" % (make_orchestrator.ORCHESTRATOR, status)
-        )
-    if "source-edits" not in results:
-        return options.Problem(
-            options.ENVIRONMENT_ERROR,
-            "%s reported no source edits" % make_orchestrator.ORCHESTRATOR,
-        )
-
-    replacements, problem = source_edits.read_source_edits(results["source-edits"])
-    if problem is not None:
-        return problem
-    log, problem = report.load(
-        [results.get("transformation-report"), results.get("conflict-report")]
-    )
-    if problem is not None:
-        return problem
-    collected, problem = patch.collect(
-        replacements, project_root, report.conflict_ranges(log)
-    )
-    if problem is not None:
-        return problem
-
-    for line in report.diagnostics(log, project_root):
-        logging_diagnostics.report_finding(line)
-    for path in collected.outside:
-        logging_diagnostics.report_warning(
-            "edits to a file outside the project were left out: %s" % path
-        )
-    for relative_path, count in collected.blocked:
-        logging_diagnostics.report_warning(
-            "left out %d edit(s) to %s that overlap a reported conflict"
-            % (count, relative_path)
-        )
-
-    patch_path = os.path.join(output_dir, command_line_opts.transformation + ".patch")
-    report_path = os.path.join(output_dir, command_line_opts.transformation + ".sarif")
-    try:
-        with open(patch_path, "wb") as handle:
-            handle.write(patch.render(collected.files))
-        report.write(report_path, log)
-    except OSError as error:
-        return options.Problem(
-            options.ENVIRONMENT_ERROR, "cannot write the results: %s" % error
-        )
-    logging_diagnostics.report_info("patch", patch_path)
-    logging_diagnostics.report_info("report", report_path)
-
-    if tool is not None:
-        return apply.apply_source_edits(
-            tool, collected.files, output_dir, command_line_opts.verbose
-        )
-    return None
-
-
-def main(argv=None):
-    command_line_opts, problem = options.resolve(argv)
-    if problem is None:
-        problem = run(command_line_opts)
-    if problem is not None:
-        logging_diagnostics.report_error(problem.message, problem.details)
-        return problem.exit_status
-    return 0
diff --git a/clang/tools/clang-ssaf-driver/lib/clang_ssaf_driver/logging_diagnostics.py b/clang/tools/clang-ssaf-driver/lib/clang_ssaf_driver/logging_diagnostics.py
deleted file mode 100644
index c5365d4e35126..0000000000000
--- a/clang/tools/clang-ssaf-driver/lib/clang_ssaf_driver/logging_diagnostics.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# 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
-
-import sys
-
-from . import PROGRAM
-
-
-def report_note(verbose, message):
-    if verbose:
-        sys.stderr.write("%s: note: %s\n" % (PROGRAM, message))
-
-
-def report_warning(message):
-    sys.stderr.write("%s: warning: %s\n" % (PROGRAM, message))
-
-
-def report_error(message, details=()):
-    sys.stderr.write("%s: error: %s\n" % (PROGRAM, message))
-    for detail in details:
-        sys.stderr.write("  %s\n" % detail)
-
-
-def report_info(key, value):
-    sys.stdout.write("%s: %s\n" % (key, value))
-    sys.stdout.flush()
-
-
-def report_finding(text):
-    sys.stderr.write(text + "\n")
diff --git a/clang/tools/clang-ssaf-driver/lib/clang_ssaf_driver/make_orchestrator.py b/clang/tools/clang-ssaf-driver/lib/clang_ssaf_driver/make_orchestrator.py
deleted file mode 100644
index 0f5190280e8e5..0000000000000
--- a/clang/tools/clang-ssaf-driver/lib/clang_ssaf_driver/make_orchestrator.py
+++ /dev/null
@@ -1,64 +0,0 @@
-# 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
-
-import os
-import subprocess
-import sys
-
-from . import logging_diagnostics
-
-ORCHESTRATOR = "clang-ssaf-orchestrator-make"
-
-RESULT_KEYS = frozenset(["source-edits", "transformation-report", "conflict-report"])
-
-
-def find_orchestrator():
-    package_dir = os.path.dirname(os.path.realpath(__file__))
-    prefix = os.path.dirname(os.path.dirname(package_dir))
-    return os.path.join(prefix, "bin", ORCHESTRATOR)
-
-
-def orchestrator_command(orchestrator, transformation, command_line_opts):
-    return (
-        [
-            sys.executable,
-            orchestrator,
-            "--extract-summaries=" + transformation.extract_summaries,
-            "--analysis=" + transformation.analysis,
-            "--transformation=" + transformation.transformation,
-            "--output-dir=" + command_line_opts.output_dir,
-        ]
-        + command_line_opts.orchestrator_args
-        + ["--"]
-        + command_line_opts.build_command
-    )
-
-
-def exit_status(return_code):
-    return 128 - return_code if return_code < 0 else return_code
-
-
-def read_result(line):
-    key, separator, value = line.rstrip(b"\n").partition(b": ")
-    key = key.decode("ascii", "replace")
-    if not separator or key not in RESULT_KEYS:
-        return None
-    return key, os.fsdecode(value)
-
-
-def run_orchestrator(command, verbose, relay=None):
-    relay = relay or sys.stdout.buffer
-    logging_diagnostics.report_note(verbose, "running: %s" % " ".join(command))
-    results = {}
-    with subprocess.Popen(command, stdout=subprocess.PIPE) as process:
-        try:
-            for line in process.stdout:
-                relay.write(line)
-                relay.flush()
-                result = read_result(line)
-                if result:
-                    results[result[0]] = result[1]
-        except KeyboardInterrupt:
-            pass
-    return exit_status(process.returncode), results
diff --git a/clang/tools/clang-ssaf-driver/lib/clang_ssaf_driver/options.py b/clang/tools/clang-ssaf-driver/lib/clang_ssaf_driver/options.py
deleted file mode 100644
index fa01c1fe313cc..0000000000000
--- a/clang/tools/clang-ssaf-driver/lib/clang_ssaf_driver/options.py
+++ /dev/null
@@ -1,159 +0,0 @@
-# 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
-
-import argparse
-import collections
-
-from . import PROGRAM, VERSION
-from .transformations import TRANSFORMATIONS
-
-Problem = collections.namedtuple(
-    "Problem", "exit_status message details", defaults=((),)
-)
-
-USAGE_ERROR = 2
-ENVIRONMENT_ERROR = 1
-
-FORWARDED_TOOLS = (
-    (
-        "--ssaf-clang",
-        "SSAF-capable clang used for the SSAF compilations (default: clang on PATH).",
-    ),
-    ("--ssaf-linker", "Path to clang-ssaf-linker (default: found on PATH)."),
-    ("--ssaf-analyzer", "Path to clang-ssaf-analyzer (default: found on PATH)."),
-    (
-        "--ssaf-src-edit-merge",
-        "Path to clang-ssaf-src-edit-merge (default: found on PATH).",
-    ),
-    (
-        "--ssaf-merge-transformation-report",
-        "Path to clang-ssaf-merge-transformation-report (default: found on PATH).",
-    ),
-    (
-        "--ssaf-merge-conflict-report",
-        "Path to clang-ssaf-merge-conflict-report (default: found on PATH).",
-    ),
-)
-
-
-def build_parser():
-    parser = argparse.ArgumentParser(
-        prog=PROGRAM,
-        usage="%(prog)s [options] --transformation=<name> [--] <build command>",
-        description="Run an SSAF transformation over a project as it builds. "
-        "The source edits are written as a patch and can be applied, and the "
-        "transformation report is printed and written as SARIF.",
-    )
-    parser.add_argument("--version", action="version", version="%(prog)s " + VERSION)
-    parser.add_argument(
-        "--transformation",
-        metavar="<name>",
-        required=True,
-        choices=sorted(TRANSFORMATIONS),
-        help="The transformation to run, one of: %s. Required."
-        % ", ".join(sorted(TRANSFORMATIONS)),
-    )
-    parser.add_argument(
-        "-o",
-        "--output-dir",
-        metavar="<dir>",
-        default="ssaf-output",
-        help="Directory for the results and the SSAF artifacts "
-        "(default: %(default)s).",
-    )
-    parser.add_argument(
-        "--apply",
-        action="store_true",
-        help="Also apply the source edits, with clang-apply-replacements.",
-    )
-    parser.add_argument(
-        "--clang-apply-replacements",
-        metavar="<path>",
-        default=None,
-        help="Path to clang-apply-replacements (default: found on PATH).",
-    )
-    for option, purpose in FORWARDED_TOOLS:
-        parser.add_argument(option, metavar="<path>", default=None, help=purpose)
-    parser.add_argument(
-        "--ssaf-extra-clang-arg",
-        metavar="<arg>",
-        action="append",
-        default=[],
-        dest="ssaf_extra_clang_args",
-        help="Additional argument for every SSAF compilation. Repeatable.",
-    )
-    parser.add_argument(
-        "-k",
-        "--keep-going",
-        action="store_true",
-        help="Carry on even if some SSAF steps failed.",
-    )
-    parser.add_argument(
-        "-v",
-        "--verbose",
-        action="store_true",
-        help="Print every command that runs.",
-    )
-    parser.add_argument(
-        "build",
-        nargs=argparse.REMAINDER,
-        metavar="<build command>",
-        help="The build command. A '--' separator before it is optional.",
-    )
-    return parser
-
-
-class CommandLineOpts:
-    def __init__(
-        self,
-        build_command=(),
-        transformation=None,
-        output_dir=None,
-        apply=False,
-        clang_apply_replacements=None,
-        orchestrator_args=(),
-        verbose=False,
-    ):
-        self.build_command = list(build_command)
-        self.transformation = transformation
-        self.output_dir = output_dir
-        self.apply = apply
-        self.clang_apply_replacements = clang_apply_replacements
-        self.orchestrator_args = list(orchestrator_args)
-        self.verbose = verbose
-
-
-def resolve(argv):
-    args = build_parser().parse_args(argv)
-
-    build_command = list(args.build)
-    if build_command and build_command[0] == "--":
-        build_command = build_command[1:]
-    if not build_command:
-        return None, Problem(USAGE_ERROR, "no build command given")
-
-    orchestrator_args = []
-    for option, _ in FORWARDED_TOOLS:
-        value = getattr(args, option[2:].replace("-", "_"))
-        if value is not None:
-            orchestrator_args.append("%s=%s" % (option, value))
-    for arg in args.ssaf_extra_clang_args:
-        orchestrator_args.append("--ssaf-extra-clang-arg=" + arg)
-    if args.keep_going:
-        orchestrator_args.append("--keep-going")
-    if args.verbose:
-        orchestrator_args.append("--verbose")
-
-    return (
-        CommandLineOpts(
-            build_command=build_command,
-            transformation=args.transformation,
-            output_dir=args.output_dir,
-            apply=args.apply,
-            clang_apply_replacements=args.clang_apply_replacements,
-            orchestrator_args=orchestrator_args,
-            verbose=args.verbose,
-        ),
-        None,
-    )
diff --git a/clang/tools/clang-ssaf-driver/lib/clang_ssaf_driver/patch.py b/clang/tools/clang-ssaf-driver/lib/clang_ssaf_driver/patch.py
deleted file mode 100644
index 2ee1be8fe2639..0000000000000
--- a/clang/tools/clang-ssaf-driver/lib/clang_ssaf_driver/patch.py
+++ /dev/null
@@ -1,129 +0,0 @@
-# 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
-
-import collections
-import difflib
-import os
-
-from .options import ENVIRONMENT_ERROR, Problem
-
-FileEdits = collections.namedtuple(
-    "FileEdits", "relative_path path edits original edited"
-)
-
-Collected = collections.namedtuple("Collected", "files outside blocked")
-
-NO_NEWLINE = b"\\ No newline at end of file\n"
-
-
-def apply_edits(original, edits):
-    pieces = []
-    position = 0
-    previous = None
-    for offset, length, text in edits:
-        if offset + length > len(original):
-            return None, "an edit at byte %d runs past the end of the file" % offset
-        if offset < position or (length == 0 and previous == (offset, 0)):
-            return None, "edits overlap at byte %d" % offset
-        pieces.append(original[position:offset])
-        pieces.append(text.encode("utf-8"))
-        position = offset + length
-        previous = (offset, length)
-    pieces.append(original[position:])
-    return b"".join(pieces), None
-
-
-def _identity(path):
-    try:
-        status = os.stat(path)
-    except OSError:
-        return path
-    return (status.st_dev, status.st_ino)
-
-
-def _overlaps(edit, start, end):
-    offset, length, _ = edit
-    if length == 0:
-        return start < offset < end
-    return offset < end and start < offset + length
-
-
-def collect(replacements, project_root, conflicts):
-    grouped = {}
-    paths = {}
-    for each in replacements:
-        path = os.path.realpath(os.path.join(project_root, each.file_path))
-        identity = _identity(path)
-        paths[identity] = min(paths.get(identity, path), path)
-        grouped.setdefault(identity, set()).add((each.offset, each.length, each.text))
-    conflicting = {}
-    for path, ranges in conflicts.items():
-        conflicting.setdefault(_identity(os.path.realpath(path)), []).extend(ranges)
-
-    files = []
-    outside = []
-    blocked = []
-    problems = []
-    for identity in sorted(grouped, key=lambda each: paths[each]):
-        path = paths[identity]
-        relative_path = os.path.relpath(path, project_root)
-        if relative_path == os.pardir or relative_path.startswith(os.pardir + os.sep):
-            outside.append(path)
-            continue
-        ranges = conflicting.get(identity, ())
-        edits = sorted(
-            (
-                edit
-                for edit in grouped[identity]
-                if not any(_overlaps(edit, start, end) for start, end in ranges)
-            ),
-            key=lambda edit: (edit[0], edit[1]),
-        )
-        if len(edits) < len(grouped[identity]):
-            blocked.append((relative_path, len(grouped[identity]) - len(edits)))
-        if not edits:
-            continue
-        try:
-            with open(path, "rb") as handle:
-                original = handle.read()
-        except OSError as error:
-            problems.append("%s: %s" % (relative_path, error.strerror))
-            continue
-        edited, problem = apply_edits(original, edits)
-        if problem:
-            problems.append("%s: %s" % (relative_path, problem))
-            continue
-        files.append(FileEdits(relative_path, path, edits, original, edited))
-
-    if problems:
-        return None, Problem(
-            ENVIRONMENT_ERROR, "the source edits cannot be applied:", problems
-        )
-    return Collected(files, outside, blocked), None
-
-
-def _lines(content):
-    lines = content.split(b"\n")
-    last = lines.pop()
-    lines = [line + b"\n" for line in lines]
-    if last:
-        lines.append(last)
-    return lines
-
-
-def render(files):
-    pieces = []
-    for each in files:
-        name = os.fsencode(each.relative_path)
-        for line in difflib.diff_bytes(
-            difflib.unified_diff,
-            _lines(each.original),
-            _lines(each.edited),
-            b"a/" + name,
-            b"b/" + name,
-        ):
-            pieces.append(line)
-            if not line.endswith(b"\n"):
-                pieces.append(b"\n" + NO_NEWLINE)
-    return b"".join(pieces)
diff --git a/clang/tools/clang-ssaf-driver/lib/clang_ssaf_driver/report.py b/clang/tools/clang-ssaf-driver/lib/clang_ssaf_driver/report.py
deleted file mode 100644
index 975a9362bb892..0000000000000
--- a/clang/tools/clang-ssaf-driver/lib/clang_ssaf_driver/report.py
+++ /dev/null
@@ -1,136 +0,0 @@
-# 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
-
-import collections
-import json
-import os
-import urllib.parse
-
-from . import PROGRAM
-from .options import ENVIRONMENT_ERROR, Problem
-
-SCHEMA = (
-    "https://docs.oasis-open.org/sarif/sarif/v2.1.0/cos02/schemas/"
-    "sarif-schema-2.1.0.json"
-)
-
-_LEVELS = {"error": "error", "warning": "warning", "note": "note", "none": "note"}
-
-_FILE_SCHEME = "file://"
-
-
-def load(paths):
-    runs = []
-    for path in paths:
-        if not path:
-            continue
-        try:
-            with open(path) as handle:
-                document = json.load(handle)
-        except (OSError, ValueError) as error:
-            return None, Problem(
-                ENVIRONMENT_ERROR, "cannot read the report %s: %s" % (path, error)
-            )
-        if not isinstance(document, dict) or not isinstance(document.get("runs"), list):
-            return None, Problem(ENVIRONMENT_ERROR, "not a SARIF log: %s" % path)
-        runs.extend(document["runs"])
-    return {"$schema": SCHEMA, "version": "2.1.0", "runs": runs}, None
-
-
-def write(path, log):
-    with open(path, "w") as handle:
-        json.dump(log, handle, indent=2, sort_keys=True)
-        handle.write("\n")
-
-
-class _Sources:
-    def __init__(self):
-        self.contents = {}
-
-    def position(self, path, offset):
-        if path not in self.contents:
-            try:
-                with open(path, "rb") as handle:
-                    self.contents[path] = handle.read()
-            except OSError:
-                self.contents[path] = None
-        content = self.contents[path]
-        if content is None or offset > len(content):
-            return None
-        line_start = content.rfind(b"\n", 0, offset) + 1
-        return content.count(b"\n", 0, offset) + 1, offset - line_start + 1
-
-
-def _path(uri):
-    if not uri.startswith(_FILE_SCHEME):
-        return uri
-    return urllib.parse.unquote(uri[len(_FILE_SCHEME) :])
-
-
-def _where(location, project_root, sources):
-    physical = location.get("physicalLocation") or {}
-    uri = (physical.get("artifactLocation") or {}).get("uri")
-    if not uri:
-        return PROGRAM
-    path = _path(uri)
-    shown = os.path.relpath(path, project_root)
-    if shown == os.pardir or shown.startswith(os.pardir + os.sep):
-        shown = path
-    region = physical.get("region") or {}
-    if "startLine" in region:
-        return "%s:%d:%d" % (shown, region["startLine"], region.get("startColumn", 1))
-    if "byteOffset" in region:
-        position = sources.position(path, region["byteOffset"])
-        if position:
-            return "%s:%d:%d" % ((shown,) + position)
-    return shown
-
-
-def _text(item):
-    return (item.get("message") or {}).get("text", "")
-
-
-def diagnostics(log, project_root):
-    sources = _Sources()
-    lines = []
-    counts = collections.Counter()
-    for run in log["runs"]:
-        for result in run.get("results") or []:
-            rule_id = result.get("ruleId", "")
-            counts[rule_id] += 1
-            locations = result.get("locations") or [{}]
-            lines.append(
-                "%s: %s: %s [%s]"
-                % (
-                    _where(locations[0], project_root, sources),
-                    _LEVELS.get(result.get("level"), "warning"),
-                    _text(result),
-                    rule_id,
-                )
-            )
-            for related in result.get("relatedLocations") or []:
-                lines.append(
-                    "%s: note: %s"
-                    % (_where(related, project_root, sources), _text(related))
-                )
-    if counts:
-        summary = ["%d %s" % (counts[rule_id], rule_id) for rule_id in sorted(counts)]
-        lines.append("%s reported" % ", ".join(summary))
-    return lines
-
-
-def conflict_ranges(log):
-    ranges = {}
-    for run in log["runs"]:
-        for result in run.get("results") or []:
-            for related in result.get("relatedLocations") or []:
-                physical = related.get("physicalLocation") or {}
-                uri = (physical.get("artifactLocation") or {}).get("uri")
-                region = physical.get("region") or {}
-                if uri and "byteOffset" in region and "byteLength" in region:
-                    start = region["byteOffset"]
-                    ranges.setdefault(_path(uri), []).append(
-                        (start, start + region["byteLength"])
-                    )
-    return ranges
diff --git a/clang/tools/clang-ssaf-driver/lib/clang_ssaf_driver/source_edits.py b/clang/tools/clang-ssaf-driver/lib/clang_ssaf_driver/source_edits.py
deleted file mode 100644
index a509e326f70eb..0000000000000
--- a/clang/tools/clang-ssaf-driver/lib/clang_ssaf_driver/source_edits.py
+++ /dev/null
@@ -1,186 +0,0 @@
-# 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
-
-import collections
-import re
-
-from .options import ENVIRONMENT_ERROR, Problem
-
-Replacement = collections.namedtuple("Replacement", "file_path offset length text")
-
-_ENTRY_KEYS = ("Offset", "Length", "ReplacementText")
-
-_LINE = re.compile(
-    r"^(?P<indent>(?:  - |    )?)(?P<key>[A-Za-z]+):(?: +(?P<value>.*))?$"
-)
-
-_ESCAPE = re.compile(r"\\(x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8}|.)")
-
-_ESCAPED = {
-    "0": "\0",
-    "a": "\a",
-    "b": "\b",
-    "t": "\t",
-    "n": "\n",
-    "v": "\v",
-    "f": "\f",
-    "r": "\r",
-    "e": "\x1b",
-    '"': '"',
-    "\\": "\\",
-    "N": "\x85",
-    "_": "\xa0",
-    "L": "\u2028",
-    "P": "\u2029",
-}
-
-_ESCAPES = {
-    "\\": "\\\\",
-    '"': '\\"',
-    "\x85": "\\N",
-    "\u2028": "\\L",
-    "\u2029": "\\P",
-}
-
-
-class _Malformed(Exception):
-    def __init__(self, line, message):
-        super().__init__(message)
-        self.line = line
-        self.message = message
-
-
-def _unescape(body, line):
-    pieces = []
-    position = 0
-    for match in _ESCAPE.finditer(body):
-        pieces.append(body[position : match.start()])
-        code = match.group(1)
-        if len(code) > 1:
-            pieces.append(chr(int(code[1:], 16)))
-        elif code in _ESCAPED:
-            pieces.append(_ESCAPED[code])
-        else:
-            raise _Malformed(line, "unknown escape '\\%s'" % code)
-        position = match.end()
-    rest = body[position:]
-    if "\\" in rest:
-        raise _Malformed(line, "unfinished escape")
-    pieces.append(rest)
-    return "".join(pieces)
-
-
-def _scalar(value, line):
-    if value is None:
-        raise _Malformed(line, "missing value")
-    if value[:1] in ("'", '"'):
-        if len(value) < 2 or value[-1] != value[0]:
-            raise _Malformed(line, "unterminated string")
-        if value[0] == "'":
-            return value[1:-1].replace("''", "'")
-        return _unescape(value[1:-1], line)
-    return value
-
-
-def _integer(value, line):
-    text = _scalar(value, line)
-    if not text.isdigit():
-        raise _Malformed(line, "expected a number, got '%s'" % text)
-    return int(text)
-
-
-def _parse(lines):
-    if lines and lines[-1] == "":
-        lines = lines[:-1]
-    if not lines or lines[0] != "---":
-        raise _Malformed(1, "expected '---'")
-    if len(lines) < 2 or lines[-1] != "...":
-        raise _Malformed(len(lines), "expected '...'")
-    entries = []
-    replacements_line = None
-    for number, text in enumerate(lines[1:-1], start=2):
-        match = _LINE.match(text)
-        if not match:
-            raise _Malformed(number, "unexpected line")
-        indent, key, value = match.group("indent", "key", "value")
-        if not indent and key == "MainSourceFile":
-            _scalar(value, number)
-        elif not indent and key == "Replacements" and replacements_line is None:
-            replacements_line = number
-            if value is not None and value != "[]":
-                raise _Malformed(number, "expected a list of replacements")
-        elif indent == "  - " and key == "FilePath" and replacements_line:
-            entries.append((number, {key: _scalar(value, number)}))
-        elif indent == "    " and key in _ENTRY_KEYS and entries:
-            entry = entries[-1][1]
-            if key in entry:
-                raise _Malformed(number, "'%s' given twice" % key)
-            if key == "ReplacementText":
-                entry[key] = _scalar(value, number)
-            else:
-                entry[key] = _integer(value, number)
-        else:
-            raise _Malformed(number, "unexpected '%s'" % key)
-    if replacements_line is None:
-        raise _Malformed(len(lines), "no replacements")
-    replacements = []
-    for number, entry in entries:
-        missing = [key for key in _ENTRY_KEYS if key not in entry]
-        if missing:
-            raise _Malformed(number, "replacement without '%s'" % missing[0])
-        replacements.append(
-            Replacement(
-                entry["FilePath"],
-                entry["Offset"],
-                entry["Length"],
-                entry["ReplacementText"],
-            )
-        )
-    return replacements
-
-
-def read_source_edits(path):
-    try:
-        with open(path, "rb") as handle:
-            text = handle.read().decode("utf-8")
-    except (OSError, UnicodeDecodeError) as error:
-        return None, Problem(
-            ENVIRONMENT_ERROR, "cannot read the source edits: %s" % error
-        )
-    lines = [line[:-1] if line.endswith("\r") else line for line in text.split("\n")]
-    try:
-        return _parse(lines), None
-    except _Malformed as error:
-        return None, Problem(
-            ENVIRONMENT_ERROR,
-            "malformed source edits: %s:%d: %s" % (path, error.line, error.message),
-        )
-
-
-def _quote(text):
-    pieces = []
-    for character in text:
-        if character in _ESCAPES:
-            pieces.append(_ESCAPES[character])
-        elif ord(character) < 0x20 or character == "\x7f":
-            pieces.append("\\x%02x" % ord(character))
-        else:
-            pieces.append(character)
-    return '"%s"' % "".join(pieces)
-
-
-def write_source_edits(path, replacements):
-    lines = ["---", "MainSourceFile:  ''"]
-    if not replacements:
-        lines.append("Replacements:    []")
-    else:
-        lines.append("Replacements:")
-    for each in replacements:
-        lines.append("  - FilePath:        %s" % _quote(each.file_path))
-        lines.append("    Offset:          %d" % each.offset)
-        lines.append("    Length:          %d" % each.length)
-        lines.append("    ReplacementText: %s" % _quote(each.text))
-    lines.append("...")
-    with open(path, "w", encoding="utf-8", errors="surrogateescape") as handle:
-        handle.write("\n".join(lines) + "\n")
diff --git a/clang/tools/clang-ssaf-driver/lib/clang_ssaf_driver/transformations.py b/clang/tools/clang-ssaf-driver/lib/clang_ssaf_driver/transformations.py
deleted file mode 100644
index 6a01c498a6cc8..0000000000000
--- a/clang/tools/clang-ssaf-driver/lib/clang_ssaf_driver/transformations.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# 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
-
-import collections
-
-Transformation = collections.namedtuple(
-    "Transformation", "extract_summaries analysis transformation"
-)
-
-TRANSFORMATIONS = {
-    "cpp-bounded-buffers": Transformation(
-        extract_summaries="PointerFlow,TypeConstrainedPointers,UnsafeBufferUsage,"
-        "VirtualMethod",
-        analysis="UnsafeBufferReachableAnalysisResult",
-        transformation="cpp-bounded-buffers",
-    ),
-}
diff --git a/clang/tools/clang-ssaf-driver/lib/clang_ssaf_driver/version.py.in b/clang/tools/clang-ssaf-driver/lib/clang_ssaf_driver/version.py.in
deleted file mode 100644
index 69b39a828847a..0000000000000
--- a/clang/tools/clang-ssaf-driver/lib/clang_ssaf_driver/version.py.in
+++ /dev/null
@@ -1,5 +0,0 @@
-# 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
-
-VERSION = "@CLANG_VERSION@"
diff --git a/clang/tools/clang-ssaf-driver/tests/__init__.py b/clang/tools/clang-ssaf-driver/tests/__init__.py
deleted file mode 100644
index 44390e67aacf4..0000000000000
--- a/clang/tools/clang-ssaf-driver/tests/__init__.py
+++ /dev/null
@@ -1,3 +0,0 @@
-# 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
diff --git a/clang/tools/clang-ssaf-driver/tests/test_apply.py b/clang/tools/clang-ssaf-driver/tests/test_apply.py
deleted file mode 100644
index 1d35a4a7e387e..0000000000000
--- a/clang/tools/clang-ssaf-driver/tests/test_apply.py
+++ /dev/null
@@ -1,118 +0,0 @@
-# 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
-
-import os
-import shutil
-import stat
-import sys
-import tempfile
-import unittest
-from unittest import mock
-
-from clang_ssaf_driver import apply, patch, source_edits
-from clang_ssaf_driver.source_edits import Replacement
-
-
-def _executable(path, body="pass\n"):
-    with open(path, "w") as handle:
-        handle.write("#!%s\nimport os, sys\n%s" % (sys.executable, body))
-    os.chmod(path, os.stat(path).st_mode | stat.S_IXUSR)
-    return path
-
-
-class ResolvingTheTool(unittest.TestCase):
-    def setUp(self):
-        self.tmp = os.path.realpath(tempfile.mkdtemp())
-        self.addCleanup(shutil.rmtree, self.tmp, True)
-        self.tool = _executable(os.path.join(self.tmp, "clang-apply-replacements"))
-
-    def test_a_path_is_taken_as_given(self):
-        self.assertEqual((self.tool, None), apply.resolve_tool(self.tool))
-
-    def test_the_default_is_found_on_path(self):
-        with mock.patch.dict(os.environ, {"PATH": self.tmp}):
-            self.assertEqual((self.tool, None), apply.resolve_tool(None))
-
-    def test_what_cannot_be_run_is_a_problem(self):
-        text = os.path.join(self.tmp, "text")
-        open(text, "w").close()
-        cases = (
-            ("no-such-tool", "no-such-tool: not found on PATH"),
-            (os.path.join(self.tmp, "missing"), "not a file: %s/missing" % self.tmp),
-            (self.tmp, "not a file: %s" % self.tmp),
-            (text, "not executable: %s" % text),
-        )
-        for value, error in cases:
-            with mock.patch.dict(os.environ, {"PATH": self.tmp}):
-                tool, problem = apply.resolve_tool(value)
-            self.assertIsNone(tool)
-            self.assertEqual("--apply needs clang-apply-replacements:", problem.message)
-            self.assertEqual(["--clang-apply-replacements: " + error], problem.details)
-
-
-class Applying(unittest.TestCase):
-    def setUp(self):
-        self.tmp = os.path.realpath(tempfile.mkdtemp())
-        self.addCleanup(shutil.rmtree, self.tmp, True)
-        self.out = os.path.join(self.tmp, "out")
-        os.makedirs(self.out)
-        self.source = os.path.join(self.tmp, "a.cpp")
-        with open(self.source, "wb") as handle:
-            handle.write(b"int *p;\n")
-        edits = [(0, 5, 'bounded_ptr<int> "q"\\')]
-        edited, _ = patch.apply_edits(b"int *p;\n", edits)
-        self.files = [patch.FileEdits("a.cpp", self.source, edits, b"", edited)]
-
-    def _tool(self, body):
-        return _executable(os.path.join(self.tmp, "car"), body)
-
-    def test_the_tool_gets_a_directory_holding_only_the_drivers_edits(self):
-        log = os.path.join(self.tmp, "log")
-        tool = self._tool(
-            "open(%r, 'w').write(repr((sys.argv[1:], os.listdir(sys.argv[1]))))\n"
-            "open(%r, 'wb').write(%r)\n" % (log, self.source, self.files[0].edited)
-        )
-        self.assertIsNone(apply.apply_source_edits(tool, self.files, self.out, False))
-        staging_dir = os.path.join(self.out, "apply")
-        with open(log) as handle:
-            self.assertEqual(
-                repr(([staging_dir], ["source-edits.yaml"])), handle.read()
-            )
-        self.assertEqual(
-            ([Replacement(self.source, 0, 5, 'bounded_ptr<int> "q"\\')], None),
-            source_edits.read_source_edits(
-                os.path.join(staging_dir, "source-edits.yaml")
-            ),
-        )
-
-    def test_an_earlier_runs_staging_is_replaced(self):
-        stale = os.path.join(self.out, "apply", "stale.yaml")
-        os.makedirs(os.path.dirname(stale))
-        open(stale, "w").close()
-        tool = self._tool(
-            "open(%r, 'wb').write(%r)\n" % (self.source, self.files[0].edited)
-        )
-        self.assertIsNone(apply.apply_source_edits(tool, self.files, self.out, False))
-        self.assertFalse(os.path.exists(stale))
-
-    def test_a_failing_tool_is_a_problem_with_its_status(self):
-        problem = apply.apply_source_edits(
-            self._tool("sys.exit(3)\n"), self.files, self.out, False
-        )
-        self.assertEqual(3, problem.exit_status)
-        self.assertEqual("clang-apply-replacements failed (exit 3)", problem.message)
-
-    def test_a_tool_that_writes_something_else_is_a_problem(self):
-        problem = apply.apply_source_edits(
-            self._tool("pass\n"), self.files, self.out, False
-        )
-        self.assertEqual(
-            "clang-apply-replacements did not write what the patch shows:",
-            problem.message,
-        )
-        self.assertEqual(["a.cpp"], problem.details)
-
-
-if __name__ == "__main__":
-    unittest.main()
diff --git a/clang/tools/clang-ssaf-driver/tests/test_driver.py b/clang/tools/clang-ssaf-driver/tests/test_driver.py
deleted file mode 100644
index 6e2312b08572f..0000000000000
--- a/clang/tools/clang-ssaf-driver/tests/test_driver.py
+++ /dev/null
@@ -1,124 +0,0 @@
-# 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
-
-import io
-import json
-import os
-import shutil
-import tempfile
-import unittest
-from unittest import mock
-
-from clang_ssaf_driver import driver, make_orchestrator, source_edits
-from clang_ssaf_driver.source_edits import Replacement
-
-
-class Running(unittest.TestCase):
-    def setUp(self):
-        self.tmp = os.path.realpath(tempfile.mkdtemp())
-        self.addCleanup(shutil.rmtree, self.tmp, True)
-        self.project = os.path.join(self.tmp, "project")
-        os.makedirs(os.path.join(self.project, "src"))
-        self.addCleanup(os.chdir, os.getcwd())
-        os.chdir(self.project)
-        with open("src/a.cpp", "wb") as handle:
-            handle.write(b"int *p;\n")
-        self.out = os.path.join(self.project, "out")
-        os.makedirs(self.out)
-        orchestrator = os.path.join(self.tmp, "clang-ssaf-orchestrator-make")
-        open(orchestrator, "w").close()
-        for name, value in (
-            ("find_orchestrator", mock.Mock(return_value=orchestrator)),
-            ("run_orchestrator", mock.Mock(return_value=(0, self._results()))),
-        ):
-            patcher = mock.patch.object(make_orchestrator, name, value)
-            patcher.start()
-            self.addCleanup(patcher.stop)
-
-    def _results(self):
-        edits = os.path.join(self.tmp, "prg.edits.yaml")
-        source_edits.write_source_edits(
-            edits, [Replacement("src/a.cpp", 0, 5, "bounded_ptr<int> ")]
-        )
-        report = os.path.join(self.tmp, "prg.report.sarif")
-        with open(report, "w") as handle:
-            json.dump(
-                {
-                    "runs": [
-                        {
-                            "results": [
-                                {
-                                    "level": "note",
-                                    "message": {"text": "m"},
-                                    "ruleId": "r",
-                                }
-                            ]
-                        }
-                    ]
-                },
-                handle,
-            )
-        return {"source-edits": edits, "transformation-report": report}
-
-    def _main(self, *extra):
-        stdout, stderr = io.StringIO(), io.StringIO()
-        with mock.patch("sys.stdout", stdout), mock.patch("sys.stderr", stderr):
-            status = driver.main(
-                ["--transformation=cpp-bounded-buffers", "-o", "out"]
-                + list(extra)
-                + ["--", "make"]
-            )
-        return status, stdout.getvalue(), stderr.getvalue()
-
-    def test_a_run_writes_the_patch_and_the_report_and_names_them(self):
-        status, stdout, stderr = self._main()
-        self.assertEqual(0, status)
-        patch_path = os.path.join(self.out, "cpp-bounded-buffers.patch")
-        report_path = os.path.join(self.out, "cpp-bounded-buffers.sarif")
-        self.assertEqual("patch: %s\nreport: %s\n" % (patch_path, report_path), stdout)
-        self.assertEqual("clang-ssaf-driver: note: m [r]\n1 r reported\n", stderr)
-        with open(patch_path, "rb") as handle:
-            self.assertIn(b"+bounded_ptr<int> p;\n", handle.read())
-        with open(report_path) as handle:
-            self.assertEqual(1, len(json.load(handle)["runs"]))
-        with open("src/a.cpp", "rb") as handle:
-            self.assertEqual(b"int *p;\n", handle.read())
-
-    def test_a_failed_orchestrator_run_writes_nothing(self):
-        make_orchestrator.run_orchestrator.return_value = (2, {})
-        status, stdout, stderr = self._main()
-        self.assertEqual(2, status)
-        self.assertEqual("", stdout)
-        self.assertEqual(
-            "clang-ssaf-driver: error: clang-ssaf-orchestrator-make failed (exit 2)\n",
-            stderr,
-        )
-        self.assertEqual([], os.listdir(self.out))
-
-    def test_a_run_without_source_edits_is_a_problem(self):
-        make_orchestrator.run_orchestrator.return_value = (0, {})
-        status, _, stderr = self._main()
-        self.assertEqual(1, status)
-        self.assertIn("reported no source edits", stderr)
-
-    def test_a_missing_orchestrator_stops_the_run_before_it_starts(self):
-        make_orchestrator.find_orchestrator.return_value = os.path.join(
-            self.tmp, "nothing-here"
-        )
-        status, _, stderr = self._main()
-        self.assertEqual(1, status)
-        self.assertIn("cannot find clang-ssaf-orchestrator-make", stderr)
-        make_orchestrator.run_orchestrator.assert_not_called()
-
-    def test_a_missing_clang_apply_replacements_stops_the_run_before_it_starts(self):
-        status, _, stderr = self._main(
-            "--apply", "--clang-apply-replacements=" + os.path.join(self.tmp, "none")
-        )
-        self.assertEqual(1, status)
-        self.assertIn("--apply needs clang-apply-replacements", stderr)
-        make_orchestrator.run_orchestrator.assert_not_called()
-
-
-if __name__ == "__main__":
-    unittest.main()
diff --git a/clang/tools/clang-ssaf-driver/tests/test_make_orchestrator.py b/clang/tools/clang-ssaf-driver/tests/test_make_orchestrator.py
deleted file mode 100644
index ec406fc4051f2..0000000000000
--- a/clang/tools/clang-ssaf-driver/tests/test_make_orchestrator.py
+++ /dev/null
@@ -1,137 +0,0 @@
-# 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
-
-import io
-import os
-import shutil
-import sys
-import tempfile
-import unittest
-from unittest import mock
-
-from clang_ssaf_driver import make_orchestrator, options
-from clang_ssaf_driver.transformations import TRANSFORMATIONS
-
-
-class Command(unittest.TestCase):
-    def test_the_orchestrator_runs_the_recipe_under_this_python(self):
-        command_line_opts, _ = options.resolve(
-            [
-                "--transformation=cpp-bounded-buffers",
-                "-o",
-                "out",
-                "--ssaf-clang=/x/clang",
-                "make",
-                "-j8",
-            ]
-        )
-        self.assertEqual(
-            [
-                sys.executable,
-                "/prefix/bin/clang-ssaf-orchestrator-make",
-                "--extract-summaries=PointerFlow,TypeConstrainedPointers,"
-                "UnsafeBufferUsage,VirtualMethod",
-                "--analysis=UnsafeBufferReachableAnalysisResult",
-                "--transformation=cpp-bounded-buffers",
-                "--output-dir=out",
-                "--ssaf-clang=/x/clang",
-                "--",
-                "make",
-                "-j8",
-            ],
-            make_orchestrator.orchestrator_command(
-                "/prefix/bin/clang-ssaf-orchestrator-make",
-                TRANSFORMATIONS["cpp-bounded-buffers"],
-                command_line_opts,
-            ),
-        )
-
-    def test_the_orchestrator_is_the_one_installed_beside_the_driver(self):
-        with mock.patch.object(
-            make_orchestrator,
-            "__file__",
-            "/prefix/lib/clang_ssaf_driver/make_orchestrator.py",
-        ):
-            self.assertEqual(
-                "/prefix/bin/clang-ssaf-orchestrator-make",
-                make_orchestrator.find_orchestrator(),
-            )
-
-
-class Results(unittest.TestCase):
-    def test_a_result_line_is_read(self):
-        self.assertEqual(
-            ("source-edits", "/out/prg.edits.yaml"),
-            make_orchestrator.read_result(b"source-edits: /out/prg.edits.yaml\n"),
-        )
-
-    def test_nothing_else_is(self):
-        for line in (
-            b"clang++ -c -o build/a.o src/a.cpp\n",
-            b"link-unit: /p/prg\n",
-            b"source-edits:\n",
-            b"make: source-edits: /x\n",
-        ):
-            self.assertIsNone(make_orchestrator.read_result(line))
-
-    def test_a_path_that_is_not_utf8_survives(self):
-        _, path = make_orchestrator.read_result(b"source-edits: /out/\xff.yaml\n")
-        self.assertEqual(b"/out/\xff.yaml", os.fsencode(path))
-
-
-class Running(unittest.TestCase):
-    def setUp(self):
-        self.tmp = tempfile.mkdtemp()
-        self.addCleanup(shutil.rmtree, self.tmp, True)
-
-    def _run(self, body):
-        script = os.path.join(self.tmp, "orchestrator")
-        with open(script, "w") as handle:
-            handle.write("import os, signal, sys\nout = sys.stdout.buffer\n" + body)
-        relay = io.BytesIO()
-        status, results = make_orchestrator.run_orchestrator(
-            [sys.executable, script], False, relay
-        )
-        return status, results, relay.getvalue()
-
-    def test_everything_is_relayed_and_the_last_results_are_kept(self):
-        printed = (
-            b"make: entering\n"
-            b"source-edits: /old\n"
-            b"\xff not utf8\n"
-            b"source-edits: /out/prg.edits.yaml\n"
-            b"transformation-report: /out/prg.report.sarif\n"
-            b"conflict-report: /out/prg.conflict-report.sarif\n"
-            b"output-dir: /out\n"
-        )
-        status, results, relayed = self._run("out.write(%r)\n" % printed)
-        self.assertEqual(0, status)
-        self.assertEqual(printed, relayed)
-        self.assertEqual(
-            {
-                "source-edits": "/out/prg.edits.yaml",
-                "transformation-report": "/out/prg.report.sarif",
-                "conflict-report": "/out/prg.conflict-report.sarif",
-            },
-            results,
-        )
-
-    def test_the_exit_status_passes_through(self):
-        status, _, _ = self._run("sys.exit(3)\n")
-        self.assertEqual(3, status)
-
-    def test_death_by_a_signal_is_the_shells_status_for_it(self):
-        status, _, _ = self._run("os.kill(os.getpid(), signal.SIGTERM)\n")
-        self.assertEqual(128 + 15, status)
-
-    def test_a_result_glued_to_the_builds_last_output_is_not_read(self):
-        printed = b"no newline" + b"source-edits: /x\n"
-        status, results, relayed = self._run("out.write(%r)\n" % printed)
-        self.assertEqual(0, status)
-        self.assertEqual(printed, relayed)
-        self.assertEqual({}, results)
-
-
-if __name__ == "__main__":
-    unittest.main()
diff --git a/clang/tools/clang-ssaf-driver/tests/test_options.py b/clang/tools/clang-ssaf-driver/tests/test_options.py
deleted file mode 100644
index ff02a812806f7..0000000000000
--- a/clang/tools/clang-ssaf-driver/tests/test_options.py
+++ /dev/null
@@ -1,107 +0,0 @@
-# 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
-
-import contextlib
-import io
-import os
-import shutil
-import unittest
-from unittest import mock
-
-from clang_ssaf_driver import options
-
-
-class Resolve(unittest.TestCase):
-    def _resolve(self, *extra):
-        return options.resolve(["--transformation=cpp-bounded-buffers"] + list(extra))
-
-    def test_a_valid_command_line_yields_the_options_as_typed(self):
-        command_line_opts, problem = self._resolve("-o", "out", "--", "make", "-j8")
-        self.assertIsNone(problem)
-        self.assertEqual(["make", "-j8"], command_line_opts.build_command)
-        self.assertEqual("cpp-bounded-buffers", command_line_opts.transformation)
-        self.assertEqual("out", command_line_opts.output_dir)
-        self.assertFalse(command_line_opts.apply)
-        self.assertEqual([], command_line_opts.orchestrator_args)
-
-    def test_the_separator_before_the_build_command_is_optional(self):
-        command_line_opts, problem = self._resolve("make", "-j8")
-        self.assertIsNone(problem)
-        self.assertEqual(["make", "-j8"], command_line_opts.build_command)
-
-    def test_an_option_after_the_build_command_is_the_builds(self):
-        command_line_opts, _ = self._resolve("make", "--apply")
-        self.assertEqual(["make", "--apply"], command_line_opts.build_command)
-        self.assertFalse(command_line_opts.apply)
-
-    def test_no_build_command_is_a_usage_error(self):
-        _, problem = self._resolve("--")
-        self.assertEqual(options.USAGE_ERROR, problem.exit_status)
-        self.assertEqual("no build command given", problem.message)
-
-    def test_the_transformation_is_required_and_must_be_known(self):
-        for argv in (["--", "make"], ["--transformation=nonexistent", "--", "make"]):
-            with mock.patch("sys.stderr", io.StringIO()):
-                with self.assertRaises(SystemExit) as raised:
-                    options.resolve(argv)
-            self.assertEqual(options.USAGE_ERROR, raised.exception.code)
-
-    def test_the_orchestrator_gets_each_forwarded_option_with_its_value(self):
-        command_line_opts, _ = self._resolve(
-            "--ssaf-clang=/x/clang",
-            "--ssaf-merge-conflict-report",
-            "/x/merge",
-            "--ssaf-extra-clang-arg=-DX",
-            "--ssaf-extra-clang-arg=-DY",
-            "-k",
-            "-v",
-            "--",
-            "make",
-        )
-        self.assertEqual(
-            [
-                "--ssaf-clang=/x/clang",
-                "--ssaf-merge-conflict-report=/x/merge",
-                "--ssaf-extra-clang-arg=-DX",
-                "--ssaf-extra-clang-arg=-DY",
-                "--keep-going",
-                "--verbose",
-            ],
-            command_line_opts.orchestrator_args,
-        )
-
-    def test_apply_and_its_tool_are_kept_for_the_driver(self):
-        command_line_opts, _ = self._resolve(
-            "--apply", "--clang-apply-replacements=/x/car", "--", "make"
-        )
-        self.assertTrue(command_line_opts.apply)
-        self.assertEqual("/x/car", command_line_opts.clang_apply_replacements)
-        self.assertEqual([], command_line_opts.orchestrator_args)
-
-    def test_resolving_makes_none_of_the_calls_the_driver_makes(self):
-        watched = (
-            (os, "getcwd"),
-            (os, "access"),
-            (os.path, "isfile"),
-            (os.path, "realpath"),
-            (shutil, "which"),
-        )
-        with contextlib.ExitStack() as stack:
-            for module, name in watched:
-                stack.enter_context(
-                    mock.patch.object(
-                        module,
-                        name,
-                        side_effect=AssertionError("%s called" % name),
-                    )
-                )
-            command_line_opts, problem = self._resolve(
-                "--apply", "--clang-apply-replacements=car", "--", "make"
-            )
-        self.assertIsNone(problem)
-        self.assertEqual("car", command_line_opts.clang_apply_replacements)
-
-
-if __name__ == "__main__":
-    unittest.main()
diff --git a/clang/tools/clang-ssaf-driver/tests/test_patch.py b/clang/tools/clang-ssaf-driver/tests/test_patch.py
deleted file mode 100644
index dec9a729b2003..0000000000000
--- a/clang/tools/clang-ssaf-driver/tests/test_patch.py
+++ /dev/null
@@ -1,237 +0,0 @@
-# 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
-
-import os
-import shutil
-import subprocess
-import tempfile
-import unittest
-
-from clang_ssaf_driver import patch
-from clang_ssaf_driver.source_edits import Replacement
-
-
-class ApplyingEdits(unittest.TestCase):
-    def _apply(self, original, edits):
-        return patch.apply_edits(original, sorted(edits))
-
-    def test_replacements_deletions_and_insertions(self):
-        self.assertEqual(
-            (b"bounded_ptr<int> p; q[4]/*T*/;", None),
-            self._apply(
-                b"int *p; q[4];",
-                [(0, 5, "bounded_ptr<int> "), (12, 0, "/*T*/")],
-            ),
-        )
-        self.assertEqual((b"int q;", None), self._apply(b"int q[4];", [(5, 3, "")]))
-
-    def test_an_insertion_goes_before_a_replacement_at_its_offset(self):
-        self.assertEqual(
-            (b"(bounded_ptr<int> )p", None),
-            self._apply(b"int *p", [(0, 0, "("), (0, 5, "bounded_ptr<int> )")]),
-        )
-
-    def test_an_insertion_at_the_end_of_a_replacement_follows_it(self):
-        self.assertEqual((b"Yx", None), self._apply(b"ab", [(0, 2, "Y"), (2, 0, "x")]))
-
-    def test_overlapping_edits_are_refused(self):
-        _, problem = self._apply(b"abcdef", [(0, 3, "x"), (2, 2, "y")])
-        self.assertEqual("edits overlap at byte 2", problem)
-        _, problem = self._apply(b"abcdef", [(1, 0, "x"), (1, 0, "y")])
-        self.assertEqual("edits overlap at byte 1", problem)
-
-    def test_an_edit_past_the_end_is_refused(self):
-        _, problem = self._apply(b"abc", [(2, 2, "x")])
-        self.assertEqual("an edit at byte 2 runs past the end of the file", problem)
-
-    def test_the_text_goes_in_as_utf8(self):
-        self.assertEqual(
-            ("éb".encode("utf-8"), None), self._apply(b"ab", [(0, 1, "é")])
-        )
-
-
-class Collecting(unittest.TestCase):
-    def setUp(self):
-        self.tmp = os.path.realpath(tempfile.mkdtemp())
-        self.addCleanup(shutil.rmtree, self.tmp, True)
-        self.root = os.path.join(self.tmp, "project")
-        os.makedirs(os.path.join(self.root, "src"))
-
-    def _file(self, relative, content):
-        path = os.path.join(self.root, relative)
-        os.makedirs(os.path.dirname(path), exist_ok=True)
-        with open(path, "wb") as handle:
-            handle.write(content)
-        return path
-
-    def _collect(self, replacements, conflicts=None):
-        collected, problem = patch.collect(replacements, self.root, conflicts or {})
-        self.assertIsNone(problem)
-        return collected
-
-    def test_edits_are_grouped_by_file_and_sorted(self):
-        self._file("src/b.cpp", b"int *b;\n")
-        self._file("src/a.cpp", b"int *a;\n")
-        collected = self._collect(
-            [
-                Replacement("src/b.cpp", 0, 5, "bounded_ptr<int> "),
-                Replacement("src/a.cpp", 0, 5, "bounded_ptr<int> "),
-            ]
-        )
-        self.assertEqual(
-            ["src/a.cpp", "src/b.cpp"], [f.relative_path for f in collected.files]
-        )
-        self.assertEqual(b"bounded_ptr<int> a;\n", collected.files[0].edited)
-        self.assertEqual(([], []), (collected.outside, collected.blocked))
-
-    def test_every_spelling_of_a_file_is_one_file_and_an_edit_counts_once(self):
-        header = self._file("src/h.h", b"int *g;\n")
-        os.link(header, os.path.join(self.root, "src", "linked.h"))
-        edit = (0, 5, "bounded_ptr<int> ")
-        collected = self._collect(
-            [
-                Replacement("src/h.h", *edit),
-                Replacement("src/../src/h.h", *edit),
-                Replacement(header, *edit),
-                Replacement("src/linked.h", *edit),
-            ]
-        )
-        self.assertEqual(["src/h.h"], [f.relative_path for f in collected.files])
-        self.assertEqual([edit], collected.files[0].edits)
-
-    def test_an_edit_that_overlaps_a_reported_conflict_is_left_out(self):
-        header = self._file("src/h.h", b"0123456789abcdef")
-        collected = self._collect(
-            [
-                Replacement("src/h.h", 0, 2, "A"),
-                Replacement("src/h.h", 2, 0, "B"),
-                Replacement("src/h.h", 4, 4, "C"),
-                Replacement("src/h.h", 7, 0, "D"),
-                Replacement("src/h.h", 10, 2, "E"),
-            ],
-            {header: [(2, 9)]},
-        )
-        self.assertEqual(
-            [(0, 2, "A"), (2, 0, "B"), (10, 2, "E")], collected.files[0].edits
-        )
-        self.assertEqual([("src/h.h", 2)], collected.blocked)
-
-    def test_a_file_whose_edits_all_conflict_is_left_out(self):
-        header = self._file("src/h.h", b"int *g;\n")
-        collected = self._collect(
-            [Replacement("src/h.h", 0, 5, "bounded_ptr<int> ")], {header: [(0, 5)]}
-        )
-        self.assertEqual([], collected.files)
-        self.assertEqual([("src/h.h", 1)], collected.blocked)
-
-    def test_a_file_outside_the_project_is_left_out(self):
-        self._file("src/a.cpp", b"int *a;\n")
-        elsewhere = os.path.join(self.tmp, "elsewhere.h")
-        with open(elsewhere, "wb") as handle:
-            handle.write(b"int *x;\n")
-        collected = self._collect(
-            [
-                Replacement("src/a.cpp", 0, 5, "bounded_ptr<int> "),
-                Replacement(elsewhere, 0, 5, "bounded_ptr<int> "),
-            ]
-        )
-        self.assertEqual(["src/a.cpp"], [f.relative_path for f in collected.files])
-        self.assertEqual([elsewhere], collected.outside)
-
-    def test_every_file_that_cannot_be_edited_is_reported_at_once(self):
-        self._file("src/a.cpp", b"abc")
-        collected, problem = patch.collect(
-            [
-                Replacement("src/a.cpp", 2, 5, "x"),
-                Replacement("src/missing.cpp", 0, 0, "x"),
-            ],
-            self.root,
-            {},
-        )
-        self.assertIsNone(collected)
-        self.assertEqual("the source edits cannot be applied:", problem.message)
-        self.assertEqual(
-            [
-                "src/a.cpp: an edit at byte 2 runs past the end of the file",
-                "src/missing.cpp: No such file or directory",
-            ],
-            list(problem.details),
-        )
-
-
-class Rendering(unittest.TestCase):
-    def setUp(self):
-        self.tmp = os.path.realpath(tempfile.mkdtemp())
-        self.addCleanup(shutil.rmtree, self.tmp, True)
-
-    def _render(self, original, edits, name="src/a.cpp"):
-        edited, problem = patch.apply_edits(original, edits)
-        self.assertIsNone(problem)
-        path = os.path.join(self.tmp, name)
-        return patch.render([patch.FileEdits(name, path, edits, original, edited)])
-
-    def test_a_unified_diff_with_paths_under_a_and_b(self):
-        self.assertEqual(
-            b"--- a/src/a.cpp\n"
-            b"+++ b/src/a.cpp\n"
-            b"@@ -1,3 +1,3 @@\n"
-            b" int f();\n"
-            b"-int *p;\n"
-            b"+bounded_ptr<int> p;\n"
-            b" int g();\n",
-            self._render(
-                b"int f();\nint *p;\nint g();\n", [(9, 5, "bounded_ptr<int> ")]
-            ),
-        )
-
-    def test_a_missing_final_newline_is_marked(self):
-        self.assertEqual(
-            b"--- a/src/a.cpp\n"
-            b"+++ b/src/a.cpp\n"
-            b"@@ -1 +1 @@\n"
-            b"-int *p;\n"
-            b"\\ No newline at end of file\n"
-            b"+bounded_ptr<int> p;\n"
-            b"\\ No newline at end of file\n",
-            self._render(b"int *p;", [(0, 5, "bounded_ptr<int> ")]),
-        )
-
-    def test_line_ends_and_bytes_are_kept_as_they_are(self):
-        rendered = self._render(
-            b"\xff\r\nint *p;\r\nold\rmac\n", [(3, 5, "bounded_ptr<int> ")]
-        )
-        self.assertIn(b"-int *p;\r\n+bounded_ptr<int> p;\r\n", rendered)
-        self.assertIn(b" old\rmac\n", rendered)
-
-    def test_no_edits_is_an_empty_patch(self):
-        self.assertEqual(b"", patch.render([]))
-
-    @unittest.skipUnless(shutil.which("patch"), "needs patch")
-    def test_patch_applies_what_was_rendered(self):
-        cases = {
-            "src/a.cpp": (b"int f();\nint *p;\nint g();\n", [(9, 5, "q ")]),
-            "src/b.cpp": (b"int *p;", [(0, 5, "bounded_ptr<int> ")]),
-            "src/c.cpp": (b"a\r\nint *p;\r\nb\rc\n", [(3, 5, "x")]),
-        }
-        files = []
-        for name, (original, edits) in sorted(cases.items()):
-            path = os.path.join(self.tmp, name)
-            os.makedirs(os.path.dirname(path), exist_ok=True)
-            with open(path, "wb") as handle:
-                handle.write(original)
-            edited, _ = patch.apply_edits(original, edits)
-            files.append(patch.FileEdits(name, path, edits, original, edited))
-        subprocess.run(
-            ["patch", "-p1", "-s"],
-            input=patch.render(files),
-            cwd=self.tmp,
-            check=True,
-        )
-        for each in files:
-            with open(each.path, "rb") as handle:
-                self.assertEqual(each.edited, handle.read())
-
-
-if __name__ == "__main__":
-    unittest.main()
diff --git a/clang/tools/clang-ssaf-driver/tests/test_report.py b/clang/tools/clang-ssaf-driver/tests/test_report.py
deleted file mode 100644
index ba60c6928590e..0000000000000
--- a/clang/tools/clang-ssaf-driver/tests/test_report.py
+++ /dev/null
@@ -1,204 +0,0 @@
-# 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
-
-import json
-import os
-import shutil
-import tempfile
-import unittest
-
-from clang_ssaf_driver import report
-
-
-def _location(uri, **region):
-    return {"physicalLocation": {"artifactLocation": {"uri": uri}, "region": region}}
-
-
-def _log(*results):
-    return {"runs": [{"results": list(results)}]}
-
-
-class Loading(unittest.TestCase):
-    def setUp(self):
-        self.tmp = tempfile.mkdtemp()
-        self.addCleanup(shutil.rmtree, self.tmp, True)
-
-    def _write(self, name, document):
-        path = os.path.join(self.tmp, name)
-        with open(path, "w") as handle:
-            if isinstance(document, str):
-                handle.write(document)
-            else:
-                json.dump(document, handle)
-        return path
-
-    def test_the_runs_of_both_reports_make_one_log(self):
-        transformation = self._write(
-            "t.sarif", {"runs": [{"tool": {"driver": {"name": "clang-ssaf"}}}]}
-        )
-        conflicts = self._write(
-            "c.sarif",
-            {"runs": [{"tool": {"driver": {"name": "clang-ssaf-src-edit-merge"}}}]},
-        )
-        log, problem = report.load([transformation, conflicts])
-        self.assertIsNone(problem)
-        self.assertEqual("2.1.0", log["version"])
-        self.assertEqual(
-            ["clang-ssaf", "clang-ssaf-src-edit-merge"],
-            [run["tool"]["driver"]["name"] for run in log["runs"]],
-        )
-
-    def test_an_absent_report_adds_nothing(self):
-        conflicts = self._write("c.sarif", {"runs": [{"results": []}]})
-        log, problem = report.load([None, conflicts])
-        self.assertIsNone(problem)
-        self.assertEqual([{"results": []}], log["runs"])
-
-    def test_what_is_not_a_sarif_log_is_a_problem(self):
-        _, problem = report.load([self._write("list.sarif", "[]")])
-        self.assertIn("not a SARIF log", problem.message)
-        _, problem = report.load([self._write("bad.sarif", "{")])
-        self.assertIn("cannot read the report", problem.message)
-
-    def test_the_log_is_written_as_json(self):
-        log, _ = report.load([])
-        path = os.path.join(self.tmp, "out.sarif")
-        report.write(path, log)
-        with open(path) as handle:
-            self.assertEqual(log, json.load(handle))
-
-
-class Diagnostics(unittest.TestCase):
-    def setUp(self):
-        self.root = os.path.realpath(tempfile.mkdtemp())
-        self.addCleanup(shutil.rmtree, self.root, True)
-        os.makedirs(os.path.join(self.root, "src"))
-        with open(os.path.join(self.root, "src", "shared.h"), "wb") as handle:
-            handle.write(b"ab\ncdef\n")
-        self.shared = "file://" + os.path.join(self.root, "src", "shared.h")
-
-    def test_a_finding_reads_like_a_compiler_diagnostic(self):
-        log = _log(
-            {
-                "level": "note",
-                "locations": [_location(self.shared, startLine=3, startColumn=7)],
-                "message": {"text": "not yet rewritten"},
-                "ruleId": "cpp-bounded-buffers-skipped",
-            }
-        )
-        self.assertEqual(
-            [
-                "src/shared.h:3:7: note: not yet rewritten "
-                "[cpp-bounded-buffers-skipped]",
-                "1 cpp-bounded-buffers-skipped reported",
-            ],
-            report.diagnostics(log, self.root),
-        )
-
-    def test_a_conflict_is_placed_by_its_bytes_and_followed_by_its_candidates(self):
-        log = _log(
-            {
-                "level": "error",
-                "locations": [_location(self.shared, byteOffset=5)],
-                "message": {"text": "dropped"},
-                "relatedLocations": [
-                    dict(
-                        _location(self.shared, byteOffset=3, byteLength=2),
-                        message={"text": 'candidate edit: "x"'},
-                    )
-                ],
-                "ruleId": "conflict",
-            }
-        )
-        self.assertEqual(
-            [
-                "src/shared.h:2:3: error: dropped [conflict]",
-                'src/shared.h:2:1: note: candidate edit: "x"',
-                "1 conflict reported",
-            ],
-            report.diagnostics(log, self.root),
-        )
-
-    def test_a_file_outside_the_project_keeps_its_whole_path(self):
-        log = _log(
-            {
-                "level": "note",
-                "locations": [_location("file:///usr/include/my%20lib.h", startLine=1)],
-                "message": {"text": "m"},
-                "ruleId": "r",
-            }
-        )
-        self.assertEqual(
-            "/usr/include/my lib.h:1:1: note: m [r]",
-            report.diagnostics(log, self.root)[0],
-        )
-
-    def test_a_finding_without_a_location_is_the_drivers_own(self):
-        self.assertEqual(
-            "clang-ssaf-driver: warning: m [r]",
-            report.diagnostics(_log({"message": {"text": "m"}, "ruleId": "r"}), "/")[0],
-        )
-
-    def test_the_findings_are_counted_per_rule(self):
-        finding = {"locations": [_location(self.shared, startLine=1)]}
-        log = {
-            "runs": [
-                {"results": [dict(finding, ruleId="b"), dict(finding, ruleId="a")]},
-                {"results": [dict(finding, ruleId="b")]},
-            ]
-        }
-        self.assertEqual("1 a, 2 b reported", report.diagnostics(log, self.root)[-1])
-
-    def test_no_findings_print_nothing(self):
-        self.assertEqual([], report.diagnostics(_log(), self.root))
-
-    def test_a_merge_tools_path_is_read_as_written(self):
-        path = os.path.join(self.root, "src", "a#b?c.h")
-        with open(path, "wb") as handle:
-            handle.write(b"x\ny\n")
-        log = _log(
-            {
-                "locations": [_location("file://" + path, byteOffset=2)],
-                "message": {"text": "m"},
-                "ruleId": "r",
-            }
-        )
-        self.assertEqual(
-            "src/a#b?c.h:2:1: warning: m [r]", report.diagnostics(log, self.root)[0]
-        )
-
-
-class ConflictRanges(unittest.TestCase):
-    def test_every_candidate_of_every_conflict_is_a_range(self):
-        log = {
-            "runs": [
-                {"results": [{"locations": [_location("file:///p/a.h", startLine=1)]}]},
-                {
-                    "results": [
-                        {
-                            "locations": [_location("file:///p/h.h", byteOffset=4)],
-                            "relatedLocations": [
-                                _location("file:///p/h.h", byteOffset=4, byteLength=3),
-                                _location("file:///p/h.h", byteOffset=6, byteLength=9),
-                            ],
-                        },
-                        {
-                            "relatedLocations": [
-                                _location(
-                                    "file:///p/my%20c.h", byteOffset=0, byteLength=1
-                                )
-                            ]
-                        },
-                    ]
-                },
-            ]
-        }
-        self.assertEqual(
-            {"/p/h.h": [(4, 7), (6, 15)], "/p/my c.h": [(0, 1)]},
-            report.conflict_ranges(log),
-        )
-
-
-if __name__ == "__main__":
-    unittest.main()
diff --git a/clang/tools/clang-ssaf-driver/tests/test_source_edits.py b/clang/tools/clang-ssaf-driver/tests/test_source_edits.py
deleted file mode 100644
index e4cb94e007c57..0000000000000
--- a/clang/tools/clang-ssaf-driver/tests/test_source_edits.py
+++ /dev/null
@@ -1,171 +0,0 @@
-# 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
-
-import os
-import shutil
-import tempfile
-import unittest
-
-from clang_ssaf_driver import source_edits
-from clang_ssaf_driver.source_edits import Replacement
-
-
-def _entry(file_path, offset, length, text):
-    return [
-        "  - FilePath:        %s" % file_path,
-        "    Offset:          %d" % offset,
-        "    Length:          %d" % length,
-        "    ReplacementText: %s" % text,
-    ]
-
-
-class Reading(unittest.TestCase):
-    def setUp(self):
-        self.tmp = tempfile.mkdtemp()
-        self.addCleanup(shutil.rmtree, self.tmp, True)
-        self.path = os.path.join(self.tmp, "edits.yaml")
-
-    def _read(self, lines, line_end=b"\n"):
-        with open(self.path, "wb") as handle:
-            handle.write(line_end.join(line.encode("utf-8") for line in lines))
-            handle.write(line_end)
-        return source_edits.read_source_edits(self.path)
-
-    def _document(self, *entries):
-        lines = ["---", "MainSourceFile:  ''", "Replacements:"]
-        for entry in entries:
-            lines.extend(entry)
-        return lines + ["..."]
-
-    def test_every_scalar_the_merge_tool_writes_is_read(self):
-        written = [
-            ("plain", "plain"),
-            ("a\tb", "a\tb"),
-            ("' lead'", " lead"),
-            ("'it''s'", "it's"),
-            ("''", ""),
-            ("'4'", "4"),
-            ("'true'", "true"),
-            ('"line\\nbreak"', "line\nbreak"),
-            ("'tab\tand\"quote\\'", 'tab\tand"quote\\'),
-            ('"\\x01\x7f"', "\x01\x7f"),
-            ('"\u00e9"', "\u00e9"),
-            ('"\U0001F600"', "\U0001F600"),
-            ('"\\L\\N\\_"', "\u2028\x85\xa0"),
-        ]
-        replacements, problem = self._read(
-            self._document(
-                *[
-                    _entry("'src/f.cpp'", index * 5, 1, text)
-                    for index, (text, _) in enumerate(written)
-                ]
-            )
-        )
-        self.assertIsNone(problem)
-        self.assertEqual(
-            [
-                Replacement("src/f.cpp", index * 5, 1, text)
-                for index, (_, text) in enumerate(written)
-            ],
-            replacements,
-        )
-
-    def test_every_escape_of_a_double_quoted_scalar_is_read(self):
-        replacements, problem = self._read(
-            self._document(
-                _entry(
-                    "f.cpp",
-                    0,
-                    0,
-                    '"\\0\\a\\b\\t\\n\\v\\f\\r\\e\\"\\\\\\x41\\u00e9\\U0001F600"',
-                )
-            )
-        )
-        self.assertIsNone(problem)
-        self.assertEqual(
-            '\0\a\b\t\n\v\f\r\x1b"\\A\u00e9\U0001F600', replacements[0].text
-        )
-
-    def test_no_replacements_is_an_empty_list(self):
-        replacements, problem = self._read(
-            ["---", "MainSourceFile:  ''", "Replacements:    []", "..."]
-        )
-        self.assertIsNone(problem)
-        self.assertEqual([], replacements)
-
-    def test_crlf_line_ends_are_read(self):
-        replacements, problem = self._read(
-            self._document(_entry("f.cpp", 1, 2, "x")), line_end=b"\r\n"
-        )
-        self.assertIsNone(problem)
-        self.assertEqual([Replacement("f.cpp", 1, 2, "x")], replacements)
-
-    def _problem(self, lines):
-        replacements, problem = self._read(lines)
-        self.assertIsNone(replacements)
-        return problem.message
-
-    def test_a_truncated_file_is_malformed(self):
-        self.assertEqual(
-            "malformed source edits: %s:7: expected '...'" % self.path,
-            self._problem(self._document(_entry("f.cpp", 1, 2, "x"))[:-1]),
-        )
-
-    def test_a_malformed_line_is_reported_with_its_number(self):
-        lines = self._document(_entry("f.cpp", 1, 2, "x"))
-        lines[4] = "    Offset:          one"
-        self.assertEqual(
-            "malformed source edits: %s:5: expected a number, got 'one'" % self.path,
-            self._problem(lines),
-        )
-
-    def test_an_unknown_escape_is_malformed(self):
-        self.assertIn(
-            "unknown escape '\\q'",
-            self._problem(self._document(_entry("f.cpp", 1, 2, '"\\q"'))),
-        )
-
-    def test_a_replacement_missing_a_field_is_malformed(self):
-        self.assertIn(
-            "replacement without 'ReplacementText'",
-            self._problem(self._document(_entry("f.cpp", 1, 2, "x")[:3])),
-        )
-
-    def test_a_file_that_cannot_be_read_is_a_problem(self):
-        _, problem = source_edits.read_source_edits(self.path)
-        self.assertIn("cannot read the source edits", problem.message)
-
-
-class Writing(unittest.TestCase):
-    def setUp(self):
-        self.tmp = tempfile.mkdtemp()
-        self.addCleanup(shutil.rmtree, self.tmp, True)
-        self.path = os.path.join(self.tmp, "edits.yaml")
-
-    def test_what_is_written_reads_back(self):
-        replacements = [
-            Replacement(os.path.join(self.tmp, "f.cpp"), 0, 3, text)
-            for text in (
-                "",
-                "bounded_ptr<int> ",
-                "it's",
-                'a "quote" and a \\',
-                "line\nbreak\ttab\r",
-                "\x01\x7f",
-                "\u00e9\U0001F600",
-                "\x85\u2028\u2029",
-            )
-        ]
-        source_edits.write_source_edits(self.path, replacements)
-        self.assertEqual(
-            (replacements, None), source_edits.read_source_edits(self.path)
-        )
-
-    def test_no_replacements_reads_back_as_none(self):
-        source_edits.write_source_edits(self.path, [])
-        self.assertEqual(([], None), source_edits.read_source_edits(self.path))
-
-
-if __name__ == "__main__":
-    unittest.main()

>From eedc8f36e33e3cd3dd339a6ae2c9aed9efaf7a6c Mon Sep 17 00:00:00 2001
From: Balazs Benics <benicsbalazs at gmail.com>
Date: Thu, 15 Oct 2026 11:53:30 +0100
Subject: [PATCH 06/14] Revert "[clang][ssaf][orchestrator] Merge
 transformation reports per link unit (#231957)"

This reverts commit ba6d822f43f05f30c1860a079053287f69ba1850.
---
 .../developer-docs/MakeOrchestratorShims.md   |  7 +-
 .../user-docs/MakeProjects.md                 | 51 ++---------
 .../Scalable/ssaf-orchestrator-make/help.test |  2 -
 .../transformation-reports.test               | 88 ------------------
 .../ssaf-orchestrator-make/two-pass.test      |  3 +-
 .../clang_ssaf_orchestrator_make/config.py    |  4 -
 .../config_orchestrator.py                    | 24 -----
 .../failure_logs.py                           |  2 -
 .../logging_diagnostics.py                    |  8 +-
 .../clang_ssaf_orchestrator_make/options.py   | 19 ----
 .../orchestrator.py                           |  7 +-
 .../clang_ssaf_orchestrator_make/shims/ar.py  |  4 +-
 .../shims/clang.py                            | 29 +++---
 .../shims/commands.py                         |  7 +-
 .../clang_ssaf_orchestrator_make/shims/ld.py  |  4 +-
 .../shims/shim.py                             | 89 ++++---------------
 .../ssaf_artifact_repository.py               | 14 +--
 .../tests/configs.py                          |  2 -
 .../tests/test_ar_shim.py                     |  5 +-
 .../tests/test_clang_shim.py                  | 37 ++------
 .../tests/test_config.py                      | 10 +--
 .../tests/test_config_orchestrator.py         | 16 ----
 .../tests/test_ld_shim.py                     | 83 +----------------
 .../tests/test_logging_diagnostics.py         | 11 ++-
 .../tests/test_ssaf_artifact_repository.py    | 34 ++++---
 25 files changed, 93 insertions(+), 467 deletions(-)
 delete mode 100644 clang/test/Analysis/Scalable/ssaf-orchestrator-make/transformation-reports.test

diff --git a/clang/docs/ScalableStaticAnalysis/developer-docs/MakeOrchestratorShims.md b/clang/docs/ScalableStaticAnalysis/developer-docs/MakeOrchestratorShims.md
index e251d98e52f72..0d6d3c10ef2e0 100644
--- a/clang/docs/ScalableStaticAnalysis/developer-docs/MakeOrchestratorShims.md
+++ b/clang/docs/ScalableStaticAnalysis/developer-docs/MakeOrchestratorShims.md
@@ -48,7 +48,7 @@ The shim bodies live in the package, as `clang_ssaf_orchestrator_make.shims`,
 split by what they do:
 
 ```text
-shim.py          the Shim class, its diagnostics, the transformation merges
+shim.py          the Shim class, its diagnostics, merge_edits
 commands.py      Files, is_object, is_archive, artifact_of, summary_of,
                  filter_build_artifacts, unique
 driver_jobs.py   Job and the -### listing reader
@@ -131,11 +131,6 @@ transform    source-edit generation for a compilation
 link         clang-ssaf-linker over a link's inputs
 archive      the same for an archive
 merge        clang-ssaf-src-edit-merge over a link's or an archive's inputs
-transformation-report
-             clang-ssaf-merge-transformation-report over the same inputs
-conflict-report
-             clang-ssaf-merge-conflict-report over the same inputs and the
-             conflicts of the merge itself
 forward      handing a job to the shim that stands in for its tool
 missing      an artifact with nothing analysed behind it
 driver-jobs  the driver refused to list a command's jobs
diff --git a/clang/docs/ScalableStaticAnalysis/user-docs/MakeProjects.md b/clang/docs/ScalableStaticAnalysis/user-docs/MakeProjects.md
index ae163b8c13890..eabba61108e18 100644
--- a/clang/docs/ScalableStaticAnalysis/user-docs/MakeProjects.md
+++ b/clang/docs/ScalableStaticAnalysis/user-docs/MakeProjects.md
@@ -45,9 +45,8 @@ There are three workflows, each going one step further than the last:
 - **Whole-program analysis**, adding `--analysis`. `clang-ssaf-analyzer` runs
   the named analyses over the link unit summary.
 - **Whole-program transformation**, adding `--transformation`. A second build
-  generates source edits and transformation reports from the analysis result,
-  and they are merged across the whole program, together with the reports of
-  the edits that conflicted.
+  generates source edits from the analysis result, and they are merged across
+  the whole program.
 
 Summary extraction and linking:
 
@@ -68,7 +67,7 @@ $ clang-ssaf-orchestrator-make \
     -- make -j8
 ```
 
-Whole-program transformation, which ends in merged source edits and reports:
+Whole-program transformation, which ends in merged source edits:
 
 ```console
 $ clang-ssaf-orchestrator-make \
@@ -112,12 +111,6 @@ orchestrator only the `make` invocation.
    * - ``--ssaf-src-edit-merge=<path>``
      - Path to ``clang-ssaf-src-edit-merge``. Defaults to the name on
        ``PATH``, and is only required with ``--transformation``.
-   * - ``--ssaf-merge-transformation-report=<path>``
-     - Path to ``clang-ssaf-merge-transformation-report``. Defaults to the
-       name on ``PATH``, and is only required with ``--transformation``.
-   * - ``--ssaf-merge-conflict-report=<path>``
-     - Path to ``clang-ssaf-merge-conflict-report``. Defaults to the name on
-       ``PATH``, and is only required with ``--transformation``.
    * - ``--ssaf-extra-clang-arg=<arg>``
      - Extra argument for every SSAF compilation. Repeatable.
    * - ``-k``, ``--keep-going``
@@ -167,14 +160,9 @@ translation units, and only the whole path tells them apart.
    * - ``<output-dir>/ssaf-artifacts/<path>.edits.yaml``
      - Source edits for the ``<path>`` build artifact.
    * - ``<output-dir>/ssaf-artifacts/<path>.conflicts.sarif``
-     - Edits dropped because they conflicted when the build assembled
-       ``<path>``.
-   * - ``<output-dir>/ssaf-artifacts/<path>.conflict-report.sarif``
-     - Every conflict behind the ``<path>`` build artifact: its own, and its
-       inputs'.
+     - Edits dropped because they conflicted.
    * - ``<output-dir>/ssaf-artifacts/<path>.report.sarif``
-     - Transformation report for the ``<path>`` build artifact: a
-       compilation's own, and its inputs' merged where the build assembled it.
+     - Transformation report for the ``<path>`` build artifact.
    * - ``<output-dir>/config-analysis.json``
      - Configuration for the analysis pass, the first build pass.
    * - ``<output-dir>/config-transformation.json``
@@ -199,35 +187,6 @@ input contributes the summary filed under its own id or nothing at all,
 so an artifact whose SSAF step failed takes the artifacts behind it down
 with it, and the run says so and exits non-zero.
 
-## Results
-
-A run names what it produced on stdout, which it shares with the build, one
-`key: value` line each:
-
-```{eval-rst}
-.. list-table::
-   :header-rows: 1
-
-   * - Key
-     - Value
-   * - ``summaries``
-     - How many summaries were written, for compilations, archives and links.
-   * - ``link-unit``
-     - The top-most build artifact.
-   * - ``link-unit-summary``
-     - Its summary.
-   * - ``analysis-result``
-     - The whole-program analysis result, with ``--analysis``.
-   * - ``source-edits``
-     - The link unit's merged source edits, with ``--transformation``.
-   * - ``transformation-report``
-     - The link unit's merged transformation report.
-   * - ``conflict-report``
-     - Every conflict found while merging the link unit's source edits.
-   * - ``output-dir``
-     - The output directory.
-```
-
 ## Failure handling
 
 A failing build step fails the run with the build's own exit status, and no
diff --git a/clang/test/Analysis/Scalable/ssaf-orchestrator-make/help.test b/clang/test/Analysis/Scalable/ssaf-orchestrator-make/help.test
index 0e9a2087ce747..3fefaae801bce 100644
--- a/clang/test/Analysis/Scalable/ssaf-orchestrator-make/help.test
+++ b/clang/test/Analysis/Scalable/ssaf-orchestrator-make/help.test
@@ -13,8 +13,6 @@
 # SSAF: --ssaf-linker
 # SSAF: --ssaf-analyzer
 # SSAF: --ssaf-src-edit-merge
-# SSAF: --ssaf-merge-transformation-report
-# SSAF: --ssaf-merge-conflict-report
 # SSAF: --ssaf-extra-clang-arg
 # SSAF: --keep-going
 # SSAF: --verbose
diff --git a/clang/test/Analysis/Scalable/ssaf-orchestrator-make/transformation-reports.test b/clang/test/Analysis/Scalable/ssaf-orchestrator-make/transformation-reports.test
deleted file mode 100644
index 5cb1fa5d55d75..0000000000000
--- a/clang/test/Analysis/Scalable/ssaf-orchestrator-make/transformation-reports.test
+++ /dev/null
@@ -1,88 +0,0 @@
-# REQUIRES: ssaf-orchestrator-make-build
-# RUN: rm -rf %t && split-file %s %t
-# RUN: mkdir -p %t/build
-
-# The link unit's transformation report holds the findings of every
-# translation unit once, and its conflict report holds the conflicts found
-# while merging any of its parts.
-
-# RUN: cd %t
-# RUN: %clang-ssaf-orchestrator-make \
-# RUN:     --extract-summaries=PointerFlow,UnsafeBufferUsage \
-# RUN:     --analysis=UnsafeBufferReachableAnalysisResult \
-# RUN:     --transformation=cpp-bounded-buffers \
-# RUN:     --ssaf-clang=%ssaf-orchestrator-make-clang \
-# RUN:     -o %t/out -- make \
-# RUN:   | FileCheck %s --check-prefix=STDOUT
-# STDOUT: source-edits: {{[^ ]*}}/out/ssaf-artifacts{{[^ ]*}}/build/prg.edits.yaml
-# STDOUT: transformation-report: {{[^ ]*}}/out/ssaf-artifacts{{[^ ]*}}/build/prg.report.sarif
-# STDOUT: conflict-report: {{[^ ]*}}/out/ssaf-artifacts{{[^ ]*}}/build/prg.conflict-report.sarif
-
-# Every translation unit reports the declaration group in the header; the
-# link unit's report has each of its two declarators once.
-# RUN: FileCheck %s --check-prefix=REPORT \
-# RUN:   --input-file=%t/out/ssaf-artifacts%t/build/prg.report.sarif
-# RUN: grep 'multi-declarator group' \
-# RUN:   %t/out/ssaf-artifacts%t/build/prg.report.sarif | count 4
-# REPORT:      "results": [
-# REPORT:        "uri": "file://{{.*}}/src/main.cpp"
-# REPORT:        "uri": "file://{{.*}}/src/main.cpp"
-# REPORT:        "uri": "file://{{.*}}/src/shared.h"
-# REPORT:        "text": "declarator of a multi-declarator group is not yet rewritten"
-# REPORT:        "uri": "file://{{.*}}/src/shared.h"
-# REPORT:        "text": "declarator of a multi-declarator group is not yet rewritten"
-# REPORT-NOT:    "uri":
-# REPORT:      "tool": {
-
-# The two halves of the archive disagree on the header, so the archive's
-# merge drops both edits. The link's own merge finds no conflict, yet the
-# link unit's conflict report has the archive's.
-# RUN: grep clang-reforge-replacement-conflict \
-# RUN:   %t/out/ssaf-artifacts%t/build/libparts.a.conflicts.sarif | count 1
-# RUN: not grep clang-reforge-replacement-conflict \
-# RUN:   %t/out/ssaf-artifacts%t/build/prg.conflicts.sarif
-# RUN: FileCheck %s --check-prefix=CONFLICTS \
-# RUN:   --input-file=%t/out/ssaf-artifacts%t/build/prg.conflict-report.sarif
-# CONFLICTS:      "results": [
-# CONFLICTS:        "uri": "file://{{.*}}/src/shared.h"
-# CONFLICTS:        "byteOffset": 39
-# CONFLICTS:        "ruleId": "clang-reforge-replacement-conflict"
-# CONFLICTS-NOT:    "ruleId":
-# CONFLICTS:        "name": "clang-ssaf-src-edit-merge",
-
-#--- Makefile
-CXX = clang++
-all: build/prg
-build/%.o: src/%.cpp src/shared.h
-	$(CXX) -c -o $@ $<
-build/libparts.a: build/a.o build/b.o
-	ar rcs $@ build/a.o build/b.o
-build/prg: build/main.o build/libparts.a
-	$(CXX) -o $@ build/main.o build/libparts.a
-
-#--- src/shared.h
-extern int *p, *q;
-extern
-#if USE_LONG
-long
-#else
-int
-#endif
-*g;
-
-#--- src/a.cpp
-#include "shared.h"
-int *g;
-int a() { return p[1] + q[1] + g[5]; }
-
-#--- src/b.cpp
-#define USE_LONG 1
-#include "shared.h"
-long b() { return p[2] + g[7]; }
-
-#--- src/main.cpp
-#include "shared.h"
-int *p, *q;
-int a();
-long b();
-int main() { return a() + (int)b(); }
diff --git a/clang/test/Analysis/Scalable/ssaf-orchestrator-make/two-pass.test b/clang/test/Analysis/Scalable/ssaf-orchestrator-make/two-pass.test
index 6d5362981b369..c9b19bd5ac7b2 100644
--- a/clang/test/Analysis/Scalable/ssaf-orchestrator-make/two-pass.test
+++ b/clang/test/Analysis/Scalable/ssaf-orchestrator-make/two-pass.test
@@ -16,8 +16,7 @@
 # STDOUT: link-unit: {{[^ ]*}}/build/prg
 # STDOUT: analysis-result: {{[^ ]*}}/out/wpa.json
 # STDOUT: source-edits: {{[^ ]*}}/out/ssaf-artifacts{{[^ ]*}}/build/prg.edits.yaml
-# STDOUT: transformation-report: {{[^ ]*}}/out/ssaf-artifacts{{[^ ]*}}/build/prg.report.sarif
-# STDOUT: conflict-report: {{[^ ]*}}/out/ssaf-artifacts{{[^ ]*}}/build/prg.conflict-report.sarif
+# STDOUT-NOT: edit-conflicts
 
 # RUN: ls %t/out/ssaf-artifacts%t/build/main.o.summary.json %t/out/ssaf-artifacts%t/build/parse.o.summary.json
 # RUN: ls %t/out/ssaf-artifacts%t/build/main.o.edits.yaml \
diff --git a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/config.py b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/config.py
index 75845d0b487d5..8c876b34dfdcb 100644
--- a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/config.py
+++ b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/config.py
@@ -95,15 +95,11 @@ def __init__(
         ssaf_clang=None,
         ssaf_extra_clang_args=(),
         ssaf_src_edit_merge=None,
-        ssaf_merge_transformation_report=None,
-        ssaf_merge_conflict_report=None,
         transformation=None,
         link_unit_id=None,
     ):
         super().__init__(ssaf_clang, ssaf_extra_clang_args)
         self.ssaf_src_edit_merge = ssaf_src_edit_merge
-        self.ssaf_merge_transformation_report = ssaf_merge_transformation_report
-        self.ssaf_merge_conflict_report = ssaf_merge_conflict_report
         self.transformation = transformation
         self.link_unit_id = link_unit_id
 
diff --git a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/config_orchestrator.py b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/config_orchestrator.py
index 8fe1c0bb3f9a8..f47b4f05cc73e 100644
--- a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/config_orchestrator.py
+++ b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/config_orchestrator.py
@@ -127,28 +127,6 @@ def configure(command_line_opts, env):
         if command_line_opts.transformation
         else None
     )
-    ssaf_merge_transformation_report = (
-        _resolve_ssaf_tool(
-            "--ssaf-merge-transformation-report",
-            "clang-ssaf-merge-transformation-report",
-            command_line_opts.ssaf_merge_transformation_report,
-            installed_shim_dir_path,
-            errors,
-        )
-        if command_line_opts.transformation
-        else None
-    )
-    ssaf_merge_conflict_report = (
-        _resolve_ssaf_tool(
-            "--ssaf-merge-conflict-report",
-            "clang-ssaf-merge-conflict-report",
-            command_line_opts.ssaf_merge_conflict_report,
-            installed_shim_dir_path,
-            errors,
-        )
-        if command_line_opts.transformation
-        else None
-    )
 
     if errors:
         return None, options.Problem(
@@ -178,8 +156,6 @@ def configure(command_line_opts, env):
     transformation_config = (
         config.SSAFTransformationPassConfig(
             ssaf_src_edit_merge=ssaf_src_edit_merge,
-            ssaf_merge_transformation_report=ssaf_merge_transformation_report,
-            ssaf_merge_conflict_report=ssaf_merge_conflict_report,
             transformation=command_line_opts.transformation,
             **common_pass_config,
         )
diff --git a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/failure_logs.py b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/failure_logs.py
index 5758619a95b6c..80ca84d7f52a9 100644
--- a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/failure_logs.py
+++ b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/failure_logs.py
@@ -18,8 +18,6 @@ class SSAFFailureKind(enum.Enum):
     LINK = "link"
     ARCHIVE = "archive"
     MERGE = "merge"
-    TRANSFORMATION_REPORT = "transformation-report"
-    CONFLICT_REPORT = "conflict-report"
     FORWARD = "forward"
     MISSING = "missing"
     DRIVER_JOBS = "driver-jobs"
diff --git a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/logging_diagnostics.py b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/logging_diagnostics.py
index a539bc46ca604..96c6ff3293b63 100644
--- a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/logging_diagnostics.py
+++ b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/logging_diagnostics.py
@@ -41,9 +41,7 @@ def report_analysis_result(wpa_result_path):
     report_info("analysis-result", wpa_result_path)
 
 
-def report_transformation(merged, transformation_report, conflict_report):
+def report_transformation(merged, conflicts_paths):
     report_info("source-edits", merged)
-    if transformation_report:
-        report_info("transformation-report", transformation_report)
-    if conflict_report:
-        report_info("conflict-report", conflict_report)
+    for conflicts_path in conflicts_paths:
+        report_info("edit-conflicts", conflicts_path)
diff --git a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/options.py b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/options.py
index 19885ea466dab..3e720de577bf3 100644
--- a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/options.py
+++ b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/options.py
@@ -79,19 +79,6 @@ def build_parser():
         default=None,
         help="Path to clang-ssaf-src-edit-merge (default: found on PATH).",
     )
-    parser.add_argument(
-        "--ssaf-merge-transformation-report",
-        metavar="<path>",
-        default=None,
-        help="Path to clang-ssaf-merge-transformation-report "
-        "(default: found on PATH).",
-    )
-    parser.add_argument(
-        "--ssaf-merge-conflict-report",
-        metavar="<path>",
-        default=None,
-        help="Path to clang-ssaf-merge-conflict-report (default: found on PATH).",
-    )
     parser.add_argument(
         "--ssaf-extra-clang-arg",
         metavar="<arg>",
@@ -134,8 +121,6 @@ def __init__(
         ssaf_linker=None,
         ssaf_analyzer=None,
         ssaf_src_edit_merge=None,
-        ssaf_merge_transformation_report=None,
-        ssaf_merge_conflict_report=None,
         keep_going=False,
         verbose=False,
     ):
@@ -149,8 +134,6 @@ def __init__(
         self.ssaf_linker = ssaf_linker
         self.ssaf_analyzer = ssaf_analyzer
         self.ssaf_src_edit_merge = ssaf_src_edit_merge
-        self.ssaf_merge_transformation_report = ssaf_merge_transformation_report
-        self.ssaf_merge_conflict_report = ssaf_merge_conflict_report
         self.keep_going = keep_going
         self.verbose = verbose
 
@@ -183,8 +166,6 @@ def resolve(argv):
             ssaf_linker=args.ssaf_linker,
             ssaf_analyzer=args.ssaf_analyzer,
             ssaf_src_edit_merge=args.ssaf_src_edit_merge,
-            ssaf_merge_transformation_report=args.ssaf_merge_transformation_report,
-            ssaf_merge_conflict_report=args.ssaf_merge_conflict_report,
             keep_going=args.keep_going,
             verbose=args.verbose,
         ),
diff --git a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/orchestrator.py b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/orchestrator.py
index 06ba03e57fe49..ce2a73cbebb0b 100644
--- a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/orchestrator.py
+++ b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/orchestrator.py
@@ -195,12 +195,7 @@ def run_ssaf_transformation_pass(
         )
     logging_diagnostics.report_transformation(
         ssaf_artifact_repo.get_path_for_artifact(edits),
-        ssaf_artifact_repo.get_path_if_present(
-            get_ssaf_artifact_id(link_unit, SSAFArtifactKind.REPORT)
-        ),
-        ssaf_artifact_repo.get_path_if_present(
-            get_ssaf_artifact_id(link_unit, SSAFArtifactKind.CONFLICT_REPORT)
-        ),
+        ssaf_artifact_repo.get_conflicts(),
     )
     return None
 
diff --git a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/ar.py b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/ar.py
index e8c7268f68ea8..70237e0e6f888 100644
--- a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/ar.py
+++ b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/ar.py
@@ -17,7 +17,7 @@
     summary_of,
     unique,
 )
-from .shim import merge_transformation_outputs
+from .shim import merge_edits
 
 
 _CREATING_OPERATIONS = frozenset("rqm")
@@ -63,7 +63,7 @@ def invoke_ssaf_tools(shim, cwd):
     )
 
     if shim.pass_config.pass_kind == config.SSAFPassKind.TRANSFORMATION:
-        merge_transformation_outputs(shim, build_artifact_id, input_build_artifact_ids)
+        merge_edits(shim, build_artifact_id, input_build_artifact_ids)
         return
 
     shim.build_graph.record_build_step(
diff --git a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/clang.py b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/clang.py
index 87ddf85e93994..f00ae9bf62767 100644
--- a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/clang.py
+++ b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/clang.py
@@ -90,7 +90,7 @@ def _summary_extraction_args(shim, build_artifact_id):
         "--ssaf-compilation-unit-id=" + build_artifact_id.get_path(),
         "--ssaf-tu-summary-file=" + summary,
     ]
-    return [summary], extra + shim.pass_config.ssaf_extra_clang_args
+    return summary, extra + shim.pass_config.ssaf_extra_clang_args
 
 
 def _transformation_args(shim, build_artifact_id):
@@ -100,11 +100,6 @@ def _transformation_args(shim, build_artifact_id):
             get_ssaf_artifact_id(build_artifact_id, SSAFArtifactKind.EDITS)
         )
     )
-    report = utils.make_parents(
-        ssaf_artifact_repo.get_path_for_artifact(
-            get_ssaf_artifact_id(build_artifact_id, SSAFArtifactKind.REPORT)
-        )
-    )
     extra = [
         "--ssaf-source-transformation=" + shim.pass_config.transformation,
         "--ssaf-global-scope-analysis-result="
@@ -112,9 +107,14 @@ def _transformation_args(shim, build_artifact_id):
         "--ssaf-compilation-unit-id=" + build_artifact_id.get_path(),
         "--ssaf-link-unit-id=" + shim.pass_config.link_unit_id,
         "--ssaf-src-edit-file=" + edits,
-        "--ssaf-transformation-report-file=" + report,
+        "--ssaf-transformation-report-file="
+        + utils.make_parents(
+            ssaf_artifact_repo.get_path_for_artifact(
+                get_ssaf_artifact_id(build_artifact_id, SSAFArtifactKind.REPORT)
+            )
+        ),
     ]
-    return [edits, report], extra + shim.pass_config.ssaf_extra_clang_args
+    return edits, extra + shim.pass_config.ssaf_extra_clang_args
 
 
 def _run_clang_driven_tool(shim, cwd):
@@ -129,19 +129,18 @@ def _run_clang_driven_tool(shim, cwd):
     output = os.path.join(cwd, job.output)
     build_artifact_id = BuildArtifactId(output)
     if shim.pass_config.pass_kind == config.SSAFPassKind.TRANSFORMATION:
-        artifacts, extra = _transformation_args(shim, build_artifact_id)
+        artifact, extra = _transformation_args(shim, build_artifact_id)
         failure_kind = SSAFFailureKind.TRANSFORM
     else:
-        artifacts, extra = _summary_extraction_args(shim, build_artifact_id)
+        artifact, extra = _summary_extraction_args(shim, build_artifact_id)
         failure_kind = SSAFFailureKind.EXTRACT
     ssaf_command = [shim.pass_config.ssaf_clang] + shim.argv[1:] + extra
 
     if not shim.run(ssaf_command, failure_kind, build_artifact_id):
-        for artifact in artifacts:
-            try:
-                os.remove(artifact)
-            except OSError:
-                pass
+        try:
+            os.remove(artifact)
+        except OSError:
+            pass
         logging_diagnostics.report_error(
             "discarded incomplete artifact for %s" % build_artifact_id.get_path()
         )
diff --git a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/commands.py b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/commands.py
index e604a13c5ffaa..f290ae9097797 100644
--- a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/commands.py
+++ b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/commands.py
@@ -23,9 +23,10 @@ def is_archive(filename):
 
 
 def artifact_of(ssaf_artifact_repo, build_artifact_id, ssaf_artifact_kind):
-    return ssaf_artifact_repo.get_path_if_present(
-        get_ssaf_artifact_id(build_artifact_id, ssaf_artifact_kind)
-    )
+    ssaf_artifact_id = get_ssaf_artifact_id(build_artifact_id, ssaf_artifact_kind)
+    if not ssaf_artifact_repo.has_artifact(ssaf_artifact_id):
+        return None
+    return ssaf_artifact_repo.get_path_for_artifact(ssaf_artifact_id)
 
 
 def summary_of(ssaf_artifact_repo, build_artifact_id):
diff --git a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/ld.py b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/ld.py
index d5df06388da4c..3d1e5924623ed 100644
--- a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/ld.py
+++ b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/ld.py
@@ -17,7 +17,7 @@
     summary_of,
     unique,
 )
-from .shim import merge_transformation_outputs
+from .shim import merge_edits
 
 
 def identify_inputs_output(argv):
@@ -80,7 +80,7 @@ def invoke_ssaf_tools(shim, cwd):
     )
 
     if shim.pass_config.pass_kind == config.SSAFPassKind.TRANSFORMATION:
-        merge_transformation_outputs(shim, build_artifact_id, input_build_artifact_ids)
+        merge_edits(shim, build_artifact_id, input_build_artifact_ids)
         return
 
     shim.build_graph.record_build_step(
diff --git a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/shim.py b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/shim.py
index 911b6d04520bc..5180bced1ab30 100644
--- a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/shim.py
+++ b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/shim.py
@@ -188,42 +188,28 @@ def protect(self, work):
         return 0
 
 
-def _input_artifacts(ssaf_artifact_repo, input_build_artifact_ids, ssaf_artifact_kind):
-    found = []
-    for each in input_build_artifact_ids:
-        artifact = artifact_of(ssaf_artifact_repo, each, ssaf_artifact_kind)
-        if artifact:
-            found.append(artifact)
-    return unique(found)
-
-
-def _output_artifact(ssaf_artifact_repo, build_artifact_id, ssaf_artifact_kind):
-    return utils.make_parents(
-        ssaf_artifact_repo.get_path_for_artifact(
-            get_ssaf_artifact_id(build_artifact_id, ssaf_artifact_kind)
-        )
-    )
-
-
-def _report_nothing_to_merge(shim, what, build_artifact_id):
-    logging_diagnostics.report_note(
-        shim.workflow_config.verbose,
-        "no %s feed %s, nothing to merge" % (what, build_artifact_id.get_path()),
-    )
-
-
 def merge_edits(shim, build_artifact_id, input_build_artifact_ids):
     ssaf_artifact_repo = shim.ssaf_artifact_repo
-    found = _input_artifacts(
-        ssaf_artifact_repo, input_build_artifact_ids, SSAFArtifactKind.EDITS
-    )
+    found = []
+    for each in input_build_artifact_ids:
+        edits = artifact_of(ssaf_artifact_repo, each, SSAFArtifactKind.EDITS)
+        if edits:
+            found.append(edits)
+    found = unique(found)
     if not found:
-        _report_nothing_to_merge(shim, "edits", build_artifact_id)
+        logging_diagnostics.report_note(
+            shim.workflow_config.verbose,
+            "no edits feed %s, nothing to merge" % build_artifact_id.get_path(),
+        )
         return
     command = [shim.pass_config.ssaf_src_edit_merge] + found
     command += [
         "-o",
-        _output_artifact(ssaf_artifact_repo, build_artifact_id, SSAFArtifactKind.EDITS),
+        utils.make_parents(
+            ssaf_artifact_repo.get_path_for_artifact(
+                get_ssaf_artifact_id(build_artifact_id, SSAFArtifactKind.EDITS)
+            )
+        ),
     ]
     command += [
         "--sarif-conflicts-out="
@@ -232,48 +218,3 @@ def merge_edits(shim, build_artifact_id, input_build_artifact_ids):
         )
     ]
     shim.run(command, SSAFFailureKind.MERGE, build_artifact_id)
-
-
-def merge_transformation_reports(shim, build_artifact_id, input_build_artifact_ids):
-    ssaf_artifact_repo = shim.ssaf_artifact_repo
-    found = _input_artifacts(
-        ssaf_artifact_repo, input_build_artifact_ids, SSAFArtifactKind.REPORT
-    )
-    if not found:
-        _report_nothing_to_merge(shim, "transformation reports", build_artifact_id)
-        return
-    command = [shim.pass_config.ssaf_merge_transformation_report] + found
-    command += [
-        "-o",
-        _output_artifact(
-            ssaf_artifact_repo, build_artifact_id, SSAFArtifactKind.REPORT
-        ),
-    ]
-    shim.run(command, SSAFFailureKind.TRANSFORMATION_REPORT, build_artifact_id)
-
-
-def merge_conflict_reports(shim, build_artifact_id, input_build_artifact_ids):
-    ssaf_artifact_repo = shim.ssaf_artifact_repo
-    found = _input_artifacts(
-        ssaf_artifact_repo, input_build_artifact_ids, SSAFArtifactKind.CONFLICT_REPORT
-    )
-    own = artifact_of(ssaf_artifact_repo, build_artifact_id, SSAFArtifactKind.CONFLICTS)
-    if own:
-        found.append(own)
-    if not found:
-        _report_nothing_to_merge(shim, "conflict reports", build_artifact_id)
-        return
-    command = [shim.pass_config.ssaf_merge_conflict_report] + found
-    command += [
-        "-o",
-        _output_artifact(
-            ssaf_artifact_repo, build_artifact_id, SSAFArtifactKind.CONFLICT_REPORT
-        ),
-    ]
-    shim.run(command, SSAFFailureKind.CONFLICT_REPORT, build_artifact_id)
-
-
-def merge_transformation_outputs(shim, build_artifact_id, input_build_artifact_ids):
-    merge_edits(shim, build_artifact_id, input_build_artifact_ids)
-    merge_transformation_reports(shim, build_artifact_id, input_build_artifact_ids)
-    merge_conflict_reports(shim, build_artifact_id, input_build_artifact_ids)
diff --git a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/ssaf_artifact_repository.py b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/ssaf_artifact_repository.py
index 51ced735233dd..5d920673350cf 100644
--- a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/ssaf_artifact_repository.py
+++ b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/ssaf_artifact_repository.py
@@ -14,7 +14,6 @@ class SSAFArtifactKind(enum.Enum):
     EDITS = ".edits.yaml"
     CONFLICTS = ".conflicts.sarif"
     REPORT = ".report.sarif"
-    CONFLICT_REPORT = ".conflict-report.sarif"
 
 
 class SSAFArtifactId:
@@ -55,11 +54,6 @@ def get_path_for_artifact(self, ssaf_artifact_id):
     def has_artifact(self, ssaf_artifact_id):
         return os.path.exists(self.get_path_for_artifact(ssaf_artifact_id))
 
-    def get_path_if_present(self, ssaf_artifact_id):
-        if not self.has_artifact(ssaf_artifact_id):
-            return None
-        return self.get_path_for_artifact(ssaf_artifact_id)
-
     def _all_paths_of_kind(self, ssaf_artifact_kind):
         return find_with_suffix(self.ssaf_artifact_dir, ssaf_artifact_kind.value)
 
@@ -74,3 +68,11 @@ def get_link_unit_name(self, summary_path):
 
     def count_summaries(self):
         return len(self._all_paths_of_kind(SSAFArtifactKind.SUMMARY))
+
+    def get_conflicts(self):
+        found = []
+        for path in self._all_paths_of_kind(SSAFArtifactKind.CONFLICTS):
+            document = read_json(path)
+            if document and any(run.get("results") for run in document.get("runs", [])):
+                found.append(path)
+        return sorted(found)
diff --git a/clang/tools/clang-ssaf-orchestrator-make/tests/configs.py b/clang/tools/clang-ssaf-orchestrator-make/tests/configs.py
index f4bf87669b06d..f95799c68e648 100644
--- a/clang/tools/clang-ssaf-orchestrator-make/tests/configs.py
+++ b/clang/tools/clang-ssaf-orchestrator-make/tests/configs.py
@@ -26,8 +26,6 @@ def transformation_config(**overrides):
         ssaf_clang="/bin/clang",
         ssaf_extra_clang_args=[],
         ssaf_src_edit_merge="/bin/clang-ssaf-src-edit-merge",
-        ssaf_merge_transformation_report="/bin/clang-ssaf-merge-transformation-report",
-        ssaf_merge_conflict_report="/bin/clang-ssaf-merge-conflict-report",
         transformation="x",
     )
     fields.update(overrides)
diff --git a/clang/tools/clang-ssaf-orchestrator-make/tests/test_ar_shim.py b/clang/tools/clang-ssaf-orchestrator-make/tests/test_ar_shim.py
index 8c30a7c30b939..cfe3daaceabf3 100644
--- a/clang/tools/clang-ssaf-orchestrator-make/tests/test_ar_shim.py
+++ b/clang/tools/clang-ssaf-orchestrator-make/tests/test_ar_shim.py
@@ -105,9 +105,8 @@ def test_in_the_transformation_pass_the_edits_are_merged_instead(self):
             ar.invoke_ssaf_tools(shim, self.root)
         self.assertEqual(
             [
-                "no %s feed %s, nothing to merge"
-                % (what, self._id("build/libx.a").get_path())
-                for what in ("edits", "transformation reports", "conflict reports")
+                "no edits feed %s, nothing to merge"
+                % self._id("build/libx.a").get_path()
             ],
             notes,
         )
diff --git a/clang/tools/clang-ssaf-orchestrator-make/tests/test_clang_shim.py b/clang/tools/clang-ssaf-orchestrator-make/tests/test_clang_shim.py
index 0ff2b2f6ffe6d..3fa76cc37312e 100644
--- a/clang/tools/clang-ssaf-orchestrator-make/tests/test_clang_shim.py
+++ b/clang/tools/clang-ssaf-orchestrator-make/tests/test_clang_shim.py
@@ -148,7 +148,7 @@ def _shim(self, pass_config=None):
 
     def test_extraction_names_the_unit_and_where_its_summary_goes(self):
         shim = self._shim()
-        (summary,), extra = clang._summary_extraction_args(shim, self._id("build/a.o"))
+        summary, extra = clang._summary_extraction_args(shim, self._id("build/a.o"))
         self.assertIn("--ssaf-extract-summaries=PointerFlow", extra)
         self.assertIn(
             "--ssaf-compilation-unit-id=" + self._id("build/a.o").get_path(), extra
@@ -160,13 +160,15 @@ def test_transformation_names_the_link_unit_and_the_analysis_result(self):
         pass_config = configs.transformation_config()
         pass_config.name_link_unit(self._id("build/prg").get_path())
         shim = self._shim(pass_config)
-        (edits, report), extra = clang._transformation_args(shim, self._id("build/a.o"))
+        edits, extra = clang._transformation_args(shim, self._id("build/a.o"))
         self.assertIn("--ssaf-link-unit-id=" + self._id("build/prg").get_path(), extra)
         self.assertIn("--ssaf-src-edit-file=" + edits, extra)
         self.assertTrue(
             any(a.startswith("--ssaf-global-scope-analysis-result=") for a in extra)
         )
-        self.assertIn("--ssaf-transformation-report-file=" + report, extra)
+        self.assertTrue(
+            any(a.startswith("--ssaf-transformation-report-file=") for a in extra)
+        )
 
     def test_the_extra_clang_arguments_come_last(self):
         shim = self._shim(configs.analysis_config(ssaf_extra_clang_args=["-DX"]))
@@ -217,35 +219,6 @@ def test_an_incomplete_artifact_is_removed_and_reported(self):
         )
         self.assertFalse(os.path.exists(summary))
 
-    def test_a_failed_transformation_leaves_neither_edits_nor_report(self):
-        shim = configs.RecordingShim(
-            ["clang", "-cc1", "-o", "build/a.o", "a.cpp"],
-            self.out,
-            configs.transformation_config(link_unit_id="build/prg"),
-        )
-        records = configs.repository_for(self.out)
-        artifacts = [
-            records.get_path_for_artifact(
-                repository.get_ssaf_artifact_id(self._id("build/a.o"), kind)
-            )
-            for kind in (
-                repository.SSAFArtifactKind.EDITS,
-                repository.SSAFArtifactKind.REPORT,
-            )
-        ]
-
-        def run(*args):
-            for artifact in artifacts:
-                open(artifact, "w").close()
-            return False
-
-        shim._shim.run = run
-        with mock.patch("sys.stderr", mock.MagicMock()):
-            clang._run_clang_driven_tool(shim, self.tmp)
-        self.assertEqual(
-            [False, False], [os.path.exists(artifact) for artifact in artifacts]
-        )
-
     def test_the_marker_chooses_the_frontend_half(self):
         shim = self._shim(
             [
diff --git a/clang/tools/clang-ssaf-orchestrator-make/tests/test_config.py b/clang/tools/clang-ssaf-orchestrator-make/tests/test_config.py
index fad66474819ed..c6dbc9cd6341b 100644
--- a/clang/tools/clang-ssaf-orchestrator-make/tests/test_config.py
+++ b/clang/tools/clang-ssaf-orchestrator-make/tests/test_config.py
@@ -39,8 +39,6 @@ def test_a_pass_carries_only_the_tools_it_runs(self):
                 "ssaf_clang",
                 "ssaf_extra_clang_args",
                 "ssaf_src_edit_merge",
-                "ssaf_merge_transformation_report",
-                "ssaf_merge_conflict_report",
                 "transformation",
                 "link_unit_id",
             },
@@ -122,13 +120,7 @@ def test_each_pass_file_carries_only_that_pass(self):
             {"extractors", "ssaf_linker", "analyses"}, set(first) - set(second)
         )
         self.assertEqual(
-            {
-                "ssaf_src_edit_merge",
-                "ssaf_merge_transformation_report",
-                "ssaf_merge_conflict_report",
-                "transformation",
-                "link_unit_id",
-            },
+            {"ssaf_src_edit_merge", "transformation", "link_unit_id"},
             set(second) - set(first),
         )
         self.assertEqual(
diff --git a/clang/tools/clang-ssaf-orchestrator-make/tests/test_config_orchestrator.py b/clang/tools/clang-ssaf-orchestrator-make/tests/test_config_orchestrator.py
index 36bd54b931a7d..3ed1e13e2b154 100644
--- a/clang/tools/clang-ssaf-orchestrator-make/tests/test_config_orchestrator.py
+++ b/clang/tools/clang-ssaf-orchestrator-make/tests/test_config_orchestrator.py
@@ -115,8 +115,6 @@ def setUp(self):
         self.linker = self._executable("clang-ssaf-linker")
         self.analyzer = self._executable("clang-ssaf-analyzer")
         self.merge = self._executable("clang-ssaf-src-edit-merge")
-        self.report_merge = self._executable("clang-ssaf-merge-transformation-report")
-        self.conflict_merge = self._executable("clang-ssaf-merge-conflict-report")
         self.project = os.path.join(self.tmp, "project")
         os.makedirs(self.project)
         self.addCleanup(os.chdir, os.getcwd())
@@ -160,8 +158,6 @@ def test_the_configuration_holds_the_resolved_tool_not_what_was_typed(self):
             "--ssaf-linker=clang-ssaf-linker",
             "--ssaf-analyzer=clang-ssaf-analyzer",
             "--ssaf-src-edit-merge=clang-ssaf-src-edit-merge",
-            "--ssaf-merge-transformation-report=clang-ssaf-merge-transformation-report",
-            "--ssaf-merge-conflict-report=clang-ssaf-merge-conflict-report",
             "--analysis=a",
             "--transformation=x",
             "--",
@@ -179,12 +175,6 @@ def test_the_configuration_holds_the_resolved_tool_not_what_was_typed(self):
         self.assertEqual(self.linker, analysis_config.ssaf_linker)
         self.assertEqual(self.analyzer, workflow_config.ssaf_analyzer)
         self.assertEqual(self.merge, transformation_config.ssaf_src_edit_merge)
-        self.assertEqual(
-            self.report_merge, transformation_config.ssaf_merge_transformation_report
-        )
-        self.assertEqual(
-            self.conflict_merge, transformation_config.ssaf_merge_conflict_report
-        )
 
     def test_a_run_analyses_and_transforms_only_where_asked(self):
         _, analysis_config, transformation_config, problem = self._configure(
@@ -199,8 +189,6 @@ def test_a_run_analyses_and_transforms_only_where_asked(self):
             "--transformation=x",
             "--ssaf-analyzer=" + self.analyzer,
             "--ssaf-src-edit-merge=" + self.merge,
-            "--ssaf-merge-transformation-report=" + self.report_merge,
-            "--ssaf-merge-conflict-report=" + self.conflict_merge,
             "--",
             "make",
         )
@@ -214,8 +202,6 @@ def test_both_passes_get_the_clang_and_its_extra_arguments(self):
             "--transformation=x",
             "--ssaf-analyzer=" + self.analyzer,
             "--ssaf-src-edit-merge=" + self.merge,
-            "--ssaf-merge-transformation-report=" + self.report_merge,
-            "--ssaf-merge-conflict-report=" + self.conflict_merge,
             "--ssaf-extra-clang-arg=-DX",
             "--",
             "make",
@@ -367,8 +353,6 @@ def test_a_tool_no_pass_will_run_is_not_resolved_at_all(self):
         workflow_config, _, _, problem = self._configure(
             "--ssaf-analyzer=/no/such/analyzer",
             "--ssaf-src-edit-merge=/no/such/merge",
-            "--ssaf-merge-transformation-report=/no/such/report-merge",
-            "--ssaf-merge-conflict-report=/no/such/conflict-merge",
             "--",
             "make",
         )
diff --git a/clang/tools/clang-ssaf-orchestrator-make/tests/test_ld_shim.py b/clang/tools/clang-ssaf-orchestrator-make/tests/test_ld_shim.py
index 13ce9d6fe7c1e..b4f802fc8ae07 100644
--- a/clang/tools/clang-ssaf-orchestrator-make/tests/test_ld_shim.py
+++ b/clang/tools/clang-ssaf-orchestrator-make/tests/test_ld_shim.py
@@ -11,7 +11,6 @@
 from clang_ssaf_orchestrator_make.shims import ld
 from clang_ssaf_orchestrator_make import ssaf_artifact_repository as repository
 from clang_ssaf_orchestrator_make import build_graph
-from clang_ssaf_orchestrator_make.failure_logs import SSAFFailureKind
 
 from . import configs
 
@@ -150,90 +149,10 @@ def test_a_link_of_nothing_we_know_runs_no_step(self):
     def test_in_the_transformation_pass_the_edits_are_merged_instead(self):
         shim = self._run(["build/a.o"], configs.transformation_config())
         self.assertEqual(
-            [
-                "no %s feed %s, nothing to merge"
-                % (what, self._id("build/prg").get_path())
-                for what in ("edits", "transformation reports", "conflict reports")
-            ],
+            ["no edits feed %s, nothing to merge" % self._id("build/prg").get_path()],
             self.notes,
         )
 
-    def _artifact(self, relative, ssaf_artifact_kind):
-        path = utils.make_parents(
-            self.ssaf_artifact_repo.get_path_for_artifact(
-                repository.get_ssaf_artifact_id(self._id(relative), ssaf_artifact_kind)
-            )
-        )
-        open(path, "w").close()
-        return path
-
-    def test_the_reports_follow_the_edits_into_the_link(self):
-        a_edits = self._artifact("build/a.o", repository.SSAFArtifactKind.EDITS)
-        a_report = self._artifact("build/a.o", repository.SSAFArtifactKind.REPORT)
-        x_edits = self._artifact("build/libx.a", repository.SSAFArtifactKind.EDITS)
-        x_report = self._artifact("build/libx.a", repository.SSAFArtifactKind.REPORT)
-        x_conflicts = self._artifact(
-            "build/libx.a", repository.SSAFArtifactKind.CONFLICT_REPORT
-        )
-        own_conflicts = self._artifact(
-            "build/prg", repository.SSAFArtifactKind.CONFLICTS
-        )
-        shim = self._run(["build/a.o", "build/libx.a"], configs.transformation_config())
-        prg = self._id("build/prg")
-        self.assertEqual(
-            [
-                (SSAFFailureKind.MERGE, prg),
-                (SSAFFailureKind.TRANSFORMATION_REPORT, prg),
-                (SSAFFailureKind.CONFLICT_REPORT, prg),
-            ],
-            [failure for failure, _ in shim.commands],
-        )
-        _, edits = shim.commands[0]
-        _, report = shim.commands[1]
-        _, conflicts = shim.commands[2]
-        self.assertEqual(
-            ["/bin/clang-ssaf-src-edit-merge", a_edits, x_edits], edits[:3]
-        )
-        self.assertEqual(
-            [
-                "/bin/clang-ssaf-merge-transformation-report",
-                a_report,
-                x_report,
-                "-o",
-                self.ssaf_artifact_repo.get_path_for_artifact(
-                    repository.get_ssaf_artifact_id(
-                        prg, repository.SSAFArtifactKind.REPORT
-                    )
-                ),
-            ],
-            report,
-        )
-        self.assertEqual(
-            [
-                "/bin/clang-ssaf-merge-conflict-report",
-                x_conflicts,
-                own_conflicts,
-                "-o",
-                self.ssaf_artifact_repo.get_path_for_artifact(
-                    repository.get_ssaf_artifact_id(
-                        prg, repository.SSAFArtifactKind.CONFLICT_REPORT
-                    )
-                ),
-            ],
-            conflicts,
-        )
-
-    def test_a_report_is_merged_even_where_no_edits_are(self):
-        self._summary("build/a.o")
-        a_report = self._artifact("build/a.o", repository.SSAFArtifactKind.REPORT)
-        shim = self._run(["build/a.o"], configs.transformation_config())
-        self.assertEqual(
-            [(SSAFFailureKind.TRANSFORMATION_REPORT, self._id("build/prg"))],
-            [failure for failure, _ in shim.commands],
-        )
-        _, report = shim.commands[0]
-        self.assertEqual(a_report, report[1])
-
 
 if __name__ == "__main__":
     unittest.main()
diff --git a/clang/tools/clang-ssaf-orchestrator-make/tests/test_logging_diagnostics.py b/clang/tools/clang-ssaf-orchestrator-make/tests/test_logging_diagnostics.py
index d9aa5780a68a7..8f4e91edf3fd7 100644
--- a/clang/tools/clang-ssaf-orchestrator-make/tests/test_logging_diagnostics.py
+++ b/clang/tools/clang-ssaf-orchestrator-make/tests/test_logging_diagnostics.py
@@ -88,16 +88,15 @@ def test_the_analysis_result(self):
             ),
         )
 
-    def test_the_transformation_names_the_link_units_edits_and_reports(self):
+    def test_the_transformation_names_every_file_that_holds_conflicts(self):
         self.assertEqual(
             "source-edits: /out/prg.edits.yaml\n"
-            "transformation-report: /out/prg.report.sarif\n"
-            "conflict-report: /out/prg.conflict-report.sarif\n",
+            "edit-conflicts: /out/libx.a.conflicts.sarif\n"
+            "edit-conflicts: /out/prg.conflicts.sarif\n",
             self._stdout(
                 lambda: logging_diagnostics.report_transformation(
                     "/out/prg.edits.yaml",
-                    "/out/prg.report.sarif",
-                    "/out/prg.conflict-report.sarif",
+                    ["/out/libx.a.conflicts.sarif", "/out/prg.conflicts.sarif"],
                 )
             ),
         )
@@ -105,7 +104,7 @@ def test_the_transformation_names_the_link_units_edits_and_reports(self):
             "source-edits: /out/prg.edits.yaml\n",
             self._stdout(
                 lambda: logging_diagnostics.report_transformation(
-                    "/out/prg.edits.yaml", None, None
+                    "/out/prg.edits.yaml", []
                 )
             ),
         )
diff --git a/clang/tools/clang-ssaf-orchestrator-make/tests/test_ssaf_artifact_repository.py b/clang/tools/clang-ssaf-orchestrator-make/tests/test_ssaf_artifact_repository.py
index 0098dc814ad26..90280fb57d7eb 100644
--- a/clang/tools/clang-ssaf-orchestrator-make/tests/test_ssaf_artifact_repository.py
+++ b/clang/tools/clang-ssaf-orchestrator-make/tests/test_ssaf_artifact_repository.py
@@ -148,25 +148,37 @@ def test_absent_summary(self):
         self.assertIsNone(self._name())
 
 
-class PresentArtifacts(unittest.TestCase):
+class Conflicts(unittest.TestCase):
     def setUp(self):
         self.tmp = tempfile.mkdtemp()
         self.addCleanup(shutil.rmtree, self.tmp, True)
         self.ssaf_artifact_repo = configs.repository_for(self.tmp)
-        self.report = repository.get_ssaf_artifact_id(
-            build_graph.BuildArtifactId("/p/prg"),
-            repository.SSAFArtifactKind.CONFLICT_REPORT,
-        )
 
-    def test_an_artifact_on_disk_is_found(self):
+    def _write(self, build_artifact_path, results):
         path = utils.make_parents(
-            self.ssaf_artifact_repo.get_path_for_artifact(self.report)
+            self.ssaf_artifact_repo.get_path_for_artifact(
+                repository.get_ssaf_artifact_id(
+                    build_graph.BuildArtifactId(build_artifact_path),
+                    repository.SSAFArtifactKind.CONFLICTS,
+                )
+            )
         )
-        open(path, "w").close()
-        self.assertEqual(path, self.ssaf_artifact_repo.get_path_if_present(self.report))
+        with open(path, "w") as handle:
+            json.dump({"version": "2.1.0", "runs": [{"results": results}]}, handle)
+        return path
+
+    def test_a_merge_that_dropped_nothing_reports_nothing(self):
+        self._write("/p/prg", [])
+        self.assertEqual([], self.ssaf_artifact_repo.get_conflicts())
 
-    def test_an_artifact_not_on_disk_is_not(self):
-        self.assertIsNone(self.ssaf_artifact_repo.get_path_if_present(self.report))
+    def test_every_merge_that_dropped_an_edit_is_reported(self):
+        library = self._write("/p/libx.a", [{"ruleId": "conflict"}])
+        program = self._write("/p/prg", [{"ruleId": "conflict"}])
+        self._write("/p/other", [])
+        self.assertEqual(
+            sorted([library, program]),
+            self.ssaf_artifact_repo.get_conflicts(),
+        )
 
 
 class Counts(unittest.TestCase):

>From 25895a052fa0961405f5a9827305494a4d978d0b Mon Sep 17 00:00:00 2001
From: Balazs Benics <benicsbalazs at gmail.com>
Date: Thu, 15 Oct 2026 11:53:30 +0100
Subject: [PATCH 07/14] Revert "[clang][ssaf] Put clang-ssaf-orchestrator-make
 in LLVM_BINARY_DIR (#231930)"

This reverts commit 3e93f25d161f7d503fa7c3fca2afae609ce183bb.
---
 clang/tools/clang-ssaf-orchestrator-make/CMakeLists.txt | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/clang/tools/clang-ssaf-orchestrator-make/CMakeLists.txt b/clang/tools/clang-ssaf-orchestrator-make/CMakeLists.txt
index aaedbb8c4f3aa..6c953ad7d265c 100644
--- a/clang/tools/clang-ssaf-orchestrator-make/CMakeLists.txt
+++ b/clang/tools/clang-ssaf-orchestrator-make/CMakeLists.txt
@@ -29,10 +29,10 @@ set(SsafOrchestratorMakeShimDir "libexec/ssaf-orchestrator-shims")
 # tool's target can depend on it. kind is FILES or PROGRAMS.
 function(add_ssaf_orchestrator_make_file source build_dir destination kind)
   get_filename_component(name "${source}" NAME)
-  set(copied "${LLVM_BINARY_DIR}/${build_dir}/${name}")
+  set(copied "${CMAKE_BINARY_DIR}/${build_dir}/${name}")
   add_custom_command(OUTPUT "${copied}"
                      COMMAND ${CMAKE_COMMAND} -E make_directory
-                       "${LLVM_BINARY_DIR}/${build_dir}"
+                       "${CMAKE_BINARY_DIR}/${build_dir}"
                      COMMAND ${CMAKE_COMMAND} -E copy
                        "${CMAKE_CURRENT_SOURCE_DIR}/${source}" "${copied}"
                      DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/${source}")
@@ -59,10 +59,10 @@ endforeach()
 configure_file(
   "${CMAKE_CURRENT_SOURCE_DIR}/${SsafOrchestratorMakePackageDir}/version.py.in"
   "${CMAKE_CURRENT_BINARY_DIR}/version.py")
-set(version_py "${LLVM_BINARY_DIR}/${SsafOrchestratorMakePackageDir}/version.py")
+set(version_py "${CMAKE_BINARY_DIR}/${SsafOrchestratorMakePackageDir}/version.py")
 add_custom_command(OUTPUT "${version_py}"
                    COMMAND ${CMAKE_COMMAND} -E make_directory
-                     "${LLVM_BINARY_DIR}/${SsafOrchestratorMakePackageDir}"
+                     "${CMAKE_BINARY_DIR}/${SsafOrchestratorMakePackageDir}"
                    COMMAND ${CMAKE_COMMAND} -E copy
                      "${CMAKE_CURRENT_BINARY_DIR}/version.py" "${version_py}"
                    DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/version.py")

>From 6e29cb29c44d0e8a5002428ad4f70586505f51eb Mon Sep 17 00:00:00 2001
From: Balazs Benics <benicsbalazs at gmail.com>
Date: Thu, 15 Oct 2026 11:53:30 +0100
Subject: [PATCH 08/14] Revert "[clang][ssaf] Add
 clang-ssaf-merge-conflict-report (#231731)"

This reverts commit f32ac72b4f1ec390a42f91e084da61854b5fac0e.
---
 .../user-docs/SourceEditGeneration.md         |  12 -
 .../Inputs/conflicts-a.sarif                  | 118 ---------
 .../Inputs/conflicts-b.sarif                  | 118 ---------
 .../Inputs/conflicts-c.sarif                  |  67 -----
 .../Inputs/no-conflicts.sarif                 |  15 --
 .../Inputs/other-tool.sarif                   |  15 --
 .../Inputs/two-runs.sarif                     |  24 --
 .../cli-errors.test                           |  69 -----
 .../ssaf-merge-conflict-report/empty.test     |  14 -
 .../ssaf-merge-conflict-report/help.test      |  19 --
 .../ssaf-merge-conflict-report/merge.test     |  28 --
 .../ssaf-merge-conflict-report/nested.test    |  17 --
 .../order-invariance.test                     |   8 -
 .../src-edit-merge-reports.test               |  26 --
 .../ssaf-merge-conflict-report/version.test   |   5 -
 clang/test/CMakeLists.txt                     |   1 -
 clang/tools/CMakeLists.txt                    |   1 -
 .../CMakeLists.txt                            |  12 -
 .../MergeConflictReport.cpp                   | 249 ------------------
 19 files changed, 818 deletions(-)
 delete mode 100644 clang/test/Analysis/Scalable/ssaf-merge-conflict-report/Inputs/conflicts-a.sarif
 delete mode 100644 clang/test/Analysis/Scalable/ssaf-merge-conflict-report/Inputs/conflicts-b.sarif
 delete mode 100644 clang/test/Analysis/Scalable/ssaf-merge-conflict-report/Inputs/conflicts-c.sarif
 delete mode 100644 clang/test/Analysis/Scalable/ssaf-merge-conflict-report/Inputs/no-conflicts.sarif
 delete mode 100644 clang/test/Analysis/Scalable/ssaf-merge-conflict-report/Inputs/other-tool.sarif
 delete mode 100644 clang/test/Analysis/Scalable/ssaf-merge-conflict-report/Inputs/two-runs.sarif
 delete mode 100644 clang/test/Analysis/Scalable/ssaf-merge-conflict-report/cli-errors.test
 delete mode 100644 clang/test/Analysis/Scalable/ssaf-merge-conflict-report/empty.test
 delete mode 100644 clang/test/Analysis/Scalable/ssaf-merge-conflict-report/help.test
 delete mode 100644 clang/test/Analysis/Scalable/ssaf-merge-conflict-report/merge.test
 delete mode 100644 clang/test/Analysis/Scalable/ssaf-merge-conflict-report/nested.test
 delete mode 100644 clang/test/Analysis/Scalable/ssaf-merge-conflict-report/order-invariance.test
 delete mode 100644 clang/test/Analysis/Scalable/ssaf-merge-conflict-report/src-edit-merge-reports.test
 delete mode 100644 clang/test/Analysis/Scalable/ssaf-merge-conflict-report/version.test
 delete mode 100644 clang/tools/clang-ssaf-merge-conflict-report/CMakeLists.txt
 delete mode 100644 clang/tools/clang-ssaf-merge-conflict-report/MergeConflictReport.cpp

diff --git a/clang/docs/ScalableStaticAnalysis/user-docs/SourceEditGeneration.md b/clang/docs/ScalableStaticAnalysis/user-docs/SourceEditGeneration.md
index 842238730a106..a0b52b3f7df38 100644
--- a/clang/docs/ScalableStaticAnalysis/user-docs/SourceEditGeneration.md
+++ b/clang/docs/ScalableStaticAnalysis/user-docs/SourceEditGeneration.md
@@ -81,15 +81,3 @@ inputs share, such as one in a header that both translation units include,
 is reported once, and the result does not depend on the order of the
 inputs. A merged report can be merged again.
 
-## Merging conflict reports
-
-`clang-ssaf-src-edit-merge --sarif-conflicts-out=` reports the overlapping
-edits it dropped while merging. `clang-ssaf-merge-conflict-report` merges
-such reports the same way, so that the conflicts found while merging the
-edits of an archive reach the report of the program it is linked into:
-
-```console
-$ clang-ssaf-merge-conflict-report libparse.a.sarif prg.sarif -o all.sarif
-```
-
-The inputs must all have been written by the same tool.
diff --git a/clang/test/Analysis/Scalable/ssaf-merge-conflict-report/Inputs/conflicts-a.sarif b/clang/test/Analysis/Scalable/ssaf-merge-conflict-report/Inputs/conflicts-a.sarif
deleted file mode 100644
index 110b144a6d266..0000000000000
--- a/clang/test/Analysis/Scalable/ssaf-merge-conflict-report/Inputs/conflicts-a.sarif
+++ /dev/null
@@ -1,118 +0,0 @@
-{
-  "$schema": "https://json.schemastore.org/sarif-2.1.0.json",
-  "runs": [
-    {
-      "results": [
-        {
-          "level": "error",
-          "locations": [
-            {
-              "physicalLocation": {
-                "artifactLocation": {
-                  "uri": "file:///src/x.cpp"
-                },
-                "region": {
-                  "byteOffset": 10
-                }
-              }
-            }
-          ],
-          "message": {
-            "text": "2 overlapping replacement(s) at file:///src/x.cpp byte 10 were dropped; resolve manually."
-          },
-          "relatedLocations": [
-            {
-              "id": 1,
-              "message": {
-                "text": "candidate edit: \"X\""
-              },
-              "physicalLocation": {
-                "artifactLocation": {
-                  "uri": "file:///src/x.cpp"
-                },
-                "region": {
-                  "byteLength": 5,
-                  "byteOffset": 10
-                }
-              }
-            },
-            {
-              "id": 2,
-              "message": {
-                "text": "candidate edit: \"Y\""
-              },
-              "physicalLocation": {
-                "artifactLocation": {
-                  "uri": "file:///src/x.cpp"
-                },
-                "region": {
-                  "byteLength": 3,
-                  "byteOffset": 10
-                }
-              }
-            }
-          ],
-          "ruleId": "clang-reforge-replacement-conflict"
-        },
-        {
-          "level": "error",
-          "locations": [
-            {
-              "physicalLocation": {
-                "artifactLocation": {
-                  "uri": "file:///src/shared.h"
-                },
-                "region": {
-                  "byteOffset": 4
-                }
-              }
-            }
-          ],
-          "message": {
-            "text": "2 overlapping replacement(s) at file:///src/shared.h byte 4 were dropped; resolve manually."
-          },
-          "relatedLocations": [
-            {
-              "id": 1,
-              "message": {
-                "text": "candidate edit: \"int\""
-              },
-              "physicalLocation": {
-                "artifactLocation": {
-                  "uri": "file:///src/shared.h"
-                },
-                "region": {
-                  "byteLength": 3,
-                  "byteOffset": 4
-                }
-              }
-            },
-            {
-              "id": 2,
-              "message": {
-                "text": "candidate edit: \"long\""
-              },
-              "physicalLocation": {
-                "artifactLocation": {
-                  "uri": "file:///src/shared.h"
-                },
-                "region": {
-                  "byteLength": 4,
-                  "byteOffset": 4
-                }
-              }
-            }
-          ],
-          "ruleId": "clang-reforge-replacement-conflict"
-        }
-      ],
-      "tool": {
-        "driver": {
-          "name": "clang-ssaf-src-edit-merge",
-          "version": "24.0.0git"
-        }
-      }
-    }
-  ],
-  "version": "2.1.0"
-}
diff --git a/clang/test/Analysis/Scalable/ssaf-merge-conflict-report/Inputs/conflicts-b.sarif b/clang/test/Analysis/Scalable/ssaf-merge-conflict-report/Inputs/conflicts-b.sarif
deleted file mode 100644
index 7a7a92bb92921..0000000000000
--- a/clang/test/Analysis/Scalable/ssaf-merge-conflict-report/Inputs/conflicts-b.sarif
+++ /dev/null
@@ -1,118 +0,0 @@
-{
-  "$schema": "https://json.schemastore.org/sarif-2.1.0.json",
-  "runs": [
-    {
-      "results": [
-        {
-          "level": "error",
-          "locations": [
-            {
-              "physicalLocation": {
-                "artifactLocation": {
-                  "uri": "file:///src/shared.h"
-                },
-                "region": {
-                  "byteOffset": 4
-                }
-              }
-            }
-          ],
-          "message": {
-            "text": "2 overlapping replacement(s) at file:///src/shared.h byte 4 were dropped; resolve manually."
-          },
-          "relatedLocations": [
-            {
-              "id": 1,
-              "message": {
-                "text": "candidate edit: \"int\""
-              },
-              "physicalLocation": {
-                "artifactLocation": {
-                  "uri": "file:///src/shared.h"
-                },
-                "region": {
-                  "byteLength": 3,
-                  "byteOffset": 4
-                }
-              }
-            },
-            {
-              "id": 2,
-              "message": {
-                "text": "candidate edit: \"long\""
-              },
-              "physicalLocation": {
-                "artifactLocation": {
-                  "uri": "file:///src/shared.h"
-                },
-                "region": {
-                  "byteLength": 4,
-                  "byteOffset": 4
-                }
-              }
-            }
-          ],
-          "ruleId": "clang-reforge-replacement-conflict"
-        },
-        {
-          "level": "error",
-          "locations": [
-            {
-              "physicalLocation": {
-                "artifactLocation": {
-                  "uri": "file:///src/y.cpp"
-                },
-                "region": {
-                  "byteOffset": 30
-                }
-              }
-            }
-          ],
-          "message": {
-            "text": "2 overlapping replacement(s) at file:///src/y.cpp byte 30 were dropped; resolve manually."
-          },
-          "relatedLocations": [
-            {
-              "id": 1,
-              "message": {
-                "text": "candidate edit: \"Q\""
-              },
-              "physicalLocation": {
-                "artifactLocation": {
-                  "uri": "file:///src/y.cpp"
-                },
-                "region": {
-                  "byteLength": 2,
-                  "byteOffset": 30
-                }
-              }
-            },
-            {
-              "id": 2,
-              "message": {
-                "text": "candidate edit: \"Z\""
-              },
-              "physicalLocation": {
-                "artifactLocation": {
-                  "uri": "file:///src/y.cpp"
-                },
-                "region": {
-                  "byteLength": 2,
-                  "byteOffset": 30
-                }
-              }
-            }
-          ],
-          "ruleId": "clang-reforge-replacement-conflict"
-        }
-      ],
-      "tool": {
-        "driver": {
-          "name": "clang-ssaf-src-edit-merge",
-          "version": "24.0.0git"
-        }
-      }
-    }
-  ],
-  "version": "2.1.0"
-}
diff --git a/clang/test/Analysis/Scalable/ssaf-merge-conflict-report/Inputs/conflicts-c.sarif b/clang/test/Analysis/Scalable/ssaf-merge-conflict-report/Inputs/conflicts-c.sarif
deleted file mode 100644
index dc5b1c020be8d..0000000000000
--- a/clang/test/Analysis/Scalable/ssaf-merge-conflict-report/Inputs/conflicts-c.sarif
+++ /dev/null
@@ -1,67 +0,0 @@
-{
-  "$schema": "https://json.schemastore.org/sarif-2.1.0.json",
-  "runs": [
-    {
-      "results": [
-        {
-          "level": "error",
-          "locations": [
-            {
-              "physicalLocation": {
-                "artifactLocation": {
-                  "uri": "file:///src/x.cpp"
-                },
-                "region": {
-                  "byteOffset": 2
-                }
-              }
-            }
-          ],
-          "message": {
-            "text": "2 overlapping replacement(s) at file:///src/x.cpp byte 2 were dropped; resolve manually."
-          },
-          "relatedLocations": [
-            {
-              "id": 1,
-              "message": {
-                "text": "candidate edit: \"A\""
-              },
-              "physicalLocation": {
-                "artifactLocation": {
-                  "uri": "file:///src/x.cpp"
-                },
-                "region": {
-                  "byteLength": 1,
-                  "byteOffset": 2
-                }
-              }
-            },
-            {
-              "id": 2,
-              "message": {
-                "text": "candidate edit: \"B\""
-              },
-              "physicalLocation": {
-                "artifactLocation": {
-                  "uri": "file:///src/x.cpp"
-                },
-                "region": {
-                  "byteLength": 1,
-                  "byteOffset": 2
-                }
-              }
-            }
-          ],
-          "ruleId": "clang-reforge-replacement-conflict"
-        }
-      ],
-      "tool": {
-        "driver": {
-          "name": "clang-ssaf-src-edit-merge",
-          "version": "24.0.0git"
-        }
-      }
-    }
-  ],
-  "version": "2.1.0"
-}
diff --git a/clang/test/Analysis/Scalable/ssaf-merge-conflict-report/Inputs/no-conflicts.sarif b/clang/test/Analysis/Scalable/ssaf-merge-conflict-report/Inputs/no-conflicts.sarif
deleted file mode 100644
index da2d8c6941462..0000000000000
--- a/clang/test/Analysis/Scalable/ssaf-merge-conflict-report/Inputs/no-conflicts.sarif
+++ /dev/null
@@ -1,15 +0,0 @@
-{
-  "$schema": "https://json.schemastore.org/sarif-2.1.0.json",
-  "runs": [
-    {
-      "results": [],
-      "tool": {
-        "driver": {
-          "name": "clang-ssaf-src-edit-merge",
-          "version": "24.0.0git"
-        }
-      }
-    }
-  ],
-  "version": "2.1.0"
-}
diff --git a/clang/test/Analysis/Scalable/ssaf-merge-conflict-report/Inputs/other-tool.sarif b/clang/test/Analysis/Scalable/ssaf-merge-conflict-report/Inputs/other-tool.sarif
deleted file mode 100644
index 1c2ea28ea3ad4..0000000000000
--- a/clang/test/Analysis/Scalable/ssaf-merge-conflict-report/Inputs/other-tool.sarif
+++ /dev/null
@@ -1,15 +0,0 @@
-{
-  "$schema": "https://json.schemastore.org/sarif-2.1.0.json",
-  "runs": [
-    {
-      "results": [],
-      "tool": {
-        "driver": {
-          "name": "clang-ssaf",
-          "version": "24.0.0git"
-        }
-      }
-    }
-  ],
-  "version": "2.1.0"
-}
diff --git a/clang/test/Analysis/Scalable/ssaf-merge-conflict-report/Inputs/two-runs.sarif b/clang/test/Analysis/Scalable/ssaf-merge-conflict-report/Inputs/two-runs.sarif
deleted file mode 100644
index cda78d1c4282d..0000000000000
--- a/clang/test/Analysis/Scalable/ssaf-merge-conflict-report/Inputs/two-runs.sarif
+++ /dev/null
@@ -1,24 +0,0 @@
-{
-  "$schema": "https://json.schemastore.org/sarif-2.1.0.json",
-  "runs": [
-    {
-      "results": [],
-      "tool": {
-        "driver": {
-          "name": "clang-ssaf-src-edit-merge",
-          "version": "24.0.0git"
-        }
-      }
-    },
-    {
-      "results": [],
-      "tool": {
-        "driver": {
-          "name": "clang-ssaf-src-edit-merge",
-          "version": "24.0.0git"
-        }
-      }
-    }
-  ],
-  "version": "2.1.0"
-}
diff --git a/clang/test/Analysis/Scalable/ssaf-merge-conflict-report/cli-errors.test b/clang/test/Analysis/Scalable/ssaf-merge-conflict-report/cli-errors.test
deleted file mode 100644
index 05a17c2f6cfab..0000000000000
--- a/clang/test/Analysis/Scalable/ssaf-merge-conflict-report/cli-errors.test
+++ /dev/null
@@ -1,69 +0,0 @@
-// Tests for clang-ssaf-merge-conflict-report errors.
-
-// RUN: rm -rf %t
-// RUN: mkdir -p %t
-
-// ============================================================================
-// CLI error: no arguments
-// ============================================================================
-
-// RUN: not clang-ssaf-merge-conflict-report 2>&1 \
-// RUN:   | FileCheck %s --check-prefix=NO-ARGS
-// NO-ARGS: clang-ssaf-merge-conflict-report{{(\.exe)?}}: Not enough positional command line arguments specified!
-
-// ============================================================================
-// CLI error: missing -o
-// ============================================================================
-
-// RUN: not clang-ssaf-merge-conflict-report %S/Inputs/conflicts-a.sarif 2>&1 \
-// RUN:   | FileCheck %s --check-prefix=NO-OUTPUT
-// NO-OUTPUT: clang-ssaf-merge-conflict-report{{(\.exe)?}}: for the -o option: must be specified at least once!
-
-// ============================================================================
-// Error: nonexistent input
-// ============================================================================
-
-// RUN: not clang-ssaf-merge-conflict-report %t/missing.sarif \
-// RUN:   -o %t/out.sarif 2>&1 \
-// RUN:   | FileCheck %s --check-prefix=MISSING -DPATH=%t/missing.sarif
-// MISSING: clang-ssaf-merge-conflict-report: error: failed to read '[[PATH]]': {{.*}}
-
-// ============================================================================
-// Error: input is not JSON
-// ============================================================================
-
-// RUN: echo 'not json' > %t/not-json.sarif
-// RUN: not clang-ssaf-merge-conflict-report %t/not-json.sarif \
-// RUN:   -o %t/out.sarif 2>&1 \
-// RUN:   | FileCheck %s --check-prefix=NOT-JSON -DPATH=%t/not-json.sarif
-// NOT-JSON: clang-ssaf-merge-conflict-report: error: failed to parse '[[PATH]]': {{.*}}
-
-// ============================================================================
-// Error: input does not have exactly one run
-// ============================================================================
-
-// RUN: not clang-ssaf-merge-conflict-report %S/Inputs/two-runs.sarif \
-// RUN:   -o %t/out.sarif 2>&1 \
-// RUN:   | FileCheck %s --check-prefix=TWO-RUNS
-// TWO-RUNS: clang-ssaf-merge-conflict-report: error: '{{.*}}two-runs.sarif' is not a SARIF log with exactly one run
-
-// ============================================================================
-// Error: inputs written by different tools
-// ============================================================================
-
-// RUN: not clang-ssaf-merge-conflict-report %S/Inputs/conflicts-a.sarif \
-// RUN:   %S/Inputs/other-tool.sarif -o %t/out.sarif 2>&1 \
-// RUN:   | FileCheck %s --check-prefix=OTHER
-// OTHER: clang-ssaf-merge-conflict-report: error: '{{.*}}other-tool.sarif' was written by 'clang-ssaf', not by 'clang-ssaf-src-edit-merge'
-
-// ============================================================================
-// Error: the output cannot be written
-// ============================================================================
-
-// RUN: not clang-ssaf-merge-conflict-report %S/Inputs/conflicts-a.sarif \
-// RUN:   -o %t/no-such-dir/out.sarif 2>&1 \
-// RUN:   | FileCheck %s --check-prefix=CANNOT-WRITE -DPATH=%t/no-such-dir/out.sarif
-// CANNOT-WRITE: clang-ssaf-merge-conflict-report: error: failed to write '[[PATH]]': {{.*}}
-
-// No error leaves an output behind.
-// RUN: not ls %t/out.sarif
diff --git a/clang/test/Analysis/Scalable/ssaf-merge-conflict-report/empty.test b/clang/test/Analysis/Scalable/ssaf-merge-conflict-report/empty.test
deleted file mode 100644
index 948cdfd95cedd..0000000000000
--- a/clang/test/Analysis/Scalable/ssaf-merge-conflict-report/empty.test
+++ /dev/null
@@ -1,14 +0,0 @@
-// Reports without conflicts merge into a report without conflicts, and add
-// nothing to a report that has some.
-
-// RUN: rm -rf %t && mkdir -p %t
-// RUN: clang-ssaf-merge-conflict-report %S/Inputs/no-conflicts.sarif \
-// RUN:   %S/Inputs/no-conflicts.sarif -o %t/none.sarif
-// RUN: FileCheck %s --input-file=%t/none.sarif
-// CHECK: "results": [],
-
-// RUN: clang-ssaf-merge-conflict-report %S/Inputs/conflicts-a.sarif \
-// RUN:   -o %t/a.sarif
-// RUN: clang-ssaf-merge-conflict-report %S/Inputs/no-conflicts.sarif \
-// RUN:   %S/Inputs/conflicts-a.sarif -o %t/none-a.sarif
-// RUN: diff %t/a.sarif %t/none-a.sarif
diff --git a/clang/test/Analysis/Scalable/ssaf-merge-conflict-report/help.test b/clang/test/Analysis/Scalable/ssaf-merge-conflict-report/help.test
deleted file mode 100644
index c8f0884255f9c..0000000000000
--- a/clang/test/Analysis/Scalable/ssaf-merge-conflict-report/help.test
+++ /dev/null
@@ -1,19 +0,0 @@
-// Test clang-ssaf-merge-conflict-report help option
-
-// RUN: clang-ssaf-merge-conflict-report --help-list-hidden \
-// RUN:           | FileCheck %s --match-full-lines
-
-// CHECK:      OVERVIEW: SSAF Conflict Report Merger
-// CHECK-EMPTY:
-// CHECK-NEXT: USAGE: clang-ssaf-merge-conflict-report{{(\.exe)?}} [options] <input.sarif>...
-// CHECK-EMPTY:
-// CHECK-NEXT: OPTIONS:
-// CHECK-NEXT:   -h                  - Alias for --help
-// CHECK-NEXT:   --help              - Display available options (--help-hidden for more)
-// CHECK-NEXT:   --help-hidden       - Display all available options
-// CHECK-NEXT:   --help-list         - Display list of available options (--help-list-hidden for more)
-// CHECK-NEXT:   --help-list-hidden  - Display list of all available options
-// CHECK-NEXT:   -o <path>           - Output file path
-// CHECK-NEXT:   --print-all-options - Print all option values after command line parsing
-// CHECK-NEXT:   --print-options     - Print non-default options after command line parsing
-// CHECK-NEXT:   --version           - Display the version of this program
diff --git a/clang/test/Analysis/Scalable/ssaf-merge-conflict-report/merge.test b/clang/test/Analysis/Scalable/ssaf-merge-conflict-report/merge.test
deleted file mode 100644
index e54317ff9b809..0000000000000
--- a/clang/test/Analysis/Scalable/ssaf-merge-conflict-report/merge.test
+++ /dev/null
@@ -1,28 +0,0 @@
-// Two conflict reports that share a conflict merge into one run.
-
-// RUN: rm -rf %t && mkdir -p %t
-// RUN: clang-ssaf-merge-conflict-report %S/Inputs/conflicts-a.sarif \
-// RUN:   %S/Inputs/conflicts-b.sarif -o %t/merged.sarif
-// RUN: FileCheck %s --input-file=%t/merged.sarif
-
-// '-' writes the report to stdout.
-// RUN: clang-ssaf-merge-conflict-report %S/Inputs/conflicts-a.sarif \
-// RUN:   %S/Inputs/conflicts-b.sarif -o - > %t/stdout.sarif
-// RUN: diff %t/merged.sarif %t/stdout.sarif
-// RUN: grep '"text": "2 overlapping replacement(s) at file:///src/shared.h' \
-// RUN:   %t/merged.sarif | count 1
-
-// The conflicts in location order, the shared one once.
-// CHECK:      "results": [
-// CHECK:        "uri": "file:///src/shared.h"
-// CHECK:        "byteOffset": 4
-// CHECK:        "text": "2 overlapping replacement(s) at file:///src/shared.h byte 4 were dropped; resolve manually."
-// CHECK:        "text": "candidate edit: \"int\""
-// CHECK:        "text": "candidate edit: \"long\""
-// CHECK:        "uri": "file:///src/x.cpp"
-// CHECK:        "byteOffset": 10
-// CHECK:        "uri": "file:///src/y.cpp"
-// CHECK:        "byteOffset": 30
-// CHECK:      "tool": {
-// CHECK:        "name": "clang-ssaf-src-edit-merge",
-// CHECK:      "version": "2.1.0"
diff --git a/clang/test/Analysis/Scalable/ssaf-merge-conflict-report/nested.test b/clang/test/Analysis/Scalable/ssaf-merge-conflict-report/nested.test
deleted file mode 100644
index 7f7bce20c8dac..0000000000000
--- a/clang/test/Analysis/Scalable/ssaf-merge-conflict-report/nested.test
+++ /dev/null
@@ -1,17 +0,0 @@
-// A merged report merges again like the reports it was made from, so that the
-// conflicts found while merging an archive's edits reach the report of the
-// program it is linked into.
-
-// RUN: rm -rf %t && mkdir -p %t
-// RUN: clang-ssaf-merge-conflict-report %S/Inputs/conflicts-a.sarif \
-// RUN:   %S/Inputs/conflicts-b.sarif -o %t/ab.sarif
-// RUN: clang-ssaf-merge-conflict-report %t/ab.sarif \
-// RUN:   %S/Inputs/conflicts-c.sarif -o %t/ab-c.sarif
-// RUN: clang-ssaf-merge-conflict-report %S/Inputs/conflicts-a.sarif \
-// RUN:   %S/Inputs/conflicts-b.sarif %S/Inputs/conflicts-c.sarif -o %t/abc.sarif
-// RUN: diff %t/ab-c.sarif %t/abc.sarif
-
-// Merging a report with itself adds nothing.
-// RUN: clang-ssaf-merge-conflict-report %t/ab.sarif %t/ab.sarif \
-// RUN:   -o %t/ab-ab.sarif
-// RUN: diff %t/ab.sarif %t/ab-ab.sarif
diff --git a/clang/test/Analysis/Scalable/ssaf-merge-conflict-report/order-invariance.test b/clang/test/Analysis/Scalable/ssaf-merge-conflict-report/order-invariance.test
deleted file mode 100644
index 18845ac4c56bd..0000000000000
--- a/clang/test/Analysis/Scalable/ssaf-merge-conflict-report/order-invariance.test
+++ /dev/null
@@ -1,8 +0,0 @@
-// The merged report does not depend on the order of the inputs.
-
-// RUN: rm -rf %t && mkdir -p %t
-// RUN: clang-ssaf-merge-conflict-report %S/Inputs/conflicts-a.sarif \
-// RUN:   %S/Inputs/conflicts-b.sarif %S/Inputs/conflicts-c.sarif -o %t/abc.sarif
-// RUN: clang-ssaf-merge-conflict-report %S/Inputs/conflicts-c.sarif \
-// RUN:   %S/Inputs/conflicts-b.sarif %S/Inputs/conflicts-a.sarif -o %t/cba.sarif
-// RUN: diff %t/abc.sarif %t/cba.sarif
diff --git a/clang/test/Analysis/Scalable/ssaf-merge-conflict-report/src-edit-merge-reports.test b/clang/test/Analysis/Scalable/ssaf-merge-conflict-report/src-edit-merge-reports.test
deleted file mode 100644
index 2581255bb5469..0000000000000
--- a/clang/test/Analysis/Scalable/ssaf-merge-conflict-report/src-edit-merge-reports.test
+++ /dev/null
@@ -1,26 +0,0 @@
-// Conflict reports written by clang-ssaf-src-edit-merge for two files merge
-// into one, and a report given twice contributes its conflicts once.
-
-// RUN: rm -rf %t.dir && mkdir -p %t.dir
-// RUN: printf '%%80s' '' > %t.dir/foo.cpp
-// RUN: printf '%%80s' '' > %t.dir/bar.cpp
-// DEFINE: %{inputs} = %S/../ssaf-src-edit-merge/Inputs
-// RUN: sed "s|@FOO@|%/t.dir/foo.cpp|g" %{inputs}/single-replacement.tpl.yaml > %t.dir/foo-a.yaml
-// RUN: sed "s|@FOO@|%/t.dir/foo.cpp|g" %{inputs}/conflict-text-y.tpl.yaml > %t.dir/foo-b.yaml
-// RUN: sed "s|@FOO@|%/t.dir/bar.cpp|g" %{inputs}/single-replacement.tpl.yaml > %t.dir/bar-a.yaml
-// RUN: sed "s|@FOO@|%/t.dir/bar.cpp|g" %{inputs}/conflict-text-z.tpl.yaml > %t.dir/bar-b.yaml
-// RUN: clang-ssaf-src-edit-merge %t.dir/foo-a.yaml %t.dir/foo-b.yaml \
-// RUN:   -o %t.dir/foo.yaml --sarif-conflicts-out=%t.dir/foo.sarif 2> /dev/null
-// RUN: clang-ssaf-src-edit-merge %t.dir/bar-a.yaml %t.dir/bar-b.yaml \
-// RUN:   -o %t.dir/bar.yaml --sarif-conflicts-out=%t.dir/bar.sarif 2> /dev/null
-
-// RUN: clang-ssaf-merge-conflict-report %t.dir/foo.sarif %t.dir/bar.sarif \
-// RUN:   %t.dir/foo.sarif -o %t.dir/merged.sarif
-// RUN: FileCheck %s --input-file=%t.dir/merged.sarif
-// RUN: grep '"ruleId": "clang-reforge-replacement-conflict"' %t.dir/merged.sarif \
-// RUN:   | count 2
-
-// CHECK:      "results": [
-// CHECK:        "uri": "file://{{.*}}bar.cpp"
-// CHECK:        "uri": "file://{{.*}}foo.cpp"
-// CHECK:        "name": "clang-ssaf-src-edit-merge",
diff --git a/clang/test/Analysis/Scalable/ssaf-merge-conflict-report/version.test b/clang/test/Analysis/Scalable/ssaf-merge-conflict-report/version.test
deleted file mode 100644
index 6a0d6babd8967..0000000000000
--- a/clang/test/Analysis/Scalable/ssaf-merge-conflict-report/version.test
+++ /dev/null
@@ -1,5 +0,0 @@
-// Test clang-ssaf-merge-conflict-report version
-
-// RUN: clang-ssaf-merge-conflict-report --version | FileCheck %s
-
-// CHECK: clang-ssaf-merge-conflict-report 0.1
diff --git a/clang/test/CMakeLists.txt b/clang/test/CMakeLists.txt
index e498ef13f71e2..793bed1fbc0a3 100644
--- a/clang/test/CMakeLists.txt
+++ b/clang/test/CMakeLists.txt
@@ -107,7 +107,6 @@ list(APPEND CLANG_TEST_DEPS
   clang-ssaf-analyzer
   clang-ssaf-format
   clang-ssaf-linker
-  clang-ssaf-merge-conflict-report
   clang-ssaf-merge-transformation-report
   clang-ssaf-src-edit-merge
   clang-sycl-linker
diff --git a/clang/tools/CMakeLists.txt b/clang/tools/CMakeLists.txt
index f85381e65ac20..c38efad58db16 100644
--- a/clang/tools/CMakeLists.txt
+++ b/clang/tools/CMakeLists.txt
@@ -18,7 +18,6 @@ add_clang_subdirectory(clang-scan-deps)
 add_clang_subdirectory(clang-ssaf-analyzer)
 add_clang_subdirectory(clang-ssaf-format)
 add_clang_subdirectory(clang-ssaf-linker)
-add_clang_subdirectory(clang-ssaf-merge-conflict-report)
 add_clang_subdirectory(clang-ssaf-merge-transformation-report)
 if(NOT WIN32)
   add_clang_subdirectory(clang-ssaf-orchestrator-make)
diff --git a/clang/tools/clang-ssaf-merge-conflict-report/CMakeLists.txt b/clang/tools/clang-ssaf-merge-conflict-report/CMakeLists.txt
deleted file mode 100644
index 1dfdba8dce21e..0000000000000
--- a/clang/tools/clang-ssaf-merge-conflict-report/CMakeLists.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-set(LLVM_LINK_COMPONENTS
-  Support
-  )
-
-add_clang_tool(clang-ssaf-merge-conflict-report
-  MergeConflictReport.cpp
-  )
-
-clang_target_link_libraries(clang-ssaf-merge-conflict-report
-  PRIVATE
-  clangScalableStaticAnalysisTool
-  )
diff --git a/clang/tools/clang-ssaf-merge-conflict-report/MergeConflictReport.cpp b/clang/tools/clang-ssaf-merge-conflict-report/MergeConflictReport.cpp
deleted file mode 100644
index 6d4aa84cf3651..0000000000000
--- a/clang/tools/clang-ssaf-merge-conflict-report/MergeConflictReport.cpp
+++ /dev/null
@@ -1,249 +0,0 @@
-//===- MergeConflictReport.cpp - SSAF Conflict Report Merge Tool ----------===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-//
-//  This file implements the tool that merges SARIF conflict reports, as
-//  written by clang-ssaf-src-edit-merge --sarif-conflicts-out or by this tool,
-//  into one report. A conflict that several inputs report, such as one found
-//  while merging the edits of two archives that are linked into the same
-//  program, is kept once.
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/ScalableStaticAnalysis/Tool/Utils.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/FormatVariadic.h"
-#include "llvm/Support/InitLLVM.h"
-#include "llvm/Support/JSON.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/ToolOutputFile.h"
-#include "llvm/Support/raw_ostream.h"
-#include <cstdint>
-#include <set>
-#include <string>
-#include <tuple>
-#include <vector>
-
-using namespace llvm;
-using namespace clang::ssaf;
-
-namespace {
-
-//===----------------------------------------------------------------------===//
-// Command-Line Options
-//===----------------------------------------------------------------------===//
-
-cl::OptionCategory
-    MergeConflictReportCategory("clang-ssaf-merge-conflict-report options");
-
-cl::list<std::string> InputPaths(cl::Positional, cl::desc("<input.sarif>..."),
-                                 cl::OneOrMore,
-                                 cl::cat(MergeConflictReportCategory));
-
-cl::opt<std::string> OutputPath("o", cl::desc("Output file path"),
-                                cl::value_desc("path"), cl::Required,
-                                cl::cat(MergeConflictReportCategory));
-
-//===----------------------------------------------------------------------===//
-// Error Messages
-//===----------------------------------------------------------------------===//
-
-namespace ErrorMessages {
-
-constexpr const char *CannotRead = "failed to read '{0}': {1}";
-
-constexpr const char *CannotParse = "failed to parse '{0}': {1}";
-
-constexpr const char *NotOneRun =
-    "'{0}' is not a SARIF log with exactly one run";
-
-constexpr const char *OtherTool = "'{0}' was written by '{1}', not by '{2}'";
-
-constexpr const char *CannotWrite = "failed to write '{0}': {1}";
-
-} // namespace ErrorMessages
-
-//===----------------------------------------------------------------------===//
-// Reading and Writing
-//===----------------------------------------------------------------------===//
-
-json::Value readLog(StringRef Path) {
-  ErrorOr<std::unique_ptr<MemoryBuffer>> Buffer = MemoryBuffer::getFile(Path);
-  if (!Buffer) {
-    fail(ErrorMessages::CannotRead, Path, Buffer.getError().message());
-  }
-  Expected<json::Value> Log = json::parse((*Buffer)->getBuffer());
-  if (!Log) {
-    fail(ErrorMessages::CannotParse, Path, toString(Log.takeError()));
-  }
-  return std::move(*Log);
-}
-
-json::Object &getRun(json::Value &Log, StringRef Path) {
-  json::Object *Root = Log.getAsObject();
-  json::Array *Runs = Root ? Root->getArray("runs") : nullptr;
-  if (!Runs || Runs->size() != 1 || !Runs->front().getAsObject()) {
-    fail(ErrorMessages::NotOneRun, Path);
-  }
-  return *Runs->front().getAsObject();
-}
-
-void writeLog(const json::Value &Log, StringRef Path) {
-  std::error_code EC;
-  ToolOutputFile Out(Path, EC, sys::fs::OF_Text);
-  if (EC) {
-    fail(ErrorMessages::CannotWrite, Path, EC.message());
-  }
-  Out.os() << formatv("{0:2}", Log) << "\n";
-  Out.os().flush();
-  if (Out.os().has_error()) {
-    fail(ErrorMessages::CannotWrite, Path, Out.os().error().message());
-  }
-  Out.keep();
-}
-
-StringRef getString(const json::Object *Object, StringRef Key) {
-  if (!Object) {
-    return "";
-  }
-  return Object->getString(Key).value_or("");
-}
-
-/// Returns a copy of \p Object without the members named in \p Excluded.
-json::Object copyExcept(const json::Object &Object,
-                        ArrayRef<StringRef> Excluded) {
-  json::Object Copy;
-  for (const auto &[Key, Value] : Object) {
-    if (!is_contained(Excluded, StringRef(Key))) {
-      Copy[Key] = Value;
-    }
-  }
-  return Copy;
-}
-
-//===----------------------------------------------------------------------===//
-// Merging
-//===----------------------------------------------------------------------===//
-
-struct Conflict {
-  std::string Uri;
-  int64_t Offset;
-  std::string Message;
-  std::string Serialized;
-  json::Value Result = nullptr;
-
-  bool operator<(const Conflict &Other) const {
-    return std::tie(Uri, Offset, Message, Serialized) <
-           std::tie(Other.Uri, Other.Offset, Other.Message, Other.Serialized);
-  }
-};
-
-class ConflictReportMerger {
-public:
-  void add(json::Value Log, StringRef Path);
-  json::Value takeMerged();
-
-private:
-  void addConflict(json::Value Result);
-
-  bool HasInput = false;
-  json::Object Root;
-  json::Object Run;
-  std::set<std::string> Seen;
-  std::vector<Conflict> Conflicts;
-};
-
-void ConflictReportMerger::add(json::Value Log, StringRef Path) {
-  json::Object &InputRun = getRun(Log, Path);
-  const json::Object *InputTool = InputRun.getObject("tool");
-  StringRef InputName =
-      getString(InputTool ? InputTool->getObject("driver") : nullptr, "name");
-
-  if (!HasInput) {
-    HasInput = true;
-    Root = copyExcept(*Log.getAsObject(), {"runs"});
-    Run = copyExcept(InputRun, {"results"});
-  } else {
-    const json::Object *Tool = Run.getObject("tool");
-    StringRef Name =
-        getString(Tool ? Tool->getObject("driver") : nullptr, "name");
-    if (InputName != Name) {
-      fail(ErrorMessages::OtherTool, Path, InputName, Name);
-    }
-  }
-
-  if (json::Array *Results = InputRun.getArray("results")) {
-    for (json::Value &Result : *Results) {
-      addConflict(std::move(Result));
-    }
-  }
-}
-
-void ConflictReportMerger::addConflict(json::Value Result) {
-  Conflict C;
-  C.Serialized = formatv("{0}", Result);
-  if (!Seen.insert(C.Serialized).second) {
-    return;
-  }
-  C.Offset = 0;
-  const json::Object *Object = Result.getAsObject();
-  const json::Array *Locations =
-      Object ? Object->getArray("locations") : nullptr;
-  if (Locations && !Locations->empty()) {
-    const json::Object *Location = Locations->front().getAsObject();
-    const json::Object *Physical =
-        Location ? Location->getObject("physicalLocation") : nullptr;
-    if (Physical) {
-      C.Uri = getString(Physical->getObject("artifactLocation"), "uri").str();
-      if (const json::Object *Region = Physical->getObject("region")) {
-        C.Offset = Region->getInteger("byteOffset").value_or(0);
-      }
-    }
-  }
-  C.Message =
-      getString(Object ? Object->getObject("message") : nullptr, "text").str();
-  C.Result = std::move(Result);
-  Conflicts.push_back(std::move(C));
-}
-
-json::Value ConflictReportMerger::takeMerged() {
-  llvm::sort(Conflicts);
-  json::Array Results;
-  for (Conflict &C : Conflicts) {
-    Results.push_back(std::move(C.Result));
-  }
-  Run["results"] = std::move(Results);
-  json::Array Runs;
-  Runs.push_back(std::move(Run));
-  Root["runs"] = std::move(Runs);
-  return std::move(Root);
-}
-
-} // namespace
-
-//===----------------------------------------------------------------------===//
-// Driver
-//===----------------------------------------------------------------------===//
-
-int main(int argc, const char **argv) {
-  llvm::StringRef ToolHeading = "SSAF Conflict Report Merger";
-
-  InitLLVM X(argc, argv);
-  initTool(argc, argv, "0.1", MergeConflictReportCategory, ToolHeading);
-
-  ConflictReportMerger Merger;
-  for (const std::string &Path : InputPaths) {
-    Merger.add(readLog(Path), Path);
-  }
-  writeLog(Merger.takeMerged(), OutputPath);
-
-  return 0;
-}

>From f6e27727d247ab80be4a7a99f11bd14309c2ba49 Mon Sep 17 00:00:00 2001
From: Balazs Benics <benicsbalazs at gmail.com>
Date: Thu, 15 Oct 2026 11:53:31 +0100
Subject: [PATCH 09/14] Revert "[clang][ssaf] Add
 clang-ssaf-merge-transformation-report (#231664)"

This reverts commit 07195e29cdbacd063bbb3e1abfb36d68ea6b5dcd.
---
 .../user-docs/SourceEditGeneration.md         |  16 -
 .../Inputs/bad-artifact-index.sarif           |  71 ----
 .../Inputs/bad-rule-index.sarif               |  71 ----
 .../Inputs/empty.sarif                        |  21 -
 .../Inputs/other-transformation.sarif         |  21 -
 .../Inputs/tu-a.sarif                         | 106 -----
 .../Inputs/tu-b.sarif                         | 118 ------
 .../Inputs/tu-c.sarif                         |  71 ----
 .../Inputs/tu-clang-order.sarif               | 124 ------
 .../Inputs/two-runs.sarif                     |  36 --
 .../clang-artifact-order.test                 |  23 --
 .../cli-errors.test                           |  87 ----
 .../empty.test                                |  16 -
 .../help.test                                 |  19 -
 .../merge.test                                |  51 ---
 .../nested.test                               |  16 -
 .../order-invariance.test                     |   8 -
 .../plugin-reports.test                       |  47 ---
 .../version.test                              |   5 -
 clang/test/CMakeLists.txt                     |   1 -
 clang/tools/CMakeLists.txt                    |   1 -
 .../CMakeLists.txt                            |  12 -
 .../MergeTransformationReport.cpp             | 386 ------------------
 23 files changed, 1327 deletions(-)
 delete mode 100644 clang/test/Analysis/Scalable/ssaf-merge-transformation-report/Inputs/bad-artifact-index.sarif
 delete mode 100644 clang/test/Analysis/Scalable/ssaf-merge-transformation-report/Inputs/bad-rule-index.sarif
 delete mode 100644 clang/test/Analysis/Scalable/ssaf-merge-transformation-report/Inputs/empty.sarif
 delete mode 100644 clang/test/Analysis/Scalable/ssaf-merge-transformation-report/Inputs/other-transformation.sarif
 delete mode 100644 clang/test/Analysis/Scalable/ssaf-merge-transformation-report/Inputs/tu-a.sarif
 delete mode 100644 clang/test/Analysis/Scalable/ssaf-merge-transformation-report/Inputs/tu-b.sarif
 delete mode 100644 clang/test/Analysis/Scalable/ssaf-merge-transformation-report/Inputs/tu-c.sarif
 delete mode 100644 clang/test/Analysis/Scalable/ssaf-merge-transformation-report/Inputs/tu-clang-order.sarif
 delete mode 100644 clang/test/Analysis/Scalable/ssaf-merge-transformation-report/Inputs/two-runs.sarif
 delete mode 100644 clang/test/Analysis/Scalable/ssaf-merge-transformation-report/clang-artifact-order.test
 delete mode 100644 clang/test/Analysis/Scalable/ssaf-merge-transformation-report/cli-errors.test
 delete mode 100644 clang/test/Analysis/Scalable/ssaf-merge-transformation-report/empty.test
 delete mode 100644 clang/test/Analysis/Scalable/ssaf-merge-transformation-report/help.test
 delete mode 100644 clang/test/Analysis/Scalable/ssaf-merge-transformation-report/merge.test
 delete mode 100644 clang/test/Analysis/Scalable/ssaf-merge-transformation-report/nested.test
 delete mode 100644 clang/test/Analysis/Scalable/ssaf-merge-transformation-report/order-invariance.test
 delete mode 100644 clang/test/Analysis/Scalable/ssaf-merge-transformation-report/plugin-reports.test
 delete mode 100644 clang/test/Analysis/Scalable/ssaf-merge-transformation-report/version.test
 delete mode 100644 clang/tools/clang-ssaf-merge-transformation-report/CMakeLists.txt
 delete mode 100644 clang/tools/clang-ssaf-merge-transformation-report/MergeTransformationReport.cpp

diff --git a/clang/docs/ScalableStaticAnalysis/user-docs/SourceEditGeneration.md b/clang/docs/ScalableStaticAnalysis/user-docs/SourceEditGeneration.md
index a0b52b3f7df38..af7fc7f56aa8c 100644
--- a/clang/docs/ScalableStaticAnalysis/user-docs/SourceEditGeneration.md
+++ b/clang/docs/ScalableStaticAnalysis/user-docs/SourceEditGeneration.md
@@ -65,19 +65,3 @@ $ clang-apply-replacements --remove-change-desc-files <dir-with-yaml>
 
 The transformation report can be consumed by any SARIF viewer.
 
-
-## Merging transformation reports
-
-A transformation report covers one translation unit.
-`clang-ssaf-merge-transformation-report` merges the reports of the
-translation units of a link unit into one:
-
-```console
-$ clang-ssaf-merge-transformation-report foo.sarif bar.sarif -o prg.sarif
-```
-
-The inputs must come from the same transformation. A finding that several
-inputs share, such as one in a header that both translation units include,
-is reported once, and the result does not depend on the order of the
-inputs. A merged report can be merged again.
-
diff --git a/clang/test/Analysis/Scalable/ssaf-merge-transformation-report/Inputs/bad-artifact-index.sarif b/clang/test/Analysis/Scalable/ssaf-merge-transformation-report/Inputs/bad-artifact-index.sarif
deleted file mode 100644
index 893cd17a4a1b5..0000000000000
--- a/clang/test/Analysis/Scalable/ssaf-merge-transformation-report/Inputs/bad-artifact-index.sarif
+++ /dev/null
@@ -1,71 +0,0 @@
-{
-  "$schema": "https://docs.oasis-open.org/sarif/sarif/v2.1.0/cos02/schemas/sarif-schema-2.1.0.json",
-  "runs": [
-    {
-      "artifacts": [
-        {
-          "length": 120,
-          "location": {
-            "index": 0,
-            "uri": "file:///src/a.cpp"
-          },
-          "mimeType": "text/plain",
-          "roles": [
-            "resultFile"
-          ]
-        }
-      ],
-      "columnKind": "unicodeCodePoints",
-      "results": [
-        {
-          "level": "note",
-          "locations": [
-            {
-              "physicalLocation": {
-                "artifactLocation": {
-                  "index": 5,
-                  "uri": "file:///src/a.cpp"
-                },
-                "region": {
-                  "endColumn": 5,
-                  "endLine": 1,
-                  "startColumn": 1,
-                  "startLine": 1
-                }
-              }
-            }
-          ],
-          "message": {
-            "text": "declarator spelled through a macro is not yet rewritten"
-          },
-          "ruleId": "cpp-bounded-buffers-skipped",
-          "ruleIndex": 0
-        }
-      ],
-      "tool": {
-        "driver": {
-          "fullName": "clang ScalableStaticAnalysisFramework source transformation (cpp-bounded-buffers)",
-          "informationUri": "https://clang.llvm.org/docs/UsersManual.html",
-          "language": "en-US",
-          "name": "clang-ssaf",
-          "rules": [
-            {
-              "defaultConfiguration": {
-                "enabled": true,
-                "level": "warning",
-                "rank": -1
-              },
-              "fullDescription": {
-                "text": ""
-              },
-              "id": "cpp-bounded-buffers-skipped",
-              "name": ""
-            }
-          ],
-          "version": "24.0.0git"
-        }
-      }
-    }
-  ],
-  "version": "2.1.0"
-}
diff --git a/clang/test/Analysis/Scalable/ssaf-merge-transformation-report/Inputs/bad-rule-index.sarif b/clang/test/Analysis/Scalable/ssaf-merge-transformation-report/Inputs/bad-rule-index.sarif
deleted file mode 100644
index 093a89d467923..0000000000000
--- a/clang/test/Analysis/Scalable/ssaf-merge-transformation-report/Inputs/bad-rule-index.sarif
+++ /dev/null
@@ -1,71 +0,0 @@
-{
-  "$schema": "https://docs.oasis-open.org/sarif/sarif/v2.1.0/cos02/schemas/sarif-schema-2.1.0.json",
-  "runs": [
-    {
-      "artifacts": [
-        {
-          "length": 120,
-          "location": {
-            "index": 0,
-            "uri": "file:///src/a.cpp"
-          },
-          "mimeType": "text/plain",
-          "roles": [
-            "resultFile"
-          ]
-        }
-      ],
-      "columnKind": "unicodeCodePoints",
-      "results": [
-        {
-          "level": "note",
-          "locations": [
-            {
-              "physicalLocation": {
-                "artifactLocation": {
-                  "index": 0,
-                  "uri": "file:///src/a.cpp"
-                },
-                "region": {
-                  "endColumn": 5,
-                  "endLine": 1,
-                  "startColumn": 1,
-                  "startLine": 1
-                }
-              }
-            }
-          ],
-          "message": {
-            "text": "declarator spelled through a macro is not yet rewritten"
-          },
-          "ruleId": "cpp-bounded-buffers-skipped",
-          "ruleIndex": 3
-        }
-      ],
-      "tool": {
-        "driver": {
-          "fullName": "clang ScalableStaticAnalysisFramework source transformation (cpp-bounded-buffers)",
-          "informationUri": "https://clang.llvm.org/docs/UsersManual.html",
-          "language": "en-US",
-          "name": "clang-ssaf",
-          "rules": [
-            {
-              "defaultConfiguration": {
-                "enabled": true,
-                "level": "warning",
-                "rank": -1
-              },
-              "fullDescription": {
-                "text": ""
-              },
-              "id": "cpp-bounded-buffers-skipped",
-              "name": ""
-            }
-          ],
-          "version": "24.0.0git"
-        }
-      }
-    }
-  ],
-  "version": "2.1.0"
-}
diff --git a/clang/test/Analysis/Scalable/ssaf-merge-transformation-report/Inputs/empty.sarif b/clang/test/Analysis/Scalable/ssaf-merge-transformation-report/Inputs/empty.sarif
deleted file mode 100644
index 944201f0be593..0000000000000
--- a/clang/test/Analysis/Scalable/ssaf-merge-transformation-report/Inputs/empty.sarif
+++ /dev/null
@@ -1,21 +0,0 @@
-{
-  "$schema": "https://docs.oasis-open.org/sarif/sarif/v2.1.0/cos02/schemas/sarif-schema-2.1.0.json",
-  "runs": [
-    {
-      "artifacts": [],
-      "columnKind": "unicodeCodePoints",
-      "results": [],
-      "tool": {
-        "driver": {
-          "fullName": "clang ScalableStaticAnalysisFramework source transformation (cpp-bounded-buffers)",
-          "informationUri": "https://clang.llvm.org/docs/UsersManual.html",
-          "language": "en-US",
-          "name": "clang-ssaf",
-          "rules": [],
-          "version": "24.0.0git"
-        }
-      }
-    }
-  ],
-  "version": "2.1.0"
-}
diff --git a/clang/test/Analysis/Scalable/ssaf-merge-transformation-report/Inputs/other-transformation.sarif b/clang/test/Analysis/Scalable/ssaf-merge-transformation-report/Inputs/other-transformation.sarif
deleted file mode 100644
index 2a950fd626de5..0000000000000
--- a/clang/test/Analysis/Scalable/ssaf-merge-transformation-report/Inputs/other-transformation.sarif
+++ /dev/null
@@ -1,21 +0,0 @@
-{
-  "$schema": "https://docs.oasis-open.org/sarif/sarif/v2.1.0/cos02/schemas/sarif-schema-2.1.0.json",
-  "runs": [
-    {
-      "artifacts": [],
-      "columnKind": "unicodeCodePoints",
-      "results": [],
-      "tool": {
-        "driver": {
-          "fullName": "clang ScalableStaticAnalysisFramework source transformation (fix-noexcept)",
-          "informationUri": "https://clang.llvm.org/docs/UsersManual.html",
-          "language": "en-US",
-          "name": "clang-ssaf",
-          "rules": [],
-          "version": "24.0.0git"
-        }
-      }
-    }
-  ],
-  "version": "2.1.0"
-}
diff --git a/clang/test/Analysis/Scalable/ssaf-merge-transformation-report/Inputs/tu-a.sarif b/clang/test/Analysis/Scalable/ssaf-merge-transformation-report/Inputs/tu-a.sarif
deleted file mode 100644
index 24a766b14c605..0000000000000
--- a/clang/test/Analysis/Scalable/ssaf-merge-transformation-report/Inputs/tu-a.sarif
+++ /dev/null
@@ -1,106 +0,0 @@
-{
-  "$schema": "https://docs.oasis-open.org/sarif/sarif/v2.1.0/cos02/schemas/sarif-schema-2.1.0.json",
-  "runs": [
-    {
-      "artifacts": [
-        {
-          "length": 120,
-          "location": {
-            "index": 0,
-            "uri": "file:///src/a.cpp"
-          },
-          "mimeType": "text/plain",
-          "roles": [
-            "resultFile"
-          ]
-        },
-        {
-          "length": 60,
-          "location": {
-            "index": 1,
-            "uri": "file:///src/shared.h"
-          },
-          "mimeType": "text/plain",
-          "roles": [
-            "resultFile"
-          ]
-        }
-      ],
-      "columnKind": "unicodeCodePoints",
-      "results": [
-        {
-          "level": "note",
-          "locations": [
-            {
-              "physicalLocation": {
-                "artifactLocation": {
-                  "index": 1,
-                  "uri": "file:///src/shared.h"
-                },
-                "region": {
-                  "endColumn": 12,
-                  "endLine": 3,
-                  "startColumn": 8,
-                  "startLine": 3
-                }
-              }
-            }
-          ],
-          "message": {
-            "text": "multi-level pointer indirection is not yet rewritten"
-          },
-          "ruleId": "cpp-bounded-buffers-skipped",
-          "ruleIndex": 0
-        },
-        {
-          "level": "note",
-          "locations": [
-            {
-              "physicalLocation": {
-                "artifactLocation": {
-                  "index": 0,
-                  "uri": "file:///src/a.cpp"
-                },
-                "region": {
-                  "endColumn": 7,
-                  "endLine": 7,
-                  "startColumn": 3,
-                  "startLine": 7
-                }
-              }
-            }
-          ],
-          "message": {
-            "text": "declarator spelled through a macro is not yet rewritten"
-          },
-          "ruleId": "cpp-bounded-buffers-skipped",
-          "ruleIndex": 0
-        }
-      ],
-      "tool": {
-        "driver": {
-          "fullName": "clang ScalableStaticAnalysisFramework source transformation (cpp-bounded-buffers)",
-          "informationUri": "https://clang.llvm.org/docs/UsersManual.html",
-          "language": "en-US",
-          "name": "clang-ssaf",
-          "rules": [
-            {
-              "defaultConfiguration": {
-                "enabled": true,
-                "level": "warning",
-                "rank": -1
-              },
-              "fullDescription": {
-                "text": ""
-              },
-              "id": "cpp-bounded-buffers-skipped",
-              "name": ""
-            }
-          ],
-          "version": "24.0.0git"
-        }
-      }
-    }
-  ],
-  "version": "2.1.0"
-}
diff --git a/clang/test/Analysis/Scalable/ssaf-merge-transformation-report/Inputs/tu-b.sarif b/clang/test/Analysis/Scalable/ssaf-merge-transformation-report/Inputs/tu-b.sarif
deleted file mode 100644
index 40d17d8736758..0000000000000
--- a/clang/test/Analysis/Scalable/ssaf-merge-transformation-report/Inputs/tu-b.sarif
+++ /dev/null
@@ -1,118 +0,0 @@
-{
-  "$schema": "https://docs.oasis-open.org/sarif/sarif/v2.1.0/cos02/schemas/sarif-schema-2.1.0.json",
-  "runs": [
-    {
-      "artifacts": [
-        {
-          "length": 60,
-          "location": {
-            "index": 0,
-            "uri": "file:///src/shared.h"
-          },
-          "mimeType": "text/plain",
-          "roles": [
-            "resultFile"
-          ]
-        },
-        {
-          "length": 90,
-          "location": {
-            "index": 1,
-            "uri": "file:///src/b.cpp"
-          },
-          "mimeType": "text/plain",
-          "roles": [
-            "resultFile"
-          ]
-        }
-      ],
-      "columnKind": "unicodeCodePoints",
-      "results": [
-        {
-          "level": "note",
-          "locations": [
-            {
-              "physicalLocation": {
-                "artifactLocation": {
-                  "index": 0,
-                  "uri": "file:///src/shared.h"
-                },
-                "region": {
-                  "endColumn": 12,
-                  "endLine": 3,
-                  "startColumn": 8,
-                  "startLine": 3
-                }
-              }
-            }
-          ],
-          "message": {
-            "text": "multi-level pointer indirection is not yet rewritten"
-          },
-          "ruleId": "cpp-bounded-buffers-skipped",
-          "ruleIndex": 1
-        },
-        {
-          "level": "note",
-          "locations": [
-            {
-              "physicalLocation": {
-                "artifactLocation": {
-                  "index": 1,
-                  "uri": "file:///src/b.cpp"
-                },
-                "region": {
-                  "endColumn": 5,
-                  "endLine": 5,
-                  "startColumn": 1,
-                  "startLine": 5
-                }
-              }
-            }
-          ],
-          "message": {
-            "text": "other finding"
-          },
-          "ruleId": "cpp-bounded-buffers-other",
-          "ruleIndex": 0
-        }
-      ],
-      "tool": {
-        "driver": {
-          "fullName": "clang ScalableStaticAnalysisFramework source transformation (cpp-bounded-buffers)",
-          "informationUri": "https://clang.llvm.org/docs/UsersManual.html",
-          "language": "en-US",
-          "name": "clang-ssaf",
-          "rules": [
-            {
-              "defaultConfiguration": {
-                "enabled": true,
-                "level": "warning",
-                "rank": -1
-              },
-              "fullDescription": {
-                "text": ""
-              },
-              "id": "cpp-bounded-buffers-other",
-              "name": ""
-            },
-            {
-              "defaultConfiguration": {
-                "enabled": true,
-                "level": "warning",
-                "rank": -1
-              },
-              "fullDescription": {
-                "text": ""
-              },
-              "id": "cpp-bounded-buffers-skipped",
-              "name": ""
-            }
-          ],
-          "version": "24.0.0git"
-        }
-      }
-    }
-  ],
-  "version": "2.1.0"
-}
diff --git a/clang/test/Analysis/Scalable/ssaf-merge-transformation-report/Inputs/tu-c.sarif b/clang/test/Analysis/Scalable/ssaf-merge-transformation-report/Inputs/tu-c.sarif
deleted file mode 100644
index 51086f43164e9..0000000000000
--- a/clang/test/Analysis/Scalable/ssaf-merge-transformation-report/Inputs/tu-c.sarif
+++ /dev/null
@@ -1,71 +0,0 @@
-{
-  "$schema": "https://docs.oasis-open.org/sarif/sarif/v2.1.0/cos02/schemas/sarif-schema-2.1.0.json",
-  "runs": [
-    {
-      "artifacts": [
-        {
-          "length": 40,
-          "location": {
-            "index": 0,
-            "uri": "file:///src/c.cpp"
-          },
-          "mimeType": "text/plain",
-          "roles": [
-            "resultFile"
-          ]
-        }
-      ],
-      "columnKind": "unicodeCodePoints",
-      "results": [
-        {
-          "level": "note",
-          "locations": [
-            {
-              "physicalLocation": {
-                "artifactLocation": {
-                  "index": 0,
-                  "uri": "file:///src/c.cpp"
-                },
-                "region": {
-                  "endColumn": 9,
-                  "endLine": 2,
-                  "startColumn": 5,
-                  "startLine": 2
-                }
-              }
-            }
-          ],
-          "message": {
-            "text": "multi-level pointer indirection is not yet rewritten"
-          },
-          "ruleId": "cpp-bounded-buffers-skipped",
-          "ruleIndex": 0
-        }
-      ],
-      "tool": {
-        "driver": {
-          "fullName": "clang ScalableStaticAnalysisFramework source transformation (cpp-bounded-buffers)",
-          "informationUri": "https://clang.llvm.org/docs/UsersManual.html",
-          "language": "en-US",
-          "name": "clang-ssaf",
-          "rules": [
-            {
-              "defaultConfiguration": {
-                "enabled": true,
-                "level": "warning",
-                "rank": -1
-              },
-              "fullDescription": {
-                "text": ""
-              },
-              "id": "cpp-bounded-buffers-skipped",
-              "name": ""
-            }
-          ],
-          "version": "24.0.0git"
-        }
-      }
-    }
-  ],
-  "version": "2.1.0"
-}
diff --git a/clang/test/Analysis/Scalable/ssaf-merge-transformation-report/Inputs/tu-clang-order.sarif b/clang/test/Analysis/Scalable/ssaf-merge-transformation-report/Inputs/tu-clang-order.sarif
deleted file mode 100644
index 8124ebbd875cc..0000000000000
--- a/clang/test/Analysis/Scalable/ssaf-merge-transformation-report/Inputs/tu-clang-order.sarif
+++ /dev/null
@@ -1,124 +0,0 @@
-{
-  "$schema": "https://docs.oasis-open.org/sarif/sarif/v2.1.0/cos02/schemas/sarif-schema-2.1.0.json",
-  "runs": [
-    {
-      "artifacts": [
-        {
-          "length": 120,
-          "location": {
-            "index": 1,
-            "uri": "file:///src/a.cpp"
-          },
-          "mimeType": "text/plain",
-          "roles": [
-            "resultFile"
-          ]
-        },
-        {
-          "length": 60,
-          "location": {
-            "index": 0,
-            "uri": "file:///src/shared.h"
-          },
-          "mimeType": "text/plain",
-          "roles": [
-            "resultFile"
-          ]
-        }
-      ],
-      "columnKind": "unicodeCodePoints",
-      "results": [
-        {
-          "level": "note",
-          "locations": [
-            {
-              "physicalLocation": {
-                "artifactLocation": {
-                  "index": 0
-                },
-                "region": {
-                  "endColumn": 12,
-                  "endLine": 3,
-                  "startColumn": 8,
-                  "startLine": 3
-                }
-              }
-            }
-          ],
-          "message": {
-            "text": "multi-level pointer indirection is not yet rewritten"
-          },
-          "ruleId": "cpp-bounded-buffers-skipped",
-          "ruleIndex": 0
-        },
-        {
-          "level": "note",
-          "locations": [
-            {
-              "physicalLocation": {
-                "artifactLocation": {
-                  "index": 1,
-                  "uri": "file:///src/a.cpp"
-                },
-                "region": {
-                  "endColumn": 7,
-                  "endLine": 7,
-                  "startColumn": 3,
-                  "startLine": 7
-                }
-              }
-            }
-          ],
-          "message": {
-            "text": "declarator spelled through a macro is not yet rewritten"
-          },
-          "relatedLocations": [
-            {
-              "id": 1,
-              "message": {
-                "text": "the macro"
-              },
-              "physicalLocation": {
-                "artifactLocation": {
-                  "index": 0
-                },
-                "region": {
-                  "endColumn": 5,
-                  "endLine": 2,
-                  "startColumn": 1,
-                  "startLine": 2
-                }
-              }
-            }
-          ],
-          "ruleId": "cpp-bounded-buffers-skipped",
-          "ruleIndex": 0
-        }
-      ],
-      "tool": {
-        "driver": {
-          "fullName": "clang ScalableStaticAnalysisFramework source transformation (cpp-bounded-buffers)",
-          "informationUri": "https://clang.llvm.org/docs/UsersManual.html",
-          "language": "en-US",
-          "name": "clang-ssaf",
-          "rules": [
-            {
-              "defaultConfiguration": {
-                "enabled": true,
-                "level": "warning",
-                "rank": -1
-              },
-              "fullDescription": {
-                "text": ""
-              },
-              "id": "cpp-bounded-buffers-skipped",
-              "name": ""
-            }
-          ],
-          "version": "24.0.0git"
-        }
-      }
-    }
-  ],
-  "version": "2.1.0"
-}
diff --git a/clang/test/Analysis/Scalable/ssaf-merge-transformation-report/Inputs/two-runs.sarif b/clang/test/Analysis/Scalable/ssaf-merge-transformation-report/Inputs/two-runs.sarif
deleted file mode 100644
index 6fc4646bfe1b7..0000000000000
--- a/clang/test/Analysis/Scalable/ssaf-merge-transformation-report/Inputs/two-runs.sarif
+++ /dev/null
@@ -1,36 +0,0 @@
-{
-  "$schema": "https://docs.oasis-open.org/sarif/sarif/v2.1.0/cos02/schemas/sarif-schema-2.1.0.json",
-  "runs": [
-    {
-      "artifacts": [],
-      "columnKind": "unicodeCodePoints",
-      "results": [],
-      "tool": {
-        "driver": {
-          "fullName": "clang ScalableStaticAnalysisFramework source transformation (cpp-bounded-buffers)",
-          "informationUri": "https://clang.llvm.org/docs/UsersManual.html",
-          "language": "en-US",
-          "name": "clang-ssaf",
-          "rules": [],
-          "version": "24.0.0git"
-        }
-      }
-    },
-    {
-      "artifacts": [],
-      "columnKind": "unicodeCodePoints",
-      "results": [],
-      "tool": {
-        "driver": {
-          "fullName": "clang ScalableStaticAnalysisFramework source transformation (cpp-bounded-buffers)",
-          "informationUri": "https://clang.llvm.org/docs/UsersManual.html",
-          "language": "en-US",
-          "name": "clang-ssaf",
-          "rules": [],
-          "version": "24.0.0git"
-        }
-      }
-    }
-  ],
-  "version": "2.1.0"
-}
diff --git a/clang/test/Analysis/Scalable/ssaf-merge-transformation-report/clang-artifact-order.test b/clang/test/Analysis/Scalable/ssaf-merge-transformation-report/clang-artifact-order.test
deleted file mode 100644
index 67de8eb13660c..0000000000000
--- a/clang/test/Analysis/Scalable/ssaf-merge-transformation-report/clang-artifact-order.test
+++ /dev/null
@@ -1,23 +0,0 @@
-// clang lists a run's artifacts in URI order but numbers them in the order
-// they were first referred to, and its results refer to them by that number.
-// A location that names its artifact only by number, in a result or in a
-// related location, is placed by the artifact's own index.
-
-// RUN: rm -rf %t && mkdir -p %t
-// RUN: clang-ssaf-merge-transformation-report %S/Inputs/tu-clang-order.sarif \
-// RUN:   %S/Inputs/tu-b.sarif -o %t/merged.sarif
-// RUN: FileCheck %s --input-file=%t/merged.sarif
-// RUN: grep 'multi-level pointer indirection' %t/merged.sarif | count 1
-
-// CHECK:      "results": [
-// CHECK:        "index": 0,
-// CHECK-NEXT:   "uri": "file:///src/a.cpp"
-// CHECK:        "text": "declarator spelled through a macro is not yet rewritten"
-// CHECK:      "relatedLocations": [
-// CHECK:        "index": 2,
-// CHECK-NEXT:   "uri": "file:///src/shared.h"
-// CHECK:        "index": 1,
-// CHECK-NEXT:   "uri": "file:///src/b.cpp"
-// CHECK:        "index": 2,
-// CHECK-NEXT:   "uri": "file:///src/shared.h"
-// CHECK:        "text": "multi-level pointer indirection is not yet rewritten"
diff --git a/clang/test/Analysis/Scalable/ssaf-merge-transformation-report/cli-errors.test b/clang/test/Analysis/Scalable/ssaf-merge-transformation-report/cli-errors.test
deleted file mode 100644
index 93a26189d8206..0000000000000
--- a/clang/test/Analysis/Scalable/ssaf-merge-transformation-report/cli-errors.test
+++ /dev/null
@@ -1,87 +0,0 @@
-// Tests for clang-ssaf-merge-transformation-report errors.
-
-// RUN: rm -rf %t
-// RUN: mkdir -p %t
-
-// ============================================================================
-// CLI error: no arguments
-// ============================================================================
-
-// RUN: not clang-ssaf-merge-transformation-report 2>&1 \
-// RUN:   | FileCheck %s --check-prefix=NO-ARGS
-// NO-ARGS: clang-ssaf-merge-transformation-report{{(\.exe)?}}: Not enough positional command line arguments specified!
-
-// ============================================================================
-// CLI error: missing -o
-// ============================================================================
-
-// RUN: not clang-ssaf-merge-transformation-report %S/Inputs/tu-a.sarif 2>&1 \
-// RUN:   | FileCheck %s --check-prefix=NO-OUTPUT
-// NO-OUTPUT: clang-ssaf-merge-transformation-report{{(\.exe)?}}: for the -o option: must be specified at least once!
-
-// ============================================================================
-// Error: nonexistent input
-// ============================================================================
-
-// RUN: not clang-ssaf-merge-transformation-report %t/missing.sarif \
-// RUN:   -o %t/out.sarif 2>&1 \
-// RUN:   | FileCheck %s --check-prefix=MISSING -DPATH=%t/missing.sarif
-// MISSING: clang-ssaf-merge-transformation-report: error: failed to read '[[PATH]]': {{.*}}
-
-// ============================================================================
-// Error: input is not JSON
-// ============================================================================
-
-// RUN: echo 'not json' > %t/not-json.sarif
-// RUN: not clang-ssaf-merge-transformation-report %t/not-json.sarif \
-// RUN:   -o %t/out.sarif 2>&1 \
-// RUN:   | FileCheck %s --check-prefix=NOT-JSON -DPATH=%t/not-json.sarif
-// NOT-JSON: clang-ssaf-merge-transformation-report: error: failed to parse '[[PATH]]': {{.*}}
-
-// ============================================================================
-// Error: input does not have exactly one run
-// ============================================================================
-
-// RUN: not clang-ssaf-merge-transformation-report %S/Inputs/two-runs.sarif \
-// RUN:   -o %t/out.sarif 2>&1 \
-// RUN:   | FileCheck %s --check-prefix=TWO-RUNS
-// TWO-RUNS: clang-ssaf-merge-transformation-report: error: '{{.*}}two-runs.sarif' is not a SARIF log with exactly one run
-
-// ============================================================================
-// Error: inputs from different transformations
-// ============================================================================
-
-// RUN: not clang-ssaf-merge-transformation-report %S/Inputs/tu-a.sarif \
-// RUN:   %S/Inputs/other-transformation.sarif -o %t/out.sarif 2>&1 \
-// RUN:   | FileCheck %s --check-prefix=OTHER
-// OTHER: clang-ssaf-merge-transformation-report: error: '{{.*}}other-transformation.sarif' reports on 'clang ScalableStaticAnalysisFramework source transformation (fix-noexcept)', not on 'clang ScalableStaticAnalysisFramework source transformation (cpp-bounded-buffers)'
-
-// ============================================================================
-// Error: a result refers to a rule its run does not define
-// ============================================================================
-
-// RUN: not clang-ssaf-merge-transformation-report \
-// RUN:   %S/Inputs/bad-rule-index.sarif -o %t/out.sarif 2>&1 \
-// RUN:   | FileCheck %s --check-prefix=BAD-RULE
-// BAD-RULE: clang-ssaf-merge-transformation-report: error: '{{.*}}bad-rule-index.sarif': a result refers to rule 3, which its run does not define
-
-// ============================================================================
-// Error: a location refers to an artifact its run does not define
-// ============================================================================
-
-// RUN: not clang-ssaf-merge-transformation-report \
-// RUN:   %S/Inputs/bad-artifact-index.sarif -o %t/out.sarif 2>&1 \
-// RUN:   | FileCheck %s --check-prefix=BAD-ARTIFACT
-// BAD-ARTIFACT: clang-ssaf-merge-transformation-report: error: '{{.*}}bad-artifact-index.sarif': a location refers to artifact 5, which its run does not define
-
-// ============================================================================
-// Error: the output cannot be written
-// ============================================================================
-
-// RUN: not clang-ssaf-merge-transformation-report %S/Inputs/tu-a.sarif \
-// RUN:   -o %t/no-such-dir/out.sarif 2>&1 \
-// RUN:   | FileCheck %s --check-prefix=CANNOT-WRITE -DPATH=%t/no-such-dir/out.sarif
-// CANNOT-WRITE: clang-ssaf-merge-transformation-report: error: failed to write '[[PATH]]': {{.*}}
-
-// No error leaves an output behind.
-// RUN: not ls %t/out.sarif
diff --git a/clang/test/Analysis/Scalable/ssaf-merge-transformation-report/empty.test b/clang/test/Analysis/Scalable/ssaf-merge-transformation-report/empty.test
deleted file mode 100644
index f2a2fc048ee14..0000000000000
--- a/clang/test/Analysis/Scalable/ssaf-merge-transformation-report/empty.test
+++ /dev/null
@@ -1,16 +0,0 @@
-// Reports without results merge into a report without results, and add
-// nothing to a report that has some.
-
-// RUN: rm -rf %t && mkdir -p %t
-// RUN: clang-ssaf-merge-transformation-report %S/Inputs/empty.sarif \
-// RUN:   %S/Inputs/empty.sarif -o %t/empty.sarif
-// RUN: FileCheck %s --input-file=%t/empty.sarif
-// CHECK: "artifacts": [],
-// CHECK: "results": [],
-// CHECK: "rules": [],
-
-// RUN: clang-ssaf-merge-transformation-report %S/Inputs/tu-a.sarif \
-// RUN:   -o %t/a.sarif
-// RUN: clang-ssaf-merge-transformation-report %S/Inputs/empty.sarif \
-// RUN:   %S/Inputs/tu-a.sarif -o %t/empty-a.sarif
-// RUN: diff %t/a.sarif %t/empty-a.sarif
diff --git a/clang/test/Analysis/Scalable/ssaf-merge-transformation-report/help.test b/clang/test/Analysis/Scalable/ssaf-merge-transformation-report/help.test
deleted file mode 100644
index 8014d652b2eb3..0000000000000
--- a/clang/test/Analysis/Scalable/ssaf-merge-transformation-report/help.test
+++ /dev/null
@@ -1,19 +0,0 @@
-// Test clang-ssaf-merge-transformation-report help option
-
-// RUN: clang-ssaf-merge-transformation-report --help-list-hidden \
-// RUN:           | FileCheck %s --match-full-lines
-
-// CHECK:      OVERVIEW: SSAF Transformation Report Merger
-// CHECK-EMPTY:
-// CHECK-NEXT: USAGE: clang-ssaf-merge-transformation-report{{(\.exe)?}} [options] <input.sarif>...
-// CHECK-EMPTY:
-// CHECK-NEXT: OPTIONS:
-// CHECK-NEXT:   -h                  - Alias for --help
-// CHECK-NEXT:   --help              - Display available options (--help-hidden for more)
-// CHECK-NEXT:   --help-hidden       - Display all available options
-// CHECK-NEXT:   --help-list         - Display list of available options (--help-list-hidden for more)
-// CHECK-NEXT:   --help-list-hidden  - Display list of all available options
-// CHECK-NEXT:   -o <path>           - Output file path
-// CHECK-NEXT:   --print-all-options - Print all option values after command line parsing
-// CHECK-NEXT:   --print-options     - Print non-default options after command line parsing
-// CHECK-NEXT:   --version           - Display the version of this program
diff --git a/clang/test/Analysis/Scalable/ssaf-merge-transformation-report/merge.test b/clang/test/Analysis/Scalable/ssaf-merge-transformation-report/merge.test
deleted file mode 100644
index 12b6832189a15..0000000000000
--- a/clang/test/Analysis/Scalable/ssaf-merge-transformation-report/merge.test
+++ /dev/null
@@ -1,51 +0,0 @@
-// Two reports that both carry a finding in a shared header, under different
-// rule and artifact indices, merge into one run.
-
-// RUN: rm -rf %t && mkdir -p %t
-// RUN: clang-ssaf-merge-transformation-report %S/Inputs/tu-a.sarif \
-// RUN:   %S/Inputs/tu-b.sarif -o %t/merged.sarif
-// RUN: FileCheck %s --input-file=%t/merged.sarif
-
-// '-' writes the report to stdout.
-// RUN: clang-ssaf-merge-transformation-report %S/Inputs/tu-a.sarif \
-// RUN:   %S/Inputs/tu-b.sarif -o - > %t/stdout.sarif
-// RUN: diff %t/merged.sarif %t/stdout.sarif
-
-// The artifacts of both runs, once each and numbered in URI order.
-// CHECK:      "artifacts": [
-// CHECK:        "index": 0,
-// CHECK-NEXT:   "uri": "file:///src/a.cpp"
-// CHECK:        "index": 1,
-// CHECK-NEXT:   "uri": "file:///src/b.cpp"
-// CHECK:        "index": 2,
-// CHECK-NEXT:   "uri": "file:///src/shared.h"
-
-// The results in location order, each pointing into the merged rules and
-// artifacts. The header's finding is kept once.
-// CHECK:      "results": [
-// CHECK:        "index": 0,
-// CHECK-NEXT:   "uri": "file:///src/a.cpp"
-// CHECK:        "ruleId": "cpp-bounded-buffers-skipped",
-// CHECK-NEXT:   "ruleIndex": 1
-// CHECK:        "index": 1,
-// CHECK-NEXT:   "uri": "file:///src/b.cpp"
-// CHECK:        "ruleId": "cpp-bounded-buffers-other",
-// CHECK-NEXT:   "ruleIndex": 0
-// CHECK:        "index": 2,
-// CHECK-NEXT:   "uri": "file:///src/shared.h"
-// CHECK:        "text": "multi-level pointer indirection is not yet rewritten"
-// CHECK:        "ruleId": "cpp-bounded-buffers-skipped",
-// CHECK-NEXT:   "ruleIndex": 1
-// CHECK-NOT:    "text": "multi-level pointer indirection is not yet rewritten"
-
-// The rules of both runs, once each and in id order, under the driver of the
-// first input.
-// CHECK:      "tool": {
-// CHECK:        "fullName": "clang ScalableStaticAnalysisFramework source transformation (cpp-bounded-buffers)",
-// CHECK:        "name": "clang-ssaf",
-// CHECK:        "rules": [
-// CHECK:          "id": "cpp-bounded-buffers-other",
-// CHECK:          "id": "cpp-bounded-buffers-skipped",
-// CHECK-NOT:      "id":
-// CHECK:        "version": "24.0.0git"
-// CHECK:      "version": "2.1.0"
diff --git a/clang/test/Analysis/Scalable/ssaf-merge-transformation-report/nested.test b/clang/test/Analysis/Scalable/ssaf-merge-transformation-report/nested.test
deleted file mode 100644
index 47db227e2f1e7..0000000000000
--- a/clang/test/Analysis/Scalable/ssaf-merge-transformation-report/nested.test
+++ /dev/null
@@ -1,16 +0,0 @@
-// A merged report merges again like the reports it was made from, so that an
-// archive's report can feed the report of the program it is linked into.
-
-// RUN: rm -rf %t && mkdir -p %t
-// RUN: clang-ssaf-merge-transformation-report %S/Inputs/tu-a.sarif \
-// RUN:   %S/Inputs/tu-b.sarif -o %t/ab.sarif
-// RUN: clang-ssaf-merge-transformation-report %t/ab.sarif \
-// RUN:   %S/Inputs/tu-c.sarif -o %t/ab-c.sarif
-// RUN: clang-ssaf-merge-transformation-report %S/Inputs/tu-a.sarif \
-// RUN:   %S/Inputs/tu-b.sarif %S/Inputs/tu-c.sarif -o %t/abc.sarif
-// RUN: diff %t/ab-c.sarif %t/abc.sarif
-
-// Merging a report with itself adds nothing.
-// RUN: clang-ssaf-merge-transformation-report %t/ab.sarif %t/ab.sarif \
-// RUN:   -o %t/ab-ab.sarif
-// RUN: diff %t/ab.sarif %t/ab-ab.sarif
diff --git a/clang/test/Analysis/Scalable/ssaf-merge-transformation-report/order-invariance.test b/clang/test/Analysis/Scalable/ssaf-merge-transformation-report/order-invariance.test
deleted file mode 100644
index 07986cd628158..0000000000000
--- a/clang/test/Analysis/Scalable/ssaf-merge-transformation-report/order-invariance.test
+++ /dev/null
@@ -1,8 +0,0 @@
-// The merged report does not depend on the order of the inputs.
-
-// RUN: rm -rf %t && mkdir -p %t
-// RUN: clang-ssaf-merge-transformation-report %S/Inputs/tu-a.sarif \
-// RUN:   %S/Inputs/tu-b.sarif %S/Inputs/tu-c.sarif -o %t/abc.sarif
-// RUN: clang-ssaf-merge-transformation-report %S/Inputs/tu-c.sarif \
-// RUN:   %S/Inputs/tu-b.sarif %S/Inputs/tu-a.sarif -o %t/cba.sarif
-// RUN: diff %t/abc.sarif %t/cba.sarif
diff --git a/clang/test/Analysis/Scalable/ssaf-merge-transformation-report/plugin-reports.test b/clang/test/Analysis/Scalable/ssaf-merge-transformation-report/plugin-reports.test
deleted file mode 100644
index fd62ce4223cc3..0000000000000
--- a/clang/test/Analysis/Scalable/ssaf-merge-transformation-report/plugin-reports.test
+++ /dev/null
@@ -1,47 +0,0 @@
-// Reports written by clang for two translation units merge into one, and a
-// report given twice contributes its findings once.
-
-// REQUIRES: plugins
-
-// RUN: rm -rf %t && split-file %s %t
-// DEFINE: %{transform} = %clang_cc1 \
-// DEFINE:   -load %llvmshlibdir/SSAFTestTransformationPlugin%pluginext \
-// DEFINE:   --ssaf-source-transformation=test-transformation \
-// DEFINE:   --ssaf-global-scope-analysis-result=%S/../source-edit-generation/Inputs/two-function-suite.json \
-// DEFINE:   --ssaf-link-unit-id=lu -emit-obj
-// RUN: %{transform} --ssaf-compilation-unit-id=a --ssaf-src-edit-file=%t/a.yaml \
-// RUN:   --ssaf-transformation-report-file=%t/a.sarif -o %t/a.o %t/a.cpp
-// RUN: %{transform} --ssaf-compilation-unit-id=b --ssaf-src-edit-file=%t/b.yaml \
-// RUN:   --ssaf-transformation-report-file=%t/b.sarif -o %t/b.o %t/b.cpp
-
-// RUN: clang-ssaf-merge-transformation-report %t/a.sarif %t/b.sarif \
-// RUN:   %t/a.sarif -o %t/merged.sarif
-// RUN: FileCheck %s --input-file=%t/merged.sarif
-// RUN: grep '"text": "visited alpha"' %t/merged.sarif | count 1
-
-// CHECK:      "artifacts": [
-// CHECK:        "index": 0,
-// CHECK-NEXT:   "uri": "file://{{.*}}a.cpp"
-// CHECK:        "index": 1,
-// CHECK-NEXT:   "uri": "file://{{.*}}b.cpp"
-// CHECK:      "results": [
-// CHECK:        "index": 0,
-// CHECK-NEXT:   "uri": "file://{{.*}}a.cpp"
-// CHECK:        "text": "visited alpha"
-// CHECK:        "ruleId": "test-touches-function",
-// CHECK-NEXT:   "ruleIndex": 0
-// CHECK:        "index": 1,
-// CHECK-NEXT:   "uri": "file://{{.*}}b.cpp"
-// CHECK:        "text": "visited beta"
-// CHECK:        "ruleId": "test-touches-function",
-// CHECK-NEXT:   "ruleIndex": 0
-// CHECK:        "name": "clang-ssaf",
-// CHECK:        "rules": [
-// CHECK:          "id": "test-touches-function",
-// CHECK-NOT:      "id":
-
-//--- a.cpp
-void alpha() {}
-
-//--- b.cpp
-void beta() {}
diff --git a/clang/test/Analysis/Scalable/ssaf-merge-transformation-report/version.test b/clang/test/Analysis/Scalable/ssaf-merge-transformation-report/version.test
deleted file mode 100644
index 94b7e457d5881..0000000000000
--- a/clang/test/Analysis/Scalable/ssaf-merge-transformation-report/version.test
+++ /dev/null
@@ -1,5 +0,0 @@
-// Test clang-ssaf-merge-transformation-report version
-
-// RUN: clang-ssaf-merge-transformation-report --version | FileCheck %s
-
-// CHECK: clang-ssaf-merge-transformation-report 0.1
diff --git a/clang/test/CMakeLists.txt b/clang/test/CMakeLists.txt
index 793bed1fbc0a3..72a4f2760df84 100644
--- a/clang/test/CMakeLists.txt
+++ b/clang/test/CMakeLists.txt
@@ -107,7 +107,6 @@ list(APPEND CLANG_TEST_DEPS
   clang-ssaf-analyzer
   clang-ssaf-format
   clang-ssaf-linker
-  clang-ssaf-merge-transformation-report
   clang-ssaf-src-edit-merge
   clang-sycl-linker
   diagtool
diff --git a/clang/tools/CMakeLists.txt b/clang/tools/CMakeLists.txt
index c38efad58db16..182489653b805 100644
--- a/clang/tools/CMakeLists.txt
+++ b/clang/tools/CMakeLists.txt
@@ -18,7 +18,6 @@ add_clang_subdirectory(clang-scan-deps)
 add_clang_subdirectory(clang-ssaf-analyzer)
 add_clang_subdirectory(clang-ssaf-format)
 add_clang_subdirectory(clang-ssaf-linker)
-add_clang_subdirectory(clang-ssaf-merge-transformation-report)
 if(NOT WIN32)
   add_clang_subdirectory(clang-ssaf-orchestrator-make)
 endif()
diff --git a/clang/tools/clang-ssaf-merge-transformation-report/CMakeLists.txt b/clang/tools/clang-ssaf-merge-transformation-report/CMakeLists.txt
deleted file mode 100644
index d243b07be0874..0000000000000
--- a/clang/tools/clang-ssaf-merge-transformation-report/CMakeLists.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-set(LLVM_LINK_COMPONENTS
-  Support
-  )
-
-add_clang_tool(clang-ssaf-merge-transformation-report
-  MergeTransformationReport.cpp
-  )
-
-clang_target_link_libraries(clang-ssaf-merge-transformation-report
-  PRIVATE
-  clangScalableStaticAnalysisTool
-  )
diff --git a/clang/tools/clang-ssaf-merge-transformation-report/MergeTransformationReport.cpp b/clang/tools/clang-ssaf-merge-transformation-report/MergeTransformationReport.cpp
deleted file mode 100644
index 3ca4b22e36ff9..0000000000000
--- a/clang/tools/clang-ssaf-merge-transformation-report/MergeTransformationReport.cpp
+++ /dev/null
@@ -1,386 +0,0 @@
-//===- MergeTransformationReport.cpp - SSAF Report Merge Tool -------------===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-//
-//  This file implements the tool that merges SARIF transformation reports, as
-//  written by clang's --ssaf-transformation-report-file or by this tool, into
-//  one report. Every input run numbers its rules and artifacts on its own, so
-//  results are renumbered against the merged run, and identical results, such
-//  as a finding in a header that several translation units include, are kept
-//  once. An artifact is numbered by its own location index where it has one,
-//  since clang lists artifacts in URI order but numbers them in the order they
-//  were first referred to.
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/ScalableStaticAnalysis/Tool/Utils.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/FormatVariadic.h"
-#include "llvm/Support/InitLLVM.h"
-#include "llvm/Support/JSON.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/ToolOutputFile.h"
-#include "llvm/Support/raw_ostream.h"
-#include <cstdint>
-#include <map>
-#include <optional>
-#include <set>
-#include <string>
-#include <tuple>
-#include <vector>
-
-using namespace llvm;
-using namespace clang::ssaf;
-
-namespace {
-
-//===----------------------------------------------------------------------===//
-// Command-Line Options
-//===----------------------------------------------------------------------===//
-
-cl::OptionCategory MergeTransformationReportCategory(
-    "clang-ssaf-merge-transformation-report options");
-
-cl::list<std::string> InputPaths(cl::Positional, cl::desc("<input.sarif>..."),
-                                 cl::OneOrMore,
-                                 cl::cat(MergeTransformationReportCategory));
-
-cl::opt<std::string> OutputPath("o", cl::desc("Output file path"),
-                                cl::value_desc("path"), cl::Required,
-                                cl::cat(MergeTransformationReportCategory));
-
-//===----------------------------------------------------------------------===//
-// Error Messages
-//===----------------------------------------------------------------------===//
-
-namespace ErrorMessages {
-
-constexpr const char *CannotRead = "failed to read '{0}': {1}";
-
-constexpr const char *CannotParse = "failed to parse '{0}': {1}";
-
-constexpr const char *NotOneRun =
-    "'{0}' is not a SARIF log with exactly one run";
-
-constexpr const char *OtherTransformation =
-    "'{0}' reports on '{1}', not on '{2}'";
-
-constexpr const char *UnknownRule =
-    "'{0}': a result refers to rule {1}, which its run does not define";
-
-constexpr const char *UnknownArtifact =
-    "'{0}': a location refers to artifact {1}, which its run does not define";
-
-constexpr const char *CannotWrite = "failed to write '{0}': {1}";
-
-} // namespace ErrorMessages
-
-//===----------------------------------------------------------------------===//
-// Reading and Writing
-//===----------------------------------------------------------------------===//
-
-json::Value readLog(StringRef Path) {
-  ErrorOr<std::unique_ptr<MemoryBuffer>> Buffer = MemoryBuffer::getFile(Path);
-  if (!Buffer) {
-    fail(ErrorMessages::CannotRead, Path, Buffer.getError().message());
-  }
-  Expected<json::Value> Log = json::parse((*Buffer)->getBuffer());
-  if (!Log) {
-    fail(ErrorMessages::CannotParse, Path, toString(Log.takeError()));
-  }
-  return std::move(*Log);
-}
-
-json::Object &getRun(json::Value &Log, StringRef Path) {
-  json::Object *Root = Log.getAsObject();
-  json::Array *Runs = Root ? Root->getArray("runs") : nullptr;
-  if (!Runs || Runs->size() != 1 || !Runs->front().getAsObject()) {
-    fail(ErrorMessages::NotOneRun, Path);
-  }
-  return *Runs->front().getAsObject();
-}
-
-void writeLog(const json::Value &Log, StringRef Path) {
-  std::error_code EC;
-  ToolOutputFile Out(Path, EC, sys::fs::OF_Text);
-  if (EC) {
-    fail(ErrorMessages::CannotWrite, Path, EC.message());
-  }
-  Out.os() << formatv("{0:2}", Log) << "\n";
-  Out.os().flush();
-  if (Out.os().has_error()) {
-    fail(ErrorMessages::CannotWrite, Path, Out.os().error().message());
-  }
-  Out.keep();
-}
-
-StringRef getString(const json::Object *Object, StringRef Key) {
-  if (!Object) {
-    return "";
-  }
-  return Object->getString(Key).value_or("");
-}
-
-json::Object *getArtifactLocation(json::Value &Location) {
-  json::Object *Object = Location.getAsObject();
-  json::Object *Physical =
-      Object ? Object->getObject("physicalLocation") : nullptr;
-  return Physical ? Physical->getObject("artifactLocation") : nullptr;
-}
-
-/// Returns a copy of \p Object without the members named in \p Excluded.
-json::Object copyExcept(const json::Object &Object,
-                        ArrayRef<StringRef> Excluded) {
-  json::Object Copy;
-  for (const auto &[Key, Value] : Object) {
-    if (!is_contained(Excluded, StringRef(Key))) {
-      Copy[Key] = Value;
-    }
-  }
-  return Copy;
-}
-
-//===----------------------------------------------------------------------===//
-// Merging
-//===----------------------------------------------------------------------===//
-
-/// A result whose rule and artifacts are named by id and URI rather than by
-/// index, so that results from different runs compare equal.
-struct Finding {
-  std::string Uri;
-  int64_t Line;
-  int64_t Column;
-  std::string RuleId;
-  std::string Message;
-  std::string Serialized;
-  json::Object Result;
-
-  bool operator<(const Finding &Other) const {
-    return std::tie(Uri, Line, Column, RuleId, Message, Serialized) <
-           std::tie(Other.Uri, Other.Line, Other.Column, Other.RuleId,
-                    Other.Message, Other.Serialized);
-  }
-};
-
-class ReportMerger {
-public:
-  void add(json::Value Log, StringRef Path);
-  json::Value takeMerged();
-
-private:
-  void addFinding(json::Object Result);
-
-  bool HasInput = false;
-  json::Object Root;
-  json::Object Run;
-  json::Object Tool;
-  json::Object Driver;
-  std::map<std::string, json::Value> Rules;
-  std::map<std::string, json::Value> Artifacts;
-  std::set<std::string> Seen;
-  std::vector<Finding> Findings;
-};
-
-void ReportMerger::add(json::Value Log, StringRef Path) {
-  json::Object &InputRun = getRun(Log, Path);
-  const json::Object *InputTool = InputRun.getObject("tool");
-  const json::Object *InputDriver =
-      InputTool ? InputTool->getObject("driver") : nullptr;
-
-  if (!HasInput) {
-    HasInput = true;
-    Root = copyExcept(*Log.getAsObject(), {"runs"});
-    Run = copyExcept(InputRun, {"artifacts", "results", "tool"});
-    if (InputTool) {
-      Tool = copyExcept(*InputTool, {"driver"});
-    }
-    if (InputDriver) {
-      Driver = copyExcept(*InputDriver, {"rules"});
-    }
-  } else if (getString(InputDriver, "name") != getString(&Driver, "name") ||
-             getString(InputDriver, "fullName") !=
-                 getString(&Driver, "fullName")) {
-    fail(ErrorMessages::OtherTransformation, Path,
-         getString(InputDriver, "fullName"), getString(&Driver, "fullName"));
-  }
-
-  std::vector<std::string> RuleIds;
-  if (const json::Array *InputRules =
-          InputDriver ? InputDriver->getArray("rules") : nullptr) {
-    for (const json::Value &Rule : *InputRules) {
-      std::string Id = getString(Rule.getAsObject(), "id").str();
-      Rules.try_emplace(Id, Rule);
-      RuleIds.push_back(std::move(Id));
-    }
-  }
-
-  std::map<int64_t, std::string> Uris;
-  if (const json::Array *InputArtifacts = InputRun.getArray("artifacts")) {
-    for (auto [Position, Artifact] : enumerate(*InputArtifacts)) {
-      const json::Object *Object = Artifact.getAsObject();
-      const json::Object *Location =
-          Object ? Object->getObject("location") : nullptr;
-      std::string Uri = getString(Location, "uri").str();
-      int64_t Index = static_cast<int64_t>(Position);
-      if (Location) {
-        Index = Location->getInteger("index").value_or(Index);
-      }
-      Artifacts.try_emplace(Uri, Artifact);
-      Uris[Index] = std::move(Uri);
-    }
-  }
-
-  json::Array *Results = InputRun.getArray("results");
-  if (!Results) {
-    return;
-  }
-  for (json::Value &Value : *Results) {
-    json::Object *Result = Value.getAsObject();
-    if (!Result) {
-      continue;
-    }
-    if (std::optional<int64_t> Index = Result->getInteger("ruleIndex")) {
-      if (*Index < 0 || *Index >= static_cast<int64_t>(RuleIds.size())) {
-        fail(ErrorMessages::UnknownRule, Path, *Index);
-      }
-      Result->try_emplace("ruleId", RuleIds[*Index]);
-      Result->erase("ruleIndex");
-    }
-    for (StringRef Key : {"locations", "relatedLocations"}) {
-      json::Array *Locations = Result->getArray(Key);
-      if (!Locations) {
-        continue;
-      }
-      for (json::Value &Location : *Locations) {
-        json::Object *Artifact = getArtifactLocation(Location);
-        if (!Artifact) {
-          continue;
-        }
-        if (std::optional<int64_t> Index = Artifact->getInteger("index")) {
-          auto Uri = Uris.find(*Index);
-          if (Uri == Uris.end()) {
-            fail(ErrorMessages::UnknownArtifact, Path, *Index);
-          }
-          Artifact->try_emplace("uri", Uri->second);
-          Artifact->erase("index");
-        }
-      }
-    }
-    addFinding(std::move(*Result));
-  }
-}
-
-void ReportMerger::addFinding(json::Object Result) {
-  json::Value Value(std::move(Result));
-  Finding F;
-  F.Serialized = formatv("{0}", Value);
-  if (!Seen.insert(F.Serialized).second) {
-    return;
-  }
-  json::Object &Object = *Value.getAsObject();
-  F.Line = 0;
-  F.Column = 0;
-  if (json::Array *Locations = Object.getArray("locations");
-      Locations && !Locations->empty()) {
-    F.Uri = getString(getArtifactLocation(Locations->front()), "uri").str();
-    const json::Object *Location = Locations->front().getAsObject();
-    const json::Object *Physical =
-        Location ? Location->getObject("physicalLocation") : nullptr;
-    if (const json::Object *Region =
-            Physical ? Physical->getObject("region") : nullptr) {
-      F.Line = Region->getInteger("startLine").value_or(0);
-      F.Column = Region->getInteger("startColumn").value_or(0);
-    }
-  }
-  F.RuleId = getString(&Object, "ruleId").str();
-  F.Message = getString(Object.getObject("message"), "text").str();
-  F.Result = std::move(Object);
-  Findings.push_back(std::move(F));
-}
-
-json::Value ReportMerger::takeMerged() {
-  std::map<std::string, int64_t> RuleIndex;
-  json::Array MergedRules;
-  for (auto &[Id, Rule] : Rules) {
-    RuleIndex[Id] = MergedRules.size();
-    MergedRules.push_back(std::move(Rule));
-  }
-
-  std::map<std::string, int64_t> ArtifactIndex;
-  json::Array MergedArtifacts;
-  for (auto &[Uri, Artifact] : Artifacts) {
-    int64_t Index = MergedArtifacts.size();
-    ArtifactIndex[Uri] = Index;
-    if (json::Object *Object = Artifact.getAsObject()) {
-      if (json::Object *Location = Object->getObject("location")) {
-        (*Location)["index"] = Index;
-      }
-    }
-    MergedArtifacts.push_back(std::move(Artifact));
-  }
-
-  llvm::sort(Findings);
-  json::Array MergedResults;
-  for (Finding &F : Findings) {
-    auto Rule = RuleIndex.find(F.RuleId);
-    if (Rule != RuleIndex.end()) {
-      F.Result["ruleIndex"] = Rule->second;
-    }
-    for (StringRef Key : {"locations", "relatedLocations"}) {
-      json::Array *Locations = F.Result.getArray(Key);
-      if (!Locations) {
-        continue;
-      }
-      for (json::Value &Location : *Locations) {
-        json::Object *Artifact = getArtifactLocation(Location);
-        if (!Artifact) {
-          continue;
-        }
-        auto Index = ArtifactIndex.find(getString(Artifact, "uri").str());
-        if (Index != ArtifactIndex.end()) {
-          (*Artifact)["index"] = Index->second;
-        }
-      }
-    }
-    MergedResults.push_back(std::move(F.Result));
-  }
-
-  Driver["rules"] = std::move(MergedRules);
-  Tool["driver"] = std::move(Driver);
-  Run["tool"] = std::move(Tool);
-  Run["artifacts"] = std::move(MergedArtifacts);
-  Run["results"] = std::move(MergedResults);
-  json::Array Runs;
-  Runs.push_back(std::move(Run));
-  Root["runs"] = std::move(Runs);
-  return std::move(Root);
-}
-
-} // namespace
-
-//===----------------------------------------------------------------------===//
-// Driver
-//===----------------------------------------------------------------------===//
-
-int main(int argc, const char **argv) {
-  llvm::StringRef ToolHeading = "SSAF Transformation Report Merger";
-
-  InitLLVM X(argc, argv);
-  initTool(argc, argv, "0.1", MergeTransformationReportCategory, ToolHeading);
-
-  ReportMerger Merger;
-  for (const std::string &Path : InputPaths) {
-    Merger.add(readLog(Path), Path);
-  }
-  writeLog(Merger.takeMerged(), OutputPath);
-
-  return 0;
-}

>From 2aa8a0fd4a73d448571f47bef6900e34e8573b4a Mon Sep 17 00:00:00 2001
From: Balazs Benics <benicsbalazs at gmail.com>
Date: Thu, 15 Oct 2026 11:53:31 +0100
Subject: [PATCH 10/14] Revert "[clang][ssaf] Interpose ld.lld in
 clang-ssaf-orchestrator-make (#231720)"

This reverts commit 9d4c617fc3999a5a2c787c7271105da77ab8aa75.
---
 .../user-docs/MakeProjects.md                 |  4 +-
 .../link-driver-ld-lld.test                   | 41 -------------------
 .../clang_ssaf_orchestrator_make/config.py    |  1 -
 .../tests/test_clang_shim.py                  | 12 +-----
 4 files changed, 4 insertions(+), 54 deletions(-)
 delete mode 100644 clang/test/Analysis/Scalable/ssaf-orchestrator-make/link-driver-ld-lld.test

diff --git a/clang/docs/ScalableStaticAnalysis/user-docs/MakeProjects.md b/clang/docs/ScalableStaticAnalysis/user-docs/MakeProjects.md
index eabba61108e18..2e3fecf6c0e26 100644
--- a/clang/docs/ScalableStaticAnalysis/user-docs/MakeProjects.md
+++ b/clang/docs/ScalableStaticAnalysis/user-docs/MakeProjects.md
@@ -201,8 +201,8 @@ either way.
 ## Interposition
 
 The orchestrator populates `<output-dir>/shims/` with links named after the
-tools a build invokes — `cc`, `clang`, `c++`, `clang++`, `ld`, `ld.lld` and
-`ar` — each pointing at the shim that stands in for it, and prepends that
+tools a build invokes — `cc`, `clang`, `c++`, `clang++`, `ld` and `ar` —
+each pointing at the shim that stands in for it, and prepends that
 directory to `PATH`. It also puts the path of a configuration file in
 `SSAF_CONFIG`.
 
diff --git a/clang/test/Analysis/Scalable/ssaf-orchestrator-make/link-driver-ld-lld.test b/clang/test/Analysis/Scalable/ssaf-orchestrator-make/link-driver-ld-lld.test
deleted file mode 100644
index e8fbf934c8e01..0000000000000
--- a/clang/test/Analysis/Scalable/ssaf-orchestrator-make/link-driver-ld-lld.test
+++ /dev/null
@@ -1,41 +0,0 @@
-
-# REQUIRES: ssaf-orchestrator-make-build
-# RUN: rm -rf %t && split-file %s %t
-# RUN: mkdir -p %t/build
-# RUN: chmod +x %t/bin/ld.lld
-
-# A clang that links with lld, by default or through -fuse-ld=lld, runs ld.lld.
-# --ld-path makes this one run a fake ld.lld the same way.
-# RUN: cd %t
-# RUN: %clang-ssaf-orchestrator-make \
-# RUN:     --extract-summaries=PointerFlow \
-# RUN:     --ssaf-clang=%ssaf-orchestrator-make-clang \
-# RUN:     -o %t/out -- make \
-# RUN:   | FileCheck %s --check-prefix=STDOUT
-# STDOUT: summaries: 2
-# STDOUT: link-unit: {{[^ ]*}}/build/prg
-
-# RUN: ls %t/build/prg
-# RUN: cat %t/out/ssaf-artifacts%t/build/prg.summary.json | FileCheck %s --check-prefix=LU
-# LU: "kind": "LinkUnit"
-
-#--- Makefile
-CXX = clang++
-all: build/prg
-build/a.o: src/a.cpp
-	$(CXX) -c -o $@ $<
-build/prg: build/a.o
-	$(CXX) --ld-path=./bin/ld.lld -o $@ build/a.o
-
-#--- src/a.cpp
-int main() { return 0; }
-
-#--- bin/ld.lld
-#!/bin/sh
-prev=
-for arg in "$@"; do
-  if [ "$prev" = "-o" ]; then
-    : > "$arg"
-  fi
-  prev=$arg
-done
diff --git a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/config.py b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/config.py
index 8c876b34dfdcb..18f0cc2611a17 100644
--- a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/config.py
+++ b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/config.py
@@ -45,7 +45,6 @@ def output_dir_marker_path(output_dir):
     "c++": "clang",
     "clang++": "clang",
     "ld": "ld",
-    "ld.lld": "ld",
     "ar": "ar",
 }
 
diff --git a/clang/tools/clang-ssaf-orchestrator-make/tests/test_clang_shim.py b/clang/tools/clang-ssaf-orchestrator-make/tests/test_clang_shim.py
index 3fa76cc37312e..2ef092395421b 100644
--- a/clang/tools/clang-ssaf-orchestrator-make/tests/test_clang_shim.py
+++ b/clang/tools/clang-ssaf-orchestrator-make/tests/test_clang_shim.py
@@ -11,7 +11,7 @@
 
 from clang_ssaf_orchestrator_make.shims import clang, shim as shim_module
 from clang_ssaf_orchestrator_make import ssaf_artifact_repository as repository
-from clang_ssaf_orchestrator_make import build_graph, config
+from clang_ssaf_orchestrator_make import build_graph
 from clang_ssaf_orchestrator_make.failure_logs import SSAFFailureKind
 
 from . import configs
@@ -24,7 +24,7 @@ def setUp(self):
         self.out = os.path.join(self.tmp, "out")
         self.links = os.path.join(self.out, "shims")
         os.makedirs(self.links)
-        for name in config.SHIM_FOR_LINK_NAME:
+        for name in ("clang", "ld"):
             path = os.path.join(self.links, name)
             open(path, "w").close()
             os.chmod(path, os.stat(path).st_mode | stat.S_IXUSR)
@@ -56,14 +56,6 @@ def test_a_versioned_tool_still_finds_its_link(self):
         )
         self.assertEqual(os.path.join(self.links, "clang"), self.shim.commands[0][1][0])
 
-    def test_a_link_run_by_ld_lld_reaches_the_ld_shim(self):
-        clang._invoke_shim_for_job(
-            self.shim, self._job(["/build/bin/ld.lld", "-o", "prg", "a.o"]), self.tmp
-        )
-        link = self.shim.commands[0][1][0]
-        self.assertEqual(os.path.join(self.links, "ld.lld"), link)
-        self.assertEqual("ld", config.SHIM_FOR_LINK_NAME[os.path.basename(link)])
-
     def test_a_job_with_no_link_is_noted_and_skipped(self):
         with configs.recorded_notes() as notes:
             clang._invoke_shim_for_job(

>From 1d1b01309d1d5490baeed1199dc28d015b8f4661 Mon Sep 17 00:00:00 2001
From: Balazs Benics <benicsbalazs at gmail.com>
Date: Thu, 15 Oct 2026 11:53:31 +0100
Subject: [PATCH 11/14] Revert "Clang ssaf orchestrator fixes (#231678)"

This reverts commit 9d9ad8a3dbc557995e00250d830a173df775705f.
---
 .../Scalable/ssaf-orchestrator-make/bare-linker.test       | 2 +-
 .../Scalable/ssaf-orchestrator-make/link-driver.test       | 3 ++-
 .../Analysis/Scalable/ssaf-orchestrator-make/lit.local.cfg | 5 +----
 clang/test/CMakeLists.txt                                  | 7 +------
 clang/tools/CMakeLists.txt                                 | 4 +---
 5 files changed, 6 insertions(+), 15 deletions(-)

diff --git a/clang/test/Analysis/Scalable/ssaf-orchestrator-make/bare-linker.test b/clang/test/Analysis/Scalable/ssaf-orchestrator-make/bare-linker.test
index 2feb92b773d02..28222ab28548d 100644
--- a/clang/test/Analysis/Scalable/ssaf-orchestrator-make/bare-linker.test
+++ b/clang/test/Analysis/Scalable/ssaf-orchestrator-make/bare-linker.test
@@ -33,7 +33,7 @@ all: build/prg
 build/%.o: src/%.cpp
 	$(CXX) -arch arm64 -c -o $@ $<
 build/prg: build/main.o build/helper.o
-	$(LD) -o $@ build/main.o build/helper.o $(LDFLAGS)
+	$(LD) -o $@ build/main.o build/helper.o $(LDFLAGS) -lc++
 
 #--- src/helper.cpp
 int helper(int *p) { return p[0]; }
diff --git a/clang/test/Analysis/Scalable/ssaf-orchestrator-make/link-driver.test b/clang/test/Analysis/Scalable/ssaf-orchestrator-make/link-driver.test
index 29d78ce5bdf61..41bba34ad44be 100644
--- a/clang/test/Analysis/Scalable/ssaf-orchestrator-make/link-driver.test
+++ b/clang/test/Analysis/Scalable/ssaf-orchestrator-make/link-driver.test
@@ -19,11 +19,12 @@
 #--- Makefile
 CXX = clang++
 LD = $(CXX)
+LDFLAGS = -stdlib=libc++
 all: build/prg
 build/a.o: src/a.cpp
 	$(CXX) -c -o $@ $<
 build/prg: build/a.o
-	$(LD) -o $@ build/a.o
+	$(LD) $(LDFLAGS) -o $@ build/a.o
 
 #--- src/a.cpp
 int main() { return 0; }
diff --git a/clang/test/Analysis/Scalable/ssaf-orchestrator-make/lit.local.cfg b/clang/test/Analysis/Scalable/ssaf-orchestrator-make/lit.local.cfg
index ee29238aef53a..515a84e0831e8 100644
--- a/clang/test/Analysis/Scalable/ssaf-orchestrator-make/lit.local.cfg
+++ b/clang/test/Analysis/Scalable/ssaf-orchestrator-make/lit.local.cfg
@@ -4,10 +4,7 @@ import lit.util
 import os
 import platform
 
-if platform.system() == "Windows":
-    config.unsupported = True
-
-if lit.util.which("make"):
+if platform.system() != "Windows" and lit.util.which("make"):
     config.available_features.add("ssaf-orchestrator-make-build")
 
 config.substitutions.append(
diff --git a/clang/test/CMakeLists.txt b/clang/test/CMakeLists.txt
index 72a4f2760df84..3ef3cf764d215 100644
--- a/clang/test/CMakeLists.txt
+++ b/clang/test/CMakeLists.txt
@@ -107,18 +107,13 @@ list(APPEND CLANG_TEST_DEPS
   clang-ssaf-analyzer
   clang-ssaf-format
   clang-ssaf-linker
+  clang-ssaf-orchestrator-make
   clang-ssaf-src-edit-merge
   clang-sycl-linker
   diagtool
   hmaptool
   )
 
-if(NOT WIN32)
-  list(APPEND CLANG_TEST_DEPS
-    clang-ssaf-orchestrator-make
-    )
-endif()
-
 if(CLANG_ENABLE_CIR)
   list(APPEND CLANG_TEST_DEPS
     cir-opt
diff --git a/clang/tools/CMakeLists.txt b/clang/tools/CMakeLists.txt
index 182489653b805..535c3071700f2 100644
--- a/clang/tools/CMakeLists.txt
+++ b/clang/tools/CMakeLists.txt
@@ -18,9 +18,7 @@ add_clang_subdirectory(clang-scan-deps)
 add_clang_subdirectory(clang-ssaf-analyzer)
 add_clang_subdirectory(clang-ssaf-format)
 add_clang_subdirectory(clang-ssaf-linker)
-if(NOT WIN32)
-  add_clang_subdirectory(clang-ssaf-orchestrator-make)
-endif()
+add_clang_subdirectory(clang-ssaf-orchestrator-make)
 add_clang_subdirectory(clang-ssaf-src-edit-merge)
 add_clang_subdirectory(clang-sycl-linker)
 add_clang_subdirectory(clang-installapi)

>From d985c9278d21ea1943671e81835f29da837b9c15 Mon Sep 17 00:00:00 2001
From: Balazs Benics <benicsbalazs at gmail.com>
Date: Thu, 15 Oct 2026 11:53:31 +0100
Subject: [PATCH 12/14] Revert "[clang][ssaf] Interpose ar in
 clang-ssaf-orchestrator-make (#231618)"

This reverts commit 4d2bc2c3a7a400db43295053a8f5e5b088339847.
---
 .../developer-docs/MakeOrchestratorShims.md   |  17 +-
 .../user-docs/MakeProjects.md                 |  14 +-
 .../ssaf-orchestrator-make/library-only.test  |  35 -----
 .../link-unit-selection.test                  |  37 +----
 .../ssaf-orchestrator-make/link-units.test    |  54 -------
 .../prebuilt-archive.test                     |  44 ------
 .../CMakeLists.txt                            |   1 -
 .../clang-ssaf-orchestrator-make/README.md    |   2 +-
 .../clang_ssaf_orchestrator_make/config.py    |   1 -
 .../failure_logs.py                           |   1 -
 .../clang_ssaf_orchestrator_make/options.py   |   2 +-
 .../clang_ssaf_orchestrator_make/shims/ar.py  | 102 ------------
 .../shims/commands.py                         |   5 -
 .../clang_ssaf_orchestrator_make/shims/ld.py  |   3 +-
 .../tests/test_ar_shim.py                     | 148 ------------------
 .../tests/test_commands.py                    |  12 +-
 .../tests/test_ld_shim.py                     |  33 +---
 17 files changed, 27 insertions(+), 484 deletions(-)
 delete mode 100644 clang/test/Analysis/Scalable/ssaf-orchestrator-make/library-only.test
 delete mode 100644 clang/test/Analysis/Scalable/ssaf-orchestrator-make/link-units.test
 delete mode 100644 clang/test/Analysis/Scalable/ssaf-orchestrator-make/prebuilt-archive.test
 delete mode 100644 clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/ar.py
 delete mode 100644 clang/tools/clang-ssaf-orchestrator-make/tests/test_ar_shim.py

diff --git a/clang/docs/ScalableStaticAnalysis/developer-docs/MakeOrchestratorShims.md b/clang/docs/ScalableStaticAnalysis/developer-docs/MakeOrchestratorShims.md
index 0d6d3c10ef2e0..f11c6d3cd3c48 100644
--- a/clang/docs/ScalableStaticAnalysis/developer-docs/MakeOrchestratorShims.md
+++ b/clang/docs/ScalableStaticAnalysis/developer-docs/MakeOrchestratorShims.md
@@ -18,7 +18,6 @@ can spell the compiler several ways, so several names lead to the same shim:
 ```text
 cc, clang, c++, clang++  ->  clang
 ld                       ->  ld
-ar                       ->  ar
 ```
 
 It also writes the configuration for the shims into a JSON document and puts
@@ -49,11 +48,11 @@ split by what they do:
 
 ```text
 shim.py          the Shim class, its diagnostics, merge_edits
-commands.py      Files, is_object, is_archive, artifact_of, summary_of,
+commands.py      Files, is_object, artifact_of, summary_of,
                  filter_build_artifacts, unique
 driver_jobs.py   Job and the -### listing reader
 run.py           run_shim
-clang.py ld.py ar.py
+clang.py ld.py
 ```
 
 Every shim has the same shape, which `run_shim` implements: run the tool the
@@ -97,11 +96,10 @@ run it, and there is no SSAF step for its tool.
 
 ## Recording what the build assembled
 
-`ld` and `ar` each read their command line for the artifact it produces and
-the artifacts it consumes, and record them in
-`<output-dir>/build-graph/<path>.buildstep.json`. The top-most link unit is
-found from these records, and they tell an artifact the build assembled from
-one it never touched.
+`ld` reads its command line for the artifact it produces and the artifacts it
+consumes, and records them in `<output-dir>/build-graph/<path>.buildstep.json`.
+The top-most link unit is found from these records, and they tell an artifact
+the build assembled from one it never touched.
 
 Everything a shim writes is named for a build artifact's path plus a suffix,
 such as `ssaf-artifacts/<path>.summary.json`.
@@ -129,8 +127,7 @@ The kind says what went wrong; the kinds are the values of `SSAFFailureKind`:
 extract      summary extraction for a compilation
 transform    source-edit generation for a compilation
 link         clang-ssaf-linker over a link's inputs
-archive      the same for an archive
-merge        clang-ssaf-src-edit-merge over a link's or an archive's inputs
+merge        clang-ssaf-src-edit-merge over a link's inputs
 forward      handing a job to the shim that stands in for its tool
 missing      an artifact with nothing analysed behind it
 driver-jobs  the driver refused to list a command's jobs
diff --git a/clang/docs/ScalableStaticAnalysis/user-docs/MakeProjects.md b/clang/docs/ScalableStaticAnalysis/user-docs/MakeProjects.md
index 2e3fecf6c0e26..e7e788a6fe38c 100644
--- a/clang/docs/ScalableStaticAnalysis/user-docs/MakeProjects.md
+++ b/clang/docs/ScalableStaticAnalysis/user-docs/MakeProjects.md
@@ -12,9 +12,9 @@ step:
 - A **compilation** gets a second compilation — the frontend job the build's
   own compiler said it would run, with the `--ssaf-*` options appended and
   nothing taken away, so extraction sees exactly what the build compiles.
-- An **archive** and a **link** get a `clang-ssaf-linker`
-  invocation over the summaries of what went into them. These are not copies
-  of the build's command and carry no `--ssaf-*` options.
+- A **link** gets a `clang-ssaf-linker` invocation over the summaries of what
+  went into it. It is not a copy of the build's command and carries no
+  `--ssaf-*` options.
 
 The mapping onto the SSAF tools is direct:
 
@@ -27,10 +27,8 @@ The mapping onto the SSAF tools is direct:
    * - ``$(CXX) -c -o parser.o parser.cpp``
      - ``clang -cc1 … -o parser.o -x c++ parser.cpp
        --ssaf-extract-summaries=…``
-   * - ``$(AR) rcs libparse.a parser.o lexer.o``
-     - ``clang-ssaf-linker static-library create parser.json lexer.json``
-   * - ``$(CXX) -o app main.o libparse.a``
-     - ``clang-ssaf-linker main.json libparse.json``
+   * - ``$(CXX) -o app main.o parser.o``
+     - ``clang-ssaf-linker main.json parser.json``
 ```
 
 ## Usage
@@ -201,7 +199,7 @@ either way.
 ## Interposition
 
 The orchestrator populates `<output-dir>/shims/` with links named after the
-tools a build invokes — `cc`, `clang`, `c++`, `clang++`, `ld` and `ar` —
+tools a build invokes — `cc`, `clang`, `c++`, `clang++` and `ld` —
 each pointing at the shim that stands in for it, and prepends that
 directory to `PATH`. It also puts the path of a configuration file in
 `SSAF_CONFIG`.
diff --git a/clang/test/Analysis/Scalable/ssaf-orchestrator-make/library-only.test b/clang/test/Analysis/Scalable/ssaf-orchestrator-make/library-only.test
deleted file mode 100644
index 9ddf3bb8a22c3..0000000000000
--- a/clang/test/Analysis/Scalable/ssaf-orchestrator-make/library-only.test
+++ /dev/null
@@ -1,35 +0,0 @@
-
-# REQUIRES: ssaf-orchestrator-make-build
-# RUN: rm -rf %t && split-file %s %t
-# RUN: mkdir -p %t/build
-
-# RUN: cd %t
-# RUN: not %clang-ssaf-orchestrator-make \
-# RUN:     --extract-summaries=PointerFlow \
-# RUN:     --ssaf-clang=%ssaf-orchestrator-make-clang \
-# RUN:     -o %t/out -- make 2>&1 \
-# RUN:   | FileCheck %s
-
-# CHECK: '{{[^ ]*}}/build/libx.a' is not a link unit
-# CHECK-SAME: build a target that links
-
-# The archive was summarised; it is simply not something to analyse.
-# RUN: cat %t/out/ssaf-artifacts%t/build/libx.a.summary.json \
-# RUN:   | FileCheck %s --check-prefix=LIB
-# LIB: "type": "StaticLibrary"
-
-#--- Makefile
-CXX = clang++
-all: build/libx.a
-build/a.o: src/a.cpp
-	$(CXX) -c -o $@ $<
-build/libx.a: build/a.o
-	$(AR) rcs $@ build/a.o
-
-#--- src/a.cpp
-int total(int *data, int n) {
-  int t = 0;
-  for (int i = 0; i < n; ++i)
-    t += data[i];
-  return t;
-}
diff --git a/clang/test/Analysis/Scalable/ssaf-orchestrator-make/link-unit-selection.test b/clang/test/Analysis/Scalable/ssaf-orchestrator-make/link-unit-selection.test
index 5ec7da3020164..735ea6b718566 100644
--- a/clang/test/Analysis/Scalable/ssaf-orchestrator-make/link-unit-selection.test
+++ b/clang/test/Analysis/Scalable/ssaf-orchestrator-make/link-unit-selection.test
@@ -1,7 +1,7 @@
 
 # REQUIRES: ssaf-orchestrator-make-build
 # RUN: rm -rf %t && split-file %s %t
-# RUN: mkdir -p %t/two/build %t/none/build %t/lib/build
+# RUN: mkdir -p %t/two/build %t/none/build
 
 # RUN: cd %t/two
 # RUN: not %clang-ssaf-orchestrator-make \
@@ -22,24 +22,6 @@
 # PICKED: summaries: 2
 # PICKED: link-unit: {{[^ ]*}}/build/two
 
-# RUN: cd %t/lib
-# RUN: not %clang-ssaf-orchestrator-make \
-# RUN:     --extract-summaries=PointerFlow \
-# RUN:     --ssaf-clang=%ssaf-orchestrator-make-clang \
-# RUN:     -o %t/lib/out -- make 2>&1 \
-# RUN:   | FileCheck %s --check-prefix=LIB-AND-BINARY
-# LIB-AND-BINARY: produced 2 unconsumed outputs and none of them consumes the
-# LIB-AND-BINARY-SAME: others
-# LIB-AND-BINARY-SAME: {{[^ ]*}}/build/libextra.a
-# LIB-AND-BINARY-SAME: {{[^ ]*}}/build/prg
-
-# RUN: %clang-ssaf-orchestrator-make \
-# RUN:     --extract-summaries=PointerFlow \
-# RUN:     --ssaf-clang=%ssaf-orchestrator-make-clang \
-# RUN:     -o %t/lib/out -- make build/prg \
-# RUN:   | FileCheck %s --check-prefix=LIB-PICKED
-# LIB-PICKED: link-unit: {{[^ ]*}}/build/prg
-
 # RUN: cd %t/none
 # RUN: not %clang-ssaf-orchestrator-make \
 # RUN:     --extract-summaries=PointerFlow \
@@ -64,23 +46,6 @@ int main() { return 0; }
 #--- two/src/two.cpp
 int main() { return 1; }
 
-#--- lib/Makefile
-CXX = clang++
-AR = ar
-all: build/prg build/libextra.a
-build/%.o: src/%.cpp
-	$(CXX) -c -o $@ $<
-build/prg: build/main.o
-	$(CXX) -o $@ $<
-build/libextra.a: build/extra.o
-	$(AR) rcs $@ $<
-
-#--- lib/src/main.cpp
-int main() { return 0; }
-
-#--- lib/src/extra.cpp
-int extra(int *p) { return p[0]; }
-
 #--- none/Makefile
 CXX = clang++
 all: build/only.o
diff --git a/clang/test/Analysis/Scalable/ssaf-orchestrator-make/link-units.test b/clang/test/Analysis/Scalable/ssaf-orchestrator-make/link-units.test
deleted file mode 100644
index 5f6b450c07f77..0000000000000
--- a/clang/test/Analysis/Scalable/ssaf-orchestrator-make/link-units.test
+++ /dev/null
@@ -1,54 +0,0 @@
-
-# REQUIRES: ssaf-orchestrator-make-build
-# RUN: rm -rf %t && split-file %s %t
-# RUN: mkdir -p %t/build
-
-# RUN: cd %t
-# RUN: %clang-ssaf-orchestrator-make \
-# RUN:     --extract-summaries=PointerFlow \
-# RUN:     --ssaf-clang=%ssaf-orchestrator-make-clang \
-# RUN:     -o %t/out -- make \
-# RUN:   | FileCheck %s --check-prefix=STDOUT
-
-# STDOUT: summaries: 5
-# STDOUT: link-unit: {{[^ ]*}}/build/prg
-# STDOUT: link-unit-summary: {{[^ ]*}}/out/ssaf-artifacts{{[^ ]*}}/build/prg.summary.json
-
-# RUN: cat %t/out/ssaf-artifacts%t/build/libhelp.a.summary.json | FileCheck %s --check-prefix=LIB
-# LIB: "type": "StaticLibrary"
-# RUN: cat %t/out/ssaf-artifacts%t/build/prg.summary.json | FileCheck %s --check-prefix=LU
-# LU: "type": "LUSummary"
-
-# RUN: cat %t/out/build-graph%t/build/libhelp.a.buildstep.json \
-# RUN:   | FileCheck %s --check-prefix=UNIT-LIB
-# UNIT-LIB-DAG: build/helper.o
-# UNIT-LIB-DAG: build/other.o
-# RUN: cat %t/out/build-graph%t/build/prg.buildstep.json \
-# RUN:   | FileCheck %s --check-prefix=UNIT-PRG
-# UNIT-PRG-DAG: build/main.o
-# UNIT-PRG-DAG: build/libhelp.a
-
-#--- Makefile
-CXX = clang++
-LIBOBJS = build/helper.o build/other.o
-all: build/prg
-build/%.o: src/%.cpp
-	$(CXX) -c -o $@ $<
-build/libhelp.a: $(LIBOBJS)
-	$(AR) rcs $@ $(LIBOBJS)
-build/prg: build/main.o build/libhelp.a
-	$(CXX) -o $@ build/main.o build/libhelp.a
-
-#--- src/helper.cpp
-int helper(int *p) { return p[0]; }
-
-#--- src/other.cpp
-int other(int *p) { return p[1]; }
-
-#--- src/main.cpp
-int helper(int *p);
-int other(int *p);
-int main() {
-  int values[2] = {1, 2};
-  return helper(values) + other(values);
-}
diff --git a/clang/test/Analysis/Scalable/ssaf-orchestrator-make/prebuilt-archive.test b/clang/test/Analysis/Scalable/ssaf-orchestrator-make/prebuilt-archive.test
deleted file mode 100644
index d903e2417f6f1..0000000000000
--- a/clang/test/Analysis/Scalable/ssaf-orchestrator-make/prebuilt-archive.test
+++ /dev/null
@@ -1,44 +0,0 @@
-
-# REQUIRES: ssaf-orchestrator-make-build
-# RUN: rm -rf %t && split-file %s %t
-# RUN: mkdir -p %t/build
-
-# Built before the run, so the output directory holds nothing under its id.
-# RUN: %clang -c -o %t/third_party/vendor.o %t/third_party/vendor.c
-# RUN: ar rcs %t/third_party/libvendor.a %t/third_party/vendor.o
-
-# RUN: cd %t
-# RUN: %clang-ssaf-orchestrator-make \
-# RUN:     --extract-summaries=PointerFlow \
-# RUN:     --ssaf-clang=%ssaf-orchestrator-make-clang \
-# RUN:     -o %t/out -- make \
-# RUN:   | FileCheck %s --check-prefix=STDOUT
-
-# STDOUT: summaries: 2
-# STDOUT: link-unit: {{[^ ]*}}/build/prg
-
-# RUN: not ls %t/out/failure-logs
-
-# RUN: cat %t/out/build-graph%t/build/prg.buildstep.json \
-# RUN:   | FileCheck %s --check-prefix=UNIT
-# UNIT-NOT: libvendor.a
-# UNIT: build/main.o
-# UNIT-NOT: libvendor.a
-
-#--- Makefile
-CC = clang
-all: build/prg
-build/main.o: src/main.c
-	$(CC) -c -o $@ $<
-build/prg: build/main.o
-	$(CC) -o $@ build/main.o third_party/libvendor.a
-
-#--- third_party/vendor.c
-int vendor(int *p) { return p[0]; }
-
-#--- src/main.c
-int vendor(int *p);
-int main(void) {
-  int values[2] = {1, 2};
-  return vendor(values);
-}
diff --git a/clang/tools/clang-ssaf-orchestrator-make/CMakeLists.txt b/clang/tools/clang-ssaf-orchestrator-make/CMakeLists.txt
index 6c953ad7d265c..a29c137eb30fc 100644
--- a/clang/tools/clang-ssaf-orchestrator-make/CMakeLists.txt
+++ b/clang/tools/clang-ssaf-orchestrator-make/CMakeLists.txt
@@ -14,7 +14,6 @@ set(SsafOrchestratorMakeLib
 
 set(SsafOrchestratorMakeShimLib
     "__init__.py"
-    "ar.py"
     "clang.py"
     "commands.py"
     "driver_jobs.py"
diff --git a/clang/tools/clang-ssaf-orchestrator-make/README.md b/clang/tools/clang-ssaf-orchestrator-make/README.md
index 6a9b691a90ccf..04c2337d5db90 100644
--- a/clang/tools/clang-ssaf-orchestrator-make/README.md
+++ b/clang/tools/clang-ssaf-orchestrator-make/README.md
@@ -1,7 +1,7 @@
 # clang-ssaf-orchestrator-make
 
 Runs a Scalable Static Analysis Framework analysis over a project by riding
-along with its `make` build. Each compilation, archive and link step the build
+along with its `make` build. Each compilation and link step the build
 performs is paired with an SSAF step that produces the corresponding summary,
 and the summaries are linked into one whole-program view.
 
diff --git a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/config.py b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/config.py
index 18f0cc2611a17..d2532c6ee8062 100644
--- a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/config.py
+++ b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/config.py
@@ -45,7 +45,6 @@ def output_dir_marker_path(output_dir):
     "c++": "clang",
     "clang++": "clang",
     "ld": "ld",
-    "ar": "ar",
 }
 
 
diff --git a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/failure_logs.py b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/failure_logs.py
index 80ca84d7f52a9..84f52c5b3f9fe 100644
--- a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/failure_logs.py
+++ b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/failure_logs.py
@@ -16,7 +16,6 @@ class SSAFFailureKind(enum.Enum):
     EXTRACT = "extract"
     TRANSFORM = "transform"
     LINK = "link"
-    ARCHIVE = "archive"
     MERGE = "merge"
     FORWARD = "forward"
     MISSING = "missing"
diff --git a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/options.py b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/options.py
index 3e720de577bf3..3a962f6274be0 100644
--- a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/options.py
+++ b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/options.py
@@ -20,7 +20,7 @@ def build_parser():
         prog=PROGRAM,
         usage="%(prog)s [options] [--] <build command>",
         description="Run an SSAF analysis over a project as it builds. The "
-        "build is executed normally; each compilation, archive and link step "
+        "build is executed normally; each compilation and link step "
         "is paired with an SSAF step that produces the corresponding summary.",
     )
     parser.add_argument("--version", action="version", version="%(prog)s " + VERSION)
diff --git a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/ar.py b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/ar.py
deleted file mode 100644
index 70237e0e6f888..0000000000000
--- a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/ar.py
+++ /dev/null
@@ -1,102 +0,0 @@
-# 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
-
-import os
-
-from .. import config, logging_diagnostics, utils
-from ..build_graph import BuildArtifactId
-from ..failure_logs import SSAFFailureKind
-from ..ssaf_artifact_repository import SSAFArtifactKind, get_ssaf_artifact_id
-from . import run
-from .commands import (
-    Files,
-    filter_build_artifacts,
-    is_archive,
-    is_object,
-    summary_of,
-    unique,
-)
-from .shim import merge_edits
-
-
-_CREATING_OPERATIONS = frozenset("rqm")
-
-
-def identify_inputs_output(argv):
-    args = []
-    index = 1
-    while index < len(argv):
-        arg = argv[index]
-        if arg in ("--plugin", "--target"):
-            index += 2
-            continue
-        if arg.startswith("--"):
-            index += 1
-            continue
-        args.append(arg)
-        index += 1
-
-    if len(args) < 2:
-        return None
-    if not set(args[0].lstrip("-")) & _CREATING_OPERATIONS:
-        return None
-    archive = args[1]
-    if not is_archive(archive):
-        return None
-    return Files([m for m in args[2:] if is_object(m)], archive)
-
-
-def invoke_ssaf_tools(shim, cwd):
-    files = identify_inputs_output(shim.argv)
-    if files is None:
-        logging_diagnostics.report_note(
-            shim.workflow_config.verbose, "not archive creation, no SSAF step to run"
-        )
-        return
-
-    ssaf_artifact_repo = shim.ssaf_artifact_repo
-    output = os.path.join(cwd, files.output)
-    build_artifact_id = BuildArtifactId(output)
-    input_build_artifact_ids = filter_build_artifacts(
-        shim.build_graph, ssaf_artifact_repo, cwd, files.inputs
-    )
-
-    if shim.pass_config.pass_kind == config.SSAFPassKind.TRANSFORMATION:
-        merge_edits(shim, build_artifact_id, input_build_artifact_ids)
-        return
-
-    shim.build_graph.record_build_step(
-        build_artifact_id,
-        inputs=input_build_artifact_ids,
-    )
-    summaries = []
-    for each in input_build_artifact_ids:
-        found = summary_of(ssaf_artifact_repo, each)
-        if found:
-            summaries.append(found)
-        else:
-            shim.log_missing_summary(build_artifact_id, each)
-    summaries = unique(summaries)
-    if not summaries:
-        logging_diagnostics.report_note(
-            shim.workflow_config.verbose,
-            "no summaries feed %s, nothing to archive" % build_artifact_id.get_path(),
-        )
-        return
-    target = utils.make_parents(
-        ssaf_artifact_repo.get_path_for_artifact(
-            get_ssaf_artifact_id(build_artifact_id, SSAFArtifactKind.SUMMARY)
-        )
-    )
-    shim.run(
-        [shim.pass_config.ssaf_linker, "static-library", "create"]
-        + summaries
-        + ["-o", target, "--namespace=" + os.path.basename(output)],
-        SSAFFailureKind.ARCHIVE,
-        build_artifact_id,
-    )
-
-
-def main(argv, env=None):
-    return run.run_shim(invoke_ssaf_tools, argv, env)
diff --git a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/commands.py b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/commands.py
index f290ae9097797..d4794cb4e734c 100644
--- a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/commands.py
+++ b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/commands.py
@@ -11,17 +11,12 @@
 Files = collections.namedtuple("Files", "inputs output")
 
 _OBJECT_EXTENSIONS = frozenset([".o", ".obj"])
-_ARCHIVE_EXTENSIONS = frozenset([".a"])
 
 
 def is_object(filename):
     return os.path.splitext(filename)[1] in _OBJECT_EXTENSIONS
 
 
-def is_archive(filename):
-    return os.path.splitext(filename)[1] in _ARCHIVE_EXTENSIONS
-
-
 def artifact_of(ssaf_artifact_repo, build_artifact_id, ssaf_artifact_kind):
     ssaf_artifact_id = get_ssaf_artifact_id(build_artifact_id, ssaf_artifact_kind)
     if not ssaf_artifact_repo.has_artifact(ssaf_artifact_id):
diff --git a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/ld.py b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/ld.py
index 3d1e5924623ed..54c5c759ed5bf 100644
--- a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/ld.py
+++ b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/ld.py
@@ -12,7 +12,6 @@
 from .commands import (
     Files,
     filter_build_artifacts,
-    is_archive,
     is_object,
     summary_of,
     unique,
@@ -30,7 +29,7 @@ def identify_inputs_output(argv):
             output = argv[index + 1]
             index += 2
             continue
-        if not arg.startswith("-") and (is_object(arg) or is_archive(arg)):
+        if not arg.startswith("-") and is_object(arg):
             inputs.append(arg)
         index += 1
     return Files(inputs, output) if inputs else None
diff --git a/clang/tools/clang-ssaf-orchestrator-make/tests/test_ar_shim.py b/clang/tools/clang-ssaf-orchestrator-make/tests/test_ar_shim.py
deleted file mode 100644
index cfe3daaceabf3..0000000000000
--- a/clang/tools/clang-ssaf-orchestrator-make/tests/test_ar_shim.py
+++ /dev/null
@@ -1,148 +0,0 @@
-# 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
-
-import os
-import shutil
-import tempfile
-import unittest
-
-from clang_ssaf_orchestrator_make import utils
-from clang_ssaf_orchestrator_make.failure_logs import SSAFFailureKind
-from clang_ssaf_orchestrator_make.shims import ar
-from clang_ssaf_orchestrator_make import ssaf_artifact_repository as repository
-from clang_ssaf_orchestrator_make import build_graph
-
-from . import configs
-
-
-class SsafStep(unittest.TestCase):
-    def setUp(self):
-        self.tmp = tempfile.mkdtemp()
-        self.addCleanup(shutil.rmtree, self.tmp, True)
-        self.root = os.path.join(self.tmp, "project")
-        self.out = os.path.join(self.tmp, "out")
-        os.makedirs(os.path.join(self.root, "build"))
-
-    def _shim(self, argv, pass_config=None):
-        return configs.RecordingShim(argv, self.out, pass_config)
-
-    def _id(self, relative):
-        return build_graph.BuildArtifactId(os.path.join(self.root, relative))
-
-    def _summary(self, relative):
-        records = configs.repository_for(self.out)
-        open(
-            utils.make_parents(
-                records.get_path_for_artifact(
-                    repository.get_ssaf_artifact_id(
-                        build_graph.BuildArtifactId(os.path.join(self.root, relative)),
-                        repository.SSAFArtifactKind.SUMMARY,
-                    )
-                )
-            ),
-            "w",
-        ).close()
-
-    def test_a_command_that_creates_no_archive_runs_no_step(self):
-        shim = self._shim(["ar", "t", "build/libx.a"])
-        with configs.recorded_notes() as notes:
-            ar.invoke_ssaf_tools(shim, self.root)
-        self.assertEqual([], shim.commands)
-        self.assertIn("not archive creation", notes[0])
-
-    def test_a_member_the_run_never_touched_is_not_an_input(self):
-        shim = self._shim(["ar", "rcs", "build/libx.a", "build/a.o"])
-        ar.invoke_ssaf_tools(shim, self.root)
-        self.assertEqual([], shim.commands)
-        self.assertEqual([], shim.missing)
-        libx = self._id("build/libx.a")
-        self.assertTrue(configs.build_graph_for(self.out).was_built(libx))
-        self.assertEqual(
-            [],
-            configs.build_graph_for(self.out).get_recorded_build_steps()[
-                libx.get_path()
-            ],
-        )
-
-    def test_the_summaries_that_exist_are_handed_to_the_linker(self):
-        self._summary("build/a.o")
-        shim = self._shim(["ar", "rcs", "build/libx.a", "build/a.o"])
-        ar.invoke_ssaf_tools(shim, self.root)
-        self.assertEqual(1, len(shim.commands))
-        failure, command = shim.commands[0]
-        self.assertEqual((SSAFFailureKind.ARCHIVE, self._id("build/libx.a")), failure)
-        self.assertEqual(
-            ["/bin/clang-ssaf-linker", "static-library", "create"], command[:3]
-        )
-        self.assertIn("--namespace=libx.a", command)
-
-    def test_the_namespace_is_the_archives_file_name_not_its_path(self):
-        self._summary("build/a.o")
-        shim = self._shim(["ar", "rcs", "build/libx.a", "build/a.o"])
-        ar.invoke_ssaf_tools(shim, self.root)
-        _, command = shim.commands[0]
-        self.assertNotIn("--namespace=build/libx.a", command)
-
-    def test_a_member_that_is_not_an_object_is_not_an_input(self):
-        self._summary("build/a.o")
-        shim = self._shim(["ar", "rcs", "build/libx.a", "build/a.o", "README"])
-        ar.invoke_ssaf_tools(shim, self.root)
-        self.assertEqual([], shim.missing)
-        self.assertEqual(
-            [self._id("build/a.o").get_path()],
-            configs.build_graph_for(self.out).get_recorded_build_steps()[
-                self._id("build/libx.a").get_path()
-            ],
-        )
-
-    def test_in_the_transformation_pass_the_edits_are_merged_instead(self):
-        shim = self._shim(
-            ["ar", "rcs", "build/libx.a", "build/a.o"],
-            configs.transformation_config(),
-        )
-        with configs.recorded_notes() as notes:
-            ar.invoke_ssaf_tools(shim, self.root)
-        self.assertEqual(
-            [
-                "no edits feed %s, nothing to merge"
-                % self._id("build/libx.a").get_path()
-            ],
-            notes,
-        )
-
-
-class Archive(unittest.TestCase):
-    def test_archive(self):
-        files = ar.identify_inputs_output(["ar", "rcs", "libx.a", "a.o", "b.o"])
-        self.assertEqual("libx.a", files.output)
-        self.assertEqual(["a.o", "b.o"], files.inputs)
-
-    def test_leading_dash_operation(self):
-        files = ar.identify_inputs_output(["ar", "-rcs", "libx.a", "a.o"])
-        self.assertEqual(["a.o"], files.inputs)
-
-    def test_plugin_option_is_not_the_operation(self):
-        files = ar.identify_inputs_output(
-            ["ar", "--plugin", "/usr/lib/liblto.so", "rcs", "libx.a", "a.o"]
-        )
-        self.assertEqual(["a.o"], files.inputs)
-
-    def test_non_creating_operations_read_as_nothing(self):
-        self.assertIsNone(ar.identify_inputs_output(["ar", "t", "libx.a"]))
-
-    def test_every_creating_operation_is_recognised(self):
-        for operation in ("r", "q", "m"):
-            files = ar.identify_inputs_output(["ar", operation + "cs", "libx.a", "a.o"])
-            self.assertEqual(["a.o"], files.inputs, operation)
-            self.assertEqual("libx.a", files.output, operation)
-
-    def test_non_archive_output_reads_as_nothing(self):
-        self.assertIsNone(ar.identify_inputs_output(["ar", "rcs", "notlib", "a.o"]))
-
-    def test_too_few_arguments(self):
-        self.assertIsNone(ar.identify_inputs_output(["ar", "rcs"]))
-
-
-if __name__ == "__main__":
-    unittest.main()
diff --git a/clang/tools/clang-ssaf-orchestrator-make/tests/test_commands.py b/clang/tools/clang-ssaf-orchestrator-make/tests/test_commands.py
index 1db814be328f3..f7d28f2af2a8a 100644
--- a/clang/tools/clang-ssaf-orchestrator-make/tests/test_commands.py
+++ b/clang/tools/clang-ssaf-orchestrator-make/tests/test_commands.py
@@ -21,12 +21,6 @@ def test_object_extensions(self):
         for name in ("a.a", "a.c", "a", "a.o.tmp", "a.O"):
             self.assertFalse(commands.is_object(name), name)
 
-    def test_archive_extensions(self):
-        for name in ("libx.a", "build/libx.a"):
-            self.assertTrue(commands.is_archive(name), name)
-        for name in ("libx.so", "libx.dylib", "libx", "libx.a.tmp"):
-            self.assertFalse(commands.is_archive(name), name)
-
 
 class Unique(unittest.TestCase):
     def test_the_first_of_each_is_kept_in_order(self):
@@ -110,11 +104,11 @@ def test_an_object_with_only_source_edits_is_kept(self):
         self._write("build/a.o", repository.SSAFArtifactKind.EDITS)
         self.assertEqual([self._id("build/a.o")], self._kept("build/a.o"))
 
-    def test_an_archive_with_only_a_record_is_kept(self):
+    def test_an_assembled_object_with_only_a_record_is_kept(self):
         self.build_graph.record_build_step(
-            self._id("build/x.a"), [self._id("build/a.o")]
+            self._id("build/combined.o"), [self._id("build/a.o")]
         )
-        self.assertEqual([self._id("build/x.a")], self._kept("build/x.a"))
+        self.assertEqual([self._id("build/combined.o")], self._kept("build/combined.o"))
 
     def test_what_the_build_never_touched_is_dropped(self):
         self.assertEqual([], self._kept("third_party/prebuilt.a", "/usr/lib/libz.a"))
diff --git a/clang/tools/clang-ssaf-orchestrator-make/tests/test_ld_shim.py b/clang/tools/clang-ssaf-orchestrator-make/tests/test_ld_shim.py
index b4f802fc8ae07..a6ae6c1872375 100644
--- a/clang/tools/clang-ssaf-orchestrator-make/tests/test_ld_shim.py
+++ b/clang/tools/clang-ssaf-orchestrator-make/tests/test_ld_shim.py
@@ -16,21 +16,15 @@
 
 
 class Inputs(unittest.TestCase):
-    def test_objects_and_archives(self):
-        files = ld.identify_inputs_output(["ld", "-o", "prg", "a.o", "libx.a", "-lm"])
-        self.assertEqual(["a.o", "libx.a"], files.inputs)
+    def test_objects(self):
+        files = ld.identify_inputs_output(["ld", "-o", "prg", "a.o", "b.o", "-lm"])
+        self.assertEqual(["a.o", "b.o"], files.inputs)
         self.assertEqual("prg", files.output)
 
-    def test_any_object_or_archive_is_named_whatever_precedes_it(self):
+    def test_any_object_is_named_whatever_precedes_it(self):
         for option in ("-force_load", "-weak_library", "-filelist", "-bundle"):
-            files = ld.identify_inputs_output(
-                ["ld", "-o", "prg", "a.o", option, "libx.a"]
-            )
-            self.assertEqual(["a.o", "libx.a"], files.inputs, option)
-
-    def test_an_option_value_that_looks_like_an_archive_is_named_as_one(self):
-        files = ld.identify_inputs_output(["ld", "-o", "prg", "a.o", "-l", "x.a"])
-        self.assertEqual(["a.o", "x.a"], files.inputs)
+            files = ld.identify_inputs_output(["ld", "-o", "prg", "a.o", option, "b.o"])
+            self.assertEqual(["a.o", "b.o"], files.inputs, option)
 
     def test_a_value_with_no_object_extension_is_not_named(self):
         files = ld.identify_inputs_output(["ld", "-o", "prg", "a.o", "-l", "x"])
@@ -108,7 +102,7 @@ def _recorded_inputs(self):
 
     def test_only_what_the_run_produced_is_linked(self):
         self._summary("build/a.o")
-        shim = self._run(["build/a.o", "third_party/prebuilt.a", "/usr/lib/libz.a"])
+        shim = self._run(["build/a.o", "third_party/prebuilt.o", "/usr/lib/crt1.o"])
         self.assertEqual([self._id("build/a.o").get_path()], self._recorded_inputs())
         self.assertEqual([], shim.missing)
         _, command = shim.commands[0]
@@ -127,19 +121,6 @@ def test_an_lto_scratch_object_is_not_an_input(self):
         self._run(["build/a.o", "-object_path_lto", "/tmp/lto.o"])
         self.assertEqual([self._id("build/a.o").get_path()], self._recorded_inputs())
 
-    def test_an_option_value_that_looks_like_an_archive_is_not_an_input(self):
-        self._summary("build/a.o")
-        self._run(["build/a.o", "-l", "x.a"])
-        self.assertEqual([self._id("build/a.o").get_path()], self._recorded_inputs())
-
-    def test_an_archive_with_nothing_behind_it_is_reported(self):
-        self.graph.record_build_step(
-            build_graph.BuildArtifactId(os.path.join(self.root, "build/libx.a")),
-            [self._id("build/a.o")],
-        )
-        shim = self._run(["build/libx.a"])
-        self.assertEqual([self._id("build/libx.a").get_path()], shim.missing)
-
     def test_a_link_of_nothing_we_know_runs_no_step(self):
         shim = self._run(["build/a.o"])
         self.assertEqual([], shim.commands)

>From b523903e3bd4402937963dcddbaaa6baefc187a3 Mon Sep 17 00:00:00 2001
From: Balazs Benics <benicsbalazs at gmail.com>
Date: Thu, 15 Oct 2026 11:53:32 +0100
Subject: [PATCH 13/14] Revert "[clang][ssaf] Add a transformation pass to
 clang-ssaf-orchestrator-make (#231601)"

This reverts commit 2250a9708e9e0c203562f4771063684f07ea87dd.
---
 .../developer-docs/MakeOrchestratorShims.md   |  16 +--
 .../user-docs/MakeProjects.md                 |  32 +----
 .../Scalable/ssaf-orchestrator-make/help.test |   2 -
 .../two-pass-compile-and-link.test            |  44 ------
 .../ssaf-orchestrator-make/two-pass.test      |  67 ---------
 .../clang_ssaf_orchestrator_make/config.py    |  21 ---
 .../config_orchestrator.py                    |  29 +---
 .../config_shims.py                           |   4 +-
 .../failure_logs.py                           |   2 -
 .../logging_diagnostics.py                    |   6 -
 .../clang_ssaf_orchestrator_make/options.py   |  26 ----
 .../orchestrator.py                           |  56 +-------
 .../shims/clang.py                            |  35 +----
 .../shims/commands.py                         |  10 +-
 .../clang_ssaf_orchestrator_make/shims/ld.py  |   7 +-
 .../shims/shim.py                             |  39 +-----
 .../ssaf_artifact_repository.py               |  22 +--
 .../tests/configs.py                          |  15 --
 .../tests/test_clang_shim.py                  |  14 --
 .../tests/test_commands.py                    |   4 -
 .../tests/test_config.py                      |  50 +------
 .../tests/test_config_orchestrator.py         |  86 +++---------
 .../tests/test_ld_shim.py                     |   7 -
 .../tests/test_logging_diagnostics.py         |  21 ---
 .../tests/test_options.py                     |   6 -
 .../tests/test_orchestrator.py                |  85 ++++--------
 .../tests/test_ssaf_artifact_repository.py    | 128 ------------------
 27 files changed, 65 insertions(+), 769 deletions(-)
 delete mode 100644 clang/test/Analysis/Scalable/ssaf-orchestrator-make/two-pass-compile-and-link.test
 delete mode 100644 clang/test/Analysis/Scalable/ssaf-orchestrator-make/two-pass.test

diff --git a/clang/docs/ScalableStaticAnalysis/developer-docs/MakeOrchestratorShims.md b/clang/docs/ScalableStaticAnalysis/developer-docs/MakeOrchestratorShims.md
index f11c6d3cd3c48..c815a30b0425d 100644
--- a/clang/docs/ScalableStaticAnalysis/developer-docs/MakeOrchestratorShims.md
+++ b/clang/docs/ScalableStaticAnalysis/developer-docs/MakeOrchestratorShims.md
@@ -47,7 +47,7 @@ The shim bodies live in the package, as `clang_ssaf_orchestrator_make.shims`,
 split by what they do:
 
 ```text
-shim.py          the Shim class, its diagnostics, merge_edits
+shim.py          the Shim class and its diagnostics
 commands.py      Files, is_object, artifact_of, summary_of,
                  filter_build_artifacts, unique
 driver_jobs.py   Job and the -### listing reader
@@ -125,23 +125,9 @@ The kind says what went wrong; the kinds are the values of `SSAFFailureKind`:
 
 ```text
 extract      summary extraction for a compilation
-transform    source-edit generation for a compilation
 link         clang-ssaf-linker over a link's inputs
-merge        clang-ssaf-src-edit-merge over a link's inputs
 forward      handing a job to the shim that stands in for its tool
 missing      an artifact with nothing analysed behind it
 driver-jobs  the driver refused to list a command's jobs
 internal     an unhandled exception inside a shim
 ```
-
-## Carrying the link unit name into the second pass
-
-One piece of state flows from the first pass to the second: the top-most link
-unit's own name, which is not an artifact id and is unknown until the first
-pass's linker has written the link unit summary.
-
-The orchestrator reads it from that summary, as the `lu_namespace` component
-whose kind is `LinkUnit`, and puts it in the transformation pass's
-configuration; the clang shim passes it as `--ssaf-link-unit-id=` to every
-source-edit generation. This is why the second pass's configuration file
-cannot be written up front.
diff --git a/clang/docs/ScalableStaticAnalysis/user-docs/MakeProjects.md b/clang/docs/ScalableStaticAnalysis/user-docs/MakeProjects.md
index e7e788a6fe38c..1bf14c500979b 100644
--- a/clang/docs/ScalableStaticAnalysis/user-docs/MakeProjects.md
+++ b/clang/docs/ScalableStaticAnalysis/user-docs/MakeProjects.md
@@ -35,16 +35,13 @@ The mapping onto the SSAF tools is direct:
 
 Run it from the project root; that is where the build runs.
 
-There are three workflows, each going one step further than the last:
+There are two workflows, the second going one step further than the first:
 
 - **Summary extraction and linking**, with `--extract-summaries`. Every
   translation unit gets a summary, and the summaries are linked the way the
   build links the objects, into one link unit summary.
 - **Whole-program analysis**, adding `--analysis`. `clang-ssaf-analyzer` runs
   the named analyses over the link unit summary.
-- **Whole-program transformation**, adding `--transformation`. A second build
-  generates source edits from the analysis result, and they are merged across
-  the whole program.
 
 Summary extraction and linking:
 
@@ -65,17 +62,6 @@ $ clang-ssaf-orchestrator-make \
     -- make -j8
 ```
 
-Whole-program transformation, which ends in merged source edits:
-
-```console
-$ clang-ssaf-orchestrator-make \
-    --extract-summaries=PointerFlow,UnsafeBufferUsage \
-    --analysis=UnsafeBufferReachableAnalysisResult \
-    --transformation=cpp-bounded-buffers \
-    -o ssaf-output \
-    -- make -j8
-```
-
 For a project configured by autoconf, run `configure` first and give the
 orchestrator only the `make` invocation.
 
@@ -92,9 +78,6 @@ orchestrator only the `make` invocation.
    * - ``--analysis=<name>``
      - Whole-program analysis to run on the link unit summary. Repeatable.
        Without it the run stops after summary extraction.
-   * - ``--transformation=<name>``
-     - Source transformation to run in the second pass. Requires
-       ``--analysis``. Without it the run stops after the analysis.
    * - ``-o``, ``--output-dir=<dir>``
      - Where the SSAF artifacts go, made absolute. Defaults to
        ``ssaf-output``. It must be absent, empty, or an earlier run's.
@@ -106,9 +89,6 @@ orchestrator only the `make` invocation.
    * - ``--ssaf-analyzer=<path>``
      - Path to ``clang-ssaf-analyzer``. Defaults to the name on ``PATH``, and
        is only required with ``--analysis``.
-   * - ``--ssaf-src-edit-merge=<path>``
-     - Path to ``clang-ssaf-src-edit-merge``. Defaults to the name on
-       ``PATH``, and is only required with ``--transformation``.
    * - ``--ssaf-extra-clang-arg=<arg>``
      - Extra argument for every SSAF compilation. Repeatable.
    * - ``-k``, ``--keep-going``
@@ -155,16 +135,8 @@ translation units, and only the whole path tells them apart.
      - Which build artifacts were inputs for the ``<path>`` build artifact.
    * - ``<output-dir>/wpa.json``
      - Whole-program analysis result.
-   * - ``<output-dir>/ssaf-artifacts/<path>.edits.yaml``
-     - Source edits for the ``<path>`` build artifact.
-   * - ``<output-dir>/ssaf-artifacts/<path>.conflicts.sarif``
-     - Edits dropped because they conflicted.
-   * - ``<output-dir>/ssaf-artifacts/<path>.report.sarif``
-     - Transformation report for the ``<path>`` build artifact.
    * - ``<output-dir>/config-analysis.json``
-     - Configuration for the analysis pass, the first build pass.
-   * - ``<output-dir>/config-transformation.json``
-     - Configuration for the transformation pass, the second build pass.
+     - Configuration for the analysis pass.
    * - ``<output-dir>/shims/``
      - Links to the shims named so they interpose the binary tools, recreated
        on every run.
diff --git a/clang/test/Analysis/Scalable/ssaf-orchestrator-make/help.test b/clang/test/Analysis/Scalable/ssaf-orchestrator-make/help.test
index 3fefaae801bce..7796cbc785840 100644
--- a/clang/test/Analysis/Scalable/ssaf-orchestrator-make/help.test
+++ b/clang/test/Analysis/Scalable/ssaf-orchestrator-make/help.test
@@ -7,12 +7,10 @@
 # CHECK: --extract-summaries
 # CHECK: --ssaf-clang
 # CHECK: --analysis
-# CHECK: --transformation
 
 # RUN: %clang-ssaf-orchestrator-make --help | FileCheck %s --check-prefix=SSAF
 # SSAF: --ssaf-linker
 # SSAF: --ssaf-analyzer
-# SSAF: --ssaf-src-edit-merge
 # SSAF: --ssaf-extra-clang-arg
 # SSAF: --keep-going
 # SSAF: --verbose
diff --git a/clang/test/Analysis/Scalable/ssaf-orchestrator-make/two-pass-compile-and-link.test b/clang/test/Analysis/Scalable/ssaf-orchestrator-make/two-pass-compile-and-link.test
deleted file mode 100644
index ed44164de92e4..0000000000000
--- a/clang/test/Analysis/Scalable/ssaf-orchestrator-make/two-pass-compile-and-link.test
+++ /dev/null
@@ -1,44 +0,0 @@
-
-# REQUIRES: ssaf-orchestrator-make-build
-# RUN: rm -rf %t && split-file %s %t
-# RUN: mkdir -p %t/build
-
-# RUN: cd %t
-# RUN: %clang-ssaf-orchestrator-make \
-# RUN:     --extract-summaries=PointerFlow,UnsafeBufferUsage \
-# RUN:     --analysis=UnsafeBufferReachableAnalysisResult \
-# RUN:     --transformation=cpp-bounded-buffers \
-# RUN:     --ssaf-clang=%ssaf-orchestrator-make-clang \
-# RUN:     -o %t/out -- make \
-# RUN:   | FileCheck %s --check-prefix=STDOUT
-
-# STDOUT: summaries: 3
-# STDOUT: link-unit: {{[^ ]*}}/build/prg
-# STDOUT: source-edits: {{[^ ]*}}/out/ssaf-artifacts{{[^ ]*}}/build/prg.edits.yaml
-
-# RUN: cat %t/out/ssaf-artifacts%t/build/prg.edits.yaml \
-# RUN:   | FileCheck %s --check-prefix=EDITS
-# EDITS: Replacements:
-# EDITS-DAG: FilePath: {{.*}}src/main.cpp
-# EDITS-DAG: FilePath: {{.*}}src/parse.cpp
-
-#--- Makefile
-CXX = clang++
-all: build/prg
-build/prg: src/main.cpp src/parse.cpp
-	$(CXX) -o $@ src/main.cpp src/parse.cpp
-
-#--- src/parse.cpp
-int total(int *data, int n) {
-  int t = 0;
-  for (int i = 0; i < n; ++i)
-    t += data[i];
-  return t;
-}
-
-#--- src/main.cpp
-int total(int *data, int n);
-int main() {
-  int values[4] = {1, 2, 3, 4};
-  return total(values, 4);
-}
diff --git a/clang/test/Analysis/Scalable/ssaf-orchestrator-make/two-pass.test b/clang/test/Analysis/Scalable/ssaf-orchestrator-make/two-pass.test
deleted file mode 100644
index c9b19bd5ac7b2..0000000000000
--- a/clang/test/Analysis/Scalable/ssaf-orchestrator-make/two-pass.test
+++ /dev/null
@@ -1,67 +0,0 @@
-
-# REQUIRES: ssaf-orchestrator-make-build
-# RUN: rm -rf %t && split-file %s %t
-# RUN: mkdir -p %t/build
-
-# RUN: cd %t
-# RUN: %clang-ssaf-orchestrator-make \
-# RUN:     --extract-summaries=PointerFlow,UnsafeBufferUsage \
-# RUN:     --analysis=UnsafeBufferReachableAnalysisResult \
-# RUN:     --transformation=cpp-bounded-buffers \
-# RUN:     --ssaf-clang=%ssaf-orchestrator-make-clang \
-# RUN:     -o %t/out -- make \
-# RUN:   | FileCheck %s --check-prefix=STDOUT
-
-# STDOUT: summaries: 3
-# STDOUT: link-unit: {{[^ ]*}}/build/prg
-# STDOUT: analysis-result: {{[^ ]*}}/out/wpa.json
-# STDOUT: source-edits: {{[^ ]*}}/out/ssaf-artifacts{{[^ ]*}}/build/prg.edits.yaml
-# STDOUT-NOT: edit-conflicts
-
-# RUN: ls %t/out/ssaf-artifacts%t/build/main.o.summary.json %t/out/ssaf-artifacts%t/build/parse.o.summary.json
-# RUN: ls %t/out/ssaf-artifacts%t/build/main.o.edits.yaml \
-# RUN:      %t/out/ssaf-artifacts%t/build/parse.o.edits.yaml
-# RUN: ls %t/out/ssaf-artifacts%t/build/main.o.report.sarif \
-# RUN:      %t/out/ssaf-artifacts%t/build/parse.o.report.sarif
-
-# RUN: cat %t/out/ssaf-artifacts%t/build/prg.edits.yaml | FileCheck %s --check-prefix=EDITS
-# EDITS: Replacements:
-# EDITS-DAG: FilePath: {{.*}}src/main.cpp
-# EDITS-DAG: FilePath: {{.*}}src/parse.cpp
-# EDITS-DAG: ReplacementText: {{.*}}bounded_ptr<int>
-
-# Both configuration files are written, one per pass.
-# RUN: FileCheck %s --check-prefix=PASS1 \
-# RUN:   --input-file=%t/out/config-analysis.json
-# PASS1: "pass_kind": "analysis"
-# RUN: FileCheck %s --check-prefix=PASS2 \
-# RUN:   --input-file=%t/out/config-transformation.json
-# PASS2-DAG: "pass_kind": "transformation"
-# PASS2-DAG: "link_unit_id":
-
-# The second pass carries the link unit name the first pass recovered.
-# RUN: FileCheck %s --check-prefix=LUID \
-# RUN:   --input-file=%t/out/config-transformation.json
-# LUID: "link_unit_id": "{{.+}}"
-#--- Makefile
-CXX = clang++
-all: build/prg
-build/%.o: src/%.cpp
-	$(CXX) -c -o $@ $<
-build/prg: build/main.o build/parse.o
-	$(CXX) -o $@ build/main.o build/parse.o
-
-#--- src/parse.cpp
-int total(int *data, int n) {
-  int t = 0;
-  for (int i = 0; i < n; ++i)
-    t += data[i];
-  return t;
-}
-
-#--- src/main.cpp
-int total(int *data, int n);
-int main() {
-  int values[4] = {1, 2, 3, 4};
-  return total(values, 4);
-}
diff --git a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/config.py b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/config.py
index d2532c6ee8062..01caf368092dd 100644
--- a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/config.py
+++ b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/config.py
@@ -50,7 +50,6 @@ def output_dir_marker_path(output_dir):
 
 class SSAFPassKind(str, enum.Enum):
     ANALYSIS = "analysis"
-    TRANSFORMATION = "transformation"
 
 
 class SSAFPassConfig:
@@ -85,26 +84,6 @@ def __init__(
         self.analyses = list(analyses)
 
 
-class SSAFTransformationPassConfig(SSAFPassConfig):
-    pass_kind = SSAFPassKind.TRANSFORMATION
-
-    def __init__(
-        self,
-        ssaf_clang=None,
-        ssaf_extra_clang_args=(),
-        ssaf_src_edit_merge=None,
-        transformation=None,
-        link_unit_id=None,
-    ):
-        super().__init__(ssaf_clang, ssaf_extra_clang_args)
-        self.ssaf_src_edit_merge = ssaf_src_edit_merge
-        self.transformation = transformation
-        self.link_unit_id = link_unit_id
-
-    def name_link_unit(self, link_unit_id):
-        self.link_unit_id = link_unit_id
-
-
 class SSAFWorkflowConfig:
     def __init__(
         self,
diff --git a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/config_orchestrator.py b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/config_orchestrator.py
index f47b4f05cc73e..a9c096ba3208f 100644
--- a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/config_orchestrator.py
+++ b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/config_orchestrator.py
@@ -116,27 +116,12 @@ def configure(command_line_opts, env):
         if command_line_opts.analyses
         else None
     )
-    ssaf_src_edit_merge = (
-        _resolve_ssaf_tool(
-            "--ssaf-src-edit-merge",
-            "clang-ssaf-src-edit-merge",
-            command_line_opts.ssaf_src_edit_merge,
-            installed_shim_dir_path,
-            errors,
-        )
-        if command_line_opts.transformation
-        else None
-    )
 
     if errors:
         return None, options.Problem(
             options.ENVIRONMENT_ERROR, "required tools not resolvable:", errors
         )
 
-    common_pass_config = dict(
-        ssaf_clang=ssaf_clang,
-        ssaf_extra_clang_args=command_line_opts.ssaf_extra_clang_args,
-    )
     workflow_config = config.SSAFWorkflowConfig(
         output_dir=output_dir,
         installed_shim_dir_path=installed_shim_dir_path,
@@ -148,18 +133,10 @@ def configure(command_line_opts, env):
         build_environment=env,
     )
     analysis_config = config.SSAFAnalysisPassConfig(
+        ssaf_clang=ssaf_clang,
+        ssaf_extra_clang_args=command_line_opts.ssaf_extra_clang_args,
         extractors=command_line_opts.extract_summaries,
         ssaf_linker=ssaf_linker,
         analyses=command_line_opts.analyses,
-        **common_pass_config,
-    )
-    transformation_config = (
-        config.SSAFTransformationPassConfig(
-            ssaf_src_edit_merge=ssaf_src_edit_merge,
-            transformation=command_line_opts.transformation,
-            **common_pass_config,
-        )
-        if command_line_opts.transformation
-        else None
     )
-    return (workflow_config, analysis_config, transformation_config), None
+    return (workflow_config, analysis_config), None
diff --git a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/config_shims.py b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/config_shims.py
index abc228dfb1c27..bfed688447ceb 100644
--- a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/config_shims.py
+++ b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/config_shims.py
@@ -18,9 +18,7 @@ def from_json(written):
         for key, value in written.items()
         if key not in shared and key != "pass_kind"
     }
-    pass_kind = config.SSAFPassKind(written["pass_kind"])
-    if pass_kind == config.SSAFPassKind.TRANSFORMATION:
-        return workflow_config, config.SSAFTransformationPassConfig(**own)
+    config.SSAFPassKind(written["pass_kind"])
     return workflow_config, config.SSAFAnalysisPassConfig(**own)
 
 
diff --git a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/failure_logs.py b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/failure_logs.py
index 84f52c5b3f9fe..fc242f39dc8fd 100644
--- a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/failure_logs.py
+++ b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/failure_logs.py
@@ -14,9 +14,7 @@
 
 class SSAFFailureKind(enum.Enum):
     EXTRACT = "extract"
-    TRANSFORM = "transform"
     LINK = "link"
-    MERGE = "merge"
     FORWARD = "forward"
     MISSING = "missing"
     DRIVER_JOBS = "driver-jobs"
diff --git a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/logging_diagnostics.py b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/logging_diagnostics.py
index 96c6ff3293b63..771da5cb22b87 100644
--- a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/logging_diagnostics.py
+++ b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/logging_diagnostics.py
@@ -39,9 +39,3 @@ def report_summaries(summaries, link_unit, summary_path):
 
 def report_analysis_result(wpa_result_path):
     report_info("analysis-result", wpa_result_path)
-
-
-def report_transformation(merged, conflicts_paths):
-    report_info("source-edits", merged)
-    for conflicts_path in conflicts_paths:
-        report_info("edit-conflicts", conflicts_path)
diff --git a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/options.py b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/options.py
index 3a962f6274be0..4650432edd9ca 100644
--- a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/options.py
+++ b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/options.py
@@ -54,13 +54,6 @@ def build_parser():
         help="Whole-program analysis to run on the link unit summary. "
         "Repeatable. Without it the run stops after summary extraction.",
     )
-    parser.add_argument(
-        "--transformation",
-        metavar="<name>",
-        default=None,
-        help="Source transformation to run in the second pass. Requires "
-        "--analysis. Without it the run stops after the analysis.",
-    )
     parser.add_argument(
         "--ssaf-linker",
         metavar="<path>",
@@ -73,12 +66,6 @@ def build_parser():
         default=None,
         help="Path to clang-ssaf-analyzer (default: found on PATH).",
     )
-    parser.add_argument(
-        "--ssaf-src-edit-merge",
-        metavar="<path>",
-        default=None,
-        help="Path to clang-ssaf-src-edit-merge (default: found on PATH).",
-    )
     parser.add_argument(
         "--ssaf-extra-clang-arg",
         metavar="<arg>",
@@ -115,12 +102,10 @@ def __init__(
         output_dir=None,
         extract_summaries=None,
         analyses=(),
-        transformation=None,
         ssaf_clang=None,
         ssaf_extra_clang_args=(),
         ssaf_linker=None,
         ssaf_analyzer=None,
-        ssaf_src_edit_merge=None,
         keep_going=False,
         verbose=False,
     ):
@@ -128,12 +113,10 @@ def __init__(
         self.output_dir = output_dir
         self.extract_summaries = extract_summaries
         self.analyses = list(analyses)
-        self.transformation = transformation
         self.ssaf_clang = ssaf_clang
         self.ssaf_extra_clang_args = list(ssaf_extra_clang_args)
         self.ssaf_linker = ssaf_linker
         self.ssaf_analyzer = ssaf_analyzer
-        self.ssaf_src_edit_merge = ssaf_src_edit_merge
         self.keep_going = keep_going
         self.verbose = verbose
 
@@ -147,25 +130,16 @@ def resolve(argv):
     if not build_command:
         return None, Problem(USAGE_ERROR, "no build command given")
 
-    if args.transformation and not args.analyses:
-        return None, Problem(
-            USAGE_ERROR,
-            "--transformation needs --analysis: the transformation consumes "
-            "the whole-program analysis result",
-        )
-
     return (
         CommandLineOpts(
             build_command=build_command,
             output_dir=args.output_dir,
             extract_summaries=args.extract_summaries,
             analyses=args.analyses,
-            transformation=args.transformation,
             ssaf_clang=args.ssaf_clang,
             ssaf_extra_clang_args=args.ssaf_extra_clang_args,
             ssaf_linker=args.ssaf_linker,
             ssaf_analyzer=args.ssaf_analyzer,
-            ssaf_src_edit_merge=args.ssaf_src_edit_merge,
             keep_going=args.keep_going,
             verbose=args.verbose,
         ),
diff --git a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/orchestrator.py b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/orchestrator.py
index ce2a73cbebb0b..eb5470da8820d 100644
--- a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/orchestrator.py
+++ b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/orchestrator.py
@@ -89,7 +89,7 @@ def clear_output_dir(output_dir):
 
 
 def _no_link_unit(message):
-    return None, None, None, options.Problem(1, message)
+    return None, None, options.Problem(1, message)
 
 
 def get_topmost_link_unit(ssaf_artifact_repo, output_dir):
@@ -115,13 +115,7 @@ def get_topmost_link_unit(ssaf_artifact_repo, output_dir):
             "or failed" % build_artifact_id.get_path()
         )
     summary = ssaf_artifact_repo.get_path_for_artifact(ssaf_artifact_id)
-    unit_id = ssaf_artifact_repo.get_link_unit_name(summary)
-    if unit_id is None:
-        return _no_link_unit(
-            "'%s' is not a link unit; whole-program analysis needs one, so "
-            "build a target that links" % build_artifact_id.get_path()
-        )
-    return build_artifact_id, summary, unit_id, None
+    return build_artifact_id, summary, None
 
 
 def run_ssaf_analysis_pass(
@@ -138,7 +132,7 @@ def run_ssaf_analysis_pass(
     if summaries == 0:
         return options.Problem(1, "no summaries were extracted")
 
-    link_unit, summary, _, problem = get_topmost_link_unit(
+    link_unit, summary, problem = get_topmost_link_unit(
         ssaf_artifact_repo, workflow_config.output_dir
     )
     if problem is not None:
@@ -168,39 +162,7 @@ def run_ssaf_analysis_pass(
     return None
 
 
-def run_ssaf_transformation_pass(
-    workflow_config, transformation_config, ssaf_artifact_repo, shim_link_dir_path
-):
-    link_unit, _, unit_id, problem = get_topmost_link_unit(
-        ssaf_artifact_repo, workflow_config.output_dir
-    )
-    if problem is not None:
-        return problem
-
-    transformation_config.name_link_unit(unit_id)
-    serialized_config_path = write_pass_config(workflow_config, transformation_config)
-    problem = run_build_with_toolchain_interposition(
-        workflow_config,
-        serialized_config_path,
-        shim_link_dir_path,
-        "rebuild for the transformation pass",
-    )
-    if problem is not None:
-        return problem
-
-    edits = get_ssaf_artifact_id(link_unit, SSAFArtifactKind.EDITS)
-    if not ssaf_artifact_repo.has_artifact(edits):
-        return options.Problem(
-            1, "no merged source edits for '%s'" % link_unit.get_path()
-        )
-    logging_diagnostics.report_transformation(
-        ssaf_artifact_repo.get_path_for_artifact(edits),
-        ssaf_artifact_repo.get_conflicts(),
-    )
-    return None
-
-
-def run_ssaf_workflow(workflow_config, analysis_config, transformation_config):
+def run_ssaf_workflow(workflow_config, analysis_config):
     warn_if_not_make(workflow_config.build_command)
 
     ssaf_artifact_repo = SSAFArtifactRepository(
@@ -224,16 +186,6 @@ def run_ssaf_workflow(workflow_config, analysis_config, transformation_config):
     if problem is not None:
         return problem
 
-    if transformation_config is not None:
-        problem = run_ssaf_transformation_pass(
-            workflow_config,
-            transformation_config,
-            ssaf_artifact_repo,
-            shim_link_dir_path,
-        )
-        if problem is not None:
-            return problem
-
     logging_diagnostics.report_output_dir(workflow_config.output_dir)
 
     failures = failure_logs.count_failure_logs(workflow_config.output_dir)
diff --git a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/clang.py b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/clang.py
index f00ae9bf62767..7525dfc22b7ee 100644
--- a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/clang.py
+++ b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/clang.py
@@ -6,7 +6,7 @@
 import re
 import subprocess
 
-from .. import config, logging_diagnostics, utils
+from .. import logging_diagnostics, utils
 from ..build_graph import BuildArtifactId
 from ..failure_logs import SSAFFailureKind
 from ..ssaf_artifact_repository import SSAFArtifactKind, get_ssaf_artifact_id
@@ -93,30 +93,6 @@ def _summary_extraction_args(shim, build_artifact_id):
     return summary, extra + shim.pass_config.ssaf_extra_clang_args
 
 
-def _transformation_args(shim, build_artifact_id):
-    ssaf_artifact_repo = shim.ssaf_artifact_repo
-    edits = utils.make_parents(
-        ssaf_artifact_repo.get_path_for_artifact(
-            get_ssaf_artifact_id(build_artifact_id, SSAFArtifactKind.EDITS)
-        )
-    )
-    extra = [
-        "--ssaf-source-transformation=" + shim.pass_config.transformation,
-        "--ssaf-global-scope-analysis-result="
-        + config.wpa_result_path(shim.workflow_config.output_dir),
-        "--ssaf-compilation-unit-id=" + build_artifact_id.get_path(),
-        "--ssaf-link-unit-id=" + shim.pass_config.link_unit_id,
-        "--ssaf-src-edit-file=" + edits,
-        "--ssaf-transformation-report-file="
-        + utils.make_parents(
-            ssaf_artifact_repo.get_path_for_artifact(
-                get_ssaf_artifact_id(build_artifact_id, SSAFArtifactKind.REPORT)
-            )
-        ),
-    ]
-    return edits, extra + shim.pass_config.ssaf_extra_clang_args
-
-
 def _run_clang_driven_tool(shim, cwd):
     job = Job(list(shim.argv[1:]))
 
@@ -128,15 +104,10 @@ def _run_clang_driven_tool(shim, cwd):
 
     output = os.path.join(cwd, job.output)
     build_artifact_id = BuildArtifactId(output)
-    if shim.pass_config.pass_kind == config.SSAFPassKind.TRANSFORMATION:
-        artifact, extra = _transformation_args(shim, build_artifact_id)
-        failure_kind = SSAFFailureKind.TRANSFORM
-    else:
-        artifact, extra = _summary_extraction_args(shim, build_artifact_id)
-        failure_kind = SSAFFailureKind.EXTRACT
+    artifact, extra = _summary_extraction_args(shim, build_artifact_id)
     ssaf_command = [shim.pass_config.ssaf_clang] + shim.argv[1:] + extra
 
-    if not shim.run(ssaf_command, failure_kind, build_artifact_id):
+    if not shim.run(ssaf_command, SSAFFailureKind.EXTRACT, build_artifact_id):
         try:
             os.remove(artifact)
         except OSError:
diff --git a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/commands.py b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/commands.py
index d4794cb4e734c..2eaf808e87095 100644
--- a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/commands.py
+++ b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/commands.py
@@ -32,13 +32,9 @@ def filter_build_artifacts(build_graph, ssaf_artifact_repo, cwd, files):
     kept = []
     for each in files:
         build_artifact_id = BuildArtifactId(os.path.join(cwd, each))
-        if (
-            artifact_of(ssaf_artifact_repo, build_artifact_id, SSAFArtifactKind.SUMMARY)
-            or artifact_of(
-                ssaf_artifact_repo, build_artifact_id, SSAFArtifactKind.EDITS
-            )
-            or build_graph.was_built(build_artifact_id)
-        ):
+        if artifact_of(
+            ssaf_artifact_repo, build_artifact_id, SSAFArtifactKind.SUMMARY
+        ) or build_graph.was_built(build_artifact_id):
             kept.append(build_artifact_id)
     return kept
 
diff --git a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/ld.py b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/ld.py
index 54c5c759ed5bf..d7fe1d65ccd72 100644
--- a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/ld.py
+++ b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/ld.py
@@ -4,7 +4,7 @@
 
 import os
 
-from .. import config, logging_diagnostics, utils
+from .. import logging_diagnostics, utils
 from ..build_graph import BuildArtifactId
 from ..failure_logs import SSAFFailureKind
 from ..ssaf_artifact_repository import SSAFArtifactKind, get_ssaf_artifact_id
@@ -16,7 +16,6 @@
     summary_of,
     unique,
 )
-from .shim import merge_edits
 
 
 def identify_inputs_output(argv):
@@ -78,10 +77,6 @@ def invoke_ssaf_tools(shim, cwd):
         shim.build_graph, ssaf_artifact_repo, cwd, files.inputs
     )
 
-    if shim.pass_config.pass_kind == config.SSAFPassKind.TRANSFORMATION:
-        merge_edits(shim, build_artifact_id, input_build_artifact_ids)
-        return
-
     shim.build_graph.record_build_step(
         build_artifact_id,
         inputs=input_build_artifact_ids,
diff --git a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/shim.py b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/shim.py
index 5180bced1ab30..114135950896b 100644
--- a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/shim.py
+++ b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/shim.py
@@ -11,12 +11,7 @@
 
 from .. import build_graph, config, failure_logs, logging_diagnostics, utils
 from ..failure_logs import SSAFFailureKind
-from ..ssaf_artifact_repository import (
-    SSAFArtifactKind,
-    SSAFArtifactRepository,
-    get_ssaf_artifact_id,
-)
-from .commands import artifact_of, unique
+from ..ssaf_artifact_repository import SSAFArtifactRepository
 
 SKIP_BINARY_TOOL_INVOCATION = "--ssaf-shim-skip-binary-tool-invocation"
 
@@ -186,35 +181,3 @@ def protect(self, work):
                 logging_diagnostics.report_error("and its log could not be written")
         # A shim must never be the reason a build fails.
         return 0
-
-
-def merge_edits(shim, build_artifact_id, input_build_artifact_ids):
-    ssaf_artifact_repo = shim.ssaf_artifact_repo
-    found = []
-    for each in input_build_artifact_ids:
-        edits = artifact_of(ssaf_artifact_repo, each, SSAFArtifactKind.EDITS)
-        if edits:
-            found.append(edits)
-    found = unique(found)
-    if not found:
-        logging_diagnostics.report_note(
-            shim.workflow_config.verbose,
-            "no edits feed %s, nothing to merge" % build_artifact_id.get_path(),
-        )
-        return
-    command = [shim.pass_config.ssaf_src_edit_merge] + found
-    command += [
-        "-o",
-        utils.make_parents(
-            ssaf_artifact_repo.get_path_for_artifact(
-                get_ssaf_artifact_id(build_artifact_id, SSAFArtifactKind.EDITS)
-            )
-        ),
-    ]
-    command += [
-        "--sarif-conflicts-out="
-        + ssaf_artifact_repo.get_path_for_artifact(
-            get_ssaf_artifact_id(build_artifact_id, SSAFArtifactKind.CONFLICTS)
-        )
-    ]
-    shim.run(command, SSAFFailureKind.MERGE, build_artifact_id)
diff --git a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/ssaf_artifact_repository.py b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/ssaf_artifact_repository.py
index 5d920673350cf..674d5c4ccbbf6 100644
--- a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/ssaf_artifact_repository.py
+++ b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/ssaf_artifact_repository.py
@@ -6,14 +6,11 @@
 import enum
 import os
 
-from .utils import coalesce_root_path, find_with_suffix, read_json
+from .utils import coalesce_root_path, find_with_suffix
 
 
 class SSAFArtifactKind(enum.Enum):
     SUMMARY = ".summary.json"
-    EDITS = ".edits.yaml"
-    CONFLICTS = ".conflicts.sarif"
-    REPORT = ".report.sarif"
 
 
 class SSAFArtifactId:
@@ -57,22 +54,5 @@ def has_artifact(self, ssaf_artifact_id):
     def _all_paths_of_kind(self, ssaf_artifact_kind):
         return find_with_suffix(self.ssaf_artifact_dir, ssaf_artifact_kind.value)
 
-    def get_link_unit_name(self, summary_path):
-        document = read_json(summary_path)
-        if document is None:
-            return None
-        for component in document.get("lu_namespace", []):
-            if component.get("kind") == "LinkUnit":
-                return component.get("name")
-        return None
-
     def count_summaries(self):
         return len(self._all_paths_of_kind(SSAFArtifactKind.SUMMARY))
-
-    def get_conflicts(self):
-        found = []
-        for path in self._all_paths_of_kind(SSAFArtifactKind.CONFLICTS):
-            document = read_json(path)
-            if document and any(run.get("results") for run in document.get("runs", [])):
-                found.append(path)
-        return sorted(found)
diff --git a/clang/tools/clang-ssaf-orchestrator-make/tests/configs.py b/clang/tools/clang-ssaf-orchestrator-make/tests/configs.py
index f95799c68e648..9a359514de7bc 100644
--- a/clang/tools/clang-ssaf-orchestrator-make/tests/configs.py
+++ b/clang/tools/clang-ssaf-orchestrator-make/tests/configs.py
@@ -21,21 +21,6 @@ def analysis_config(**overrides):
     return config.SSAFAnalysisPassConfig(**fields)
 
 
-def transformation_config(**overrides):
-    fields = dict(
-        ssaf_clang="/bin/clang",
-        ssaf_extra_clang_args=[],
-        ssaf_src_edit_merge="/bin/clang-ssaf-src-edit-merge",
-        transformation="x",
-    )
-    fields.update(overrides)
-    return config.SSAFTransformationPassConfig(**fields)
-
-
-def pass_configs():
-    return analysis_config(), transformation_config(link_unit_id="build/prg")
-
-
 def workflow_config(env=None, output_dir="/out", verbose=False):
     env = env or {}
     return config.SSAFWorkflowConfig(
diff --git a/clang/tools/clang-ssaf-orchestrator-make/tests/test_clang_shim.py b/clang/tools/clang-ssaf-orchestrator-make/tests/test_clang_shim.py
index 2ef092395421b..720d8bcbe089f 100644
--- a/clang/tools/clang-ssaf-orchestrator-make/tests/test_clang_shim.py
+++ b/clang/tools/clang-ssaf-orchestrator-make/tests/test_clang_shim.py
@@ -148,20 +148,6 @@ def test_extraction_names_the_unit_and_where_its_summary_goes(self):
         self.assertIn("--ssaf-tu-summary-file=" + summary, extra)
         self.assertTrue(os.path.isdir(os.path.dirname(summary)))
 
-    def test_transformation_names_the_link_unit_and_the_analysis_result(self):
-        pass_config = configs.transformation_config()
-        pass_config.name_link_unit(self._id("build/prg").get_path())
-        shim = self._shim(pass_config)
-        edits, extra = clang._transformation_args(shim, self._id("build/a.o"))
-        self.assertIn("--ssaf-link-unit-id=" + self._id("build/prg").get_path(), extra)
-        self.assertIn("--ssaf-src-edit-file=" + edits, extra)
-        self.assertTrue(
-            any(a.startswith("--ssaf-global-scope-analysis-result=") for a in extra)
-        )
-        self.assertTrue(
-            any(a.startswith("--ssaf-transformation-report-file=") for a in extra)
-        )
-
     def test_the_extra_clang_arguments_come_last(self):
         shim = self._shim(configs.analysis_config(ssaf_extra_clang_args=["-DX"]))
         _, extra = clang._summary_extraction_args(shim, self._id("build/a.o"))
diff --git a/clang/tools/clang-ssaf-orchestrator-make/tests/test_commands.py b/clang/tools/clang-ssaf-orchestrator-make/tests/test_commands.py
index f7d28f2af2a8a..6990f7c304c5c 100644
--- a/clang/tools/clang-ssaf-orchestrator-make/tests/test_commands.py
+++ b/clang/tools/clang-ssaf-orchestrator-make/tests/test_commands.py
@@ -100,10 +100,6 @@ def test_a_compiled_object_is_kept(self):
         self._write("build/a.o", repository.SSAFArtifactKind.SUMMARY)
         self.assertEqual([self._id("build/a.o")], self._kept("build/a.o"))
 
-    def test_an_object_with_only_source_edits_is_kept(self):
-        self._write("build/a.o", repository.SSAFArtifactKind.EDITS)
-        self.assertEqual([self._id("build/a.o")], self._kept("build/a.o"))
-
     def test_an_assembled_object_with_only_a_record_is_kept(self):
         self.build_graph.record_build_step(
             self._id("build/combined.o"), [self._id("build/a.o")]
diff --git a/clang/tools/clang-ssaf-orchestrator-make/tests/test_config.py b/clang/tools/clang-ssaf-orchestrator-make/tests/test_config.py
index c6dbc9cd6341b..e0aafdc425bcd 100644
--- a/clang/tools/clang-ssaf-orchestrator-make/tests/test_config.py
+++ b/clang/tools/clang-ssaf-orchestrator-make/tests/test_config.py
@@ -13,9 +13,6 @@
 class Passes(unittest.TestCase):
     def test_a_pass_names_its_own_configuration_file(self):
         self.assertEqual("config-analysis.json", configs.analysis_config().file_name)
-        self.assertEqual(
-            "config-transformation.json", configs.transformation_config().file_name
-        )
 
     def test_a_pass_kind_is_stored_as_its_plain_string(self):
         written = json.loads(json.dumps(configs.analysis_config().to_json()))
@@ -33,36 +30,10 @@ def test_a_pass_carries_only_the_tools_it_runs(self):
             },
             set(configs.analysis_config().to_json()),
         )
-        self.assertEqual(
-            {
-                "pass_kind",
-                "ssaf_clang",
-                "ssaf_extra_clang_args",
-                "ssaf_src_edit_merge",
-                "transformation",
-                "link_unit_id",
-            },
-            set(configs.transformation_config().to_json()),
-        )
 
     def test_a_pass_knows_nothing_of_the_run_it_belongs_to(self):
         run_only = config.SSAFWorkflowConfig.written_field_names()
-        for pass_config in configs.pass_configs():
-            self.assertEqual(set(), run_only & set(pass_config.to_json()), pass_config)
-
-    def test_both_passes_compile_so_both_carry_the_clang(self):
-        for pass_config in (
-            configs.analysis_config(ssaf_extra_clang_args=["-DX"]),
-            configs.transformation_config(ssaf_extra_clang_args=["-DX"]),
-        ):
-            self.assertEqual("/bin/clang", pass_config.ssaf_clang)
-            self.assertEqual(["-DX"], pass_config.ssaf_extra_clang_args)
-
-    def test_the_link_unit_is_named_after_the_analysis_build(self):
-        transformation_config = configs.transformation_config()
-        self.assertIsNone(transformation_config.link_unit_id)
-        transformation_config.name_link_unit("build/prg")
-        self.assertEqual("build/prg", transformation_config.link_unit_id)
+        self.assertEqual(set(), run_only & set(configs.analysis_config().to_json()))
 
 
 class OutputDirPaths(unittest.TestCase):
@@ -111,24 +82,5 @@ def test_an_absent_path_is_empty_so_the_live_path_is_never_searched(self):
         self.assertEqual("", config.SSAFWorkflowConfig().restored_path_env_var)
 
 
-class Serialization(unittest.TestCase):
-    def test_each_pass_file_carries_only_that_pass(self):
-        analysis_config, transformation_config = configs.pass_configs()
-        first = analysis_config.to_json()
-        second = transformation_config.to_json()
-        self.assertEqual(
-            {"extractors", "ssaf_linker", "analyses"}, set(first) - set(second)
-        )
-        self.assertEqual(
-            {"ssaf_src_edit_merge", "transformation", "link_unit_id"},
-            set(second) - set(first),
-        )
-        self.assertEqual(
-            {"pass_kind", "ssaf_clang", "ssaf_extra_clang_args"},
-            set(first) & set(second),
-        )
-        self.assertNotEqual(first["pass_kind"], second["pass_kind"])
-
-
 if __name__ == "__main__":
     unittest.main()
diff --git a/clang/tools/clang-ssaf-orchestrator-make/tests/test_config_orchestrator.py b/clang/tools/clang-ssaf-orchestrator-make/tests/test_config_orchestrator.py
index 3ed1e13e2b154..6a512c24bf9dd 100644
--- a/clang/tools/clang-ssaf-orchestrator-make/tests/test_config_orchestrator.py
+++ b/clang/tools/clang-ssaf-orchestrator-make/tests/test_config_orchestrator.py
@@ -114,7 +114,6 @@ def setUp(self):
         self.clang = self._executable("clang")
         self.linker = self._executable("clang-ssaf-linker")
         self.analyzer = self._executable("clang-ssaf-analyzer")
-        self.merge = self._executable("clang-ssaf-src-edit-merge")
         self.project = os.path.join(self.tmp, "project")
         os.makedirs(self.project)
         self.addCleanup(os.chdir, os.getcwd())
@@ -140,12 +139,10 @@ def _configure_argv(self, argv, env=None):
         configs, problem = config_orchestrator.configure(
             command_line_opts, {} if env is None else env
         )
-        return (configs or (None, None, None)) + (problem,)
+        return (configs or (None, None)) + (problem,)
 
     def test_a_valid_command_line_yields_the_configuration(self):
-        workflow_config, analysis_config, _, problem = self._configure(
-            "--", "make", "-j8"
-        )
+        workflow_config, analysis_config, problem = self._configure("--", "make", "-j8")
         self.assertIsNone(problem)
         self.assertEqual(["make", "-j8"], workflow_config.build_command)
         self.assertEqual("PointerFlow", analysis_config.extractors)
@@ -157,62 +154,19 @@ def test_the_configuration_holds_the_resolved_tool_not_what_was_typed(self):
             "--ssaf-clang=clang",
             "--ssaf-linker=clang-ssaf-linker",
             "--ssaf-analyzer=clang-ssaf-analyzer",
-            "--ssaf-src-edit-merge=clang-ssaf-src-edit-merge",
             "--analysis=a",
-            "--transformation=x",
             "--",
             "make",
         ]
         with mock.patch.dict(os.environ, {"PATH": self.tmp}):
-            (
-                workflow_config,
-                analysis_config,
-                transformation_config,
-                problem,
-            ) = self._configure_argv(argv)
+            workflow_config, analysis_config, problem = self._configure_argv(argv)
         self.assertIsNone(problem)
         self.assertEqual(self.clang, analysis_config.ssaf_clang)
         self.assertEqual(self.linker, analysis_config.ssaf_linker)
         self.assertEqual(self.analyzer, workflow_config.ssaf_analyzer)
-        self.assertEqual(self.merge, transformation_config.ssaf_src_edit_merge)
-
-    def test_a_run_analyses_and_transforms_only_where_asked(self):
-        _, analysis_config, transformation_config, problem = self._configure(
-            "--", "make"
-        )
-        self.assertIsNone(problem)
-        self.assertIsInstance(analysis_config, config.SSAFAnalysisPassConfig)
-        self.assertIsNone(transformation_config)
-
-        _, analysis_config, transformation_config, problem = self._configure(
-            "--analysis=a",
-            "--transformation=x",
-            "--ssaf-analyzer=" + self.analyzer,
-            "--ssaf-src-edit-merge=" + self.merge,
-            "--",
-            "make",
-        )
-        self.assertIsNone(problem)
-        self.assertEqual(["a"], analysis_config.analyses)
-        self.assertEqual("x", transformation_config.transformation)
-
-    def test_both_passes_get_the_clang_and_its_extra_arguments(self):
-        _, analysis_config, transformation_config, problem = self._configure(
-            "--analysis=a",
-            "--transformation=x",
-            "--ssaf-analyzer=" + self.analyzer,
-            "--ssaf-src-edit-merge=" + self.merge,
-            "--ssaf-extra-clang-arg=-DX",
-            "--",
-            "make",
-        )
-        self.assertIsNone(problem)
-        for pass_config in (analysis_config, transformation_config):
-            self.assertEqual(self.clang, pass_config.ssaf_clang)
-            self.assertEqual(["-DX"], pass_config.ssaf_extra_clang_args)
 
     def test_the_environment_reaches_the_config_but_not_the_file(self):
-        workflow_config, _, _, problem = self._configure(
+        workflow_config, _, problem = self._configure(
             "--", "make", env={"PATH": "/usr/bin", "SECRET": "x"}
         )
         self.assertIsNone(problem)
@@ -222,7 +176,7 @@ def test_the_environment_reaches_the_config_but_not_the_file(self):
 
     def test_an_output_dir_holding_the_project_is_refused(self):
         for value in (".", "..", os.getcwd()):
-            workflow_config, _, _, problem = self._configure("-o", value, "--", "make")
+            workflow_config, _, problem = self._configure("-o", value, "--", "make")
             self.assertIsNone(workflow_config, value)
             self.assertEqual(options.ENVIRONMENT_ERROR, problem.exit_status)
             self.assertIn("would contain the project", problem.message)
@@ -231,7 +185,7 @@ def test_a_directory_no_run_made_is_not_deleted(self):
         other = os.path.join(self.project, "src")
         os.makedirs(other)
         open(os.path.join(other, "main.c"), "w").close()
-        workflow_config, _, _, problem = self._configure("-o", other, "--", "make")
+        workflow_config, _, problem = self._configure("-o", other, "--", "make")
         self.assertIsNone(workflow_config)
         self.assertEqual(options.ENVIRONMENT_ERROR, problem.exit_status)
         self.assertIn("no earlier run made it", problem.message)
@@ -240,7 +194,7 @@ def test_a_directory_no_run_made_is_not_deleted(self):
     def test_an_empty_directory_is_taken(self):
         empty = os.path.join(self.tmp, "empty")
         os.makedirs(empty)
-        workflow_config, _, _, problem = self._configure("-o", empty, "--", "make")
+        workflow_config, _, problem = self._configure("-o", empty, "--", "make")
         self.assertIsNone(problem)
         self.assertEqual(os.path.realpath(empty), workflow_config.output_dir)
 
@@ -248,20 +202,18 @@ def test_a_directory_an_earlier_run_made_is_taken(self):
         earlier = os.path.join(self.tmp, "earlier")
         os.makedirs(os.path.join(earlier, "ssaf-artifacts"))
         open(config.output_dir_marker_path(earlier), "w").close()
-        _, _, _, problem = self._configure("-o", earlier, "--", "make")
+        _, _, problem = self._configure("-o", earlier, "--", "make")
         self.assertIsNone(problem)
 
     def test_a_relative_output_dir_is_made_absolute(self):
-        workflow_config, _, _, problem = self._configure(
-            "-o", "somewhere", "--", "make"
-        )
+        workflow_config, _, problem = self._configure("-o", "somewhere", "--", "make")
         self.assertIsNone(problem)
         self.assertEqual(
             os.path.join(os.getcwd(), "somewhere"), workflow_config.output_dir
         )
 
     def test_an_unresolvable_ssaf_tool(self):
-        workflow_config, _, _, problem = self._configure_argv(
+        workflow_config, _, problem = self._configure_argv(
             [
                 "--extract-summaries=PointerFlow",
                 "--ssaf-clang=/no/such/clang",
@@ -276,7 +228,7 @@ def test_an_unresolvable_ssaf_tool(self):
         self.assertIn("/no/such/clang", problem.details[0])
 
     def test_the_ssaf_tools_take_no_flags(self):
-        workflow_config, _, _, problem = self._configure_argv(
+        workflow_config, _, problem = self._configure_argv(
             [
                 "--extract-summaries=PointerFlow",
                 "--ssaf-clang=%s -O2" % self.clang,
@@ -305,7 +257,7 @@ def test_a_detail_names_the_option_and_the_path(self):
 
     def test_a_tool_absent_from_path_names_what_was_looked_for(self):
         with mock.patch.dict(os.environ, {"PATH": self.elsewhere}):
-            workflow_config, _, _, problem = self._configure_argv(
+            workflow_config, _, problem = self._configure_argv(
                 [
                     "--extract-summaries=PointerFlow",
                     "--ssaf-clang=" + self.clang,
@@ -320,7 +272,7 @@ def test_a_tool_absent_from_path_names_what_was_looked_for(self):
         )
 
     def test_every_unresolvable_tool_is_reported_at_once(self):
-        workflow_config, _, _, problem = self._configure_argv(
+        workflow_config, _, problem = self._configure_argv(
             [
                 "--extract-summaries=PointerFlow",
                 "--ssaf-clang=/no/such/clang",
@@ -342,19 +294,13 @@ def test_every_unresolvable_tool_is_reported_at_once(self):
         )
 
     def test_the_analyzer_is_only_required_when_an_analysis_is_asked_for(self):
-        workflow_config, _, transformation_config, problem = self._configure(
-            "--", "make"
-        )
+        workflow_config, _, problem = self._configure("--", "make")
         self.assertIsNone(problem)
         self.assertIsNone(workflow_config.ssaf_analyzer)
-        self.assertIsNone(transformation_config)
 
     def test_a_tool_no_pass_will_run_is_not_resolved_at_all(self):
-        workflow_config, _, _, problem = self._configure(
-            "--ssaf-analyzer=/no/such/analyzer",
-            "--ssaf-src-edit-merge=/no/such/merge",
-            "--",
-            "make",
+        workflow_config, _, problem = self._configure(
+            "--ssaf-analyzer=/no/such/analyzer", "--", "make"
         )
         self.assertIsNone(problem)
         self.assertIsNone(workflow_config.ssaf_analyzer)
diff --git a/clang/tools/clang-ssaf-orchestrator-make/tests/test_ld_shim.py b/clang/tools/clang-ssaf-orchestrator-make/tests/test_ld_shim.py
index a6ae6c1872375..2b2e5ec35c146 100644
--- a/clang/tools/clang-ssaf-orchestrator-make/tests/test_ld_shim.py
+++ b/clang/tools/clang-ssaf-orchestrator-make/tests/test_ld_shim.py
@@ -127,13 +127,6 @@ def test_a_link_of_nothing_we_know_runs_no_step(self):
         self.assertEqual([], shim.missing)
         self.assertIn("nothing to link", self.notes[-1])
 
-    def test_in_the_transformation_pass_the_edits_are_merged_instead(self):
-        shim = self._run(["build/a.o"], configs.transformation_config())
-        self.assertEqual(
-            ["no edits feed %s, nothing to merge" % self._id("build/prg").get_path()],
-            self.notes,
-        )
-
 
 if __name__ == "__main__":
     unittest.main()
diff --git a/clang/tools/clang-ssaf-orchestrator-make/tests/test_logging_diagnostics.py b/clang/tools/clang-ssaf-orchestrator-make/tests/test_logging_diagnostics.py
index 8f4e91edf3fd7..18b1ef57533e2 100644
--- a/clang/tools/clang-ssaf-orchestrator-make/tests/test_logging_diagnostics.py
+++ b/clang/tools/clang-ssaf-orchestrator-make/tests/test_logging_diagnostics.py
@@ -88,27 +88,6 @@ def test_the_analysis_result(self):
             ),
         )
 
-    def test_the_transformation_names_every_file_that_holds_conflicts(self):
-        self.assertEqual(
-            "source-edits: /out/prg.edits.yaml\n"
-            "edit-conflicts: /out/libx.a.conflicts.sarif\n"
-            "edit-conflicts: /out/prg.conflicts.sarif\n",
-            self._stdout(
-                lambda: logging_diagnostics.report_transformation(
-                    "/out/prg.edits.yaml",
-                    ["/out/libx.a.conflicts.sarif", "/out/prg.conflicts.sarif"],
-                )
-            ),
-        )
-        self.assertEqual(
-            "source-edits: /out/prg.edits.yaml\n",
-            self._stdout(
-                lambda: logging_diagnostics.report_transformation(
-                    "/out/prg.edits.yaml", []
-                )
-            ),
-        )
-
     def test_results_are_flushed_as_they_are_written(self):
         flushes = []
         stream = io.StringIO()
diff --git a/clang/tools/clang-ssaf-orchestrator-make/tests/test_options.py b/clang/tools/clang-ssaf-orchestrator-make/tests/test_options.py
index edb027f91d114..a1ac1cbdf4eae 100644
--- a/clang/tools/clang-ssaf-orchestrator-make/tests/test_options.py
+++ b/clang/tools/clang-ssaf-orchestrator-make/tests/test_options.py
@@ -49,12 +49,6 @@ def test_a_separator_with_nothing_after_it_is_the_same(self):
         self.assertIsNone(command_line_opts)
         self.assertEqual(options.USAGE_ERROR, problem.exit_status)
 
-    def test_a_transformation_needs_an_analysis(self):
-        command_line_opts, problem = self._resolve("--transformation=x", "--", "make")
-        self.assertIsNone(command_line_opts)
-        self.assertEqual(options.USAGE_ERROR, problem.exit_status)
-        self.assertIn("--analysis", problem.message)
-
     def test_resolving_makes_none_of_the_calls_configure_makes(self):
         # Not every filesystem call: argparse reads the locale through
         # gettext. These are the calls the configuration layer makes, and the
diff --git a/clang/tools/clang-ssaf-orchestrator-make/tests/test_orchestrator.py b/clang/tools/clang-ssaf-orchestrator-make/tests/test_orchestrator.py
index 9a527d8d98c2e..1b967192f9835 100644
--- a/clang/tools/clang-ssaf-orchestrator-make/tests/test_orchestrator.py
+++ b/clang/tools/clang-ssaf-orchestrator-make/tests/test_orchestrator.py
@@ -87,8 +87,8 @@ def test_an_environment_error_stops_before_the_build(self):
         self.assertIn("--ssaf-clang", message)
         self.assertEqual([], self.run_calls)
 
-    def test_a_configured_run_is_handed_its_three_configurations(self):
-        configured = ("workflow", "analysis", "transformation")
+    def test_a_configured_run_is_handed_its_two_configurations(self):
+        configured = ("workflow", "analysis")
         with mock.patch.object(
             config_orchestrator, "configure", return_value=(configured, None)
         ):
@@ -125,37 +125,21 @@ def setUp(self):
         )
         self.analysis_config = config.SSAFAnalysisPassConfig(
             ssaf_clang="/bin/clang",
-            ssaf_extra_clang_args=["-DX"],
             extractors="PointerFlow",
             ssaf_linker="/bin/clang-ssaf-linker",
-            analyses=["A"],
         )
-        self.transformation_config = config.SSAFTransformationPassConfig(
-            ssaf_clang="/bin/clang",
-            ssaf_extra_clang_args=["-DX"],
-            ssaf_src_edit_merge="/bin/clang-ssaf-src-edit-merge",
-            transformation="x",
-        )
-        self.transformation_config.name_link_unit("build/prg")
 
-    def test_each_pass_is_written_under_the_output_directory(self):
-        for pass_config in (self.analysis_config, self.transformation_config):
-            path = orchestrator.write_pass_config(self.workflow_config, pass_config)
-            self.assertEqual(os.path.join(self.tmp, pass_config.file_name), path)
-            self.assertTrue(os.path.isfile(path))
+    def test_a_pass_is_written_under_the_output_directory(self):
+        path = orchestrator.write_pass_config(
+            self.workflow_config, self.analysis_config
+        )
+        self.assertEqual(os.path.join(self.tmp, self.analysis_config.file_name), path)
+        self.assertTrue(os.path.isfile(path))
 
     def test_nothing_is_left_behind_by_the_write(self):
         orchestrator.write_pass_config(self.workflow_config, self.analysis_config)
         self.assertEqual(["config-analysis.json"], os.listdir(self.tmp))
 
-    def test_both_passes_can_be_written_and_coexist(self):
-        for pass_config in (self.analysis_config, self.transformation_config):
-            orchestrator.write_pass_config(self.workflow_config, pass_config)
-        self.assertEqual(
-            ["config-analysis.json", "config-transformation.json"],
-            sorted(os.listdir(self.tmp)),
-        )
-
     def test_the_document_does_not_carry_its_own_path(self):
         path = orchestrator.write_pass_config(
             self.workflow_config, self.analysis_config
@@ -172,15 +156,16 @@ def test_an_output_directory_that_does_not_exist_is_not_silently_skipped(self):
         with self.assertRaises(OSError):
             orchestrator.write_pass_config(workflow_config, self.analysis_config)
 
-    def test_a_shim_reads_back_the_run_and_its_own_pass_whole(self):
-        for written in (self.analysis_config, self.transformation_config):
-            path = orchestrator.write_pass_config(self.workflow_config, written)
-            workflow_config, pass_config = config_shims.bootstrap_from_env(
-                {config.SSAF_CONFIG_ENV_VAR: path}
-            )
-            self.assertEqual(self.workflow_config.to_json(), workflow_config.to_json())
-            self.assertIs(type(written), type(pass_config))
-            self.assertEqual(written.to_json(), pass_config.to_json())
+    def test_a_shim_reads_back_the_run_and_its_own_pass(self):
+        path = orchestrator.write_pass_config(
+            self.workflow_config, self.analysis_config
+        )
+        workflow_config, pass_config = config_shims.bootstrap_from_env(
+            {config.SSAF_CONFIG_ENV_VAR: path}
+        )
+        self.assertEqual(self.workflow_config.to_json(), workflow_config.to_json())
+        self.assertIsInstance(pass_config, config.SSAFAnalysisPassConfig)
+        self.assertEqual("PointerFlow", pass_config.extractors)
 
 
 class RunBuild(unittest.TestCase):
@@ -311,7 +296,7 @@ def _record(self, output_path, inputs):
             inputs,
         )
 
-    def _summary(self, build_artifact_path, document=None):
+    def _summary(self, build_artifact_path):
         path = utils.make_parents(
             self.ssaf_artifact_repo.get_path_for_artifact(
                 repository.get_ssaf_artifact_id(
@@ -320,17 +305,16 @@ def _summary(self, build_artifact_path, document=None):
                 )
             )
         )
-        if document is None:
-            document = {
-                "lu_namespace": [
-                    {"kind": "LinkUnit", "name": os.path.basename(build_artifact_path)}
-                ]
-            }
+        document = {
+            "lu_namespace": [
+                {"kind": "LinkUnit", "name": os.path.basename(build_artifact_path)}
+            ]
+        }
         with open(path, "w") as handle:
             json.dump(document, handle)
 
     def test_no_link_unit_at_all(self):
-        link_unit, _, _, problem = orchestrator.get_topmost_link_unit(
+        link_unit, _, problem = orchestrator.get_topmost_link_unit(
             self.ssaf_artifact_repo, self.tmp
         )
         self.assertIsNone(link_unit)
@@ -339,7 +323,7 @@ def test_no_link_unit_at_all(self):
     def test_several_that_consume_none_of_each_other(self):
         self._record("/p/one", ["a.o"])
         self._record("/p/two", ["b.o"])
-        link_unit, _, _, problem = orchestrator.get_topmost_link_unit(
+        link_unit, _, problem = orchestrator.get_topmost_link_unit(
             self.ssaf_artifact_repo, self.tmp
         )
         self.assertIsNone(link_unit)
@@ -349,34 +333,21 @@ def test_several_that_consume_none_of_each_other(self):
 
     def test_one_whose_summary_was_never_written(self):
         self._record("/p/prg", ["a.o"])
-        link_unit, _, _, problem = orchestrator.get_topmost_link_unit(
+        link_unit, _, problem = orchestrator.get_topmost_link_unit(
             self.ssaf_artifact_repo, self.tmp
         )
         self.assertIsNone(link_unit)
         self.assertIn("no summary", problem.message)
         self.assertIn("p/prg", problem.message)
 
-    def test_one_whose_summary_names_no_link_unit(self):
-        self._record("/p/libx.a", ["a.o"])
-        self._summary(
-            "/p/libx.a", {"namespace": {"kind": "StaticLibrary", "name": "libx.a"}}
-        )
-        link_unit, _, _, problem = orchestrator.get_topmost_link_unit(
-            self.ssaf_artifact_repo, self.tmp
-        )
-        self.assertIsNone(link_unit)
-        self.assertIn("is not a link unit", problem.message)
-        self.assertIn("p/libx.a", problem.message)
-
     def test_one_with_its_summary_is_the_answer(self):
         self._record("/p/prg", ["a.o"])
         self._summary("/p/prg")
-        link_unit, _, unit_id, problem = orchestrator.get_topmost_link_unit(
+        link_unit, _, problem = orchestrator.get_topmost_link_unit(
             self.ssaf_artifact_repo, self.tmp
         )
         self.assertIsNone(problem)
         self.assertEqual("/p/prg", link_unit.get_path())
-        self.assertEqual("prg", unit_id)
 
 
 if __name__ == "__main__":
diff --git a/clang/tools/clang-ssaf-orchestrator-make/tests/test_ssaf_artifact_repository.py b/clang/tools/clang-ssaf-orchestrator-make/tests/test_ssaf_artifact_repository.py
index 90280fb57d7eb..f8b63c9b1acff 100644
--- a/clang/tools/clang-ssaf-orchestrator-make/tests/test_ssaf_artifact_repository.py
+++ b/clang/tools/clang-ssaf-orchestrator-make/tests/test_ssaf_artifact_repository.py
@@ -2,7 +2,6 @@
 # See https://llvm.org/LICENSE.txt for license information.
 # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 
-import json
 import os
 import shutil
 import tempfile
@@ -51,42 +50,6 @@ def test_artifact_paths(self):
                 )
             ),
         )
-        self.assertEqual(
-            "/out/ssaf-artifacts/p/build/a.o.edits.yaml",
-            self.ssaf_artifact_repo.get_path_for_artifact(
-                repository.get_ssaf_artifact_id(
-                    build_graph.BuildArtifactId("/p/build/a.o"),
-                    repository.SSAFArtifactKind.EDITS,
-                )
-            ),
-        )
-        self.assertEqual(
-            "/out/ssaf-artifacts/p/build/a.o.report.sarif",
-            self.ssaf_artifact_repo.get_path_for_artifact(
-                repository.get_ssaf_artifact_id(
-                    build_graph.BuildArtifactId("/p/build/a.o"),
-                    repository.SSAFArtifactKind.REPORT,
-                )
-            ),
-        )
-        self.assertEqual(
-            "/out/ssaf-artifacts/p/prg.edits.yaml",
-            self.ssaf_artifact_repo.get_path_for_artifact(
-                repository.get_ssaf_artifact_id(
-                    build_graph.BuildArtifactId("/p/prg"),
-                    repository.SSAFArtifactKind.EDITS,
-                )
-            ),
-        )
-        self.assertEqual(
-            "/out/ssaf-artifacts/p/prg.conflicts.sarif",
-            self.ssaf_artifact_repo.get_path_for_artifact(
-                repository.get_ssaf_artifact_id(
-                    build_graph.BuildArtifactId("/p/prg"),
-                    repository.SSAFArtifactKind.CONFLICTS,
-                )
-            ),
-        )
 
 
 class Construction(unittest.TestCase):
@@ -98,89 +61,6 @@ def test_constructing_it_creates_no_directory(self):
         self.assertFalse(os.path.exists(output_dir))
 
 
-class LinkUnitName(unittest.TestCase):
-    def setUp(self):
-        self.tmp = tempfile.mkdtemp()
-        self.addCleanup(shutil.rmtree, self.tmp, True)
-        self.ssaf_artifact_repo = configs.repository_for(self.tmp)
-        self.graph = configs.build_graph_for(self.tmp)
-
-    def _summary_path(self):
-        return self.ssaf_artifact_repo.get_path_for_artifact(
-            repository.get_ssaf_artifact_id(
-                build_graph.BuildArtifactId("/p/prg"),
-                repository.SSAFArtifactKind.SUMMARY,
-            )
-        )
-
-    def _write(self, document):
-        path = utils.make_parents(self._summary_path())
-        with open(path, "w") as handle:
-            json.dump(document, handle)
-
-    def _name(self):
-        return self.ssaf_artifact_repo.get_link_unit_name(self._summary_path())
-
-    def test_reads_the_link_unit_name(self):
-        self._write({"lu_namespace": [{"kind": "LinkUnit", "name": "prg"}]})
-        self.assertEqual("prg", self._name())
-
-    def test_a_library_names_no_link_unit(self):
-        self._write({"namespace": {"kind": "StaticLibrary", "name": "libx"}})
-        self.assertIsNone(self._name())
-
-    def test_skips_other_namespace_kinds(self):
-        self._write(
-            {
-                "lu_namespace": [
-                    {"kind": "StaticLibrary", "name": "libx"},
-                    {"kind": "LinkUnit", "name": "prg"},
-                ]
-            }
-        )
-        self.assertEqual("prg", self._name())
-
-    def test_absent_namespace(self):
-        self._write({})
-        self.assertIsNone(self._name())
-
-    def test_absent_summary(self):
-        self.assertIsNone(self._name())
-
-
-class Conflicts(unittest.TestCase):
-    def setUp(self):
-        self.tmp = tempfile.mkdtemp()
-        self.addCleanup(shutil.rmtree, self.tmp, True)
-        self.ssaf_artifact_repo = configs.repository_for(self.tmp)
-
-    def _write(self, build_artifact_path, results):
-        path = utils.make_parents(
-            self.ssaf_artifact_repo.get_path_for_artifact(
-                repository.get_ssaf_artifact_id(
-                    build_graph.BuildArtifactId(build_artifact_path),
-                    repository.SSAFArtifactKind.CONFLICTS,
-                )
-            )
-        )
-        with open(path, "w") as handle:
-            json.dump({"version": "2.1.0", "runs": [{"results": results}]}, handle)
-        return path
-
-    def test_a_merge_that_dropped_nothing_reports_nothing(self):
-        self._write("/p/prg", [])
-        self.assertEqual([], self.ssaf_artifact_repo.get_conflicts())
-
-    def test_every_merge_that_dropped_an_edit_is_reported(self):
-        library = self._write("/p/libx.a", [{"ruleId": "conflict"}])
-        program = self._write("/p/prg", [{"ruleId": "conflict"}])
-        self._write("/p/other", [])
-        self.assertEqual(
-            sorted([library, program]),
-            self.ssaf_artifact_repo.get_conflicts(),
-        )
-
-
 class Counts(unittest.TestCase):
     def setUp(self):
         self.tmp = tempfile.mkdtemp()
@@ -212,14 +92,6 @@ def test_each_kind_is_counted_apart_at_any_depth(self):
                 )
             )
         )
-        self._write(
-            self.ssaf_artifact_repo.get_path_for_artifact(
-                repository.get_ssaf_artifact_id(
-                    build_graph.BuildArtifactId("/p/a.o"),
-                    repository.SSAFArtifactKind.EDITS,
-                )
-            )
-        )
         self._write(
             self.graph.get_buildstep_record_path(build_graph.BuildArtifactId("/p/prg"))
         )

>From ae1257d6b7ee872ad28185b1793ab09f8ba9709d Mon Sep 17 00:00:00 2001
From: Balazs Benics <benicsbalazs at gmail.com>
Date: Thu, 15 Oct 2026 11:53:32 +0100
Subject: [PATCH 14/14] Revert "[clang][ssaf] Add clang-ssaf-orchestrator-make
 (#231583)"

This reverts commit dbde204202ad44d728664126996aca39959d15a2.
---
 .../developer-docs/MakeOrchestratorShims.md   | 133 ------
 .../user-docs/MakeProjects.md                 | 252 -----------
 .../ssaf-orchestrator-make/bad-args.test      |  13 -
 .../ssaf-orchestrator-make/bare-linker.test   |  46 --
 .../build-failures.test                       |  35 --
 .../extract-summaries.test                    |  67 ---
 .../failure-handling.test                     |  78 ----
 .../Scalable/ssaf-orchestrator-make/help.test |  27 --
 .../incremental-tree.test                     |  58 ---
 .../ssaf-orchestrator-make/interposition.test |  88 ----
 .../ssaf-orchestrator-make/link-driver.test   |  30 --
 .../link-unit-selection.test                  |  56 ---
 .../ssaf-orchestrator-make/lit.local.cfg      |  62 ---
 .../path-interposition.test                   |  42 --
 .../recursive-make.test                       |  61 ---
 .../same-basename-objects.test                |  61 ---
 .../shim-outside-a-run.test                   |  17 -
 .../ssaf-orchestrator-make/unittests.test     |   8 -
 .../unreachable-compiler.test                 |  27 --
 .../whole-program-analysis.test               |  59 ---
 clang/test/CMakeLists.txt                     |   1 -
 clang/tools/CMakeLists.txt                    |   1 -
 .../CMakeLists.txt                            |  94 ----
 .../clang-ssaf-orchestrator-make/README.md    |  51 ---
 .../bin/clang-ssaf-orchestrator-make          |  15 -
 .../clang_ssaf_orchestrator_make/__init__.py  |  10 -
 .../build_graph.py                            |  73 ---
 .../clang_ssaf_orchestrator_make/config.py    | 115 -----
 .../config_orchestrator.py                    | 142 ------
 .../config_shims.py                           |  31 --
 .../failure_logs.py                           |  48 --
 .../interposition.py                          |  31 --
 .../logging_diagnostics.py                    |  41 --
 .../clang_ssaf_orchestrator_make/options.py   | 147 -------
 .../orchestrator.py                           | 211 ---------
 .../shims/__init__.py                         |   3 -
 .../shims/clang.py                            | 128 ------
 .../shims/commands.py                         |  49 ---
 .../shims/driver_jobs.py                      |  58 ---
 .../clang_ssaf_orchestrator_make/shims/ld.py  |  88 ----
 .../clang_ssaf_orchestrator_make/shims/run.py |  23 -
 .../shims/shim.py                             | 183 --------
 .../ssaf_artifact_repository.py               |  58 ---
 .../lib/clang_ssaf_orchestrator_make/utils.py |  54 ---
 .../version.py.in                             |   5 -
 .../clang-ssaf-orchestrator-make/shims/shim   |  45 --
 .../tests/__init__.py                         |   3 -
 .../tests/configs.py                          |  84 ----
 .../tests/test_build_graph.py                 | 222 ----------
 .../tests/test_clang_shim.py                  | 244 -----------
 .../tests/test_commands.py                    | 114 -----
 .../tests/test_config.py                      |  86 ----
 .../tests/test_config_orchestrator.py         | 348 ---------------
 .../tests/test_config_shims.py                |  63 ---
 .../tests/test_driver_jobs.py                 | 150 -------
 .../tests/test_failure_logs.py                |  93 ----
 .../tests/test_interposition.py               |  69 ---
 .../tests/test_ld_shim.py                     | 132 ------
 .../tests/test_logging_diagnostics.py         | 101 -----
 .../tests/test_options.py                     |  82 ----
 .../tests/test_orchestrator.py                | 354 ---------------
 .../tests/test_run.py                         |  84 ----
 .../tests/test_shim.py                        | 414 ------------------
 .../tests/test_ssaf_artifact_repository.py    | 102 -----
 .../tests/test_utils.py                       |  94 ----
 65 files changed, 5764 deletions(-)
 delete mode 100644 clang/docs/ScalableStaticAnalysis/developer-docs/MakeOrchestratorShims.md
 delete mode 100644 clang/docs/ScalableStaticAnalysis/user-docs/MakeProjects.md
 delete mode 100644 clang/test/Analysis/Scalable/ssaf-orchestrator-make/bad-args.test
 delete mode 100644 clang/test/Analysis/Scalable/ssaf-orchestrator-make/bare-linker.test
 delete mode 100644 clang/test/Analysis/Scalable/ssaf-orchestrator-make/build-failures.test
 delete mode 100644 clang/test/Analysis/Scalable/ssaf-orchestrator-make/extract-summaries.test
 delete mode 100644 clang/test/Analysis/Scalable/ssaf-orchestrator-make/failure-handling.test
 delete mode 100644 clang/test/Analysis/Scalable/ssaf-orchestrator-make/help.test
 delete mode 100644 clang/test/Analysis/Scalable/ssaf-orchestrator-make/incremental-tree.test
 delete mode 100644 clang/test/Analysis/Scalable/ssaf-orchestrator-make/interposition.test
 delete mode 100644 clang/test/Analysis/Scalable/ssaf-orchestrator-make/link-driver.test
 delete mode 100644 clang/test/Analysis/Scalable/ssaf-orchestrator-make/link-unit-selection.test
 delete mode 100644 clang/test/Analysis/Scalable/ssaf-orchestrator-make/lit.local.cfg
 delete mode 100644 clang/test/Analysis/Scalable/ssaf-orchestrator-make/path-interposition.test
 delete mode 100644 clang/test/Analysis/Scalable/ssaf-orchestrator-make/recursive-make.test
 delete mode 100644 clang/test/Analysis/Scalable/ssaf-orchestrator-make/same-basename-objects.test
 delete mode 100644 clang/test/Analysis/Scalable/ssaf-orchestrator-make/shim-outside-a-run.test
 delete mode 100644 clang/test/Analysis/Scalable/ssaf-orchestrator-make/unittests.test
 delete mode 100644 clang/test/Analysis/Scalable/ssaf-orchestrator-make/unreachable-compiler.test
 delete mode 100644 clang/test/Analysis/Scalable/ssaf-orchestrator-make/whole-program-analysis.test
 delete mode 100644 clang/tools/clang-ssaf-orchestrator-make/CMakeLists.txt
 delete mode 100644 clang/tools/clang-ssaf-orchestrator-make/README.md
 delete mode 100755 clang/tools/clang-ssaf-orchestrator-make/bin/clang-ssaf-orchestrator-make
 delete mode 100644 clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/__init__.py
 delete mode 100644 clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/build_graph.py
 delete mode 100644 clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/config.py
 delete mode 100644 clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/config_orchestrator.py
 delete mode 100644 clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/config_shims.py
 delete mode 100644 clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/failure_logs.py
 delete mode 100644 clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/interposition.py
 delete mode 100644 clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/logging_diagnostics.py
 delete mode 100644 clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/options.py
 delete mode 100644 clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/orchestrator.py
 delete mode 100644 clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/__init__.py
 delete mode 100644 clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/clang.py
 delete mode 100644 clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/commands.py
 delete mode 100644 clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/driver_jobs.py
 delete mode 100644 clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/ld.py
 delete mode 100644 clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/run.py
 delete mode 100644 clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/shim.py
 delete mode 100644 clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/ssaf_artifact_repository.py
 delete mode 100644 clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/utils.py
 delete mode 100644 clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/version.py.in
 delete mode 100755 clang/tools/clang-ssaf-orchestrator-make/shims/shim
 delete mode 100644 clang/tools/clang-ssaf-orchestrator-make/tests/__init__.py
 delete mode 100644 clang/tools/clang-ssaf-orchestrator-make/tests/configs.py
 delete mode 100644 clang/tools/clang-ssaf-orchestrator-make/tests/test_build_graph.py
 delete mode 100644 clang/tools/clang-ssaf-orchestrator-make/tests/test_clang_shim.py
 delete mode 100644 clang/tools/clang-ssaf-orchestrator-make/tests/test_commands.py
 delete mode 100644 clang/tools/clang-ssaf-orchestrator-make/tests/test_config.py
 delete mode 100644 clang/tools/clang-ssaf-orchestrator-make/tests/test_config_orchestrator.py
 delete mode 100644 clang/tools/clang-ssaf-orchestrator-make/tests/test_config_shims.py
 delete mode 100644 clang/tools/clang-ssaf-orchestrator-make/tests/test_driver_jobs.py
 delete mode 100644 clang/tools/clang-ssaf-orchestrator-make/tests/test_failure_logs.py
 delete mode 100644 clang/tools/clang-ssaf-orchestrator-make/tests/test_interposition.py
 delete mode 100644 clang/tools/clang-ssaf-orchestrator-make/tests/test_ld_shim.py
 delete mode 100644 clang/tools/clang-ssaf-orchestrator-make/tests/test_logging_diagnostics.py
 delete mode 100644 clang/tools/clang-ssaf-orchestrator-make/tests/test_options.py
 delete mode 100644 clang/tools/clang-ssaf-orchestrator-make/tests/test_orchestrator.py
 delete mode 100644 clang/tools/clang-ssaf-orchestrator-make/tests/test_run.py
 delete mode 100644 clang/tools/clang-ssaf-orchestrator-make/tests/test_shim.py
 delete mode 100644 clang/tools/clang-ssaf-orchestrator-make/tests/test_ssaf_artifact_repository.py
 delete mode 100644 clang/tools/clang-ssaf-orchestrator-make/tests/test_utils.py

diff --git a/clang/docs/ScalableStaticAnalysis/developer-docs/MakeOrchestratorShims.md b/clang/docs/ScalableStaticAnalysis/developer-docs/MakeOrchestratorShims.md
deleted file mode 100644
index c815a30b0425d..0000000000000
--- a/clang/docs/ScalableStaticAnalysis/developer-docs/MakeOrchestratorShims.md
+++ /dev/null
@@ -1,133 +0,0 @@
-# Make Orchestrator Shims
-
-`clang-ssaf-orchestrator-make` analyses a project by riding along with its
-build. It does that with a set of small programs — *shims* — that stand in
-for the tools the build invokes. This describes how they are selected, what
-each one does, and how they learn what run they are part of; the user-facing
-behaviour is in {doc}`../user-docs/MakeProjects`.
-
-## Setting up the build's environment
-
-At the start of a run the orchestrator does two things to the environment the
-build will see.
-
-It fills `<output-dir>/shims/` with links named after the build tools, all
-pointing at one shim program, and prepends that directory to `PATH`. A build
-can spell the compiler several ways, so several names lead to the same shim:
-
-```text
-cc, clang, c++, clang++  ->  clang
-ld                       ->  ld
-```
-
-It also writes the configuration for the shims into a JSON document and puts
-that document's path in `SSAF_CONFIG`. A shim that finds no `SSAF_CONFIG`
-reports an error and exits without running anything.
-
-## Running the binary tool
-
-A shim has to run the tool the build asked for, by the name the build spelled,
-but on the modified `PATH` that name finds the shim itself.
-`SSAFWorkflowConfig.restored_path_env_var` therefore holds the build's `PATH`
-as it was before the shim link directory went in front of it.
-`Shim.bin_tool_path` looks the tool up on that `PATH`, and
-`Shim.get_unmodified_env` gives the tool an environment with that `PATH`
-restored and `SSAF_CONFIG` removed.
-
-## The shim program
-
-`libexec/ssaf-orchestrator-shims/` holds one program, `shim`, and every link
-points at it. It puts the package on `sys.path`, looks up the name it was
-invoked under in `SHIM_FOR_LINK_NAME`, the table the links were made from, and
-imports the module that stands in for that tool. It is a file rather than a
-package module because it is symlinked under several names, and `argv[0]` is
-what tells it which tool it stands in for.
-
-The shim bodies live in the package, as `clang_ssaf_orchestrator_make.shims`,
-split by what they do:
-
-```text
-shim.py          the Shim class and its diagnostics
-commands.py      Files, is_object, artifact_of, summary_of,
-                 filter_build_artifacts, unique
-driver_jobs.py   Job and the -### listing reader
-run.py           run_shim
-clang.py ld.py
-```
-
-Every shim has the same shape, which `run_shim` implements: run the tool the
-build asked for, then do the SSAF work. A failure in the first half is the
-build's own. A failure in the second is logged, and the build carries on.
-
-## The clang shim has two roles
-
-One program serves both, and a marker on the command line tells them apart.
-
-**Invoked as the clang driver.** The build spelled `cc`, `clang`, `c++` or
-`clang++`, and `PATH` found the link. The shim runs the binary tool on the
-build's command line untouched, asks it with `-###` how that command
-decomposes into jobs, and forwards each job to the shim that stands in for its
-tool.
-
-**Invoked as cc1 by the shim's driver role.** A forwarded job ends in
-`--ssaf-shim-skip-binary-tool-invocation`, which only the driver role appends.
-The binary tool has therefore already run, and the shim does only the SSAF
-work: it runs the SSAF clang over the job with the `--ssaf-*` options added.
-`Shim.__init__` removes the marker as the command enters the shim, so nothing
-downstream sees it.
-
-## Matching a job to a shim
-
-For each job in the driver's `-###` listing, take the program the job names,
-strip its directory and any trailing `-<digits>`, and look the result up among
-the links:
-
-```text
-/…/toolchains/…/usr/bin/clang   ->  clang     ->  <output-dir>/shims/clang
-/…/build/bin/clang-<N>          ->  clang     ->  <output-dir>/shims/clang
-/usr/bin/ld                     ->  ld        ->  <output-dir>/shims/ld
-/usr/bin/dsymutil               ->  dsymutil  ->  no link; nothing stands in
-```
-
-The suffix is stripped because a driver names its own binary `clang` when
-installed and `clang-<N>`, after its major version, in a build tree. A job
-with no matching link is noted and skipped: the build's compiler has already
-run it, and there is no SSAF step for its tool.
-
-## Recording what the build assembled
-
-`ld` reads its command line for the artifact it produces and the artifacts it
-consumes, and records them in `<output-dir>/build-graph/<path>.buildstep.json`.
-The top-most link unit is found from these records, and they tell an artifact
-the build assembled from one it never touched.
-
-Everything a shim writes is named for a build artifact's path plus a suffix,
-such as `ssaf-artifacts/<path>.summary.json`.
-
-## Failure logs
-
-A failure log is a diagnostic about a command rather than something the
-command produced, so it lives apart, under `failure-logs/`. The run counts
-every log at its end, which is how a failure a shim logged and moved past
-still fails the run.
-
-A log is named for the artifact it concerns: the output of the command that
-failed, or the input whose summary is missing. A command that names no output,
-such as `clang -c a.c b.c`, and an internal error in a shim are logged instead
-under the directory the command ran in, named for a hash of the command:
-
-```text
-failure-logs/<path>.<kind>.log        named for an artifact
-failure-logs/<dir>/<hash>.<kind>.log  named for a command
-```
-
-The kind says what went wrong; the kinds are the values of `SSAFFailureKind`:
-
-```text
-extract      summary extraction for a compilation
-link         clang-ssaf-linker over a link's inputs
-forward      handing a job to the shim that stands in for its tool
-missing      an artifact with nothing analysed behind it
-driver-jobs  the driver refused to list a command's jobs
-internal     an unhandled exception inside a shim
-```
diff --git a/clang/docs/ScalableStaticAnalysis/user-docs/MakeProjects.md b/clang/docs/ScalableStaticAnalysis/user-docs/MakeProjects.md
deleted file mode 100644
index 1bf14c500979b..0000000000000
--- a/clang/docs/ScalableStaticAnalysis/user-docs/MakeProjects.md
+++ /dev/null
@@ -1,252 +0,0 @@
-# Make-Based Projects
-
-Running SSAF over a whole project means running summary extraction for every
-translation unit the project compiles, and linking those summaries the way the
-build links the objects they describe. `clang-ssaf-orchestrator-make` does that
-for projects built with make. The design based on tool shims is documented in
-{doc}`../developer-docs/MakeOrchestratorShims`.
-
-The build is executed normally, and each step it takes is paired with an SSAF
-step:
-
-- A **compilation** gets a second compilation — the frontend job the build's
-  own compiler said it would run, with the `--ssaf-*` options appended and
-  nothing taken away, so extraction sees exactly what the build compiles.
-- A **link** gets a `clang-ssaf-linker` invocation over the summaries of what
-  went into it. It is not a copy of the build's command and carries no
-  `--ssaf-*` options.
-
-The mapping onto the SSAF tools is direct:
-
-```{eval-rst}
-.. list-table::
-   :header-rows: 1
-
-   * - Build step
-     - SSAF step
-   * - ``$(CXX) -c -o parser.o parser.cpp``
-     - ``clang -cc1 … -o parser.o -x c++ parser.cpp
-       --ssaf-extract-summaries=…``
-   * - ``$(CXX) -o app main.o parser.o``
-     - ``clang-ssaf-linker main.json parser.json``
-```
-
-## Usage
-
-Run it from the project root; that is where the build runs.
-
-There are two workflows, the second going one step further than the first:
-
-- **Summary extraction and linking**, with `--extract-summaries`. Every
-  translation unit gets a summary, and the summaries are linked the way the
-  build links the objects, into one link unit summary.
-- **Whole-program analysis**, adding `--analysis`. `clang-ssaf-analyzer` runs
-  the named analyses over the link unit summary.
-
-Summary extraction and linking:
-
-```console
-$ clang-ssaf-orchestrator-make \
-    --extract-summaries=PointerFlow,UnsafeBufferUsage \
-    -o ssaf-output \
-    -- make -j8
-```
-
-Whole-program analysis:
-
-```console
-$ clang-ssaf-orchestrator-make \
-    --extract-summaries=PointerFlow,UnsafeBufferUsage \
-    --analysis=UnsafeBufferReachableAnalysisResult \
-    -o ssaf-output \
-    -- make -j8
-```
-
-For a project configured by autoconf, run `configure` first and give the
-orchestrator only the `make` invocation.
-
-## Options
-
-```{eval-rst}
-.. list-table::
-   :header-rows: 1
-
-   * - Option
-     - Purpose
-   * - ``--extract-summaries=<name,...>``
-     - Summary extractors to run over every translation unit. Required.
-   * - ``--analysis=<name>``
-     - Whole-program analysis to run on the link unit summary. Repeatable.
-       Without it the run stops after summary extraction.
-   * - ``-o``, ``--output-dir=<dir>``
-     - Where the SSAF artifacts go, made absolute. Defaults to
-       ``ssaf-output``. It must be absent, empty, or an earlier run's.
-   * - ``--ssaf-clang=<path>``
-     - SSAF-capable clang used for the SSAF compilations. Defaults to
-       ``clang`` on ``PATH``.
-   * - ``--ssaf-linker=<path>``
-     - Path to ``clang-ssaf-linker``. Defaults to the name on ``PATH``.
-   * - ``--ssaf-analyzer=<path>``
-     - Path to ``clang-ssaf-analyzer``. Defaults to the name on ``PATH``, and
-       is only required with ``--analysis``.
-   * - ``--ssaf-extra-clang-arg=<arg>``
-     - Extra argument for every SSAF compilation. Repeatable.
-   * - ``-k``, ``--keep-going``
-     - Exit successfully even though some SSAF steps failed. The failures are
-       still reported.
-   * - ``-v``, ``--verbose``
-     - Print every command the orchestrator and the shims run, on stderr.
-   * - ``--version``
-     - The clang version this was built from.
-```
-
-Each `--ssaf-*` tool must resolve to one executable file. A value naming more
-than one word, a directory, something that is not executable, or a path inside
-our own installed shim directory — which is what an earlier run's links on
-`PATH` look like — is refused, and every unresolvable tool is reported at
-once.
-
-## Artifacts
-
-A build artifact is named by its resolved **path**, so two spellings of one
-file name the same artifact. That path is what a buildstep record names, and
-the value of `--ssaf-compilation-unit-id=`.
-
-An SSAF artifact is filed under the same path with its leading separator
-dropped, so an object at `/work/parse/build/parser.o` gets a summary at
-`<output-dir>/ssaf-artifacts/work/parse/build/parser.o.summary.json`.
-
-No part of the path is elided, because the path is what tells two
-translation units apart. A build that compiles one source into
-`build/first/parser.o` and another into `build/second/parser.o` has two
-translation units, and only the whole path tells them apart.
-
-```{eval-rst}
-.. list-table::
-   :header-rows: 1
-
-   * - Path
-     - Contents
-   * - ``<output-dir>/ssaf-artifacts/<path>.summary.json``
-     - What SSAF holds for ``<path>``: a TU summary where the path names a
-       compilation's object, and whatever the SSAF linker wrote where the
-       build assembled it.
-   * - ``<output-dir>/build-graph/<path>.buildstep.json``
-     - Which build artifacts were inputs for the ``<path>`` build artifact.
-   * - ``<output-dir>/wpa.json``
-     - Whole-program analysis result.
-   * - ``<output-dir>/config-analysis.json``
-     - Configuration for the analysis pass.
-   * - ``<output-dir>/shims/``
-     - Links to the shims named so they interpose the binary tools, recreated
-       on every run.
-   * - ``<output-dir>/.clang-ssaf-orchestrator-make``
-     - SSAF ownership attribute for cleanup.
-   * - ``<output-dir>/failure-logs/<path>.<kind>.log``
-     - What went wrong for ``<path>``: a command writing it whose SSAF step
-       failed, or an input that had no summary.
-   * - ``<output-dir>/failure-logs/<dir>/<hash>.<kind>.log``
-     - What went wrong for a command that names no output, and any internal
-       error in a shim; ``<hash>`` names the command and ``<dir>`` is where
-       it ran. Every ``.log`` anywhere under the output directory counts
-       against the run; a log is always a failure.
-```
-
-The buildstep records are what the top-most link unit is found from. An
-input contributes the summary filed under its own id or nothing at all,
-so an artifact whose SSAF step failed takes the artifacts behind it down
-with it, and the run says so and exits non-zero.
-
-## Failure handling
-
-A failing build step fails the run with the build's own exit status, and no
-SSAF step runs for it.
-
-A failing SSAF step never fails the build: it is reported and logged to a
-`.log` under `<output-dir>/failure-logs/`, and the build carries on. The run
-exits non-zero afterwards, because the artifacts are incomplete. `-k` makes the
-run exit zero instead; the failures are still reported, so the message appears
-either way.
-
-## Interposition
-
-The orchestrator populates `<output-dir>/shims/` with links named after the
-tools a build invokes — `cc`, `clang`, `c++`, `clang++` and `ld` —
-each pointing at the shim that stands in for it, and prepends that
-directory to `PATH`. It also puts the path of a configuration file in
-`SSAF_CONFIG`.
-
-It changes nothing else in the build: no variable is replaced, so whatever the
-Makefile put in `CXX` — flags, a dialect, a define — arrives at the compiler
-exactly as it was written, and at the SSAF compilation with it.
-
-## What is not supported
-
-**Compilers other than clang.** Every compilation gets an SSAF step replaying
-the frontend job the build's own compiler said it would run, and that replay
-carries the `--ssaf-*` options, which only clang has. A project built by GCC
-therefore cannot be analysed, and the orchestrator does not pretend otherwise:
-`gcc` and `g++` are not among the names it interposes, so such a build is left
-alone rather than analysed into an empty result. On a platform where `gcc` and
-`g++` are clang this means a build spelling those names is not analysed
-either. GNU make defaults `CXX` to `g++`,
-so a Makefile that never sets it needs `CXX=clang++` on the make command line.
-The clang the build uses and the one named by `--ssaf-clang` must also be
-compatible with each other, since the frontend command line one produces is
-replayed by the other.
-
-**Compiler launchers**, such as `ccache`, `distcc`, `sccache` and `xcrun`.
-Run the build without the launcher instead, by overriding the variable that
-adds it on the make command line, as in `-- make CC=clang CXX=clang++`.
-
-**A compiler named by an absolute path**, in a recipe or through a variable:
-
-```make
-CXX = /opt/toolchain/bin/clang++     # PATH is never consulted
-CC := $(shell xcrun -find clang)     # an absolute path at parse time
-```
-
-Name the compiler by its bare name on the make command line instead, with its
-directory on `PATH`:
-
-```console
-$ PATH=/opt/toolchain/bin:$PATH clang-ssaf-orchestrator-make \
-    --extract-summaries=PointerFlow -- make CXX=clang++
-```
-
-**Inputs named indirectly on a link line.** A link that outgrows `ARG_MAX` and
-passes its objects through ld64's `-filelist`, given to `ld` or to the driver,
-is read as it stands, so those objects are not seen and the step contributes
-no link unit summary.
-
-**Linkers not named `ld`.** A link the driver hands to `ld.lld`, `ld64.lld`,
-`ld.gold` or `mold`, through `-fuse-ld=` or the toolchain's default, has no
-shim standing in for it, so it contributes nothing, and a project linked that
-way has no link unit.
-
-**Frontend command lines.** A recipe running `clang -cc1 …` directly, or
-`clang @file.rsp` whose first token is `-cc1`, is compiled, but its SSAF step
-fails: the driver cannot list the jobs of a frontend command line.
-
-**Assembler sources.** A `.s` or `.S` input carries a `-cc1as` job, whose SSAF
-step fails.
-
-## Implementation details
-
-How a compilation decomposes is worked out by asking the compiler driver, using
-the `-###` option.
-
-Because a compilation's SSAF step replays the build's own action, it writes the
-build's outputs a second time — the object, and any dependency file or
-serialized diagnostics the job asked for — with the SSAF clang rather than the
-build's. Build products are not preserved; this is an analysis run, not a
-build.
-
-Every build gets make's `-B` appended, because a translation unit that make
-considers up to date is not compiled and so gets no SSAF step. A build command
-that is not make draws a warning.
-
-Each run starts by deleting the output directory, recreating it and marking it
-with a `.clang-ssaf-orchestrator-make` file. An existing output directory is
-deleted only when it is empty or carries that mark, and never when it is, or
-contains, the project.
diff --git a/clang/test/Analysis/Scalable/ssaf-orchestrator-make/bad-args.test b/clang/test/Analysis/Scalable/ssaf-orchestrator-make/bad-args.test
deleted file mode 100644
index cd04850a31fe6..0000000000000
--- a/clang/test/Analysis/Scalable/ssaf-orchestrator-make/bad-args.test
+++ /dev/null
@@ -1,13 +0,0 @@
-
-# RUN: not %clang-ssaf-orchestrator-make 2>&1 | FileCheck %s --check-prefix=NO-EXTRACTORS
-# NO-EXTRACTORS: error: the following arguments are required: --extract-summaries
-
-# RUN: not %clang-ssaf-orchestrator-make --extract-summaries=PointerFlow 2>&1 \
-# RUN:   | FileCheck %s --check-prefix=NO-BUILD
-# NO-BUILD: no build command given
-
-# RUN: not %clang-ssaf-orchestrator-make --extract-summaries=PointerFlow \
-# RUN:   --ssaf-clang=/no/such/clang -- make 2>&1 \
-# RUN:   | FileCheck %s --check-prefix=NO-CLANG
-# NO-CLANG: required tools not resolvable:
-# NO-CLANG: --ssaf-clang: not a file: /no/such/clang
diff --git a/clang/test/Analysis/Scalable/ssaf-orchestrator-make/bare-linker.test b/clang/test/Analysis/Scalable/ssaf-orchestrator-make/bare-linker.test
deleted file mode 100644
index 28222ab28548d..0000000000000
--- a/clang/test/Analysis/Scalable/ssaf-orchestrator-make/bare-linker.test
+++ /dev/null
@@ -1,46 +0,0 @@
-
-# REQUIRES: ssaf-orchestrator-make-build
-# REQUIRES: system-darwin, aarch64-registered-target
-# REQUIRES: ssaf-orchestrator-make-sdkroot
-
-# RUN: rm -rf %t && split-file %s %t
-# RUN: mkdir -p %t/build
-
-# RUN: cd %t
-# RUN: %clang-ssaf-orchestrator-make \
-# RUN:     --extract-summaries=PointerFlow \
-# RUN:     --ssaf-clang=%ssaf-orchestrator-make-clang \
-# RUN:     -o %t/out -- make \
-# RUN:   | FileCheck %s --check-prefix=STDOUT
-
-# STDOUT: summaries: 3
-# STDOUT: link-unit: {{[^ ]*}}/build/prg
-
-# RUN: cat %t/out/ssaf-artifacts%t/build/prg.summary.json | FileCheck %s --check-prefix=LU
-# LU: "type": "LUSummary"
-
-# RUN: cat %t/out/build-graph%t/build/prg.buildstep.json \
-# RUN:   | FileCheck %s --check-prefix=UNIT
-# UNIT-DAG: {{[^ ]*}}/build/main.o
-# UNIT-DAG: {{[^ ]*}}/build/helper.o
-
-# RUN: ls %t/build/prg
-
-#--- Makefile
-CXX = clang++
-LDFLAGS = -lSystem -syslibroot $(SDKROOT) -arch arm64 -platform_version macos 15.0 15.0
-all: build/prg
-build/%.o: src/%.cpp
-	$(CXX) -arch arm64 -c -o $@ $<
-build/prg: build/main.o build/helper.o
-	$(LD) -o $@ build/main.o build/helper.o $(LDFLAGS) -lc++
-
-#--- src/helper.cpp
-int helper(int *p) { return p[0]; }
-
-#--- src/main.cpp
-int helper(int *p);
-int main() {
-  int values[2] = {1, 2};
-  return helper(values);
-}
diff --git a/clang/test/Analysis/Scalable/ssaf-orchestrator-make/build-failures.test b/clang/test/Analysis/Scalable/ssaf-orchestrator-make/build-failures.test
deleted file mode 100644
index f06a7494b87cd..0000000000000
--- a/clang/test/Analysis/Scalable/ssaf-orchestrator-make/build-failures.test
+++ /dev/null
@@ -1,35 +0,0 @@
-
-# REQUIRES: ssaf-orchestrator-make-build
-# RUN: rm -rf %t && split-file %s %t
-# RUN: mkdir -p %t/build
-
-# A build command that cannot be run at all.
-# RUN: cd %t
-# RUN: not %clang-ssaf-orchestrator-make \
-# RUN:     --extract-summaries=PointerFlow \
-# RUN:     --ssaf-clang=%ssaf-orchestrator-make-clang \
-# RUN:     -o %t/out -- %t/no-such-build-tool 2>&1 \
-# RUN:   | FileCheck %s --check-prefix=UNRUNNABLE
-# UNRUNNABLE: error: cannot run '{{.*}}/no-such-build-tool'
-
-# A build that runs and fails takes the run down with its own status.
-# RUN: not %clang-ssaf-orchestrator-make \
-# RUN:     --extract-summaries=PointerFlow \
-# RUN:     --ssaf-clang=%ssaf-orchestrator-make-clang \
-# RUN:     -o %t/out -- make broken 2>&1 \
-# RUN:   | FileCheck %s --check-prefix=FAILED
-# FAILED: error: build failed (exit {{[1-9][0-9]*}})
-
-#--- Makefile
-CXX = clang++
-all: build/prg
-broken: src/broken.cpp
-	$(CXX) -c -o build/broken.o $<
-build/prg: src/a.cpp
-	$(CXX) -o $@ $<
-
-#--- src/a.cpp
-int main() { return 0; }
-
-#--- src/broken.cpp
-this is not C++ at all
diff --git a/clang/test/Analysis/Scalable/ssaf-orchestrator-make/extract-summaries.test b/clang/test/Analysis/Scalable/ssaf-orchestrator-make/extract-summaries.test
deleted file mode 100644
index 79dfa32bee2f8..0000000000000
--- a/clang/test/Analysis/Scalable/ssaf-orchestrator-make/extract-summaries.test
+++ /dev/null
@@ -1,67 +0,0 @@
-
-# REQUIRES: ssaf-orchestrator-make-build
-# RUN: rm -rf %t && split-file %s %t
-# RUN: mkdir -p %t/build
-
-# RUN: cd %t
-# RUN: %clang-ssaf-orchestrator-make \
-# RUN:     --extract-summaries=PointerFlow,UnsafeBufferUsage \
-# RUN:     --ssaf-clang=%ssaf-orchestrator-make-clang \
-# RUN:     -o %t/out -- make \
-# RUN:   | FileCheck %s --check-prefix=STDOUT
-
-# STDOUT: summaries: 3
-# STDOUT: link-unit: {{[^ ]*}}/build/prg
-
-# RUN: ls %t/build/a.o %t/build/b.o %t/build/prg
-
-# RUN: cat %t/out/ssaf-artifacts%t/build/a.o.summary.json \
-# RUN:   | FileCheck %s --check-prefix=CU-A
-# CU-A: "name": "{{[^ ]*}}/build/a.o"
-# RUN: cat %t/out/ssaf-artifacts%t/build/b.o.summary.json \
-# RUN:   | FileCheck %s --check-prefix=CU-B
-# CU-B: "name": "{{[^ ]*}}/build/b.o"
-
-# RUN: cat %t/out/ssaf-artifacts%t/build/a.o.summary.json | FileCheck %s --check-prefix=KIND
-# KIND: "type": "TUSummary"
-
-# RUN: cat %t/out/ssaf-artifacts%t/build/prg.summary.json \
-# RUN:   | FileCheck %s --check-prefix=LU
-# LU: "kind": "LinkUnit"
-# LU: "type": "LUSummary"
-
-# The SSAF step replays the build's own job, so it writes the build's outputs
-# a second time -- including the depfile -MMD asked for, and in the directory
-# the job named rather than the one the SSAF step ran in.
-# RUN: rm %t/build/a.d
-# RUN: cd %t
-# RUN: %clang-ssaf-orchestrator-make \
-# RUN:     --extract-summaries=PointerFlow \
-# RUN:     --ssaf-clang=%ssaf-orchestrator-make-clang \
-# RUN:     -o %t/out2 -- make
-# RUN: ls %t/build/a.d
-# RUN: ls %t && not ls %t/a.d
-
-#--- Makefile
-CXX = clang++
-CXXFLAGS = -MMD -MP
-all: build/prg
-build/%.o: src/%.cpp
-	$(CXX) $(CXXFLAGS) -c -o $@ $<
-build/prg: build/a.o build/b.o
-	$(CXX) -o $@ build/a.o build/b.o
-
-#--- src/a.cpp
-int sum(int *p, int n) {
-  int total = 0;
-  for (int i = 0; i < n; ++i)
-    total += p[i];
-  return total;
-}
-
-#--- src/b.cpp
-int sum(int *p, int n);
-int main() {
-  int values[4] = {1, 2, 3, 4};
-  return sum(values, 4);
-}
diff --git a/clang/test/Analysis/Scalable/ssaf-orchestrator-make/failure-handling.test b/clang/test/Analysis/Scalable/ssaf-orchestrator-make/failure-handling.test
deleted file mode 100644
index b6e7bd6ed977d..0000000000000
--- a/clang/test/Analysis/Scalable/ssaf-orchestrator-make/failure-handling.test
+++ /dev/null
@@ -1,78 +0,0 @@
-
-# REQUIRES: ssaf-orchestrator-make-build
-# RUN: rm -rf %t && split-file %s %t
-# RUN: mkdir -p %t/build
-# RUN: chmod +x %t/failing-clang %t/one-failing-clang
-
-# RUN: cd %t
-# RUN: not %clang-ssaf-orchestrator-make \
-# RUN:     --extract-summaries=PointerFlow \
-# RUN:     --ssaf-clang=%t/failing-clang \
-# RUN:     -o %t/out -- make 2>&1 \
-# RUN:   | FileCheck %s --check-prefix=FAILED
-# FAILED: no summaries
-
-# RUN: ls %t/build/a.o %t/build/b.o %t/build/prg
-# RUN: grep 'stub refuses' %t/out/failure-logs%t/build/a.o.extract.log
-
-# RUN: ls %t/out/ssaf-artifacts%t/build && not ls %t/out/ssaf-artifacts%t/build/a.o.summary.json
-
-# RUN: env BINARY_CLANG=%ssaf-orchestrator-make-clang \
-# RUN:     not %clang-ssaf-orchestrator-make \
-# RUN:     --extract-summaries=PointerFlow \
-# RUN:     --ssaf-clang=%t/one-failing-clang \
-# RUN:     -o %t/out2 -- make 2>&1 \
-# RUN:   | FileCheck %s --check-prefix=PARTIAL
-# PARTIAL: 1 SSAF step(s) failed; see the log files under {{[^ ]*}}/out2
-
-# RUN: ls %t/out2/ssaf-artifacts%t/build | FileCheck %s --check-prefix=PARTIAL-TU \
-# RUN:   --implicit-check-not={{a\.o\.summary\.json}}
-# PARTIAL-TU: {{b\.o\.summary\.json}}
-# RUN: ls %t/out2/ssaf-artifacts%t/build/prg.summary.json
-
-# RUN: env BINARY_CLANG=%ssaf-orchestrator-make-clang \
-# RUN:     %clang-ssaf-orchestrator-make -k \
-# RUN:     --extract-summaries=PointerFlow \
-# RUN:     --ssaf-clang=%t/one-failing-clang \
-# RUN:     -o %t/out3 -- make 2>&1 \
-# RUN:   | FileCheck %s --check-prefix=KEPT-GOING
-# KEPT-GOING: 1 SSAF step(s) failed
-
-#--- Makefile
-CXX = clang++
-all: build/prg
-build/%.o: src/%.cpp
-	$(CXX) -c -o $@ $<
-build/prg: build/a.o build/b.o
-	$(CXX) -o $@ build/a.o build/b.o
-
-#--- src/a.cpp
-int b();
-int main() { return b(); }
-
-#--- src/b.cpp
-int b() { return 0; }
-
-#--- failing-clang
-#!/bin/sh
-for arg in "$@"; do
-  case "$arg" in
-    --ssaf-tu-summary-file=*)
-      file="${arg#*=}"
-      mkdir -p "$(dirname "$file")"
-      echo '{}' > "$file"
-      ;;
-  esac
-done
-echo "stub refuses to extract" >&2
-exit 1
-
-#--- one-failing-clang
-#!/bin/sh
-"$BINARY_CLANG" "$@" || exit $?
-for arg in "$@"; do
-  case "$arg" in
-    *a.o.summary.json) echo "stub refuses to extract" >&2; exit 1 ;;
-  esac
-done
-exit 0
diff --git a/clang/test/Analysis/Scalable/ssaf-orchestrator-make/help.test b/clang/test/Analysis/Scalable/ssaf-orchestrator-make/help.test
deleted file mode 100644
index 7796cbc785840..0000000000000
--- a/clang/test/Analysis/Scalable/ssaf-orchestrator-make/help.test
+++ /dev/null
@@ -1,27 +0,0 @@
-
-# RUN: %clang-ssaf-orchestrator-make --help | FileCheck %s
-
-# CHECK: usage: clang-ssaf-orchestrator-make [options] [--] <build command>
-# CHECK: --version
-# CHECK: --output-dir
-# CHECK: --extract-summaries
-# CHECK: --ssaf-clang
-# CHECK: --analysis
-
-# RUN: %clang-ssaf-orchestrator-make --help | FileCheck %s --check-prefix=SSAF
-# SSAF: --ssaf-linker
-# SSAF: --ssaf-analyzer
-# SSAF: --ssaf-extra-clang-arg
-# SSAF: --keep-going
-# SSAF: --verbose
-
-# RUN: %clang-ssaf-orchestrator-make --version | FileCheck %s --check-prefix=VERSION
-# VERSION: clang-ssaf-orchestrator-make {{[0-9]+\.[0-9]+\.[0-9]+}}
-
-# The tool imports its own package, whatever else of that name PYTHONPATH holds,
-# so it and its shims are always the same code.
-# RUN: rm -rf %t && mkdir -p %t/clang_ssaf_orchestrator_make
-# RUN: echo 'raise SystemExit("a decoy was imported")' \
-# RUN:   > %t/clang_ssaf_orchestrator_make/__init__.py
-# RUN: env PYTHONPATH=%t %clang-ssaf-orchestrator-make --version \
-# RUN:   | FileCheck %s --check-prefix=VERSION
diff --git a/clang/test/Analysis/Scalable/ssaf-orchestrator-make/incremental-tree.test b/clang/test/Analysis/Scalable/ssaf-orchestrator-make/incremental-tree.test
deleted file mode 100644
index 6129bf9ce6b52..0000000000000
--- a/clang/test/Analysis/Scalable/ssaf-orchestrator-make/incremental-tree.test
+++ /dev/null
@@ -1,58 +0,0 @@
-
-# REQUIRES: ssaf-orchestrator-make-build
-# RUN: rm -rf %t && split-file %s %t
-# RUN: mkdir -p %t/build
-
-# RUN: make -C %t CXX=%ssaf-orchestrator-make-clang
-# RUN: ls %t/build/a.o %t/build/b.o %t/build/prg
-
-# RUN: cd %t
-# RUN: %clang-ssaf-orchestrator-make \
-# RUN:     --extract-summaries=PointerFlow \
-# RUN:     --ssaf-clang=%ssaf-orchestrator-make-clang \
-# RUN:     -o %t/out -- make \
-# RUN:   | FileCheck %s --check-prefix=STDOUT
-
-# STDOUT: summaries: 3
-# RUN: ls %t/out/ssaf-artifacts%t/build/a.o.summary.json %t/out/ssaf-artifacts%t/build/b.o.summary.json
-
-# RUN: %clang-ssaf-orchestrator-make \
-# RUN:     --extract-summaries=PointerFlow \
-# RUN:     --ssaf-clang=%ssaf-orchestrator-make-clang \
-# RUN:     -o %t/out -- make other \
-# RUN:   | FileCheck %s --check-prefix=SECOND
-# SECOND: summaries: 2
-# SECOND: link-unit: {{[^ ]*}}/build/other
-
-# RUN: ls %t/out/build-graph%t/build/other.buildstep.json
-# RUN: not ls %t/out/build-graph%t/build/prg.buildstep.json
-# RUN: not ls %t/out/ssaf-artifacts%t/build/a.o.summary.json
-
-#--- Makefile
-CXX = clang++
-all: build/prg
-other: build/other
-build/%.o: src/%.cpp
-	$(CXX) -c -o $@ $<
-build/prg: build/a.o build/b.o
-	$(CXX) -o $@ build/a.o build/b.o
-build/other: build/c.o
-	$(CXX) -o $@ build/c.o
-
-#--- src/a.cpp
-int total(int *p, int n) {
-  int t = 0;
-  for (int i = 0; i < n; ++i)
-    t += p[i];
-  return t;
-}
-
-#--- src/b.cpp
-int total(int *p, int n);
-int main() {
-  int values[2] = {1, 2};
-  return total(values, 2);
-}
-
-#--- src/c.cpp
-int main() { return 0; }
diff --git a/clang/test/Analysis/Scalable/ssaf-orchestrator-make/interposition.test b/clang/test/Analysis/Scalable/ssaf-orchestrator-make/interposition.test
deleted file mode 100644
index d6939670694ab..0000000000000
--- a/clang/test/Analysis/Scalable/ssaf-orchestrator-make/interposition.test
+++ /dev/null
@@ -1,88 +0,0 @@
-
-# REQUIRES: ssaf-orchestrator-make-build
-# RUN: rm -rf %t && split-file %s %t
-# RUN: mkdir -p %t/build
-# RUN: chmod +x %t/bin/c++ %t/fake-clang %t/fake-linker
-
-# RUN: cd %t
-# RUN: env BINARY_CXX=%ssaf-orchestrator-make-clang \
-# RUN:     PATH="%t/bin:%ssaf-orchestrator-make-env-path" \
-# RUN:     %clang-ssaf-orchestrator-make \
-# RUN:     --extract-summaries=PointerFlow \
-# RUN:     --ssaf-clang=%t/fake-clang \
-# RUN:     --ssaf-linker=%t/fake-linker \
-# RUN:     --ssaf-extra-clang-arg=-DFROM_EXTRA \
-# RUN:     -o %t/out -- make
-
-# RUN: FileCheck %s --check-prefix=BINARY --input-file=%t/bin/binary.log \
-# RUN:   --implicit-check-not=--ssaf- --implicit-check-not=FROM_EXTRA
-# BINARY: -Wall -c -o build/a.o src/a.cpp
-# BINARY-NEXT: SSAF_CONFIG=unset
-
-# RUN: FileCheck %s --check-prefix=SSAF --input-file=%t/ssaf.log
-# SSAF: -cc1
-# SSAF-SAME: -triple
-# SSAF-SAME: -x c++
-# SSAF-SAME: --ssaf-extract-summaries=PointerFlow
-# SSAF-SAME: --ssaf-compilation-unit-id={{[^ ]*}}/build/a.o
-# SSAF-SAME: --ssaf-tu-summary-file={{[^ ]*}}/out/ssaf-artifacts{{[^ ]*}}/build/a.o.summary.json
-# SSAF-SAME: -DFROM_EXTRA
-
-# RUN: FileCheck %s --check-prefix=SAME-JOB --input-file=%t/ssaf.log
-# SAME-JOB: -emit-obj
-# SAME-JOB-SAME: -o build/a.o
-
-# RUN: FileCheck %s --check-prefix=LINK --input-file=%t/link.log
-# LINK: {{[^ ]*}}/out/ssaf-artifacts{{[^ ]*}}/build/a.o.summary.json -o {{[^ ]*}}/out/ssaf-artifacts{{[^ ]*}}/build/prg.summary.json
-
-#--- Makefile
-CXX = c++
-all: build/prg
-build/a.o: src/a.cpp
-	$(CXX) -Wall -c -o $@ $<
-build/prg: build/a.o
-	$(CXX) -o $@ build/a.o
-
-#--- src/a.cpp
-int main() { return 0; }
-
-#--- bin/c++
-#!/bin/sh
-dir=$(cd "$(dirname "$0")" && pwd)
-for arg in "$@"; do
-  if [ "$arg" = "-###" ]; then exec "$BINARY_CXX" "$@"; fi
-done
-echo "$@" >> "$dir/binary.log"
-echo "SSAF_CONFIG=${SSAF_CONFIG:-unset}" >> "$dir/binary.log"
-exec "$BINARY_CXX" "$@"
-
-#--- fake-clang
-#!/bin/sh
-dir=$(cd "$(dirname "$0")" && pwd)
-echo "$@" >> "$dir/ssaf.log"
-for arg in "$@"; do
-  case "$arg" in
-    --ssaf-tu-summary-file=*)
-      file="${arg#*=}"
-      mkdir -p "$(dirname "$file")"
-      echo '{}' > "$file"
-      ;;
-  esac
-done
-exit 0
-
-#--- fake-linker
-#!/bin/sh
-dir=$(cd "$(dirname "$0")" && pwd)
-echo "$@" >> "$dir/link.log"
-prev=""
-for arg in "$@"; do
-  if [ "$prev" = "-o" ]; then
-    mkdir -p "$(dirname "$arg")"
-    name=$(basename "$arg" .json)
-    printf '{"type": "LUSummary", "lu_namespace": [{"kind": "LinkUnit", ' > "$arg"
-    printf '"name": "%s"}]}\n' "$name" >> "$arg"
-  fi
-  prev="$arg"
-done
-exit 0
diff --git a/clang/test/Analysis/Scalable/ssaf-orchestrator-make/link-driver.test b/clang/test/Analysis/Scalable/ssaf-orchestrator-make/link-driver.test
deleted file mode 100644
index 41bba34ad44be..0000000000000
--- a/clang/test/Analysis/Scalable/ssaf-orchestrator-make/link-driver.test
+++ /dev/null
@@ -1,30 +0,0 @@
-
-# REQUIRES: ssaf-orchestrator-make-build
-# RUN: rm -rf %t && split-file %s %t
-# RUN: mkdir -p %t/build
-
-# RUN: cd %t
-# RUN: %clang-ssaf-orchestrator-make \
-# RUN:     --extract-summaries=PointerFlow \
-# RUN:     --ssaf-clang=%ssaf-orchestrator-make-clang \
-# RUN:     -o %t/out -- make \
-# RUN:   | FileCheck %s --check-prefix=STDOUT
-# STDOUT: summaries: 2
-# STDOUT: link-unit: {{[^ ]*}}/build/prg
-
-# RUN: ls %t/build/prg
-# RUN: cat %t/out/ssaf-artifacts%t/build/prg.summary.json | FileCheck %s --check-prefix=LU
-# LU: "kind": "LinkUnit"
-
-#--- Makefile
-CXX = clang++
-LD = $(CXX)
-LDFLAGS = -stdlib=libc++
-all: build/prg
-build/a.o: src/a.cpp
-	$(CXX) -c -o $@ $<
-build/prg: build/a.o
-	$(LD) $(LDFLAGS) -o $@ build/a.o
-
-#--- src/a.cpp
-int main() { return 0; }
diff --git a/clang/test/Analysis/Scalable/ssaf-orchestrator-make/link-unit-selection.test b/clang/test/Analysis/Scalable/ssaf-orchestrator-make/link-unit-selection.test
deleted file mode 100644
index 735ea6b718566..0000000000000
--- a/clang/test/Analysis/Scalable/ssaf-orchestrator-make/link-unit-selection.test
+++ /dev/null
@@ -1,56 +0,0 @@
-
-# REQUIRES: ssaf-orchestrator-make-build
-# RUN: rm -rf %t && split-file %s %t
-# RUN: mkdir -p %t/two/build %t/none/build
-
-# RUN: cd %t/two
-# RUN: not %clang-ssaf-orchestrator-make \
-# RUN:     --extract-summaries=PointerFlow \
-# RUN:     --ssaf-clang=%ssaf-orchestrator-make-clang \
-# RUN:     -o %t/two/out -- make 2>&1 \
-# RUN:   | FileCheck %s --check-prefix=AMBIGUOUS
-# AMBIGUOUS: produced 2 unconsumed outputs and none of them consumes the others
-# AMBIGUOUS-SAME: {{[^ ]*}}/build/one
-# AMBIGUOUS-SAME: {{[^ ]*}}/build/two
-# AMBIGUOUS-SAME: Build one of them on its own
-
-# RUN: %clang-ssaf-orchestrator-make \
-# RUN:     --extract-summaries=PointerFlow \
-# RUN:     --ssaf-clang=%ssaf-orchestrator-make-clang \
-# RUN:     -o %t/two/out -- make build/two \
-# RUN:   | FileCheck %s --check-prefix=PICKED
-# PICKED: summaries: 2
-# PICKED: link-unit: {{[^ ]*}}/build/two
-
-# RUN: cd %t/none
-# RUN: not %clang-ssaf-orchestrator-make \
-# RUN:     --extract-summaries=PointerFlow \
-# RUN:     --ssaf-clang=%ssaf-orchestrator-make-clang \
-# RUN:     -o %t/none/out -- make 2>&1 \
-# RUN:   | FileCheck %s --check-prefix=NO-LINK
-# NO-LINK: produced no link unit
-
-#--- two/Makefile
-CXX = clang++
-all: build/one build/two
-build/%.o: src/%.cpp
-	$(CXX) -c -o $@ $<
-build/one: build/one.o
-	$(CXX) -o $@ $<
-build/two: build/two.o
-	$(CXX) -o $@ $<
-
-#--- two/src/one.cpp
-int main() { return 0; }
-
-#--- two/src/two.cpp
-int main() { return 1; }
-
-#--- none/Makefile
-CXX = clang++
-all: build/only.o
-build/%.o: src/%.cpp
-	$(CXX) -c -o $@ $<
-
-#--- none/src/only.cpp
-int only(int *p) { return p[0]; }
diff --git a/clang/test/Analysis/Scalable/ssaf-orchestrator-make/lit.local.cfg b/clang/test/Analysis/Scalable/ssaf-orchestrator-make/lit.local.cfg
deleted file mode 100644
index 515a84e0831e8..0000000000000
--- a/clang/test/Analysis/Scalable/ssaf-orchestrator-make/lit.local.cfg
+++ /dev/null
@@ -1,62 +0,0 @@
-# -*- Python -*-
-
-import lit.util
-import os
-import platform
-
-if platform.system() != "Windows" and lit.util.which("make"):
-    config.available_features.add("ssaf-orchestrator-make-build")
-
-config.substitutions.append(
-    (
-        "%clang-ssaf-orchestrator-make",
-        '"%s" "%s"'
-        % (
-            config.python_executable,
-            os.path.join(config.llvm_tools_dir, "clang-ssaf-orchestrator-make"),
-        ),
-    )
-)
-
-config.substitutions.append(
-    ("%ssaf-orchestrator-make-python", '"%s"' % config.python_executable)
-)
-
-config.substitutions.append(
-    (
-        "%ssaf-orchestrator-make-libs",
-        os.path.join(os.path.dirname(config.llvm_tools_dir), "lib"),
-    )
-)
-
-config.substitutions.append(
-    (
-        "%ssaf-orchestrator-make-shims",
-        os.path.join(
-            os.path.dirname(config.llvm_tools_dir),
-            "libexec",
-            "ssaf-orchestrator-shims",
-        ),
-    )
-)
-
-if "SDKROOT" in config.environment:
-    config.available_features.add("ssaf-orchestrator-make-sdkroot")
-
-config.substitutions.append(
-    (
-        "%ssaf-orchestrator-make-src",
-        os.path.join(config.clang_src_dir, "tools", "clang-ssaf-orchestrator-make"),
-    )
-)
-
-config.substitutions.append(
-    ("%ssaf-orchestrator-make-env-path", config.environment["PATH"])
-)
-
-config.substitutions.append(
-    (
-        "%ssaf-orchestrator-make-clang",
-        config.clang if config.have_llvm_driver else os.path.realpath(config.clang),
-    )
-)
diff --git a/clang/test/Analysis/Scalable/ssaf-orchestrator-make/path-interposition.test b/clang/test/Analysis/Scalable/ssaf-orchestrator-make/path-interposition.test
deleted file mode 100644
index 49a5bf2238492..0000000000000
--- a/clang/test/Analysis/Scalable/ssaf-orchestrator-make/path-interposition.test
+++ /dev/null
@@ -1,42 +0,0 @@
-
-# REQUIRES: ssaf-orchestrator-make-build
-# RUN: rm -rf %t && split-file %s %t
-# RUN: mkdir -p %t/build
-
-# RUN: cd %t
-# RUN: %clang-ssaf-orchestrator-make \
-# RUN:     --extract-summaries=PointerFlow \
-# RUN:     --ssaf-clang=%ssaf-orchestrator-make-clang \
-# RUN:     -o %t/out -- make \
-# RUN:   | FileCheck %s --check-prefix=KEPT
-# KEPT: summaries: 2
-# KEPT: link-unit: {{[^ ]*}}/build/prg
-
-# RUN: ls %t/build/a.o %t/build/prg
-# RUN: cat %t/out/ssaf-artifacts%t/build/a.o.summary.json | FileCheck %s --check-prefix=CU
-# CU: "name": "{{[^ ]*}}/build/a.o"
-
-# Under -v every step says what it ran, on stderr so the result lines stay
-# machine-readable.
-# RUN: %clang-ssaf-orchestrator-make -v \
-# RUN:     --extract-summaries=PointerFlow \
-# RUN:     --ssaf-clang=%ssaf-orchestrator-make-clang \
-# RUN:     -o %t/out2 -- make 2>&1 >/dev/null \
-# RUN:   | FileCheck %s --check-prefix=NOTES
-# NOTES-DAG: note: make -B
-# NOTES-DAG: note: binary: {{.*}}clang++
-# NOTES-DAG: note: ssaf: {{.*}}--ssaf-shim-skip-binary-tool-invocation
-
-#--- Makefile
-CXX = clang++ -DFROM_MAKEFILE=1
-all: build/prg
-build/a.o: src/a.cpp
-	$(CXX) -c -o $@ $<
-build/prg: build/a.o
-	$(CXX) -o $@ build/a.o
-
-#--- src/a.cpp
-#ifndef FROM_MAKEFILE
-#error "the Makefile's own CXX flags were lost"
-#endif
-int main() { return 0; }
diff --git a/clang/test/Analysis/Scalable/ssaf-orchestrator-make/recursive-make.test b/clang/test/Analysis/Scalable/ssaf-orchestrator-make/recursive-make.test
deleted file mode 100644
index 770dd5242f059..0000000000000
--- a/clang/test/Analysis/Scalable/ssaf-orchestrator-make/recursive-make.test
+++ /dev/null
@@ -1,61 +0,0 @@
-
-# REQUIRES: ssaf-orchestrator-make-build
-# RUN: rm -rf %t && split-file %s %t
-# RUN: mkdir -p %t/build %t/sub/build
-
-# RUN: cd %t
-# RUN: %clang-ssaf-orchestrator-make \
-# RUN:     --extract-summaries=PointerFlow \
-# RUN:     --ssaf-clang=%ssaf-orchestrator-make-clang \
-# RUN:     -o %t/out -- make \
-# RUN:   | FileCheck %s --check-prefix=STDOUT
-
-# STDOUT: summaries: 3
-# STDOUT: link-unit: {{[^ ]*}}/build/prg
-
-# RUN: ls %t/out/ssaf-artifacts%t/build/main.o.summary.json %t/out/ssaf-artifacts%t/sub/build/s.o.summary.json
-# RUN: cat %t/out/ssaf-artifacts%t/sub/build/s.o.summary.json \
-# RUN:   | FileCheck %s --check-prefix=SUB-CU
-# SUB-CU: "name": "{{[^ ]*}}/sub/build/s.o"
-
-# RUN: cat %t/out/build-graph%t/build/prg.buildstep.json \
-# RUN:   | FileCheck %s --check-prefix=UNIT
-# UNIT-DAG: {{[^ ]*}}/build/main.o
-# UNIT-DAG: {{[^ ]*}}/sub/build/s.o
-
-# The default output directory is relative, and a sub-make runs the shims from
-# a different directory than the one it was resolved against.
-# RUN: %clang-ssaf-orchestrator-make \
-# RUN:     --extract-summaries=PointerFlow \
-# RUN:     --ssaf-clang=%ssaf-orchestrator-make-clang \
-# RUN:     -- make \
-# RUN:   | FileCheck %s --check-prefix=DEFAULT-OUT
-# DEFAULT-OUT: output-dir: {{.*}}/ssaf-output
-# RUN: ls %t/ssaf-output/ssaf-artifacts%t/build/main.o.summary.json \
-# RUN:      %t/ssaf-output/ssaf-artifacts%t/sub/build/s.o.summary.json
-
-#--- Makefile
-CXX = clang++
-all: build/prg
-build/main.o: src/main.cpp
-	$(CXX) -c -o $@ $<
-sub/build/s.o:
-	$(MAKE) -C sub
-build/prg: build/main.o sub/build/s.o
-	$(CXX) -o $@ build/main.o sub/build/s.o
-
-#--- src/main.cpp
-int sub(int *p);
-int main() {
-  int values[1] = {1};
-  return sub(values);
-}
-
-#--- sub/Makefile
-CXX = clang++
-all: build/s.o
-build/s.o: src/s.cpp
-	$(CXX) -c -o $@ $<
-
-#--- sub/src/s.cpp
-int sub(int *p) { return p[0]; }
diff --git a/clang/test/Analysis/Scalable/ssaf-orchestrator-make/same-basename-objects.test b/clang/test/Analysis/Scalable/ssaf-orchestrator-make/same-basename-objects.test
deleted file mode 100644
index 95dc087613bc2..0000000000000
--- a/clang/test/Analysis/Scalable/ssaf-orchestrator-make/same-basename-objects.test
+++ /dev/null
@@ -1,61 +0,0 @@
-
-# REQUIRES: ssaf-orchestrator-make-build
-# RUN: rm -rf %t && split-file %s %t
-# RUN: mkdir -p %t/build/first %t/build/second
-
-# RUN: cd %t
-# RUN: %clang-ssaf-orchestrator-make \
-# RUN:     --extract-summaries=PointerFlow \
-# RUN:     --ssaf-clang=%ssaf-orchestrator-make-clang \
-# RUN:     -o %t/out -- make \
-# RUN:   | FileCheck %s --check-prefix=STDOUT
-
-# STDOUT: summaries: 4
-# RUN: ls %t/out/ssaf-artifacts%t/build/first/parser.o.summary.json %t/out/ssaf-artifacts%t/build/second/parser.o.summary.json
-
-# RUN: cat %t/out/ssaf-artifacts%t/build/first/parser.o.summary.json | FileCheck %s --check-prefix=FIRST
-# FIRST: "name": "{{[^ ]*}}/build/first/parser.o"
-# RUN: cat %t/out/ssaf-artifacts%t/build/second/parser.o.summary.json | FileCheck %s --check-prefix=SECOND
-# SECOND: "name": "{{[^ ]*}}/build/second/parser.o"
-
-# RUN: cat %t/out/build-graph%t/build/prg.buildstep.json \
-# RUN:   | FileCheck %s --check-prefix=UNIT
-# UNIT-DAG: {{[^ ]*}}/build/first/parser.o
-# UNIT-DAG: {{[^ ]*}}/build/second/parser.o
-
-#--- Makefile
-CXX = clang++
-OBJS = build/main.o build/first/parser.o build/second/parser.o
-all: build/prg
-build/main.o: src/main.cpp
-	$(CXX) -c -o $@ $<
-build/first/parser.o: src/first/parser.cpp
-	$(CXX) -c -o $@ $<
-build/second/parser.o: src/second/parser.cpp
-	$(CXX) -c -o $@ $<
-build/prg: $(OBJS)
-	$(CXX) -o $@ $(OBJS)
-
-#--- src/first/parser.cpp
-int first_total(int *p, int n) {
-  int t = 0;
-  for (int i = 0; i < n; ++i)
-    t += p[i];
-  return t;
-}
-
-#--- src/second/parser.cpp
-int second_total(int *p, int n) {
-  int t = 0;
-  for (int i = 0; i < n; ++i)
-    t += p[i] * 2;
-  return t;
-}
-
-#--- src/main.cpp
-int first_total(int *p, int n);
-int second_total(int *p, int n);
-int main() {
-  int values[2] = {1, 2};
-  return first_total(values, 2) + second_total(values, 2);
-}
diff --git a/clang/test/Analysis/Scalable/ssaf-orchestrator-make/shim-outside-a-run.test b/clang/test/Analysis/Scalable/ssaf-orchestrator-make/shim-outside-a-run.test
deleted file mode 100644
index 5ce38a94fab3c..0000000000000
--- a/clang/test/Analysis/Scalable/ssaf-orchestrator-make/shim-outside-a-run.test
+++ /dev/null
@@ -1,17 +0,0 @@
-
-# REQUIRES: ssaf-orchestrator-make-build
-# RUN: rm -rf %t && mkdir -p %t
-# RUN: ln -s %ssaf-orchestrator-make-shims/shim %t/ld
-
-# A link left behind by an interrupted run still knows which tool it stands
-# in for, and refuses to stand in for it.
-# RUN: not env -u SSAF_CONFIG %t/ld -o %t/prg 2>&1 | FileCheck %s
-# CHECK: error: missing configuration file
-# CHECK-NEXT: SSAF_CONFIG is not set
-
-# Reached under a name no link carries -- its own, say -- it says so rather
-# than guessing.
-# RUN: not env -u SSAF_CONFIG %ssaf-orchestrator-make-shims/shim 2>&1 \
-# RUN:   | FileCheck %s --check-prefix=NOT-A-LINK
-# NOT-A-LINK: error: no shim stands in for shim
-# NOT-A-LINK-NEXT: reached through the links an orchestrator run creates
diff --git a/clang/test/Analysis/Scalable/ssaf-orchestrator-make/unittests.test b/clang/test/Analysis/Scalable/ssaf-orchestrator-make/unittests.test
deleted file mode 100644
index ce50b1cf96807..0000000000000
--- a/clang/test/Analysis/Scalable/ssaf-orchestrator-make/unittests.test
+++ /dev/null
@@ -1,8 +0,0 @@
-
-# RUN: env PYTHONDONTWRITEBYTECODE=1 PYTHONPATH=%ssaf-orchestrator-make-libs \
-# RUN:     %ssaf-orchestrator-make-python -m unittest discover \
-# RUN:   -s %ssaf-orchestrator-make-src/tests -t %ssaf-orchestrator-make-src \
-# RUN:   > %t.log 2>&1
-# RUN: FileCheck %s --input-file=%t.log --implicit-check-not=FAILED
-
-# CHECK: {{^OK}}
diff --git a/clang/test/Analysis/Scalable/ssaf-orchestrator-make/unreachable-compiler.test b/clang/test/Analysis/Scalable/ssaf-orchestrator-make/unreachable-compiler.test
deleted file mode 100644
index 883d766763c3f..0000000000000
--- a/clang/test/Analysis/Scalable/ssaf-orchestrator-make/unreachable-compiler.test
+++ /dev/null
@@ -1,27 +0,0 @@
-
-# REQUIRES: ssaf-orchestrator-make-build
-# RUN: rm -rf %t && split-file %s %t
-# RUN: mkdir -p %t/build
-# RUN: sed -e "s|@CXX@|%ssaf-orchestrator-make-clang|g" %t/Makefile.in > %t/Makefile
-
-# RUN: cd %t
-# RUN: not %clang-ssaf-orchestrator-make \
-# RUN:     --extract-summaries=PointerFlow \
-# RUN:     --ssaf-clang=%ssaf-orchestrator-make-clang \
-# RUN:     -o %t/out -- make 2>&1 \
-# RUN:   | FileCheck %s --check-prefix=MISSED
-# MISSED: no summaries
-
-# RUN: ls %t/build/a.o %t/build/prg
-# RUN: not ls %t/out/ssaf-artifacts%t/build/*.summary.json
-
-#--- Makefile.in
-CXX = @CXX@
-all: build/prg
-build/a.o: src/a.cpp
-	$(CXX) -c -o $@ $<
-build/prg: build/a.o
-	$(CXX) -o $@ build/a.o
-
-#--- src/a.cpp
-int main() { return 0; }
diff --git a/clang/test/Analysis/Scalable/ssaf-orchestrator-make/whole-program-analysis.test b/clang/test/Analysis/Scalable/ssaf-orchestrator-make/whole-program-analysis.test
deleted file mode 100644
index 28f6c716d0d41..0000000000000
--- a/clang/test/Analysis/Scalable/ssaf-orchestrator-make/whole-program-analysis.test
+++ /dev/null
@@ -1,59 +0,0 @@
-
-# REQUIRES: ssaf-orchestrator-make-build
-# RUN: rm -rf %t && split-file %s %t
-# RUN: mkdir -p %t/build
-# RUN: chmod +x %t/failing-analyzer
-
-# RUN: cd %t
-# RUN: %clang-ssaf-orchestrator-make \
-# RUN:     --extract-summaries=PointerFlow,UnsafeBufferUsage \
-# RUN:     --analysis=UnsafeBufferReachableAnalysisResult \
-# RUN:     --ssaf-clang=%ssaf-orchestrator-make-clang \
-# RUN:     -o %t/out -- make \
-# RUN:   | FileCheck %s --check-prefix=STDOUT
-
-# STDOUT: summaries: 3
-# STDOUT: link-unit: {{[^ ]*}}/build/prg
-# STDOUT: link-unit-summary: {{[^ ]*}}/out/ssaf-artifacts{{[^ ]*}}/build/prg.summary.json
-# STDOUT: analysis-result: {{[^ ]*}}/out/wpa.json
-# STDOUT: output-dir: {{[^ ]*}}/out
-
-# RUN: FileCheck %s --check-prefix=WPA --input-file=%t/out/wpa.json
-# WPA: "type": "WPASuite"
-
-# A failing analysis fails the run, which says how the analyzer exited.
-# RUN: not %clang-ssaf-orchestrator-make \
-# RUN:     --extract-summaries=PointerFlow \
-# RUN:     --analysis=UnsafeBufferReachableAnalysisResult \
-# RUN:     --ssaf-clang=%ssaf-orchestrator-make-clang \
-# RUN:     --ssaf-analyzer=%t/failing-analyzer \
-# RUN:     -o %t/out2 -- make 2>&1 \
-# RUN:   | FileCheck %s --check-prefix=FAILED
-# FAILED: error: whole-program analysis failed (exit 3)
-
-#--- Makefile
-CXX = clang++
-all: build/prg
-build/%.o: src/%.cpp
-	$(CXX) -c -o $@ $<
-build/prg: build/main.o build/parse.o
-	$(CXX) -o $@ build/main.o build/parse.o
-
-#--- src/parse.cpp
-int total(int *data, int n) {
-  int t = 0;
-  for (int i = 0; i < n; ++i)
-    t += data[i];
-  return t;
-}
-
-#--- src/main.cpp
-int total(int *data, int n);
-int main() {
-  int values[4] = {1, 2, 3, 4};
-  return total(values, 4);
-}
-
-#--- failing-analyzer
-#!/bin/sh
-exit 3
diff --git a/clang/test/CMakeLists.txt b/clang/test/CMakeLists.txt
index 3ef3cf764d215..4063f58ad0e08 100644
--- a/clang/test/CMakeLists.txt
+++ b/clang/test/CMakeLists.txt
@@ -107,7 +107,6 @@ list(APPEND CLANG_TEST_DEPS
   clang-ssaf-analyzer
   clang-ssaf-format
   clang-ssaf-linker
-  clang-ssaf-orchestrator-make
   clang-ssaf-src-edit-merge
   clang-sycl-linker
   diagtool
diff --git a/clang/tools/CMakeLists.txt b/clang/tools/CMakeLists.txt
index 535c3071700f2..855af780d4e02 100644
--- a/clang/tools/CMakeLists.txt
+++ b/clang/tools/CMakeLists.txt
@@ -18,7 +18,6 @@ add_clang_subdirectory(clang-scan-deps)
 add_clang_subdirectory(clang-ssaf-analyzer)
 add_clang_subdirectory(clang-ssaf-format)
 add_clang_subdirectory(clang-ssaf-linker)
-add_clang_subdirectory(clang-ssaf-orchestrator-make)
 add_clang_subdirectory(clang-ssaf-src-edit-merge)
 add_clang_subdirectory(clang-sycl-linker)
 add_clang_subdirectory(clang-installapi)
diff --git a/clang/tools/clang-ssaf-orchestrator-make/CMakeLists.txt b/clang/tools/clang-ssaf-orchestrator-make/CMakeLists.txt
deleted file mode 100644
index a29c137eb30fc..0000000000000
--- a/clang/tools/clang-ssaf-orchestrator-make/CMakeLists.txt
+++ /dev/null
@@ -1,94 +0,0 @@
-set(SsafOrchestratorMakeLib
-    "__init__.py"
-    "build_graph.py"
-    "config.py"
-    "config_orchestrator.py"
-    "config_shims.py"
-    "failure_logs.py"
-    "interposition.py"
-    "logging_diagnostics.py"
-    "options.py"
-    "orchestrator.py"
-    "ssaf_artifact_repository.py"
-    "utils.py")
-
-set(SsafOrchestratorMakeShimLib
-    "__init__.py"
-    "clang.py"
-    "commands.py"
-    "driver_jobs.py"
-    "ld.py"
-    "run.py"
-    "shim.py")
-
-set(SsafOrchestratorMakePackageDir "lib/clang_ssaf_orchestrator_make")
-set(SsafOrchestratorMakeShimDir "libexec/ssaf-orchestrator-shims")
-
-# Copy one file into the build tree and install it, recording the copy so the
-# tool's target can depend on it. kind is FILES or PROGRAMS.
-function(add_ssaf_orchestrator_make_file source build_dir destination kind)
-  get_filename_component(name "${source}" NAME)
-  set(copied "${CMAKE_BINARY_DIR}/${build_dir}/${name}")
-  add_custom_command(OUTPUT "${copied}"
-                     COMMAND ${CMAKE_COMMAND} -E make_directory
-                       "${CMAKE_BINARY_DIR}/${build_dir}"
-                     COMMAND ${CMAKE_COMMAND} -E copy
-                       "${CMAKE_CURRENT_SOURCE_DIR}/${source}" "${copied}"
-                     DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/${source}")
-  set(SSAF_ORCHESTRATOR_MAKE_DEPENDS
-      ${SSAF_ORCHESTRATOR_MAKE_DEPENDS} "${copied}" PARENT_SCOPE)
-  install(${kind} "${source}"
-          DESTINATION "${destination}"
-          COMPONENT clang-ssaf-orchestrator-make)
-endfunction()
-
-add_ssaf_orchestrator_make_file("bin/clang-ssaf-orchestrator-make"
-                                "bin" "${CMAKE_INSTALL_BINDIR}" PROGRAMS)
-
-foreach(lib ${SsafOrchestratorMakeLib})
-  add_ssaf_orchestrator_make_file(
-    "${SsafOrchestratorMakePackageDir}/${lib}"
-    "${SsafOrchestratorMakePackageDir}"
-    "${SsafOrchestratorMakePackageDir}" FILES)
-endforeach()
-
-# Substituted at configure time into this directory's own build area, then
-# copied like every other file, so that deleting the package from the build
-# tree leaves a rule to put it back.
-configure_file(
-  "${CMAKE_CURRENT_SOURCE_DIR}/${SsafOrchestratorMakePackageDir}/version.py.in"
-  "${CMAKE_CURRENT_BINARY_DIR}/version.py")
-set(version_py "${CMAKE_BINARY_DIR}/${SsafOrchestratorMakePackageDir}/version.py")
-add_custom_command(OUTPUT "${version_py}"
-                   COMMAND ${CMAKE_COMMAND} -E make_directory
-                     "${CMAKE_BINARY_DIR}/${SsafOrchestratorMakePackageDir}"
-                   COMMAND ${CMAKE_COMMAND} -E copy
-                     "${CMAKE_CURRENT_BINARY_DIR}/version.py" "${version_py}"
-                   DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/version.py")
-list(APPEND SSAF_ORCHESTRATOR_MAKE_DEPENDS "${version_py}")
-install(FILES "${CMAKE_CURRENT_BINARY_DIR}/version.py"
-        DESTINATION "${SsafOrchestratorMakePackageDir}"
-        COMPONENT clang-ssaf-orchestrator-make)
-
-foreach(lib ${SsafOrchestratorMakeShimLib})
-  add_ssaf_orchestrator_make_file(
-    "${SsafOrchestratorMakePackageDir}/shims/${lib}"
-    "${SsafOrchestratorMakePackageDir}/shims"
-    "${SsafOrchestratorMakePackageDir}/shims" FILES)
-endforeach()
-
-# One program, symlinked under every name a build might spell.
-add_ssaf_orchestrator_make_file(
-  "shims/shim"
-  "${SsafOrchestratorMakeShimDir}"
-  "${CMAKE_INSTALL_LIBEXECDIR}/ssaf-orchestrator-shims" PROGRAMS)
-
-add_custom_target(clang-ssaf-orchestrator-make ALL
-                  DEPENDS ${SSAF_ORCHESTRATOR_MAKE_DEPENDS})
-set_target_properties(clang-ssaf-orchestrator-make
-                      PROPERTIES FOLDER "Clang/Tools")
-if(NOT LLVM_ENABLE_IDE)
-  add_llvm_install_targets("install-clang-ssaf-orchestrator-make"
-                           DEPENDS clang-ssaf-orchestrator-make
-                           COMPONENT clang-ssaf-orchestrator-make)
-endif()
diff --git a/clang/tools/clang-ssaf-orchestrator-make/README.md b/clang/tools/clang-ssaf-orchestrator-make/README.md
deleted file mode 100644
index 04c2337d5db90..0000000000000
--- a/clang/tools/clang-ssaf-orchestrator-make/README.md
+++ /dev/null
@@ -1,51 +0,0 @@
-# clang-ssaf-orchestrator-make
-
-Runs a Scalable Static Analysis Framework analysis over a project by riding
-along with its `make` build. Each compilation and link step the build
-performs is paired with an SSAF step that produces the corresponding summary,
-and the summaries are linked into one whole-program view.
-
-- Using it: [Make-Based Projects](
-  ../../docs/ScalableStaticAnalysis/user-docs/MakeProjects.md)
-- How the shims work: [Make Orchestrator Shims](
-  ../../docs/ScalableStaticAnalysis/developer-docs/MakeOrchestratorShims.md)
-
-## Layout
-
-| | |
-|---|---|
-| `bin/` | the entry script, installed to `bin/` |
-| `lib/clang_ssaf_orchestrator_make/` | the package, installed to `lib/` |
-| `…/shims/` | the shim bodies and their utilities |
-| `shims/` | the shim program, installed to `libexec/ssaf-orchestrator-shims/` |
-| `tests/` | the Python unit tests |
-
-The shim program is what a build reaches: at the start of a run the orchestrator
-fills `<output-dir>/shims/` with links named after the tools a build might
-spell, all pointing at it, and prepends that directory to `PATH`. It is
-symlinked under several names, so `argv[0]` is what tells it which tool it
-stands in for, and it finds the package by walking up from its own location —
-which is why it is a file beside the package rather than part of it.
-
-## Running the tests
-
-```
-PYTHONPATH=lib python3 -m unittest discover  # from this directory
-llvm-lit clang/test/Analysis/Scalable/ssaf-orchestrator-make
-```
-
-The lit suite runs the unit tests too, against the copy in the build tree, so
-`ninja check-clang` covers both. The tool is a declared dependency of
-`check-clang`.
-
-## Packaging
-
-CMake copies the Python files into the build tree and installs them under the
-`clang-ssaf-orchestrator-make` component. The component is not listed in any
-distribution cache, so a distribution build will not pick it up without being
-told to.
-
-There is no `pyproject.toml`. The entry point is installed by CMake, as it is
-for every other Python tool under `clang/tools/`, so a manifest here would
-declare an installation path that does not exist. The Python version floor is
-the monorepo's, recorded in the root `pyproject.toml`.
diff --git a/clang/tools/clang-ssaf-orchestrator-make/bin/clang-ssaf-orchestrator-make b/clang/tools/clang-ssaf-orchestrator-make/bin/clang-ssaf-orchestrator-make
deleted file mode 100755
index 92a3b272aa248..0000000000000
--- a/clang/tools/clang-ssaf-orchestrator-make/bin/clang-ssaf-orchestrator-make
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/usr/bin/env python3
-# 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
-
-import os.path
-import sys
-
-this_dir = os.path.dirname(os.path.realpath(__file__))
-sys.path.insert(0, os.path.join(os.path.dirname(this_dir), "lib"))
-
-from clang_ssaf_orchestrator_make import orchestrator
-
-if __name__ == "__main__":
-    sys.exit(orchestrator.main(sys.argv[1:]))
diff --git a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/__init__.py b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/__init__.py
deleted file mode 100644
index 01f0dae478b11..0000000000000
--- a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/__init__.py
+++ /dev/null
@@ -1,10 +0,0 @@
-# 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
-
-PROGRAM = "clang-ssaf-orchestrator-make"
-
-try:
-    from .version import VERSION
-except ImportError:
-    VERSION = "unknown (not built)"
diff --git a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/build_graph.py b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/build_graph.py
deleted file mode 100644
index 21e285a33bea2..0000000000000
--- a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/build_graph.py
+++ /dev/null
@@ -1,73 +0,0 @@
-# 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
-
-
-import os
-
-from .utils import coalesce_root_path, make_parents, read_json, write_json
-
-BUILDSTEP_RECORD_SUFFIX = ".buildstep.json"
-
-
-class BuildArtifactId:
-    __slots__ = ("abs_path",)
-
-    def __init__(self, build_artifact_path):
-        self.abs_path = os.path.realpath(build_artifact_path)
-
-    def get_path(self):
-        return self.abs_path
-
-    def __eq__(self, other):
-        return isinstance(other, BuildArtifactId) and other.abs_path == self.abs_path
-
-    def __hash__(self):
-        return hash(self.abs_path)
-
-    def __repr__(self):
-        return "BuildArtifactId(%r)" % (self.abs_path,)
-
-
-class BuildGraph:
-    def __init__(self, build_graph_dir):
-        self.build_graph_dir = os.path.abspath(build_graph_dir)
-
-    def get_buildstep_record_path(self, output_build_artifact_id):
-        return coalesce_root_path(
-            self.build_graph_dir,
-            output_build_artifact_id.get_path() + BUILDSTEP_RECORD_SUFFIX,
-        )
-
-    def was_built(self, build_artifact_id):
-        return os.path.exists(self.get_buildstep_record_path(build_artifact_id))
-
-    def record_build_step(self, output_build_artifact_id, inputs):
-        path = make_parents(self.get_buildstep_record_path(output_build_artifact_id))
-        write_json(
-            path,
-            {
-                "output": output_build_artifact_id.get_path(),
-                "inputs": [each.get_path() for each in inputs],
-            },
-        )
-        return path
-
-    def get_recorded_build_steps(self):
-        steps = {}
-        for directory, _, filenames in os.walk(self.build_graph_dir):
-            for name in sorted(filenames):
-                if not name.endswith(BUILDSTEP_RECORD_SUFFIX):
-                    continue
-                document = read_json(os.path.join(directory, name))
-                if document is None or "output" not in document:
-                    continue
-                steps[document["output"]] = list(document.get("inputs", []))
-        return steps
-
-    @staticmethod
-    def find_topmost_outputs(steps):
-        consumed = set()
-        for inputs in steps.values():
-            consumed.update(inputs)
-        return sorted(output for output in steps if output not in consumed)
diff --git a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/config.py b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/config.py
deleted file mode 100644
index 01caf368092dd..0000000000000
--- a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/config.py
+++ /dev/null
@@ -1,115 +0,0 @@
-# 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
-
-import enum
-import os
-
-SSAF_CONFIG_ENV_VAR = "SSAF_CONFIG"
-
-SHIM_LINK_DIR = "shims"
-BUILD_GRAPH_DIR = "build-graph"
-SSAF_ARTIFACT_DIR = "ssaf-artifacts"
-FAILURE_LOG_DIR = "failure-logs"
-WPA_RESULT_FILE = "wpa.json"
-OUTPUT_DIR_MARKER = ".clang-ssaf-orchestrator-make"
-
-
-def shim_link_dir(output_dir):
-    return os.path.join(output_dir, SHIM_LINK_DIR)
-
-
-def build_graph_dir(output_dir):
-    return os.path.join(output_dir, BUILD_GRAPH_DIR)
-
-
-def ssaf_artifact_dir(output_dir):
-    return os.path.join(output_dir, SSAF_ARTIFACT_DIR)
-
-
-def failure_log_dir(output_dir):
-    return os.path.join(output_dir, FAILURE_LOG_DIR)
-
-
-def wpa_result_path(output_dir):
-    return os.path.join(output_dir, WPA_RESULT_FILE)
-
-
-def output_dir_marker_path(output_dir):
-    return os.path.join(output_dir, OUTPUT_DIR_MARKER)
-
-
-SHIM_FOR_LINK_NAME = {
-    "cc": "clang",
-    "clang": "clang",
-    "c++": "clang",
-    "clang++": "clang",
-    "ld": "ld",
-}
-
-
-class SSAFPassKind(str, enum.Enum):
-    ANALYSIS = "analysis"
-
-
-class SSAFPassConfig:
-    def __init__(self, ssaf_clang=None, ssaf_extra_clang_args=()):
-        self.ssaf_clang = ssaf_clang
-        self.ssaf_extra_clang_args = list(ssaf_extra_clang_args)
-
-    @property
-    def file_name(self):
-        return "config-%s.json" % self.pass_kind.value
-
-    def to_json(self):
-        fields = dict(vars(self))
-        fields["pass_kind"] = self.pass_kind.value
-        return fields
-
-
-class SSAFAnalysisPassConfig(SSAFPassConfig):
-    pass_kind = SSAFPassKind.ANALYSIS
-
-    def __init__(
-        self,
-        ssaf_clang=None,
-        ssaf_extra_clang_args=(),
-        extractors=None,
-        ssaf_linker=None,
-        analyses=(),
-    ):
-        super().__init__(ssaf_clang, ssaf_extra_clang_args)
-        self.extractors = extractors
-        self.ssaf_linker = ssaf_linker
-        self.analyses = list(analyses)
-
-
-class SSAFWorkflowConfig:
-    def __init__(
-        self,
-        output_dir=None,
-        installed_shim_dir_path=None,
-        restored_path_env_var="",
-        verbose=False,
-        build_command=(),
-        ssaf_analyzer=None,
-        keep_going=False,
-        build_environment=None,
-    ):
-        self.output_dir = output_dir
-        self.installed_shim_dir_path = installed_shim_dir_path
-        self.restored_path_env_var = restored_path_env_var
-        self.verbose = verbose
-        self.build_command = list(build_command)
-        self.ssaf_analyzer = ssaf_analyzer
-        self.keep_going = keep_going
-        self.build_environment = dict(build_environment or {})
-
-    @classmethod
-    def written_field_names(cls):
-        return frozenset(cls().to_json())
-
-    def to_json(self):
-        fields = dict(vars(self))
-        del fields["build_environment"]
-        return fields
diff --git a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/config_orchestrator.py b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/config_orchestrator.py
deleted file mode 100644
index a9c096ba3208f..0000000000000
--- a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/config_orchestrator.py
+++ /dev/null
@@ -1,142 +0,0 @@
-# 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
-
-import os
-import shlex
-import shutil
-import sys
-
-from . import config, options
-
-
-def _resolve_ssaf_tool(
-    cl_option, default_tool_name, cl_option_value, installed_shim_dir_path, errors
-):
-    error_prefix = "%s: " % cl_option
-    words = (
-        shlex.split(cl_option_value)
-        if cl_option_value is not None
-        else [default_tool_name]
-    )
-    if not words:
-        errors.append(error_prefix + "nothing to run")
-        return None
-    if len(words) > 1:
-        errors.append(
-            error_prefix + "expected one executable, got '%s'" % cl_option_value
-        )
-        return None
-    name_or_path = words[0]
-    if os.sep in name_or_path:
-        candidate = os.path.abspath(name_or_path)
-    else:
-        candidate = shutil.which(name_or_path)
-    if not candidate:
-        errors.append(error_prefix + "%s: not found on PATH" % name_or_path)
-        return None
-    if not os.path.isfile(candidate):
-        errors.append(error_prefix + "not a file: %s" % candidate)
-        return None
-    if not os.access(candidate, os.X_OK):
-        errors.append(error_prefix + "not executable: %s" % candidate)
-        return None
-    if os.path.dirname(os.path.realpath(candidate)) == installed_shim_dir_path:
-        errors.append(
-            error_prefix + "%s is one of our own shims; an earlier run's shim links "
-            "are on PATH" % candidate
-        )
-        return None
-    return candidate
-
-
-def _may_be_cleared(output_dir):
-    try:
-        entries = os.listdir(output_dir)
-    except FileNotFoundError:
-        return True
-    except OSError:
-        return False
-    return not entries or config.OUTPUT_DIR_MARKER in entries
-
-
-def find_installed_shim_dir():
-    entry = sys.modules.get("__main__")
-    script = getattr(entry, "__file__", None) or sys.argv[0]
-    script_dir = os.path.dirname(os.path.realpath(script))
-    prefix = os.path.dirname(script_dir)
-    installed = os.path.join(prefix, "libexec", "ssaf-orchestrator-shims")
-    if os.path.isdir(installed):
-        return installed
-    return os.path.join(prefix, "shims")
-
-
-def configure(command_line_opts, env):
-    installed_shim_dir_path = find_installed_shim_dir()
-
-    project_root = os.path.realpath(os.getcwd())
-    output_dir = os.path.realpath(command_line_opts.output_dir)
-    if project_root == output_dir or project_root.startswith(output_dir + os.sep):
-        return None, options.Problem(
-            options.ENVIRONMENT_ERROR,
-            "--output-dir would contain the project, and its contents are "
-            "deleted at the start of a run: %s" % output_dir,
-        )
-    if not _may_be_cleared(output_dir):
-        return None, options.Problem(
-            options.ENVIRONMENT_ERROR,
-            "--output-dir is not empty and no earlier run made it, and its "
-            "contents are deleted at the start of a run: %s" % output_dir,
-        )
-
-    errors = []
-
-    ssaf_clang = _resolve_ssaf_tool(
-        "--ssaf-clang",
-        "clang",
-        command_line_opts.ssaf_clang,
-        installed_shim_dir_path,
-        errors,
-    )
-    ssaf_linker = _resolve_ssaf_tool(
-        "--ssaf-linker",
-        "clang-ssaf-linker",
-        command_line_opts.ssaf_linker,
-        installed_shim_dir_path,
-        errors,
-    )
-    ssaf_analyzer = (
-        _resolve_ssaf_tool(
-            "--ssaf-analyzer",
-            "clang-ssaf-analyzer",
-            command_line_opts.ssaf_analyzer,
-            installed_shim_dir_path,
-            errors,
-        )
-        if command_line_opts.analyses
-        else None
-    )
-
-    if errors:
-        return None, options.Problem(
-            options.ENVIRONMENT_ERROR, "required tools not resolvable:", errors
-        )
-
-    workflow_config = config.SSAFWorkflowConfig(
-        output_dir=output_dir,
-        installed_shim_dir_path=installed_shim_dir_path,
-        restored_path_env_var=env.get("PATH", ""),
-        verbose=command_line_opts.verbose,
-        build_command=command_line_opts.build_command,
-        ssaf_analyzer=ssaf_analyzer,
-        keep_going=command_line_opts.keep_going,
-        build_environment=env,
-    )
-    analysis_config = config.SSAFAnalysisPassConfig(
-        ssaf_clang=ssaf_clang,
-        ssaf_extra_clang_args=command_line_opts.ssaf_extra_clang_args,
-        extractors=command_line_opts.extract_summaries,
-        ssaf_linker=ssaf_linker,
-        analyses=command_line_opts.analyses,
-    )
-    return (workflow_config, analysis_config), None
diff --git a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/config_shims.py b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/config_shims.py
deleted file mode 100644
index bfed688447ceb..0000000000000
--- a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/config_shims.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# 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
-
-import json
-import os
-
-from . import config
-
-
-def from_json(written):
-    shared = config.SSAFWorkflowConfig.written_field_names()
-    workflow_config = config.SSAFWorkflowConfig(
-        **{key: value for key, value in written.items() if key in shared}
-    )
-    own = {
-        key: value
-        for key, value in written.items()
-        if key not in shared and key != "pass_kind"
-    }
-    config.SSAFPassKind(written["pass_kind"])
-    return workflow_config, config.SSAFAnalysisPassConfig(**own)
-
-
-def bootstrap_from_env(env=None):
-    env = os.environ if env is None else env
-    path = env.get(config.SSAF_CONFIG_ENV_VAR)
-    if not path:
-        return None, None
-    with open(path) as handle:
-        return from_json(json.load(handle))
diff --git a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/failure_logs.py b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/failure_logs.py
deleted file mode 100644
index fc242f39dc8fd..0000000000000
--- a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/failure_logs.py
+++ /dev/null
@@ -1,48 +0,0 @@
-# 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
-
-import enum
-import hashlib
-import os
-
-from . import config
-from .utils import coalesce_root_path, find_with_suffix
-
-FAILURE_LOG_SUFFIX = ".log"
-
-
-class SSAFFailureKind(enum.Enum):
-    EXTRACT = "extract"
-    LINK = "link"
-    FORWARD = "forward"
-    MISSING = "missing"
-    DRIVER_JOBS = "driver-jobs"
-    INTERNAL = "internal"
-
-
-def _command_hash(command):
-    joined = "\0".join(command).encode("utf-8", "surrogateescape")
-    return hashlib.sha1(joined).hexdigest()[:12]
-
-
-def get_failure_log_path(output_dir, ssaf_failure_kind, command, build_artifact_id):
-    if build_artifact_id is None:
-        name = os.path.join(os.getcwd(), _command_hash(command))
-    else:
-        name = build_artifact_id.get_path()
-    return coalesce_root_path(
-        config.failure_log_dir(output_dir),
-        "%s.%s%s" % (name, ssaf_failure_kind.value, FAILURE_LOG_SUFFIX),
-    )
-
-
-def has_failure_log_for(output_dir, build_artifact_id):
-    return any(
-        os.path.exists(get_failure_log_path(output_dir, each, None, build_artifact_id))
-        for each in SSAFFailureKind
-    )
-
-
-def count_failure_logs(output_dir):
-    return len(find_with_suffix(output_dir, FAILURE_LOG_SUFFIX))
diff --git a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/interposition.py b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/interposition.py
deleted file mode 100644
index 14c05ac751750..0000000000000
--- a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/interposition.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# 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
-
-import os
-
-from . import config
-
-SHIM_PROGRAM = "shim"
-
-
-def create_shim_links(shim_link_dir_path, installed_shim_dir_path):
-    os.makedirs(shim_link_dir_path)
-    program = os.path.join(installed_shim_dir_path, SHIM_PROGRAM)
-    if not os.access(program, os.X_OK):
-        raise OSError("shim is not executable: %s" % program)
-    for name in config.SHIM_FOR_LINK_NAME:
-        os.symlink(program, os.path.join(shim_link_dir_path, name))
-    return shim_link_dir_path
-
-
-def make_environment(serialized_config_path, shim_link_dir_path, env):
-    result = dict(env)
-    result[config.SSAF_CONFIG_ENV_VAR] = serialized_config_path
-    build_path = result.get("PATH", "")
-    result["PATH"] = (
-        os.pathsep.join([shim_link_dir_path, build_path])
-        if build_path
-        else shim_link_dir_path
-    )
-    return result
diff --git a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/logging_diagnostics.py b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/logging_diagnostics.py
deleted file mode 100644
index 771da5cb22b87..0000000000000
--- a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/logging_diagnostics.py
+++ /dev/null
@@ -1,41 +0,0 @@
-# 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
-
-import sys
-
-from . import PROGRAM
-
-
-def report_note(verbose, message):
-    if verbose:
-        sys.stderr.write("%s: note: %s\n" % (PROGRAM, message))
-
-
-def report_warning(message):
-    sys.stderr.write("%s: warning: %s\n" % (PROGRAM, message))
-
-
-def report_error(message, details=()):
-    sys.stderr.write("%s: error: %s\n" % (PROGRAM, message))
-    for detail in details:
-        sys.stderr.write("  %s\n" % detail)
-
-
-def report_info(key, value):
-    sys.stdout.write("%s: %s\n" % (key, value))
-    sys.stdout.flush()
-
-
-def report_output_dir(output_dir):
-    report_info("output-dir", output_dir)
-
-
-def report_summaries(summaries, link_unit, summary_path):
-    report_info("summaries", summaries)
-    report_info("link-unit", link_unit)
-    report_info("link-unit-summary", summary_path)
-
-
-def report_analysis_result(wpa_result_path):
-    report_info("analysis-result", wpa_result_path)
diff --git a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/options.py b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/options.py
deleted file mode 100644
index 4650432edd9ca..0000000000000
--- a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/options.py
+++ /dev/null
@@ -1,147 +0,0 @@
-# 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
-
-import argparse
-import collections
-
-from . import PROGRAM, VERSION
-
-Problem = collections.namedtuple(
-    "Problem", "exit_status message details", defaults=((),)
-)
-
-USAGE_ERROR = 2
-ENVIRONMENT_ERROR = 1
-
-
-def build_parser():
-    parser = argparse.ArgumentParser(
-        prog=PROGRAM,
-        usage="%(prog)s [options] [--] <build command>",
-        description="Run an SSAF analysis over a project as it builds. The "
-        "build is executed normally; each compilation and link step "
-        "is paired with an SSAF step that produces the corresponding summary.",
-    )
-    parser.add_argument("--version", action="version", version="%(prog)s " + VERSION)
-    parser.add_argument(
-        "-o",
-        "--output-dir",
-        metavar="<dir>",
-        default="ssaf-output",
-        help="Directory for the SSAF artifacts (default: %(default)s).",
-    )
-    parser.add_argument(
-        "--extract-summaries",
-        metavar="<name,...>",
-        required=True,
-        help="Comma-separated summary extractors to run over every "
-        "translation unit. Required.",
-    )
-    parser.add_argument(
-        "--ssaf-clang",
-        metavar="<path>",
-        default=None,
-        help="SSAF-capable clang used for the SSAF compilations "
-        "(default: clang on PATH).",
-    )
-    parser.add_argument(
-        "--analysis",
-        metavar="<name>",
-        action="append",
-        default=[],
-        dest="analyses",
-        help="Whole-program analysis to run on the link unit summary. "
-        "Repeatable. Without it the run stops after summary extraction.",
-    )
-    parser.add_argument(
-        "--ssaf-linker",
-        metavar="<path>",
-        default=None,
-        help="Path to clang-ssaf-linker (default: found on PATH).",
-    )
-    parser.add_argument(
-        "--ssaf-analyzer",
-        metavar="<path>",
-        default=None,
-        help="Path to clang-ssaf-analyzer (default: found on PATH).",
-    )
-    parser.add_argument(
-        "--ssaf-extra-clang-arg",
-        metavar="<arg>",
-        action="append",
-        default=[],
-        dest="ssaf_extra_clang_args",
-        help="Additional argument for every SSAF compilation. Repeatable.",
-    )
-    parser.add_argument(
-        "-k",
-        "--keep-going",
-        action="store_true",
-        help="Exit successfully even if some SSAF steps failed.",
-    )
-    parser.add_argument(
-        "-v",
-        "--verbose",
-        action="store_true",
-        help="Print every command the orchestrator and the shims run.",
-    )
-    parser.add_argument(
-        "build",
-        nargs=argparse.REMAINDER,
-        metavar="<build command>",
-        help="The build command. A '--' separator before it is optional.",
-    )
-    return parser
-
-
-class CommandLineOpts:
-    def __init__(
-        self,
-        build_command=(),
-        output_dir=None,
-        extract_summaries=None,
-        analyses=(),
-        ssaf_clang=None,
-        ssaf_extra_clang_args=(),
-        ssaf_linker=None,
-        ssaf_analyzer=None,
-        keep_going=False,
-        verbose=False,
-    ):
-        self.build_command = list(build_command)
-        self.output_dir = output_dir
-        self.extract_summaries = extract_summaries
-        self.analyses = list(analyses)
-        self.ssaf_clang = ssaf_clang
-        self.ssaf_extra_clang_args = list(ssaf_extra_clang_args)
-        self.ssaf_linker = ssaf_linker
-        self.ssaf_analyzer = ssaf_analyzer
-        self.keep_going = keep_going
-        self.verbose = verbose
-
-
-def resolve(argv):
-    args = build_parser().parse_args(argv)
-
-    build_command = list(args.build)
-    if build_command and build_command[0] == "--":
-        build_command = build_command[1:]
-    if not build_command:
-        return None, Problem(USAGE_ERROR, "no build command given")
-
-    return (
-        CommandLineOpts(
-            build_command=build_command,
-            output_dir=args.output_dir,
-            extract_summaries=args.extract_summaries,
-            analyses=args.analyses,
-            ssaf_clang=args.ssaf_clang,
-            ssaf_extra_clang_args=args.ssaf_extra_clang_args,
-            ssaf_linker=args.ssaf_linker,
-            ssaf_analyzer=args.ssaf_analyzer,
-            keep_going=args.keep_going,
-            verbose=args.verbose,
-        ),
-        None,
-    )
diff --git a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/orchestrator.py b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/orchestrator.py
deleted file mode 100644
index eb5470da8820d..0000000000000
--- a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/orchestrator.py
+++ /dev/null
@@ -1,211 +0,0 @@
-# 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
-
-import json
-import os
-import shutil
-import re
-import subprocess
-
-from . import (
-    build_graph,
-    config,
-    config_orchestrator,
-    failure_logs,
-    interposition,
-    logging_diagnostics,
-    options,
-)
-from .ssaf_artifact_repository import (
-    SSAFArtifactKind,
-    SSAFArtifactRepository,
-    get_ssaf_artifact_id,
-)
-
-
-def warn_if_not_make(build_command):
-    supported = frozenset(["make", "gmake"])
-    for word in build_command:
-        if word in ("env", "/usr/bin/env") or re.match(r"^[A-Za-z_]\w*=", word):
-            continue
-        if os.path.basename(word) in supported:
-            return
-        not_make = word
-        break
-    else:
-        return
-    logging_diagnostics.report_warning(
-        "'%s' is not make; -B will be appended to it anyway, and "
-        "nothing forces the rebuild the artifacts need" % not_make
-    )
-
-
-def write_pass_config(workflow_config, pass_config):
-    path = os.path.join(workflow_config.output_dir, pass_config.file_name)
-    document = workflow_config.to_json()
-    document.update(pass_config.to_json())
-    temporary = "%s.%d.tmp" % (path, os.getpid())
-    with open(temporary, "w") as handle:
-        json.dump(document, handle, indent=2, sort_keys=True)
-    os.replace(temporary, path)
-    return path
-
-
-def _exit_status(returncode):
-    return 128 - returncode if returncode < 0 else returncode
-
-
-def run_build_with_toolchain_interposition(
-    workflow_config, serialized_config_path, shim_link_dir_path, failure_description
-):
-    # Without -B, make skips an up-to-date artifact, so it is never analysed.
-    argv = workflow_config.build_command + ["-B"]
-    logging_diagnostics.report_note(workflow_config.verbose, " ".join(argv))
-    try:
-        status = _exit_status(
-            subprocess.call(
-                argv,
-                env=interposition.make_environment(
-                    serialized_config_path,
-                    shim_link_dir_path,
-                    workflow_config.build_environment,
-                ),
-            )
-        )
-    except OSError as error:
-        return options.Problem(127, "cannot run '%s': %s" % (argv[0], error))
-    if status != 0:
-        return options.Problem(
-            status, "%s failed (exit %d)" % (failure_description, status)
-        )
-    return None
-
-
-def clear_output_dir(output_dir):
-    shutil.rmtree(output_dir, ignore_errors=True)
-    os.makedirs(output_dir)
-    open(config.output_dir_marker_path(output_dir), "w").close()
-
-
-def _no_link_unit(message):
-    return None, None, options.Problem(1, message)
-
-
-def get_topmost_link_unit(ssaf_artifact_repo, output_dir):
-    graph = build_graph.BuildGraph(config.build_graph_dir(output_dir))
-    candidates = graph.find_topmost_outputs(graph.get_recorded_build_steps())
-    if not candidates:
-        return _no_link_unit(
-            "the build produced no link unit; whole-program analysis needs one, "
-            "so build a target that links"
-        )
-    if len(candidates) > 1:
-        return _no_link_unit(
-            "the build produced %d unconsumed outputs and none of them consumes "
-            "the others: %s. Build one of them on its own."
-            % (len(candidates), ", ".join(candidates))
-        )
-
-    build_artifact_id = build_graph.BuildArtifactId(candidates[0])
-    ssaf_artifact_id = get_ssaf_artifact_id(build_artifact_id, SSAFArtifactKind.SUMMARY)
-    if not ssaf_artifact_repo.has_artifact(ssaf_artifact_id):
-        return _no_link_unit(
-            "no summary for '%s'; the SSAF step that produces it did not run "
-            "or failed" % build_artifact_id.get_path()
-        )
-    summary = ssaf_artifact_repo.get_path_for_artifact(ssaf_artifact_id)
-    return build_artifact_id, summary, None
-
-
-def run_ssaf_analysis_pass(
-    workflow_config, analysis_config, ssaf_artifact_repo, shim_link_dir_path
-):
-    serialized_config_path = write_pass_config(workflow_config, analysis_config)
-    problem = run_build_with_toolchain_interposition(
-        workflow_config, serialized_config_path, shim_link_dir_path, "build"
-    )
-    if problem is not None:
-        return problem
-
-    summaries = ssaf_artifact_repo.count_summaries()
-    if summaries == 0:
-        return options.Problem(1, "no summaries were extracted")
-
-    link_unit, summary, problem = get_topmost_link_unit(
-        ssaf_artifact_repo, workflow_config.output_dir
-    )
-    if problem is not None:
-        return problem
-
-    logging_diagnostics.report_summaries(summaries, link_unit.get_path(), summary)
-
-    if analysis_config.analyses:
-        analyze = [
-            workflow_config.ssaf_analyzer,
-            summary,
-            "-o",
-            config.wpa_result_path(workflow_config.output_dir),
-        ]
-        for name in analysis_config.analyses:
-            analyze += ["-a", name]
-        logging_diagnostics.report_note(workflow_config.verbose, " ".join(analyze))
-        status = _exit_status(subprocess.call(analyze))
-        if status != 0:
-            return options.Problem(
-                status, "whole-program analysis failed (exit %d)" % status
-            )
-        logging_diagnostics.report_analysis_result(
-            config.wpa_result_path(workflow_config.output_dir)
-        )
-
-    return None
-
-
-def run_ssaf_workflow(workflow_config, analysis_config):
-    warn_if_not_make(workflow_config.build_command)
-
-    ssaf_artifact_repo = SSAFArtifactRepository(
-        config.ssaf_artifact_dir(workflow_config.output_dir)
-    )
-    try:
-        clear_output_dir(workflow_config.output_dir)
-        shim_link_dir_path = interposition.create_shim_links(
-            config.shim_link_dir(workflow_config.output_dir),
-            workflow_config.installed_shim_dir_path,
-        )
-    except OSError as error:
-        return options.Problem(
-            options.ENVIRONMENT_ERROR,
-            "cannot prepare the output directory: %s" % error,
-        )
-
-    problem = run_ssaf_analysis_pass(
-        workflow_config, analysis_config, ssaf_artifact_repo, shim_link_dir_path
-    )
-    if problem is not None:
-        return problem
-
-    logging_diagnostics.report_output_dir(workflow_config.output_dir)
-
-    failures = failure_logs.count_failure_logs(workflow_config.output_dir)
-    if failures:
-        return options.Problem(
-            0 if workflow_config.keep_going else 1,
-            "%d SSAF step(s) failed; see the log files under %s"
-            % (failures, workflow_config.output_dir),
-        )
-    return None
-
-
-def main(argv=None, env=None):
-    env = dict(os.environ) if env is None else env
-    command_line_opts, problem = options.resolve(argv)
-    if problem is None:
-        configs, problem = config_orchestrator.configure(command_line_opts, env)
-    if problem is None:
-        problem = run_ssaf_workflow(*configs)
-    if problem is not None:
-        logging_diagnostics.report_error(problem.message, problem.details)
-        return problem.exit_status
-    return 0
diff --git a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/__init__.py b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/__init__.py
deleted file mode 100644
index 44390e67aacf4..0000000000000
--- a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/__init__.py
+++ /dev/null
@@ -1,3 +0,0 @@
-# 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
diff --git a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/clang.py b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/clang.py
deleted file mode 100644
index 7525dfc22b7ee..0000000000000
--- a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/clang.py
+++ /dev/null
@@ -1,128 +0,0 @@
-# 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
-
-import os
-import re
-import subprocess
-
-from .. import logging_diagnostics, utils
-from ..build_graph import BuildArtifactId
-from ..failure_logs import SSAFFailureKind
-from ..ssaf_artifact_repository import SSAFArtifactKind, get_ssaf_artifact_id
-from . import run
-from .driver_jobs import Job, parse_driver_job_listing
-from .shim import SKIP_BINARY_TOOL_INVOCATION
-
-
-def _shim_name_for(tool):
-    """Strip the directory and any version suffix from a tool's path."""
-    return re.sub(r"-\d+$", "", os.path.basename(tool))
-
-
-def _output_build_artifact_id(job, cwd):
-    if not job.output:
-        return None
-    return BuildArtifactId(os.path.join(cwd, job.output))
-
-
-def _invoke_shim_for_job(shim, job, cwd):
-    name = _shim_name_for(job.argv[0]) if job.argv else ""
-    link = os.path.join(shim.shim_link_dir, name) if name else ""
-    if not link or not os.path.isfile(link):
-        logging_diagnostics.report_note(
-            shim.workflow_config.verbose,
-            "no shim stands in for %s; the compiler has already run it" % name,
-        )
-        return
-    shim.run(
-        [link] + job.argv[1:] + [SKIP_BINARY_TOOL_INVOCATION],
-        SSAFFailureKind.FORWARD,
-        _output_build_artifact_id(job, cwd),
-        relay_output=True,
-    )
-
-
-def _get_driver_jobs(shim, listing_command, cwd):
-    logging_diagnostics.report_note(
-        shim.workflow_config.verbose, "binary: %s" % " ".join(listing_command)
-    )
-    completed = subprocess.run(
-        listing_command,
-        cwd=cwd,
-        env=shim.get_unmodified_env(),
-        stdout=subprocess.PIPE,
-        stderr=subprocess.PIPE,
-    )
-    return parse_driver_job_listing(completed.stderr), completed
-
-
-def _invoke_all_jobs(shim, bin_tool_path, cwd):
-    listing_command = [bin_tool_path, "-###"] + shim.argv[1:]
-    jobs, completed = _get_driver_jobs(shim, listing_command, cwd)
-    if not jobs:
-        if completed.returncode != 0:
-            shim.log_failure(
-                listing_command,
-                completed,
-                SSAFFailureKind.DRIVER_JOBS,
-                _output_build_artifact_id(Job(list(shim.argv[1:])), cwd),
-            )
-        else:
-            logging_diagnostics.report_note(
-                shim.workflow_config.verbose, "no jobs for %s" % " ".join(shim.argv[1:])
-            )
-        return
-
-    for job in jobs:
-        _invoke_shim_for_job(shim, job, cwd)
-
-
-def _summary_extraction_args(shim, build_artifact_id):
-    ssaf_artifact_repo = shim.ssaf_artifact_repo
-    summary = utils.make_parents(
-        ssaf_artifact_repo.get_path_for_artifact(
-            get_ssaf_artifact_id(build_artifact_id, SSAFArtifactKind.SUMMARY)
-        )
-    )
-    extra = [
-        "--ssaf-extract-summaries=" + shim.pass_config.extractors,
-        "--ssaf-compilation-unit-id=" + build_artifact_id.get_path(),
-        "--ssaf-tu-summary-file=" + summary,
-    ]
-    return summary, extra + shim.pass_config.ssaf_extra_clang_args
-
-
-def _run_clang_driven_tool(shim, cwd):
-    job = Job(list(shim.argv[1:]))
-
-    if not job.output:
-        logging_diagnostics.report_note(
-            shim.workflow_config.verbose, "no output, no SSAF step to run: %r" % (job,)
-        )
-        return
-
-    output = os.path.join(cwd, job.output)
-    build_artifact_id = BuildArtifactId(output)
-    artifact, extra = _summary_extraction_args(shim, build_artifact_id)
-    ssaf_command = [shim.pass_config.ssaf_clang] + shim.argv[1:] + extra
-
-    if not shim.run(ssaf_command, SSAFFailureKind.EXTRACT, build_artifact_id):
-        try:
-            os.remove(artifact)
-        except OSError:
-            pass
-        logging_diagnostics.report_error(
-            "discarded incomplete artifact for %s" % build_artifact_id.get_path()
-        )
-
-
-def invoke_ssaf_tools(shim, cwd):
-    if shim.skip_binary_tool_invocation:
-        _run_clang_driven_tool(shim, cwd)
-    else:
-        _invoke_all_jobs(shim, shim.bin_tool_path(), cwd)
-
-
-def main(argv, env=None):
-    return run.run_shim(invoke_ssaf_tools, argv, env)
diff --git a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/commands.py b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/commands.py
deleted file mode 100644
index 2eaf808e87095..0000000000000
--- a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/commands.py
+++ /dev/null
@@ -1,49 +0,0 @@
-# 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
-
-import collections
-import os
-
-from ..build_graph import BuildArtifactId
-from ..ssaf_artifact_repository import SSAFArtifactKind, get_ssaf_artifact_id
-
-Files = collections.namedtuple("Files", "inputs output")
-
-_OBJECT_EXTENSIONS = frozenset([".o", ".obj"])
-
-
-def is_object(filename):
-    return os.path.splitext(filename)[1] in _OBJECT_EXTENSIONS
-
-
-def artifact_of(ssaf_artifact_repo, build_artifact_id, ssaf_artifact_kind):
-    ssaf_artifact_id = get_ssaf_artifact_id(build_artifact_id, ssaf_artifact_kind)
-    if not ssaf_artifact_repo.has_artifact(ssaf_artifact_id):
-        return None
-    return ssaf_artifact_repo.get_path_for_artifact(ssaf_artifact_id)
-
-
-def summary_of(ssaf_artifact_repo, build_artifact_id):
-    return artifact_of(ssaf_artifact_repo, build_artifact_id, SSAFArtifactKind.SUMMARY)
-
-
-def filter_build_artifacts(build_graph, ssaf_artifact_repo, cwd, files):
-    kept = []
-    for each in files:
-        build_artifact_id = BuildArtifactId(os.path.join(cwd, each))
-        if artifact_of(
-            ssaf_artifact_repo, build_artifact_id, SSAFArtifactKind.SUMMARY
-        ) or build_graph.was_built(build_artifact_id):
-            kept.append(build_artifact_id)
-    return kept
-
-
-def unique(items):
-    seen = set()
-    kept = []
-    for item in items:
-        if item not in seen:
-            seen.add(item)
-            kept.append(item)
-    return kept
diff --git a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/driver_jobs.py b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/driver_jobs.py
deleted file mode 100644
index 5f0e0e96f5d85..0000000000000
--- a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/driver_jobs.py
+++ /dev/null
@@ -1,58 +0,0 @@
-# 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
-
-import os
-import re
-
-_JOB_PREFIX = b' "'
-
-_ESCAPE_PAIR = re.compile(rb'\\[\\"$]')
-_ARGUMENT = re.compile(rb'"((?:[^"\\]|\\.)*)"', re.DOTALL)
-_UNESCAPE = re.compile(rb'\\(["\\$])')
-
-
-def _quotes_balanced(record):
-    return _ESCAPE_PAIR.sub(b"", record).count(b'"') % 2 == 0
-
-
-def _records(data):
-    lines = data.split(b"\n")
-    found = []
-    index = 0
-    while index < len(lines):
-        line = lines[index]
-        if line.startswith(_JOB_PREFIX):
-            record = line
-            while not _quotes_balanced(record) and index + 1 < len(lines):
-                index += 1
-                record += b"\n" + lines[index]
-            found.append(record)
-        index += 1
-    return found
-
-
-def _tokenize(record):
-    return [
-        os.fsdecode(_UNESCAPE.sub(rb"\1", match.group(1)))
-        for match in _ARGUMENT.finditer(record)
-    ]
-
-
-class Job:
-    def __init__(self, argv):
-        self.argv = argv
-
-    @property
-    def output(self):
-        for index, arg in enumerate(self.argv):
-            if arg == "-o" and index + 1 < len(self.argv):
-                return self.argv[index + 1]
-        return None
-
-    def __repr__(self):
-        return "Job(argv=%r, output=%r)" % (self.argv, self.output)
-
-
-def parse_driver_job_listing(data):
-    return [Job(_tokenize(record)) for record in _records(data)]
diff --git a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/ld.py b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/ld.py
deleted file mode 100644
index d7fe1d65ccd72..0000000000000
--- a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/ld.py
+++ /dev/null
@@ -1,88 +0,0 @@
-# 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
-
-import os
-
-from .. import logging_diagnostics, utils
-from ..build_graph import BuildArtifactId
-from ..failure_logs import SSAFFailureKind
-from ..ssaf_artifact_repository import SSAFArtifactKind, get_ssaf_artifact_id
-from . import run
-from .commands import (
-    Files,
-    filter_build_artifacts,
-    is_object,
-    summary_of,
-    unique,
-)
-
-
-def identify_inputs_output(argv):
-    inputs = []
-    output = None
-    index = 1
-    while index < len(argv):
-        arg = argv[index]
-        if arg == "-o" and index + 1 < len(argv):
-            output = argv[index + 1]
-            index += 2
-            continue
-        if not arg.startswith("-") and is_object(arg):
-            inputs.append(arg)
-        index += 1
-    return Files(inputs, output) if inputs else None
-
-
-def link_summaries(shim, build_artifact_id, input_build_artifact_ids):
-    ssaf_artifact_repo = shim.ssaf_artifact_repo
-    summaries = []
-    for each in input_build_artifact_ids:
-        found = summary_of(ssaf_artifact_repo, each)
-        if found:
-            summaries.append(found)
-        else:
-            shim.log_missing_summary(build_artifact_id, each)
-    summaries = unique(summaries)
-    if not summaries:
-        logging_diagnostics.report_note(
-            shim.workflow_config.verbose,
-            "no summaries feed %s, nothing to link" % build_artifact_id.get_path(),
-        )
-        return
-    target = utils.make_parents(
-        ssaf_artifact_repo.get_path_for_artifact(
-            get_ssaf_artifact_id(build_artifact_id, SSAFArtifactKind.SUMMARY)
-        )
-    )
-    shim.run(
-        [shim.pass_config.ssaf_linker] + summaries + ["-o", target],
-        SSAFFailureKind.LINK,
-        build_artifact_id,
-    )
-
-
-def invoke_ssaf_tools(shim, cwd):
-    files = identify_inputs_output(shim.argv)
-    if files is None:
-        logging_diagnostics.report_note(
-            shim.workflow_config.verbose, "nothing linked, no SSAF step to run"
-        )
-        return
-
-    ssaf_artifact_repo = shim.ssaf_artifact_repo
-    output = os.path.join(cwd, files.output or "a.out")
-    build_artifact_id = BuildArtifactId(output)
-    input_build_artifact_ids = filter_build_artifacts(
-        shim.build_graph, ssaf_artifact_repo, cwd, files.inputs
-    )
-
-    shim.build_graph.record_build_step(
-        build_artifact_id,
-        inputs=input_build_artifact_ids,
-    )
-    link_summaries(shim, build_artifact_id, input_build_artifact_ids)
-
-
-def main(argv, env=None):
-    return run.run_shim(invoke_ssaf_tools, argv, env)
diff --git a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/run.py b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/run.py
deleted file mode 100644
index a345390a319bc..0000000000000
--- a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/run.py
+++ /dev/null
@@ -1,23 +0,0 @@
-# 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
-
-import os
-
-from .. import config_shims
-from .shim import Shim, error_no_config
-
-
-def run_shim(invoke_ssaf_tools, argv, env=None):
-    workflow_config, pass_config = config_shims.bootstrap_from_env(env)
-    if workflow_config is None:
-        return error_no_config()
-
-    shim = Shim(workflow_config, pass_config, argv)
-    cwd = os.getcwd()
-    if not shim.skip_binary_tool_invocation:
-        status = shim.run_bin_tool(shim.bin_tool_path(), cwd)
-        if status != 0:
-            return status
-
-    return shim.protect(lambda: invoke_ssaf_tools(shim, cwd))
diff --git a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/shim.py b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/shim.py
deleted file mode 100644
index 114135950896b..0000000000000
--- a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/shims/shim.py
+++ /dev/null
@@ -1,183 +0,0 @@
-# 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
-
-import os
-import shutil
-import signal
-import subprocess
-import sys
-import traceback
-
-from .. import build_graph, config, failure_logs, logging_diagnostics, utils
-from ..failure_logs import SSAFFailureKind
-from ..ssaf_artifact_repository import SSAFArtifactRepository
-
-SKIP_BINARY_TOOL_INVOCATION = "--ssaf-shim-skip-binary-tool-invocation"
-
-
-def error_no_config():
-    logging_diagnostics.report_error(
-        "missing configuration file",
-        [
-            "%s is not set, so this is not an orchestrator run"
-            % config.SSAF_CONFIG_ENV_VAR
-        ],
-    )
-    return 1
-
-
-class Shim:
-    def __init__(self, workflow_config, pass_config, argv):
-        self.workflow_config = workflow_config
-        self.pass_config = pass_config
-        argv = list(argv)
-        self.skip_binary_tool_invocation = (
-            len(argv) > 1 and argv[-1] == SKIP_BINARY_TOOL_INVOCATION
-        )
-        if self.skip_binary_tool_invocation:
-            del argv[-1]
-        self.argv = argv
-        self.invoked_as = os.path.basename(self.argv[0])
-        self._ssaf_artifact_repo = None
-        self._build_graph = None
-
-    @property
-    def ssaf_artifact_repo(self):
-        if self._ssaf_artifact_repo is None:
-            self._ssaf_artifact_repo = SSAFArtifactRepository(
-                config.ssaf_artifact_dir(self.workflow_config.output_dir)
-            )
-        return self._ssaf_artifact_repo
-
-    @property
-    def build_graph(self):
-        if self._build_graph is None:
-            self._build_graph = build_graph.BuildGraph(
-                config.build_graph_dir(self.workflow_config.output_dir)
-            )
-        return self._build_graph
-
-    @property
-    def shim_link_dir(self):
-        return config.shim_link_dir(self.workflow_config.output_dir)
-
-    def log_failure(self, command, completed, ssaf_failure_kind, build_artifact_id):
-        log_path = utils.make_parents(
-            failure_logs.get_failure_log_path(
-                self.workflow_config.output_dir,
-                ssaf_failure_kind,
-                command,
-                build_artifact_id,
-            )
-        )
-        with open(log_path, "wb") as handle:
-            handle.write(("$ " + " ".join(command) + "\n").encode("utf-8"))
-            handle.write(completed.stdout or b"")
-            handle.write(completed.stderr or b"")
-        logging_diagnostics.report_error(
-            "SSAF step failed (exit %d), see %s" % (completed.returncode, log_path)
-        )
-
-    def log_missing_summary(self, build_artifact_id, input_build_artifact_id):
-        output_dir = self.workflow_config.output_dir
-        path = input_build_artifact_id.get_path()
-        if failure_logs.has_failure_log_for(output_dir, input_build_artifact_id):
-            logging_diagnostics.report_note(
-                self.workflow_config.verbose,
-                "no summary for %s; already reported" % path,
-            )
-            return
-        message = (
-            "no summary for %s, consumed by %s; nothing it was assembled from "
-            "was analysed" % (path, build_artifact_id.get_path())
-        )
-        log = utils.make_parents(
-            failure_logs.get_failure_log_path(
-                output_dir, SSAFFailureKind.MISSING, self.argv, input_build_artifact_id
-            )
-        )
-        with open(log, "w") as handle:
-            handle.write(message + "\n")
-        logging_diagnostics.report_error(message)
-
-    def get_unmodified_env(self):
-        result = dict(os.environ)
-        result.pop(config.SSAF_CONFIG_ENV_VAR, None)
-        result["PATH"] = self.workflow_config.restored_path_env_var
-        return result
-
-    def bin_tool_path(self):
-        return shutil.which(
-            self.invoked_as, path=self.workflow_config.restored_path_env_var
-        )
-
-    def run_bin_tool(self, bin_tool_path, cwd):
-        if not bin_tool_path:
-            logging_diagnostics.report_error(
-                "cannot find the binary %s" % self.invoked_as
-            )
-            return 127
-        command = [bin_tool_path] + self.argv[1:]
-        logging_diagnostics.report_note(
-            self.workflow_config.verbose, "binary: %s" % " ".join(command)
-        )
-        try:
-            status = subprocess.call(command, cwd=cwd, env=self.get_unmodified_env())
-        except OSError as error:
-            logging_diagnostics.report_error("cannot run %s: %s" % (command[0], error))
-            return 127
-        if status < 0:
-            return self._propagate_process_return_status(status)
-        return status
-
-    def _propagate_process_return_status(self, return_status):
-        signal_number = -return_status
-        try:
-            signal.signal(signal_number, signal.SIG_DFL)
-            os.kill(os.getpid(), signal_number)
-        except OSError:
-            pass
-        return 128 + signal_number
-
-    def run(self, command, ssaf_failure_kind, build_artifact_id, relay_output=False):
-        logging_diagnostics.report_note(
-            self.workflow_config.verbose, "ssaf: %s" % " ".join(command)
-        )
-        try:
-            completed = subprocess.run(
-                command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT
-            )
-            if relay_output and completed.stdout:
-                sys.stderr.write(completed.stdout.decode("utf-8", "replace"))
-                sys.stderr.flush()
-        except OSError as error:
-            logging_diagnostics.report_error("cannot run %s: %s" % (command[0], error))
-            return False
-        if completed.returncode == 0:
-            return True
-        self.log_failure(command, completed, ssaf_failure_kind, build_artifact_id)
-        return False
-
-    def protect(self, work):
-        try:
-            work()
-        except Exception:  # noqa: BLE001 - deliberately everything
-            logging_diagnostics.report_error("internal error in %s" % self.invoked_as)
-            traceback.print_exc(file=sys.stderr)
-            try:
-                path = utils.make_parents(
-                    failure_logs.get_failure_log_path(
-                        self.workflow_config.output_dir,
-                        SSAFFailureKind.INTERNAL,
-                        self.argv,
-                        None,
-                    )
-                )
-                with open(path, "w") as handle:
-                    handle.write("%s\n\n" % " ".join(self.argv))
-                    traceback.print_exc(file=handle)
-            except Exception:
-                logging_diagnostics.report_error("and its log could not be written")
-        # A shim must never be the reason a build fails.
-        return 0
diff --git a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/ssaf_artifact_repository.py b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/ssaf_artifact_repository.py
deleted file mode 100644
index 674d5c4ccbbf6..0000000000000
--- a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/ssaf_artifact_repository.py
+++ /dev/null
@@ -1,58 +0,0 @@
-# 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
-
-
-import enum
-import os
-
-from .utils import coalesce_root_path, find_with_suffix
-
-
-class SSAFArtifactKind(enum.Enum):
-    SUMMARY = ".summary.json"
-
-
-class SSAFArtifactId:
-    __slots__ = ("build_artifact_id", "ssaf_artifact_kind")
-
-    def __init__(self, build_artifact_id, ssaf_artifact_kind):
-        self.build_artifact_id = build_artifact_id
-        self.ssaf_artifact_kind = ssaf_artifact_kind
-
-    def get_build_artifact_id(self):
-        return self.build_artifact_id
-
-    def __repr__(self):
-        return "SSAFArtifactId(%r, %r)" % (
-            self.build_artifact_id,
-            self.ssaf_artifact_kind,
-        )
-
-
-def get_ssaf_artifact_id(build_artifact_id, ssaf_artifact_kind):
-    return SSAFArtifactId(build_artifact_id, ssaf_artifact_kind)
-
-
-class SSAFArtifactRepository:
-    def __init__(self, ssaf_artifact_dir):
-        self.ssaf_artifact_dir = os.path.abspath(ssaf_artifact_dir)
-
-    def get_build_artifact_path(self, ssaf_artifact_id):
-        return ssaf_artifact_id.get_build_artifact_id().get_path()
-
-    def get_path_for_artifact(self, ssaf_artifact_id):
-        return coalesce_root_path(
-            self.ssaf_artifact_dir,
-            self.get_build_artifact_path(ssaf_artifact_id)
-            + ssaf_artifact_id.ssaf_artifact_kind.value,
-        )
-
-    def has_artifact(self, ssaf_artifact_id):
-        return os.path.exists(self.get_path_for_artifact(ssaf_artifact_id))
-
-    def _all_paths_of_kind(self, ssaf_artifact_kind):
-        return find_with_suffix(self.ssaf_artifact_dir, ssaf_artifact_kind.value)
-
-    def count_summaries(self):
-        return len(self._all_paths_of_kind(SSAFArtifactKind.SUMMARY))
diff --git a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/utils.py b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/utils.py
deleted file mode 100644
index eae135ef4a626..0000000000000
--- a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/utils.py
+++ /dev/null
@@ -1,54 +0,0 @@
-# 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
-
-import errno
-import json
-import os
-
-from . import logging_diagnostics
-
-
-def coalesce_root_path(root, path):
-    coalesced = os.path.normpath(os.path.join(root, path.lstrip(os.sep)))
-    if coalesced != root and not coalesced.startswith(root + os.sep):
-        raise ValueError("path leaves %s: %s" % (root, coalesced))
-    return coalesced
-
-
-def find_with_suffix(root, suffix):
-    found = []
-    for directory, _, filenames in os.walk(root):
-        for name in sorted(filenames):
-            if name.endswith(suffix):
-                found.append(os.path.join(directory, name))
-    return found
-
-
-def make_parents(path):
-    directory = os.path.dirname(path)
-    if directory:
-        try:
-            os.makedirs(directory)
-        except OSError as error:
-            if error.errno != errno.EEXIST:
-                raise
-    return path
-
-
-def read_json(path):
-    try:
-        with open(path) as handle:
-            return json.load(handle)
-    except OSError:
-        return None
-    except ValueError as error:
-        logging_diagnostics.report_error("%s is not valid JSON: %s" % (path, error))
-        return None
-
-
-def write_json(path, document):
-    temporary = "%s.%d.tmp" % (path, os.getpid())
-    with open(temporary, "w") as handle:
-        json.dump(document, handle, indent=2)
-    os.replace(temporary, path)
diff --git a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/version.py.in b/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/version.py.in
deleted file mode 100644
index 69b39a828847a..0000000000000
--- a/clang/tools/clang-ssaf-orchestrator-make/lib/clang_ssaf_orchestrator_make/version.py.in
+++ /dev/null
@@ -1,5 +0,0 @@
-# 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
-
-VERSION = "@CLANG_VERSION@"
diff --git a/clang/tools/clang-ssaf-orchestrator-make/shims/shim b/clang/tools/clang-ssaf-orchestrator-make/shims/shim
deleted file mode 100755
index 122b203fd2728..0000000000000
--- a/clang/tools/clang-ssaf-orchestrator-make/shims/shim
+++ /dev/null
@@ -1,45 +0,0 @@
-#!/usr/bin/env python3
-# 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
-
-import os
-import sys
-from importlib import import_module
-
-
-def _add_package_to_path():
-    here = os.path.dirname(os.path.realpath(__file__))
-    while True:
-        candidate = os.path.join(here, "lib")
-        if os.path.isdir(os.path.join(candidate, "clang_ssaf_orchestrator_make")):
-            sys.path.insert(0, candidate)
-            return
-        parent = os.path.dirname(here)
-        if parent == here:
-            raise ImportError(
-                "cannot find clang_ssaf_orchestrator_make beside %s" % __file__
-            )
-        here = parent
-
-
-_add_package_to_path()
-
-from clang_ssaf_orchestrator_make import config  # noqa: E402
-from clang_ssaf_orchestrator_make import logging_diagnostics  # noqa: E402
-
-
-def main(argv):
-    invoked_as = os.path.basename(argv[0])
-    name = config.SHIM_FOR_LINK_NAME.get(invoked_as)
-    if name is None:
-        logging_diagnostics.report_error(
-            "no shim stands in for %s" % invoked_as,
-            ["this is reached through the links an orchestrator run creates"],
-        )
-        return 1
-    return import_module("clang_ssaf_orchestrator_make.shims." + name).main(argv)
-
-
-if __name__ == "__main__":
-    sys.exit(main(sys.argv))
diff --git a/clang/tools/clang-ssaf-orchestrator-make/tests/__init__.py b/clang/tools/clang-ssaf-orchestrator-make/tests/__init__.py
deleted file mode 100644
index 44390e67aacf4..0000000000000
--- a/clang/tools/clang-ssaf-orchestrator-make/tests/__init__.py
+++ /dev/null
@@ -1,3 +0,0 @@
-# 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
diff --git a/clang/tools/clang-ssaf-orchestrator-make/tests/configs.py b/clang/tools/clang-ssaf-orchestrator-make/tests/configs.py
deleted file mode 100644
index 9a359514de7bc..0000000000000
--- a/clang/tools/clang-ssaf-orchestrator-make/tests/configs.py
+++ /dev/null
@@ -1,84 +0,0 @@
-# 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
-
-import contextlib
-from unittest import mock
-
-from clang_ssaf_orchestrator_make import build_graph, config, logging_diagnostics
-from clang_ssaf_orchestrator_make import ssaf_artifact_repository as repository
-
-
-def analysis_config(**overrides):
-    fields = dict(
-        ssaf_clang="/bin/clang",
-        ssaf_extra_clang_args=[],
-        extractors="PointerFlow",
-        ssaf_linker="/bin/clang-ssaf-linker",
-        analyses=[],
-    )
-    fields.update(overrides)
-    return config.SSAFAnalysisPassConfig(**fields)
-
-
-def workflow_config(env=None, output_dir="/out", verbose=False):
-    env = env or {}
-    return config.SSAFWorkflowConfig(
-        output_dir=output_dir,
-        installed_shim_dir_path="/libexec",
-        restored_path_env_var=env.get("PATH", ""),
-        verbose=verbose,
-        build_command=["make"],
-        ssaf_analyzer="/bin/clang-ssaf-analyzer",
-        keep_going=False,
-        build_environment=env,
-    )
-
-
- at contextlib.contextmanager
-def recorded_notes():
-    notes = []
-    with mock.patch.object(
-        logging_diagnostics,
-        "report_note",
-        lambda verbose, message: notes.append(message),
-    ):
-        yield notes
-
-
-class RecordingShim:
-    """A Shim whose SSAF invocations are recorded rather than run."""
-
-    def __init__(self, argv, output_dir, pass_config=None):
-        from clang_ssaf_orchestrator_make.shims import shim as shim_module
-
-        self.commands = []
-        self.relayed = []
-        self.missing = []
-        self._shim = shim_module.Shim(
-            workflow_config(output_dir=output_dir),
-            pass_config or analysis_config(),
-            argv,
-        )
-        self._shim.run = self._run
-        self._shim.log_missing_summary = (
-            lambda build_artifact_id, input_build_artifact_id: self.missing.append(
-                input_build_artifact_id.get_path()
-            )
-        )
-
-    def _run(self, command, ssaf_failure_kind, build_artifact_id, relay_output=False):
-        self.commands.append(((ssaf_failure_kind, build_artifact_id), command))
-        self.relayed.append(relay_output)
-        return True
-
-    def __getattr__(self, name):
-        return getattr(self._shim, name)
-
-
-def repository_for(output_dir):
-    return repository.SSAFArtifactRepository(config.ssaf_artifact_dir(output_dir))
-
-
-def build_graph_for(output_dir):
-    return build_graph.BuildGraph(config.build_graph_dir(output_dir))
diff --git a/clang/tools/clang-ssaf-orchestrator-make/tests/test_build_graph.py b/clang/tools/clang-ssaf-orchestrator-make/tests/test_build_graph.py
deleted file mode 100644
index f5caa9363858a..0000000000000
--- a/clang/tools/clang-ssaf-orchestrator-make/tests/test_build_graph.py
+++ /dev/null
@@ -1,222 +0,0 @@
-# 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
-
-import io
-import os
-import shutil
-import tempfile
-import unittest
-from unittest import mock
-
-from clang_ssaf_orchestrator_make import build_graph, utils
-from clang_ssaf_orchestrator_make import ssaf_artifact_repository as repository
-
-from . import configs
-
-
-def _id(build_artifact_path):
-    return build_graph.BuildArtifactId(build_artifact_path)
-
-
-class BuildArtifactIds(unittest.TestCase):
-    def test_an_id_is_the_path_without_the_leading_separator(self):
-        self.assertEqual(
-            "p/build/foo.o",
-            build_graph.BuildArtifactId("/p/build/foo.o").get_path().lstrip(os.sep),
-        )
-
-    def test_the_id_is_independent_of_how_the_path_was_spelled(self):
-        self.assertEqual(
-            build_graph.BuildArtifactId("/p/build/foo.o"),
-            build_graph.BuildArtifactId("/p/./build/../build/foo.o"),
-        )
-
-    def test_nothing_is_left_to_climb_out_of_the_output_directory_with(self):
-        build_artifact_id = build_graph.BuildArtifactId("/elsewhere/../deep/foo.o")
-        self.assertEqual("/deep/foo.o", build_artifact_id.get_path())
-        self.assertNotIn("..", build_artifact_id.get_path())
-
-    def test_two_paths_are_two_ids(self):
-        first = build_graph.BuildArtifactId("/a/foo.o")
-        second = build_graph.BuildArtifactId("/b/foo.o")
-        self.assertNotEqual(first, second)
-        self.assertEqual(first, build_graph.BuildArtifactId("/a/foo.o"))
-
-    def test_same_basename_in_different_directories_do_not_collide(self):
-        self.assertNotEqual(
-            build_graph.BuildArtifactId("/p/build/arm64/parser.o"),
-            build_graph.BuildArtifactId("/p/build/x86_64/parser.o"),
-        )
-        self.assertEqual(
-            "p/build/arm64/parser.o",
-            build_graph.BuildArtifactId("/p/build/arm64/parser.o")
-            .get_path()
-            .lstrip(os.sep),
-        )
-
-    def test_no_part_of_the_path_is_elided(self):
-        self.assertEqual(
-            "p/a/very/deep/nested/dir/parser.o",
-            build_graph.BuildArtifactId("/p/a/very/deep/nested/dir/parser.o")
-            .get_path()
-            .lstrip(os.sep),
-        )
-
-
-class SymlinkedPaths(unittest.TestCase):
-    def setUp(self):
-        self.tmp = os.path.realpath(tempfile.mkdtemp())
-        self.addCleanup(shutil.rmtree, self.tmp, True)
-        self.real = os.path.join(self.tmp, "real")
-        os.makedirs(os.path.join(self.real, "build"))
-        self.link = os.path.join(self.tmp, "link")
-        os.symlink(self.real, self.link)
-
-    def test_an_artifact_reached_through_a_symlink_gets_the_real_path_id(self):
-        directly = os.path.join(self.real, "build", "a.o")
-        self.assertEqual(
-            directly,
-            build_graph.BuildArtifactId(
-                os.path.join(self.link, "build", "a.o")
-            ).get_path(),
-        )
-
-
-class BuildstepRecords(unittest.TestCase):
-    def setUp(self):
-        self.tmp = tempfile.mkdtemp()
-        self.addCleanup(shutil.rmtree, self.tmp, True)
-        self.ssaf_artifact_repo = configs.repository_for(self.tmp)
-        self.graph = configs.build_graph_for(self.tmp)
-
-    def test_round_trip(self):
-        self.graph.record_build_step(
-            build_graph.BuildArtifactId("/p/build/prg"),
-            [_id("/a.o"), _id("/b.o")],
-        )
-        self.assertEqual(
-            {"/p/build/prg": ["/a.o", "/b.o"]}, self.graph.get_recorded_build_steps()
-        )
-
-    def test_several_build_steps_in_nested_directories(self):
-        self.graph.record_build_step(
-            build_graph.BuildArtifactId("/p/libx.a"),
-            [_id("/a.o")],
-        )
-        self.graph.record_build_step(
-            build_graph.BuildArtifactId("/p/build/sub/prg"),
-            [_id("/p/libx.a")],
-        )
-        self.assertEqual(
-            {"/p/libx.a", "/p/build/sub/prg"},
-            set(self.graph.get_recorded_build_steps()),
-        )
-
-    def test_one_output_has_one_record_and_the_last_call_wins(self):
-        first = self.graph.record_build_step(
-            build_graph.BuildArtifactId("/p/libx.a"),
-            [_id("/a.o")],
-        )
-        second = self.graph.record_build_step(
-            build_graph.BuildArtifactId("/p/libx.a"),
-            [_id("/b.o")],
-        )
-        self.assertEqual(first, second)
-        self.assertEqual(["/b.o"], self.graph.get_recorded_build_steps()["/p/libx.a"])
-
-    def test_a_record_whose_output_extends_another_is_not_read_back(self):
-        self.graph.record_build_step(
-            build_graph.BuildArtifactId("/p/prg.o"),
-            [_id("/a.o")],
-        )
-        self.graph.record_build_step(
-            build_graph.BuildArtifactId("/p/prg"),
-            [_id("/p/prg.o")],
-        )
-        self.assertEqual(["/p/prg.o"], self.graph.get_recorded_build_steps()["/p/prg"])
-
-    def test_a_summary_beside_a_record_is_not_read_as_one(self):
-        self.graph.record_build_step(
-            build_graph.BuildArtifactId("/p/prg"),
-            [_id("/a.o")],
-        )
-        open(
-            utils.make_parents(
-                self.ssaf_artifact_repo.get_path_for_artifact(
-                    repository.get_ssaf_artifact_id(
-                        build_graph.BuildArtifactId("/p/prg"),
-                        repository.SSAFArtifactKind.SUMMARY,
-                    )
-                )
-            ),
-            "w",
-        ).close()
-        self.assertEqual(["/a.o"], self.graph.get_recorded_build_steps()["/p/prg"])
-
-    def test_a_truncated_record_is_skipped_and_reported(self):
-        self.graph.record_build_step(
-            build_graph.BuildArtifactId("/p/good"),
-            [_id("/a.o")],
-        )
-        broken = utils.make_parents(
-            self.graph.get_buildstep_record_path(
-                build_graph.BuildArtifactId("/p/broken")
-            )
-        )
-        with open(broken, "w") as handle:
-            handle.write('{"kind": "li')
-        stream = io.StringIO()
-        with mock.patch("sys.stderr", stream):
-            self.assertEqual(["/p/good"], list(self.graph.get_recorded_build_steps()))
-        self.assertIn("is not valid JSON", stream.getvalue())
-        self.assertIn(broken, stream.getvalue())
-
-    def test_reading_an_absent_directory_yields_nothing(self):
-        self.assertEqual(
-            {},
-            configs.build_graph_for(self.tmp + "/none").get_recorded_build_steps(),
-        )
-
-
-class TopMostOutputs(unittest.TestCase):
-    def _topmost(self, steps):
-        return build_graph.BuildGraph.find_topmost_outputs(steps)
-
-    def test_single_binary(self):
-        self.assertEqual(["/p/prg"], self._topmost({"/p/prg": ["/a.o", "/b.o"]}))
-
-    def test_anything_another_step_consumed_is_not_top_most(self):
-        self.assertEqual(
-            ["/p/prg"],
-            self._topmost(
-                {"/p/libx.a": [_id("/a.o")], "/p/prg": ["main.o", "/p/libx.a"]}
-            ),
-        )
-
-    def test_intermediate_binary_is_not_top_most(self):
-        self.assertEqual(
-            ["/p/prg"],
-            self._topmost({"part.o": [_id("/a.o"), _id("/b.o")], "/p/prg": ["part.o"]}),
-        )
-
-    def test_an_unconsumed_output_is_a_candidate_whatever_produced_it(self):
-        self.assertEqual(["/p/libx.a"], self._topmost({"/p/libx.a": ["/a.o"]}))
-
-    def test_a_library_nothing_links_is_a_candidate_beside_a_binary(self):
-        self.assertEqual(
-            ["/p/libx.a", "/p/prg"],
-            self._topmost({"/p/libx.a": [_id("/a.o")], "/p/prg": ["main.o"]}),
-        )
-
-    def test_several_unrelated_binaries(self):
-        self.assertEqual(
-            ["tests", "tool"], self._topmost({"tool": [_id("/a.o")], "tests": ["b.o"]})
-        )
-
-    def test_nothing_recorded(self):
-        self.assertEqual([], self._topmost({}))
-
-
-if __name__ == "__main__":
-    unittest.main()
diff --git a/clang/tools/clang-ssaf-orchestrator-make/tests/test_clang_shim.py b/clang/tools/clang-ssaf-orchestrator-make/tests/test_clang_shim.py
deleted file mode 100644
index 720d8bcbe089f..0000000000000
--- a/clang/tools/clang-ssaf-orchestrator-make/tests/test_clang_shim.py
+++ /dev/null
@@ -1,244 +0,0 @@
-# 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
-
-import os
-import shutil
-import stat
-import tempfile
-import unittest
-from unittest import mock
-
-from clang_ssaf_orchestrator_make.shims import clang, shim as shim_module
-from clang_ssaf_orchestrator_make import ssaf_artifact_repository as repository
-from clang_ssaf_orchestrator_make import build_graph
-from clang_ssaf_orchestrator_make.failure_logs import SSAFFailureKind
-
-from . import configs
-
-
-class ForwardingAJob(unittest.TestCase):
-    def setUp(self):
-        self.tmp = tempfile.mkdtemp()
-        self.addCleanup(shutil.rmtree, self.tmp, True)
-        self.out = os.path.join(self.tmp, "out")
-        self.links = os.path.join(self.out, "shims")
-        os.makedirs(self.links)
-        for name in ("clang", "ld"):
-            path = os.path.join(self.links, name)
-            open(path, "w").close()
-            os.chmod(path, os.stat(path).st_mode | stat.S_IXUSR)
-        self.shim = configs.RecordingShim(["c++", "-o", "prg"], self.out)
-
-    def _job(self, argv):
-        return clang.Job(argv)
-
-    def test_a_job_whose_tool_has_a_link_is_forwarded_with_the_marker(self):
-        clang._invoke_shim_for_job(
-            self.shim, self._job(["/toolchain/bin/ld", "-o", "prg", "a.o"]), self.tmp
-        )
-        failure, command = self.shim.commands[0]
-        self.assertEqual(
-            (
-                SSAFFailureKind.FORWARD,
-                build_graph.BuildArtifactId(os.path.join(self.tmp, "prg")),
-            ),
-            failure,
-        )
-        self.assertEqual(os.path.join(self.links, "ld"), command[0])
-        self.assertEqual(["-o", "prg", "a.o"], command[1:-1])
-        self.assertEqual(shim_module.SKIP_BINARY_TOOL_INVOCATION, command[-1])
-        self.assertEqual([True], self.shim.relayed)
-
-    def test_a_versioned_tool_still_finds_its_link(self):
-        clang._invoke_shim_for_job(
-            self.shim, self._job(["/build/bin/clang-23", "-cc1", "-o", "a.o"]), self.tmp
-        )
-        self.assertEqual(os.path.join(self.links, "clang"), self.shim.commands[0][1][0])
-
-    def test_a_job_with_no_link_is_noted_and_skipped(self):
-        with configs.recorded_notes() as notes:
-            clang._invoke_shim_for_job(
-                self.shim, self._job(["/usr/bin/dsymutil", "prg"]), self.tmp
-            )
-        self.assertEqual([], self.shim.commands)
-        self.assertIn("no shim stands in for dsymutil", notes[0])
-
-    def test_a_job_with_no_program_at_all_is_skipped(self):
-        clang._invoke_shim_for_job(self.shim, self._job([]), self.tmp)
-        self.assertEqual([], self.shim.commands)
-
-    def test_a_job_with_no_output_is_logged_under_its_command(self):
-        clang._invoke_shim_for_job(
-            self.shim, self._job(["/usr/bin/ld", "a.o"]), self.tmp
-        )
-        self.assertEqual((SSAFFailureKind.FORWARD, None), self.shim.commands[0][0])
-
-
-class ListingTheJobs(unittest.TestCase):
-    def setUp(self):
-        self.tmp = tempfile.mkdtemp()
-        self.addCleanup(shutil.rmtree, self.tmp, True)
-        self.shim = configs.RecordingShim(
-            ["c++", "-c", "-o", "build/a.o", "a.cpp"],
-            os.path.join(self.tmp, "out"),
-        )
-
-    def _completed(self, stderr, returncode=0):
-        return mock.Mock(stderr=stderr, stdout=b"", returncode=returncode)
-
-    def test_a_listing_with_no_jobs_is_noted(self):
-        with mock.patch(
-            "subprocess.run", return_value=self._completed(b"")
-        ), configs.recorded_notes() as notes:
-            clang._invoke_all_jobs(self.shim, "/bin/clang", self.tmp)
-        self.assertEqual([], self.shim.commands)
-        self.assertEqual("binary: /bin/clang -### -c -o build/a.o a.cpp", notes[0])
-        self.assertIn("no jobs for", notes[1])
-
-    def test_a_driver_that_failed_is_logged_rather_than_noted(self):
-        logged = []
-        self.shim._shim.log_failure = lambda *args: logged.append(args)
-        with mock.patch(
-            "subprocess.run", return_value=self._completed(b"", returncode=1)
-        ):
-            clang._invoke_all_jobs(self.shim, "/bin/clang", self.tmp)
-        command, _, failure_kind, build_artifact_id = logged[0]
-        self.assertEqual(
-            ["/bin/clang", "-###", "-c", "-o", "build/a.o", "a.cpp"], command
-        )
-        self.assertEqual(SSAFFailureKind.DRIVER_JOBS, failure_kind)
-        self.assertEqual(
-            build_graph.BuildArtifactId(os.path.join(self.tmp, "build", "a.o")),
-            build_artifact_id,
-        )
-
-    def test_the_driver_is_asked_with_the_builds_own_arguments(self):
-        with mock.patch("subprocess.run", return_value=self._completed(b"")) as ran:
-            clang._invoke_all_jobs(self.shim, "/bin/clang", self.tmp)
-        self.assertEqual(
-            ["/bin/clang", "-###", "-c", "-o", "build/a.o", "a.cpp"],
-            ran.call_args[0][0],
-        )
-
-
-class TheSsafArguments(unittest.TestCase):
-    def setUp(self):
-        self.tmp = tempfile.mkdtemp()
-        self.addCleanup(shutil.rmtree, self.tmp, True)
-        self.out = os.path.join(self.tmp, "out")
-
-    def _id(self, relative):
-        return build_graph.BuildArtifactId(os.path.join(self.tmp, relative))
-
-    def _shim(self, pass_config=None):
-        return configs.RecordingShim(
-            ["clang", "-cc1", "-o", "build/a.o", "a.cpp"],
-            self.out,
-            pass_config,
-        )
-
-    def test_extraction_names_the_unit_and_where_its_summary_goes(self):
-        shim = self._shim()
-        summary, extra = clang._summary_extraction_args(shim, self._id("build/a.o"))
-        self.assertIn("--ssaf-extract-summaries=PointerFlow", extra)
-        self.assertIn(
-            "--ssaf-compilation-unit-id=" + self._id("build/a.o").get_path(), extra
-        )
-        self.assertIn("--ssaf-tu-summary-file=" + summary, extra)
-        self.assertTrue(os.path.isdir(os.path.dirname(summary)))
-
-    def test_the_extra_clang_arguments_come_last(self):
-        shim = self._shim(configs.analysis_config(ssaf_extra_clang_args=["-DX"]))
-        _, extra = clang._summary_extraction_args(shim, self._id("build/a.o"))
-        self.assertEqual("-DX", extra[-1])
-
-
-class RunningTheFrontend(unittest.TestCase):
-    def setUp(self):
-        self.tmp = tempfile.mkdtemp()
-        self.addCleanup(shutil.rmtree, self.tmp, True)
-        self.out = os.path.join(self.tmp, "out")
-
-    def _shim(self, argv):
-        return configs.RecordingShim(argv, self.out)
-
-    def _id(self, relative):
-        return build_graph.BuildArtifactId(os.path.join(self.tmp, relative))
-
-    def test_a_job_with_no_output_runs_nothing(self):
-        shim = self._shim(["clang", "-cc1", "-E", "a.cpp"])
-        with configs.recorded_notes() as notes:
-            clang._run_clang_driven_tool(shim, self.tmp)
-        self.assertEqual([], shim.commands)
-        self.assertIn("no output", notes[0])
-
-    def test_the_ssaf_clang_gets_the_jobs_own_arguments_then_the_options(self):
-        shim = self._shim(["clang", "-cc1", "-o", "build/a.o", "a.cpp"])
-        clang._run_clang_driven_tool(shim, self.tmp)
-        failure, command = shim.commands[0]
-        self.assertEqual((SSAFFailureKind.EXTRACT, self._id("build/a.o")), failure)
-        self.assertEqual("/bin/clang", command[0])
-        self.assertEqual(["-cc1", "-o", "build/a.o", "a.cpp"], command[1:5])
-        self.assertTrue(command[5].startswith("--ssaf-"))
-
-    def test_an_incomplete_artifact_is_removed_and_reported(self):
-        shim = self._shim(["clang", "-cc1", "-o", "build/a.o", "a.cpp"])
-        shim._shim.run = lambda *args: False
-        stream = mock.MagicMock()
-        with mock.patch("sys.stderr", stream):
-            clang._run_clang_driven_tool(shim, self.tmp)
-        records = configs.repository_for(self.out)
-        summary = records.get_path_for_artifact(
-            repository.get_ssaf_artifact_id(
-                build_graph.BuildArtifactId(os.path.join(self.tmp, "build", "a.o")),
-                repository.SSAFArtifactKind.SUMMARY,
-            )
-        )
-        self.assertFalse(os.path.exists(summary))
-
-    def test_the_marker_chooses_the_frontend_half(self):
-        shim = self._shim(
-            [
-                "clang",
-                "-cc1",
-                "-o",
-                "build/a.o",
-                "a.cpp",
-                shim_module.SKIP_BINARY_TOOL_INVOCATION,
-            ]
-        )
-        self.assertTrue(shim.skip_binary_tool_invocation)
-        clang.invoke_ssaf_tools(shim, self.tmp)
-        self.assertEqual(
-            (SSAFFailureKind.EXTRACT, self._id("build/a.o")), shim.commands[0][0]
-        )
-
-
-class ShimNameForTool(unittest.TestCase):
-    def test_the_directory_is_dropped(self):
-        self.assertEqual("ld", clang._shim_name_for("/usr/bin/ld"))
-
-    def test_a_version_suffix_is_dropped(self):
-        self.assertEqual("clang", clang._shim_name_for("/opt/llvm/bin/clang-23"))
-
-    def test_an_unversioned_name_is_left_alone(self):
-        self.assertEqual(
-            "clang",
-            clang._shim_name_for(
-                "/Applications/Xcode.app/Contents/Developer/Toolchains/"
-                "XcodeDefault.xctoolchain/usr/bin/clang"
-            ),
-        )
-
-    def test_only_a_trailing_numeric_suffix_is_dropped(self):
-        self.assertEqual("clang-cl", clang._shim_name_for("/x/clang-cl"))
-        self.assertEqual("ld64.lld", clang._shim_name_for("/x/ld64.lld"))
-
-    def test_a_suffixed_link_name_still_reaches_its_link(self):
-        for name in ("cc", "clang", "c++", "clang++"):
-            self.assertEqual(name, clang._shim_name_for("/x/%s-14" % name))
-
-
-if __name__ == "__main__":
-    unittest.main()
diff --git a/clang/tools/clang-ssaf-orchestrator-make/tests/test_commands.py b/clang/tools/clang-ssaf-orchestrator-make/tests/test_commands.py
deleted file mode 100644
index 6990f7c304c5c..0000000000000
--- a/clang/tools/clang-ssaf-orchestrator-make/tests/test_commands.py
+++ /dev/null
@@ -1,114 +0,0 @@
-# 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
-
-import os
-import shutil
-import tempfile
-import unittest
-
-from clang_ssaf_orchestrator_make import build_graph, utils
-from clang_ssaf_orchestrator_make import ssaf_artifact_repository as repository
-
-from . import configs
-from clang_ssaf_orchestrator_make.shims import commands
-
-
-class Extensions(unittest.TestCase):
-    def test_object_extensions(self):
-        for name in ("a.o", "build/a.o", "a.obj", "A.O".lower()):
-            self.assertTrue(commands.is_object(name), name)
-        for name in ("a.a", "a.c", "a", "a.o.tmp", "a.O"):
-            self.assertFalse(commands.is_object(name), name)
-
-
-class Unique(unittest.TestCase):
-    def test_the_first_of_each_is_kept_in_order(self):
-        self.assertEqual(["b", "a", "c"], commands.unique(["b", "a", "b", "c", "a"]))
-
-    def test_nothing_stays_nothing(self):
-        self.assertEqual([], commands.unique([]))
-
-    def test_the_input_is_not_modified(self):
-        items = ["a", "a"]
-        commands.unique(items)
-        self.assertEqual(["a", "a"], items)
-
-
-class InputsAndOutput(unittest.TestCase):
-    def test_it_carries_what_went_in_and_what_came_out(self):
-        files = commands.Files(["a.o"], "prg")
-        self.assertEqual(["a.o"], files.inputs)
-        self.assertEqual("prg", files.output)
-
-
-class _OverABuild(unittest.TestCase):
-    def setUp(self):
-        self.root = tempfile.mkdtemp()
-        self.addCleanup(shutil.rmtree, self.root, True)
-        self.out = tempfile.mkdtemp()
-        self.addCleanup(shutil.rmtree, self.out, True)
-        self.ssaf_artifact_repo = configs.repository_for(self.out)
-        self.build_graph = configs.build_graph_for(self.out)
-
-    def _path(self, relative):
-        return os.path.join(self.root, relative)
-
-    def _id(self, relative):
-        return build_graph.BuildArtifactId(self._path(relative))
-
-    def _write(self, relative, ssaf_artifact_kind):
-        path = self.ssaf_artifact_repo.get_path_for_artifact(
-            repository.get_ssaf_artifact_id(self._id(relative), ssaf_artifact_kind)
-        )
-        open(utils.make_parents(path), "w").close()
-        return path
-
-
-class SummaryOf(_OverABuild):
-    def test_an_object_resolves_to_its_own_summary(self):
-        want = self._write("build/a.o", repository.SSAFArtifactKind.SUMMARY)
-        self.assertEqual(
-            want, commands.summary_of(self.ssaf_artifact_repo, self._id("build/a.o"))
-        )
-
-    def test_an_artifact_the_build_did_not_produce_resolves_to_nothing(self):
-        self.assertIsNone(
-            commands.summary_of(
-                self.ssaf_artifact_repo,
-                build_graph.BuildArtifactId("/usr/lib/libSystem.dylib"),
-            )
-        )
-
-    def test_an_assembled_artifact_does_not_reach_past_its_own(self):
-        self._write("build/a.o", repository.SSAFArtifactKind.SUMMARY)
-        self.build_graph.record_build_step(
-            self._id("build/lib.a"), [self._id("build/a.o")]
-        )
-        self.assertIsNone(
-            commands.summary_of(self.ssaf_artifact_repo, self._id("build/lib.a"))
-        )
-
-
-class FilterBuildArtifacts(_OverABuild):
-    def _kept(self, *files):
-        return commands.filter_build_artifacts(
-            self.build_graph, self.ssaf_artifact_repo, self.root, list(files)
-        )
-
-    def test_a_compiled_object_is_kept(self):
-        self._write("build/a.o", repository.SSAFArtifactKind.SUMMARY)
-        self.assertEqual([self._id("build/a.o")], self._kept("build/a.o"))
-
-    def test_an_assembled_object_with_only_a_record_is_kept(self):
-        self.build_graph.record_build_step(
-            self._id("build/combined.o"), [self._id("build/a.o")]
-        )
-        self.assertEqual([self._id("build/combined.o")], self._kept("build/combined.o"))
-
-    def test_what_the_build_never_touched_is_dropped(self):
-        self.assertEqual([], self._kept("third_party/prebuilt.a", "/usr/lib/libz.a"))
-
-
-if __name__ == "__main__":
-    unittest.main()
diff --git a/clang/tools/clang-ssaf-orchestrator-make/tests/test_config.py b/clang/tools/clang-ssaf-orchestrator-make/tests/test_config.py
deleted file mode 100644
index e0aafdc425bcd..0000000000000
--- a/clang/tools/clang-ssaf-orchestrator-make/tests/test_config.py
+++ /dev/null
@@ -1,86 +0,0 @@
-# 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
-
-import json
-import unittest
-
-from clang_ssaf_orchestrator_make import config
-
-from . import configs
-
-
-class Passes(unittest.TestCase):
-    def test_a_pass_names_its_own_configuration_file(self):
-        self.assertEqual("config-analysis.json", configs.analysis_config().file_name)
-
-    def test_a_pass_kind_is_stored_as_its_plain_string(self):
-        written = json.loads(json.dumps(configs.analysis_config().to_json()))
-        self.assertEqual("analysis", written["pass_kind"])
-
-    def test_a_pass_carries_only_the_tools_it_runs(self):
-        self.assertEqual(
-            {
-                "pass_kind",
-                "ssaf_clang",
-                "ssaf_extra_clang_args",
-                "extractors",
-                "ssaf_linker",
-                "analyses",
-            },
-            set(configs.analysis_config().to_json()),
-        )
-
-    def test_a_pass_knows_nothing_of_the_run_it_belongs_to(self):
-        run_only = config.SSAFWorkflowConfig.written_field_names()
-        self.assertEqual(set(), run_only & set(configs.analysis_config().to_json()))
-
-
-class OutputDirPaths(unittest.TestCase):
-    def test_the_shim_links_and_the_analysis_result_sit_at_the_root(self):
-        self.assertEqual("/out/shims", config.shim_link_dir("/out"))
-        self.assertEqual("/out/wpa.json", config.wpa_result_path("/out"))
-
-    def test_each_owner_has_a_directory_of_its_own(self):
-        self.assertEqual("/out/build-graph", config.build_graph_dir("/out"))
-        self.assertEqual("/out/ssaf-artifacts", config.ssaf_artifact_dir("/out"))
-        self.assertEqual("/out/failure-logs", config.failure_log_dir("/out"))
-
-
-class WorkflowConfig(unittest.TestCase):
-    def test_it_carries_what_is_true_of_the_run_whichever_pass_is_running(self):
-        self.assertEqual(
-            {
-                "output_dir",
-                "installed_shim_dir_path",
-                "restored_path_env_var",
-                "verbose",
-                "build_command",
-                "ssaf_analyzer",
-                "keep_going",
-            },
-            set(configs.workflow_config().to_json()),
-        )
-
-    def test_the_build_environment_is_never_written(self):
-        workflow_config = configs.workflow_config(
-            env={"SECRET": "x", "PATH": "/usr/bin"}
-        )
-        self.assertEqual("x", workflow_config.build_environment["SECRET"])
-        self.assertNotIn("build_environment", workflow_config.to_json())
-        self.assertNotIn("SECRET", json.dumps(workflow_config.to_json()))
-
-    def test_every_written_key_is_also_reachable_as_an_attribute(self):
-        workflow_config = configs.workflow_config()
-        written = workflow_config.to_json()
-        self.assertEqual(
-            written,
-            {name: getattr(workflow_config, name) for name in written},
-        )
-
-    def test_an_absent_path_is_empty_so_the_live_path_is_never_searched(self):
-        self.assertEqual("", config.SSAFWorkflowConfig().restored_path_env_var)
-
-
-if __name__ == "__main__":
-    unittest.main()
diff --git a/clang/tools/clang-ssaf-orchestrator-make/tests/test_config_orchestrator.py b/clang/tools/clang-ssaf-orchestrator-make/tests/test_config_orchestrator.py
deleted file mode 100644
index 6a512c24bf9dd..0000000000000
--- a/clang/tools/clang-ssaf-orchestrator-make/tests/test_config_orchestrator.py
+++ /dev/null
@@ -1,348 +0,0 @@
-# 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
-
-import json
-import os
-import shutil
-import stat
-import sys
-import tempfile
-import types
-import unittest
-from unittest import mock
-
-from clang_ssaf_orchestrator_make import config, config_orchestrator, options
-
-
-class Executables:
-    def setUp(self):
-        self.tmp = tempfile.mkdtemp()
-        self.addCleanup(shutil.rmtree, self.tmp, True)
-        self.elsewhere = os.path.join(self.tmp, "nowhere")
-
-    def _executable(self, name):
-        path = os.path.join(self.tmp, name)
-        with open(path, "w") as handle:
-            handle.write("#!/bin/sh\n")
-        os.chmod(path, os.stat(path).st_mode | stat.S_IXUSR)
-        return path
-
-
-class ResolveSsafTool(Executables, unittest.TestCase):
-    def _resolve(self, option_value, installed_shim_dir_path=None, name="sh"):
-        errors = []
-        path = config_orchestrator._resolve_ssaf_tool(
-            "--ssaf-clang",
-            name,
-            option_value,
-            installed_shim_dir_path or self.elsewhere,
-            errors,
-        )
-        return path, errors
-
-    def test_no_value_takes_the_default_name_from_path(self):
-        planted = self._executable("default-tool")
-        with mock.patch.dict(os.environ, {"PATH": self.tmp}):
-            path, errors = self._resolve(None, name="default-tool")
-        self.assertEqual([], errors)
-        self.assertEqual(planted, path)
-
-    def test_the_tool_is_made_absolute(self):
-        self._executable("cc")
-        with mock.patch.dict(os.environ, {"PATH": self.tmp}):
-            path, errors = self._resolve("cc")
-        self.assertEqual([], errors)
-        self.assertEqual(os.path.join(self.tmp, "cc"), path)
-
-    def test_anything_but_one_executable_is_refused(self):
-        tool = self._executable("cc")
-        path, errors = self._resolve("%s -std=gnu11" % tool)
-        self.assertIsNone(path)
-        self.assertEqual(
-            ["--ssaf-clang: expected one executable, got '%s -std=gnu11'" % tool],
-            errors,
-        )
-
-    def test_a_missing_tool_is_reported(self):
-        path, errors = self._resolve("no-such-tool-xyz")
-        self.assertIsNone(path)
-        self.assertIn("not found on PATH", errors[0])
-
-    def test_a_directory_is_not_a_tool(self):
-        path, errors = self._resolve(self.tmp)
-        self.assertIsNone(path)
-        self.assertIn("not a file", errors[0])
-
-    def test_a_non_executable_is_reported(self):
-        plain = os.path.join(self.tmp, "plain")
-        with open(plain, "w") as handle:
-            handle.write("")
-        path, errors = self._resolve(plain)
-        self.assertIsNone(path)
-        self.assertIn("not executable", errors[0])
-
-    def test_an_empty_value_is_reported_rather_than_run(self):
-        path, errors = self._resolve("   ")
-        self.assertIsNone(path)
-        self.assertIn("nothing to run", errors[0])
-
-    def test_one_of_our_own_shims_is_refused(self):
-        shim = self._executable("cc")
-        path, errors = self._resolve(shim, os.path.realpath(self.tmp))
-        self.assertIsNone(path)
-        self.assertIn("one of our own shims", errors[0])
-
-    def test_refusals_accumulate_in_the_order_they_were_asked(self):
-        errors = []
-        for option_name in ("--ssaf-clang", "--ssaf-linker"):
-            config_orchestrator._resolve_ssaf_tool(
-                option_name, "sh", "/no/such/tool", self.elsewhere, errors
-            )
-        self.assertEqual(
-            [
-                "--ssaf-clang: not a file: /no/such/tool",
-                "--ssaf-linker: not a file: /no/such/tool",
-            ],
-            errors,
-        )
-
-
-class Configure(Executables, unittest.TestCase):
-    def setUp(self):
-        super().setUp()
-        self.clang = self._executable("clang")
-        self.linker = self._executable("clang-ssaf-linker")
-        self.analyzer = self._executable("clang-ssaf-analyzer")
-        self.project = os.path.join(self.tmp, "project")
-        os.makedirs(self.project)
-        self.addCleanup(os.chdir, os.getcwd())
-        os.chdir(self.project)
-        patch = mock.patch.object(
-            config_orchestrator, "find_installed_shim_dir", return_value=self.elsewhere
-        )
-        patch.start()
-        self.addCleanup(patch.stop)
-
-    def _configure(self, *extra, env=None):
-        argv = [
-            "--extract-summaries=PointerFlow",
-            "--ssaf-clang=" + self.clang,
-            "--ssaf-linker=" + self.linker,
-        ]
-        argv.extend(extra)
-        return self._configure_argv(argv, env)
-
-    def _configure_argv(self, argv, env=None):
-        command_line_opts, problem = options.resolve(argv)
-        self.assertIsNone(problem)
-        configs, problem = config_orchestrator.configure(
-            command_line_opts, {} if env is None else env
-        )
-        return (configs or (None, None)) + (problem,)
-
-    def test_a_valid_command_line_yields_the_configuration(self):
-        workflow_config, analysis_config, problem = self._configure("--", "make", "-j8")
-        self.assertIsNone(problem)
-        self.assertEqual(["make", "-j8"], workflow_config.build_command)
-        self.assertEqual("PointerFlow", analysis_config.extractors)
-        self.assertEqual(self.clang, analysis_config.ssaf_clang)
-
-    def test_the_configuration_holds_the_resolved_tool_not_what_was_typed(self):
-        argv = [
-            "--extract-summaries=PointerFlow",
-            "--ssaf-clang=clang",
-            "--ssaf-linker=clang-ssaf-linker",
-            "--ssaf-analyzer=clang-ssaf-analyzer",
-            "--analysis=a",
-            "--",
-            "make",
-        ]
-        with mock.patch.dict(os.environ, {"PATH": self.tmp}):
-            workflow_config, analysis_config, problem = self._configure_argv(argv)
-        self.assertIsNone(problem)
-        self.assertEqual(self.clang, analysis_config.ssaf_clang)
-        self.assertEqual(self.linker, analysis_config.ssaf_linker)
-        self.assertEqual(self.analyzer, workflow_config.ssaf_analyzer)
-
-    def test_the_environment_reaches_the_config_but_not_the_file(self):
-        workflow_config, _, problem = self._configure(
-            "--", "make", env={"PATH": "/usr/bin", "SECRET": "x"}
-        )
-        self.assertIsNone(problem)
-        self.assertEqual("x", workflow_config.build_environment["SECRET"])
-        self.assertEqual("/usr/bin", workflow_config.restored_path_env_var)
-        self.assertNotIn("SECRET", json.dumps(workflow_config.to_json()))
-
-    def test_an_output_dir_holding_the_project_is_refused(self):
-        for value in (".", "..", os.getcwd()):
-            workflow_config, _, problem = self._configure("-o", value, "--", "make")
-            self.assertIsNone(workflow_config, value)
-            self.assertEqual(options.ENVIRONMENT_ERROR, problem.exit_status)
-            self.assertIn("would contain the project", problem.message)
-
-    def test_a_directory_no_run_made_is_not_deleted(self):
-        other = os.path.join(self.project, "src")
-        os.makedirs(other)
-        open(os.path.join(other, "main.c"), "w").close()
-        workflow_config, _, problem = self._configure("-o", other, "--", "make")
-        self.assertIsNone(workflow_config)
-        self.assertEqual(options.ENVIRONMENT_ERROR, problem.exit_status)
-        self.assertIn("no earlier run made it", problem.message)
-        self.assertEqual(["main.c"], os.listdir(other))
-
-    def test_an_empty_directory_is_taken(self):
-        empty = os.path.join(self.tmp, "empty")
-        os.makedirs(empty)
-        workflow_config, _, problem = self._configure("-o", empty, "--", "make")
-        self.assertIsNone(problem)
-        self.assertEqual(os.path.realpath(empty), workflow_config.output_dir)
-
-    def test_a_directory_an_earlier_run_made_is_taken(self):
-        earlier = os.path.join(self.tmp, "earlier")
-        os.makedirs(os.path.join(earlier, "ssaf-artifacts"))
-        open(config.output_dir_marker_path(earlier), "w").close()
-        _, _, problem = self._configure("-o", earlier, "--", "make")
-        self.assertIsNone(problem)
-
-    def test_a_relative_output_dir_is_made_absolute(self):
-        workflow_config, _, problem = self._configure("-o", "somewhere", "--", "make")
-        self.assertIsNone(problem)
-        self.assertEqual(
-            os.path.join(os.getcwd(), "somewhere"), workflow_config.output_dir
-        )
-
-    def test_an_unresolvable_ssaf_tool(self):
-        workflow_config, _, problem = self._configure_argv(
-            [
-                "--extract-summaries=PointerFlow",
-                "--ssaf-clang=/no/such/clang",
-                "--ssaf-linker=" + self.linker,
-                "--",
-                "make",
-            ]
-        )
-        self.assertIsNone(workflow_config)
-        self.assertEqual(options.ENVIRONMENT_ERROR, problem.exit_status)
-        self.assertEqual(1, len(problem.details))
-        self.assertIn("/no/such/clang", problem.details[0])
-
-    def test_the_ssaf_tools_take_no_flags(self):
-        workflow_config, _, problem = self._configure_argv(
-            [
-                "--extract-summaries=PointerFlow",
-                "--ssaf-clang=%s -O2" % self.clang,
-                "--ssaf-linker=" + self.linker,
-                "--",
-                "make",
-            ]
-        )
-        self.assertIsNone(workflow_config)
-        self.assertEqual(
-            ["--ssaf-clang: expected one executable, got '%s -O2'" % self.clang],
-            problem.details,
-        )
-
-    def test_a_detail_names_the_option_and_the_path(self):
-        *_, problem = self._configure_argv(
-            [
-                "--extract-summaries=PointerFlow",
-                "--ssaf-clang=/no/such/clang",
-                "--ssaf-linker=" + self.linker,
-                "--",
-                "make",
-            ]
-        )
-        self.assertEqual(["--ssaf-clang: not a file: /no/such/clang"], problem.details)
-
-    def test_a_tool_absent_from_path_names_what_was_looked_for(self):
-        with mock.patch.dict(os.environ, {"PATH": self.elsewhere}):
-            workflow_config, _, problem = self._configure_argv(
-                [
-                    "--extract-summaries=PointerFlow",
-                    "--ssaf-clang=" + self.clang,
-                    "--",
-                    "make",
-                ]
-            )
-        self.assertIsNone(workflow_config)
-        self.assertEqual(
-            ["--ssaf-linker: clang-ssaf-linker: not found on PATH"],
-            problem.details,
-        )
-
-    def test_every_unresolvable_tool_is_reported_at_once(self):
-        workflow_config, _, problem = self._configure_argv(
-            [
-                "--extract-summaries=PointerFlow",
-                "--ssaf-clang=/no/such/clang",
-                "--ssaf-linker=/no/such/linker",
-                "--ssaf-analyzer=/no/such/analyzer",
-                "--analysis=a",
-                "--",
-                "make",
-            ]
-        )
-        self.assertIsNone(workflow_config)
-        self.assertEqual(
-            [
-                "--ssaf-clang: not a file: /no/such/clang",
-                "--ssaf-linker: not a file: /no/such/linker",
-                "--ssaf-analyzer: not a file: /no/such/analyzer",
-            ],
-            problem.details,
-        )
-
-    def test_the_analyzer_is_only_required_when_an_analysis_is_asked_for(self):
-        workflow_config, _, problem = self._configure("--", "make")
-        self.assertIsNone(problem)
-        self.assertIsNone(workflow_config.ssaf_analyzer)
-
-    def test_a_tool_no_pass_will_run_is_not_resolved_at_all(self):
-        workflow_config, _, problem = self._configure(
-            "--ssaf-analyzer=/no/such/analyzer", "--", "make"
-        )
-        self.assertIsNone(problem)
-        self.assertIsNone(workflow_config.ssaf_analyzer)
-
-
-class InstalledShims(Executables, unittest.TestCase):
-    def _found_from(self, script):
-        entry = types.SimpleNamespace(__file__=script)
-        with mock.patch.dict(sys.modules, {"__main__": entry}):
-            return config_orchestrator.find_installed_shim_dir()
-
-    def test_an_installed_layout_finds_libexec(self):
-        prefix = os.path.join(self.tmp, "prefix")
-        libexec = os.path.join(prefix, "libexec", "ssaf-orchestrator-shims")
-        os.makedirs(libexec)
-        os.makedirs(os.path.join(prefix, "bin"))
-        found = self._found_from(
-            os.path.join(prefix, "bin", "clang-ssaf-orchestrator-make")
-        )
-        self.assertEqual(os.path.realpath(libexec), found)
-
-    def test_a_source_tree_falls_back_to_shims(self):
-        root = os.path.join(self.tmp, "tool")
-        os.makedirs(os.path.join(root, "bin"))
-        found = self._found_from(
-            os.path.join(root, "bin", "clang-ssaf-orchestrator-make")
-        )
-        self.assertEqual(os.path.realpath(os.path.join(root, "shims")), found)
-
-    def test_the_result_is_resolved_so_the_own_shim_guard_can_compare_it(self):
-        prefix = os.path.join(self.tmp, "real")
-        libexec = os.path.join(prefix, "libexec", "ssaf-orchestrator-shims")
-        os.makedirs(libexec)
-        os.makedirs(os.path.join(prefix, "bin"))
-        through = os.path.join(self.tmp, "through")
-        os.symlink(prefix, through)
-        found = self._found_from(
-            os.path.join(through, "bin", "clang-ssaf-orchestrator-make")
-        )
-        self.assertEqual(os.path.realpath(found), found)
-        self.assertEqual(os.path.realpath(libexec), found)
-
-
-if __name__ == "__main__":
-    unittest.main()
diff --git a/clang/tools/clang-ssaf-orchestrator-make/tests/test_config_shims.py b/clang/tools/clang-ssaf-orchestrator-make/tests/test_config_shims.py
deleted file mode 100644
index 3e43137e6ca58..0000000000000
--- a/clang/tools/clang-ssaf-orchestrator-make/tests/test_config_shims.py
+++ /dev/null
@@ -1,63 +0,0 @@
-# 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
-
-import os
-import shutil
-import tempfile
-import unittest
-
-from clang_ssaf_orchestrator_make import config, config_shims
-
-from . import configs
-
-
-class Serialization(unittest.TestCase):
-    def test_nothing_is_read_outside_an_orchestrator_run(self):
-        self.assertEqual((None, None), config_shims.bootstrap_from_env({}))
-
-
-class ReadingBack(unittest.TestCase):
-    def setUp(self):
-        self.tmp = tempfile.mkdtemp()
-        self.addCleanup(shutil.rmtree, self.tmp, True)
-
-    def _written(self, **overrides):
-        document = configs.workflow_config().to_json()
-        document.update(configs.analysis_config().to_json())
-        document.update(overrides)
-        return document
-
-    def test_an_analysis_document_rebuilds_an_analysis_pass(self):
-        _, pass_config = config_shims.from_json(self._written())
-        self.assertIsInstance(pass_config, config.SSAFAnalysisPassConfig)
-
-    def test_a_document_with_no_pass_kind_is_refused(self):
-        document = self._written()
-        del document["pass_kind"]
-        with self.assertRaises(KeyError):
-            config_shims.from_json(document)
-
-    def test_an_unknown_pass_kind_is_refused(self):
-        with self.assertRaises(ValueError):
-            config_shims.from_json(self._written(pass_kind="something-else"))
-
-    def test_an_unexpected_key_is_refused(self):
-        with self.assertRaises(TypeError):
-            config_shims.from_json(self._written(unexpected="x"))
-
-    def test_nothing_is_read_when_the_variable_is_empty(self):
-        self.assertEqual(
-            (None, None),
-            config_shims.bootstrap_from_env({config.SSAF_CONFIG_ENV_VAR: ""}),
-        )
-
-    def test_a_variable_naming_a_file_that_is_not_there(self):
-        with self.assertRaises(OSError):
-            config_shims.bootstrap_from_env(
-                {config.SSAF_CONFIG_ENV_VAR: os.path.join(self.tmp, "absent")}
-            )
-
-
-if __name__ == "__main__":
-    unittest.main()
diff --git a/clang/tools/clang-ssaf-orchestrator-make/tests/test_driver_jobs.py b/clang/tools/clang-ssaf-orchestrator-make/tests/test_driver_jobs.py
deleted file mode 100644
index 7bb079bb2bb11..0000000000000
--- a/clang/tools/clang-ssaf-orchestrator-make/tests/test_driver_jobs.py
+++ /dev/null
@@ -1,150 +0,0 @@
-# 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
-
-import os
-import unittest
-
-from clang_ssaf_orchestrator_make.shims import driver_jobs as under_test
-
-PREAMBLE = (
-    b"clang version 24.0.0git\n"
-    b"Target: arm64-apple-darwin24.6.0\n"
-    b"Thread model: posix\n"
-    b"InstalledDir: /opt/llvm/bin\n"
-)
-
-
-def listing(*jobs):
-    return PREAMBLE + b"".join(b" " + job + b"\n" for job in jobs)
-
-
-def _program(job):
-    return os.path.basename(job.argv[0])
-
-
-CC1_COMPILE = (
-    b'"/opt/llvm/bin/clang" "-cc1" "-triple" "arm64-apple-macosx15.0.0" '
-    b'"-emit-obj" "-o" "build/a.o" "-x" "c++" "src/a.cpp"'
-)
-LINK = b'"/usr/bin/ld" "-o" "build/prg" "build/a.o" "-lc++"'
-
-
-class Preamble(unittest.TestCase):
-    def test_preamble_is_not_mistaken_for_jobs(self):
-        self.assertEqual(under_test.parse_driver_job_listing(PREAMBLE), [])
-
-    def test_build_config_line_some_builds_add_is_ignored(self):
-        data = PREAMBLE + b"Build config: +assertions\n" + b" " + CC1_COMPILE + b"\n"
-        self.assertEqual(len(under_test.parse_driver_job_listing(data)), 1)
-
-    def test_in_process_marker_is_not_a_job(self):
-        data = PREAMBLE + b" (in-process)\n" + b" " + CC1_COMPILE + b"\n"
-        jobs = under_test.parse_driver_job_listing(data)
-        self.assertEqual(len(jobs), 1)
-        self.assertEqual(jobs[0].argv[1], "-cc1")
-
-    def test_diagnostics_before_and_after_the_preamble_are_ignored(self):
-        data = (
-            b"clang: error: unknown argument: '--nope'\n"
-            + PREAMBLE
-            + b"clang: warning: argument unused [-Wunused-command-line-argument]\n"
-            + b" "
-            + CC1_COMPILE
-            + b"\n"
-        )
-        self.assertEqual(len(under_test.parse_driver_job_listing(data)), 1)
-
-    def test_empty_listing(self):
-        self.assertEqual(under_test.parse_driver_job_listing(b""), [])
-
-
-class Escaping(unittest.TestCase):
-    def _value(self, quoted):
-        data = listing(b'"/opt/llvm/bin/clang" "-cc1" "-D" ' + quoted)
-        return under_test.parse_driver_job_listing(data)[0].argv[-1]
-
-    def test_space_is_raw_inside_quotes(self):
-        self.assertEqual(self._value(b'"A=x y"'), "A=x y")
-
-    def test_escaped_double_quote(self):
-        self.assertEqual(self._value(b'"A=\\"q\\""'), 'A="q"')
-
-    def test_escaped_backslash(self):
-        self.assertEqual(self._value(b'"A=a\\\\b"'), "A=a\\b")
-
-    def test_escaped_dollar(self):
-        self.assertEqual(self._value(b'"A=\\$(PWD)/x"'), "A=$(PWD)/x")
-
-    def test_tab_is_raw(self):
-        self.assertEqual(self._value(b'"A=a\tb"'), "A=a\tb")
-
-    def test_apostrophe_and_backtick_are_raw(self):
-        self.assertEqual(self._value(b'"A=it\'s `x`"'), "A=it's `x`")
-
-    def test_shell_metacharacters_are_raw(self):
-        self.assertEqual(self._value(b'"A=a;b|c&d"'), "A=a;b|c&d")
-
-    def test_empty_argument(self):
-        self.assertEqual(self._value(b'""'), "")
-
-    def test_non_utf8_bytes_survive(self):
-        value = self._value(b'"A=\xff\xfe"')
-        self.assertEqual(value.encode("utf-8", "surrogateescape"), b"A=\xff\xfe")
-
-    def test_newline_inside_an_argument_does_not_end_the_job(self):
-        data = listing(b'"/opt/llvm/bin/clang" "-cc1" "-D" "A=a\nb" "-x" "c++" "a.cpp"')
-        jobs = under_test.parse_driver_job_listing(data)
-        self.assertEqual(len(jobs), 1)
-        self.assertEqual(jobs[0].argv[3], "A=a\nb")
-        self.assertEqual(jobs[0].argv[-1], "a.cpp")
-
-
-class Classification(unittest.TestCase):
-    def test_an_assembler_job_is_read_like_any_other(self):
-        data = listing(b'"/opt/llvm/bin/clang" "-cc1as" "-triple" "arm64--" "a.s"')
-        job = under_test.parse_driver_job_listing(data)[0]
-        self.assertEqual("/opt/llvm/bin/clang", job.argv[0])
-        self.assertEqual("-cc1as", job.argv[1])
-
-    def test_the_output_is_the_key_the_artifact_takes(self):
-        job = under_test.parse_driver_job_listing(listing(CC1_COMPILE))[0]
-        self.assertEqual(job.output, "build/a.o")
-
-    def test_the_repr_names_what_a_reader_of_a_verbose_run_needs(self):
-        job = under_test.parse_driver_job_listing(listing(CC1_COMPILE))[0]
-        self.assertEqual("Job(argv=%r, output='build/a.o')" % (job.argv,), repr(job))
-
-    def test_missing_option_value(self):
-        job = under_test.parse_driver_job_listing(
-            listing(b'"/opt/llvm/bin/clang" "-cc1" "-o"')
-        )[0]
-        self.assertIsNone(job.output)
-
-
-class Decomposition(unittest.TestCase):
-    def test_compile_and_link(self):
-        jobs = under_test.parse_driver_job_listing(listing(CC1_COMPILE, LINK))
-        self.assertEqual(["clang", "ld"], [_program(j) for j in jobs])
-
-    def test_multiple_architectures_have_distinct_outputs(self):
-        arm = (
-            b'"/opt/llvm/bin/clang" "-cc1" "-triple" "arm64-apple-macosx15.0.0" '
-            b'"-o" "/tmp/p-aaa/p-arm64.o" "-x" "c++" "p.cpp"'
-        )
-        intel = (
-            b'"/opt/llvm/bin/clang" "-cc1" "-triple" "x86_64-apple-macosx15.0.0" '
-            b'"-o" "/tmp/p-bbb/p-x86_64.o" "-x" "c++" "p.cpp"'
-        )
-        lipo = b'"/usr/bin/lipo" "-create" "-output" "p.o" "/tmp/p-aaa/p-arm64.o"'
-        jobs = under_test.parse_driver_job_listing(listing(arm, intel, lipo))
-        self.assertEqual(["clang", "clang", "lipo"], [_program(j) for j in jobs])
-        self.assertNotEqual(jobs[0].output, jobs[1].output)
-
-    def test_link_only_has_no_frontend_job(self):
-        jobs = under_test.parse_driver_job_listing(listing(LINK))
-        self.assertEqual(["ld"], [_program(j) for j in jobs])
-
-
-if __name__ == "__main__":
-    unittest.main()
diff --git a/clang/tools/clang-ssaf-orchestrator-make/tests/test_failure_logs.py b/clang/tools/clang-ssaf-orchestrator-make/tests/test_failure_logs.py
deleted file mode 100644
index f3d06fa37fdf6..0000000000000
--- a/clang/tools/clang-ssaf-orchestrator-make/tests/test_failure_logs.py
+++ /dev/null
@@ -1,93 +0,0 @@
-# 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
-
-import os
-import shutil
-import tempfile
-import unittest
-from unittest import mock
-
-from clang_ssaf_orchestrator_make import build_graph, config, failure_logs, utils
-from clang_ssaf_orchestrator_make.failure_logs import SSAFFailureKind
-
-
-class NamedForTheCommand(unittest.TestCase):
-    def _path(self, command, cwd="/p"):
-        with mock.patch("os.getcwd", return_value=cwd):
-            return failure_logs.get_failure_log_path(
-                "/out", SSAFFailureKind.FORWARD, command, None
-            )
-
-    def test_two_commands_get_two_logs(self):
-        self.assertNotEqual(self._path(["ld", "a.o"]), self._path(["ld", "b.o"]))
-
-    def test_one_command_in_two_directories_gets_two_logs(self):
-        self.assertNotEqual(
-            self._path(["ld", "a.o"], "/p/lib1"), self._path(["ld", "a.o"], "/p/lib2")
-        )
-
-    def test_the_same_command_in_the_same_directory_gets_the_same_log(self):
-        self.assertEqual(self._path(["ld", "a.o"]), self._path(["ld", "a.o"]))
-
-
-class HasFailureLogFor(unittest.TestCase):
-    def setUp(self):
-        self.tmp = tempfile.mkdtemp()
-        self.addCleanup(shutil.rmtree, self.tmp, True)
-
-    def _write(self, ssaf_failure_kind, build_artifact_path):
-        path = failure_logs.get_failure_log_path(
-            self.tmp,
-            ssaf_failure_kind,
-            None,
-            build_graph.BuildArtifactId(build_artifact_path),
-        )
-        open(utils.make_parents(path), "w").close()
-
-    def _has_log(self, build_artifact_path):
-        return failure_logs.has_failure_log_for(
-            self.tmp, build_graph.BuildArtifactId(build_artifact_path)
-        )
-
-    def test_a_log_of_any_kind_is_a_log_for_its_artifact(self):
-        for each in SSAFFailureKind:
-            self._write(each, "/p/%s.o" % each.value)
-            self.assertTrue(self._has_log("/p/%s.o" % each.value), each)
-
-    def test_a_log_for_a_longer_name_is_not_a_log_for_this_one(self):
-        self._write(SSAFFailureKind.EXTRACT, "/p/a.o.x.o")
-        self.assertFalse(self._has_log("/p/a.o"))
-
-
-class CountFailureLogs(unittest.TestCase):
-    def setUp(self):
-        self.tmp = tempfile.mkdtemp()
-        self.addCleanup(shutil.rmtree, self.tmp, True)
-
-    def _write(self, directory, name):
-        path = utils.make_parents(os.path.join(directory, name))
-        open(path, "w").close()
-
-    def test_an_output_directory_that_is_not_there_counts_nothing(self):
-        self.assertEqual(
-            0, failure_logs.count_failure_logs(os.path.join(self.tmp, "none"))
-        )
-
-    def test_logs_about_artifacts_and_about_commands_add_up(self):
-        self._write(config.failure_log_dir(self.tmp), "p/a.o.extract.log")
-        self._write(config.failure_log_dir(self.tmp), "p/0123456789ab.internal.log")
-        self.assertEqual(2, failure_logs.count_failure_logs(self.tmp))
-
-    def test_a_log_anywhere_under_the_output_directory_is_counted(self):
-        self._write(config.ssaf_artifact_dir(self.tmp), "p/a.o.extract.log")
-        self.assertEqual(1, failure_logs.count_failure_logs(self.tmp))
-
-    def test_what_is_not_a_log_is_not_counted(self):
-        self._write(config.ssaf_artifact_dir(self.tmp), "p/a.o.summary.json")
-        self._write(self.tmp, "wpa.json")
-        self.assertEqual(0, failure_logs.count_failure_logs(self.tmp))
-
-
-if __name__ == "__main__":
-    unittest.main()
diff --git a/clang/tools/clang-ssaf-orchestrator-make/tests/test_interposition.py b/clang/tools/clang-ssaf-orchestrator-make/tests/test_interposition.py
deleted file mode 100644
index 12df308875ecb..0000000000000
--- a/clang/tools/clang-ssaf-orchestrator-make/tests/test_interposition.py
+++ /dev/null
@@ -1,69 +0,0 @@
-# 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
-
-import os
-import shutil
-import stat
-import tempfile
-import unittest
-
-from clang_ssaf_orchestrator_make import config, interposition
-
-
-class ShimLinks(unittest.TestCase):
-    def setUp(self):
-        self.tmp = tempfile.mkdtemp()
-        self.addCleanup(shutil.rmtree, self.tmp, True)
-        self.installed_shim_dir_path = os.path.join(self.tmp, "libexec")
-        os.makedirs(self.installed_shim_dir_path)
-        self.program = os.path.join(
-            self.installed_shim_dir_path, interposition.SHIM_PROGRAM
-        )
-        with open(self.program, "w") as handle:
-            handle.write("#!/bin/sh\n")
-        os.chmod(self.program, os.stat(self.program).st_mode | stat.S_IXUSR)
-        self.shim_link_dir_path = os.path.join(self.tmp, "shims")
-
-    def test_every_tool_name_is_created_every_run(self):
-        interposition.create_shim_links(
-            self.shim_link_dir_path, self.installed_shim_dir_path
-        )
-        self.assertEqual(
-            sorted(config.SHIM_FOR_LINK_NAME),
-            sorted(os.listdir(self.shim_link_dir_path)),
-        )
-
-    def test_every_name_is_a_link_to_the_one_program(self):
-        interposition.create_shim_links(
-            self.shim_link_dir_path, self.installed_shim_dir_path
-        )
-        for name in config.SHIM_FOR_LINK_NAME:
-            link = os.path.join(self.shim_link_dir_path, name)
-            self.assertTrue(os.path.islink(link), link)
-            self.assertEqual(self.program, os.readlink(link))
-
-    def test_a_program_that_cannot_be_run_is_refused(self):
-        os.chmod(self.program, 0o644)
-        with self.assertRaises(OSError):
-            interposition.create_shim_links(
-                self.shim_link_dir_path, self.installed_shim_dir_path
-            )
-
-
-class BuildEnvironment(unittest.TestCase):
-    def test_a_build_with_no_path_sees_only_the_shim_link_directory(self):
-        for env in ({}, {"PATH": ""}):
-            result = interposition.make_environment("/out/c.json", "/out/shims", env)
-            self.assertEqual("/out/shims", result["PATH"], env)
-
-    def test_the_shim_directory_goes_in_front_of_the_builds_own_path(self):
-        env = interposition.make_environment(
-            "/out/config-analysis.json", "/out/shims", {"PATH": "/usr/bin"}
-        )
-        self.assertEqual(os.pathsep.join(["/out/shims", "/usr/bin"]), env["PATH"])
-        self.assertEqual("/out/config-analysis.json", env[config.SSAF_CONFIG_ENV_VAR])
-
-
-if __name__ == "__main__":
-    unittest.main()
diff --git a/clang/tools/clang-ssaf-orchestrator-make/tests/test_ld_shim.py b/clang/tools/clang-ssaf-orchestrator-make/tests/test_ld_shim.py
deleted file mode 100644
index 2b2e5ec35c146..0000000000000
--- a/clang/tools/clang-ssaf-orchestrator-make/tests/test_ld_shim.py
+++ /dev/null
@@ -1,132 +0,0 @@
-# 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
-
-import os
-import shutil
-import tempfile
-import unittest
-
-from clang_ssaf_orchestrator_make import utils
-from clang_ssaf_orchestrator_make.shims import ld
-from clang_ssaf_orchestrator_make import ssaf_artifact_repository as repository
-from clang_ssaf_orchestrator_make import build_graph
-
-from . import configs
-
-
-class Inputs(unittest.TestCase):
-    def test_objects(self):
-        files = ld.identify_inputs_output(["ld", "-o", "prg", "a.o", "b.o", "-lm"])
-        self.assertEqual(["a.o", "b.o"], files.inputs)
-        self.assertEqual("prg", files.output)
-
-    def test_any_object_is_named_whatever_precedes_it(self):
-        for option in ("-force_load", "-weak_library", "-filelist", "-bundle"):
-            files = ld.identify_inputs_output(["ld", "-o", "prg", "a.o", option, "b.o"])
-            self.assertEqual(["a.o", "b.o"], files.inputs, option)
-
-    def test_a_value_with_no_object_extension_is_not_named(self):
-        files = ld.identify_inputs_output(["ld", "-o", "prg", "a.o", "-l", "x"])
-        self.assertEqual(["a.o"], files.inputs)
-
-    def test_a_link_with_no_objects_reads_as_nothing(self):
-        self.assertIsNone(ld.identify_inputs_output(["ld", "-v"]))
-
-    def test_bare_tool_reads_as_nothing(self):
-        self.assertIsNone(ld.identify_inputs_output(["ld"]))
-
-
-class Output(unittest.TestCase):
-    def test_partial_link_output_is_not_read_back_as_an_input(self):
-        files = ld.identify_inputs_output(
-            ["ld", "-r", "-o", "combined.o", "a.o", "b.o"]
-        )
-        self.assertEqual("combined.o", files.output)
-        self.assertEqual(["a.o", "b.o"], files.inputs)
-
-    def test_only_a_whole_argument_names_the_output(self):
-        for option in (
-            "-object_path_lto",
-            "-objc_abi_version",
-            "-order_file",
-            "-order_file_statistics",
-            "-oso_prefix",
-            "-object-file-name=x.o",
-        ):
-            files = ld.identify_inputs_output(["ld", "-o", "prg", "a.o", option])
-            self.assertEqual("prg", files.output, option)
-
-    def test_a_joined_output_is_not_read(self):
-        files = ld.identify_inputs_output(["ld", "-obuild/prg", "a.o"])
-        self.assertIsNone(files.output)
-
-
-class SsafStep(unittest.TestCase):
-    def setUp(self):
-        self.tmp = tempfile.mkdtemp()
-        self.addCleanup(shutil.rmtree, self.tmp, True)
-        self.root = os.path.join(self.tmp, "project")
-        self.out = os.path.join(self.tmp, "out")
-        os.makedirs(os.path.join(self.root, "build"))
-        self.ssaf_artifact_repo = configs.repository_for(self.out)
-        self.graph = configs.build_graph_for(self.out)
-
-    def _id(self, relative):
-        return build_graph.BuildArtifactId(os.path.join(self.root, relative))
-
-    def _summary(self, relative):
-        open(
-            utils.make_parents(
-                self.ssaf_artifact_repo.get_path_for_artifact(
-                    repository.get_ssaf_artifact_id(
-                        build_graph.BuildArtifactId(os.path.join(self.root, relative)),
-                        repository.SSAFArtifactKind.SUMMARY,
-                    )
-                )
-            ),
-            "w",
-        ).close()
-
-    def _run(self, arguments, pass_config=None):
-        shim = configs.RecordingShim(
-            ["ld", "-o", "build/prg"] + arguments, self.out, pass_config
-        )
-        with configs.recorded_notes() as notes:
-            ld.invoke_ssaf_tools(shim, self.root)
-        self.notes = notes
-        return shim
-
-    def _recorded_inputs(self):
-        return self.graph.get_recorded_build_steps()[self._id("build/prg").get_path()]
-
-    def test_only_what_the_run_produced_is_linked(self):
-        self._summary("build/a.o")
-        shim = self._run(["build/a.o", "third_party/prebuilt.o", "/usr/lib/crt1.o"])
-        self.assertEqual([self._id("build/a.o").get_path()], self._recorded_inputs())
-        self.assertEqual([], shim.missing)
-        _, command = shim.commands[0]
-        self.assertIn(
-            self.ssaf_artifact_repo.get_path_for_artifact(
-                repository.get_ssaf_artifact_id(
-                    build_graph.BuildArtifactId(os.path.join(self.root, "build/a.o")),
-                    repository.SSAFArtifactKind.SUMMARY,
-                )
-            ),
-            command,
-        )
-
-    def test_an_lto_scratch_object_is_not_an_input(self):
-        self._summary("build/a.o")
-        self._run(["build/a.o", "-object_path_lto", "/tmp/lto.o"])
-        self.assertEqual([self._id("build/a.o").get_path()], self._recorded_inputs())
-
-    def test_a_link_of_nothing_we_know_runs_no_step(self):
-        shim = self._run(["build/a.o"])
-        self.assertEqual([], shim.commands)
-        self.assertEqual([], shim.missing)
-        self.assertIn("nothing to link", self.notes[-1])
-
-
-if __name__ == "__main__":
-    unittest.main()
diff --git a/clang/tools/clang-ssaf-orchestrator-make/tests/test_logging_diagnostics.py b/clang/tools/clang-ssaf-orchestrator-make/tests/test_logging_diagnostics.py
deleted file mode 100644
index 18b1ef57533e2..0000000000000
--- a/clang/tools/clang-ssaf-orchestrator-make/tests/test_logging_diagnostics.py
+++ /dev/null
@@ -1,101 +0,0 @@
-# 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
-
-import io
-import unittest
-from unittest import mock
-
-from clang_ssaf_orchestrator_make import logging_diagnostics
-
-
-class Diagnostics(unittest.TestCase):
-    def _stderr(self, work):
-        stream = io.StringIO()
-        with mock.patch("sys.stderr", stream):
-            work()
-        return stream.getvalue()
-
-    def test_an_error_says_so(self):
-        self.assertEqual(
-            "clang-ssaf-orchestrator-make: error: it broke\n",
-            self._stderr(lambda: logging_diagnostics.report_error("it broke")),
-        )
-
-    def test_details_are_indented_under_their_error(self):
-        self.assertEqual(
-            "clang-ssaf-orchestrator-make: error: two reasons\n"
-            "  the first\n"
-            "  the second\n",
-            self._stderr(
-                lambda: logging_diagnostics.report_error(
-                    "two reasons", ["the first", "the second"]
-                )
-            ),
-        )
-
-    def test_a_warning_says_so(self):
-        self.assertEqual(
-            "clang-ssaf-orchestrator-make: warning: careful\n",
-            self._stderr(lambda: logging_diagnostics.report_warning("careful")),
-        )
-
-    def test_an_error_is_not_mistakable_for_a_note(self):
-        error = self._stderr(lambda: logging_diagnostics.report_error("same words"))
-        note = self._stderr(lambda: logging_diagnostics.report_note(True, "same words"))
-        self.assertNotEqual(error, note)
-
-    def test_a_note_is_silent_unless_asked_for(self):
-        self.assertEqual(
-            "", self._stderr(lambda: logging_diagnostics.report_note(False, "quiet"))
-        )
-        self.assertEqual(
-            "clang-ssaf-orchestrator-make: note: loud\n",
-            self._stderr(lambda: logging_diagnostics.report_note(True, "loud")),
-        )
-
-
-class Results(unittest.TestCase):
-    def _stdout(self, work):
-        stream = io.StringIO()
-        with mock.patch("sys.stdout", stream):
-            work()
-        return stream.getvalue()
-
-    def test_the_output_directory(self):
-        self.assertEqual(
-            "output-dir: /out\n",
-            self._stdout(lambda: logging_diagnostics.report_output_dir("/out")),
-        )
-
-    def test_the_summaries_and_the_link_unit(self):
-        self.assertEqual(
-            "summaries: 3\n"
-            "link-unit: p/build/prg\n"
-            "link-unit-summary: /out/p/build/prg.summary.json\n",
-            self._stdout(
-                lambda: logging_diagnostics.report_summaries(
-                    3, "p/build/prg", "/out/p/build/prg.summary.json"
-                )
-            ),
-        )
-
-    def test_the_analysis_result(self):
-        self.assertEqual(
-            "analysis-result: /out/wpa.json\n",
-            self._stdout(
-                lambda: logging_diagnostics.report_analysis_result("/out/wpa.json")
-            ),
-        )
-
-    def test_results_are_flushed_as_they_are_written(self):
-        flushes = []
-        stream = io.StringIO()
-        stream.flush = lambda: flushes.append(stream.getvalue())
-        with mock.patch("sys.stdout", stream):
-            logging_diagnostics.report_summaries(1, "prg", "/out/prg.json")
-        self.assertEqual(3, len(flushes))
-
-
-if __name__ == "__main__":
-    unittest.main()
diff --git a/clang/tools/clang-ssaf-orchestrator-make/tests/test_options.py b/clang/tools/clang-ssaf-orchestrator-make/tests/test_options.py
deleted file mode 100644
index a1ac1cbdf4eae..0000000000000
--- a/clang/tools/clang-ssaf-orchestrator-make/tests/test_options.py
+++ /dev/null
@@ -1,82 +0,0 @@
-# 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
-
-import contextlib
-import os
-import shutil
-import unittest
-from unittest import mock
-
-from clang_ssaf_orchestrator_make import options
-
-
-class Resolve(unittest.TestCase):
-    def _resolve(self, *extra):
-        return options.resolve(["--extract-summaries=PointerFlow"] + list(extra))
-
-    def test_a_valid_command_line_yields_the_options_as_typed(self):
-        command_line_opts, problem = self._resolve("--", "make", "-j8")
-        self.assertIsNone(problem)
-        self.assertEqual(["make", "-j8"], command_line_opts.build_command)
-        self.assertEqual("PointerFlow", command_line_opts.extract_summaries)
-
-    def test_nothing_on_disk_is_consulted(self):
-        command_line_opts, problem = self._resolve(
-            "--ssaf-clang=/no/such/clang",
-            "-o",
-            "/no/such/output",
-            "--",
-            "make",
-        )
-        self.assertIsNone(problem)
-        self.assertEqual("/no/such/clang", command_line_opts.ssaf_clang)
-        self.assertEqual("/no/such/output", command_line_opts.output_dir)
-
-    def test_the_separator_is_not_part_of_the_build_command(self):
-        command_line_opts, problem = self._resolve("--", "make")
-        self.assertIsNone(problem)
-        self.assertEqual(["make"], command_line_opts.build_command)
-
-    def test_no_build_command_is_a_usage_error(self):
-        command_line_opts, problem = self._resolve()
-        self.assertIsNone(command_line_opts)
-        self.assertEqual(options.USAGE_ERROR, problem.exit_status)
-        self.assertIn("no build command", problem.message)
-
-    def test_a_separator_with_nothing_after_it_is_the_same(self):
-        command_line_opts, problem = self._resolve("--")
-        self.assertIsNone(command_line_opts)
-        self.assertEqual(options.USAGE_ERROR, problem.exit_status)
-
-    def test_resolving_makes_none_of_the_calls_configure_makes(self):
-        # Not every filesystem call: argparse reads the locale through
-        # gettext. These are the calls the configuration layer makes, and the
-        # ones that would mean resolution had started doing its job.
-        watched = (
-            (os, "getcwd"),
-            (os, "listdir"),
-            (os, "access"),
-            (os.path, "isdir"),
-            (os.path, "realpath"),
-            (shutil, "which"),
-        )
-        with contextlib.ExitStack() as stack:
-            for module, name in watched:
-                stack.enter_context(
-                    mock.patch.object(
-                        module,
-                        name,
-                        side_effect=AssertionError("%s called" % name),
-                    )
-                )
-            command_line_opts, problem = self._resolve(
-                "--ssaf-clang=/no/such/clang", "-o", "nowhere", "--", "make"
-            )
-        self.assertIsNone(problem)
-        self.assertEqual("/no/such/clang", command_line_opts.ssaf_clang)
-        self.assertEqual("nowhere", command_line_opts.output_dir)
-
-
-if __name__ == "__main__":
-    unittest.main()
diff --git a/clang/tools/clang-ssaf-orchestrator-make/tests/test_orchestrator.py b/clang/tools/clang-ssaf-orchestrator-make/tests/test_orchestrator.py
deleted file mode 100644
index 1b967192f9835..0000000000000
--- a/clang/tools/clang-ssaf-orchestrator-make/tests/test_orchestrator.py
+++ /dev/null
@@ -1,354 +0,0 @@
-# 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
-
-import io
-import json
-import os
-import shutil
-import tempfile
-import unittest
-from unittest import mock
-
-from clang_ssaf_orchestrator_make import build_graph, config, config_orchestrator
-from clang_ssaf_orchestrator_make import config_shims, options, orchestrator, utils
-from clang_ssaf_orchestrator_make import ssaf_artifact_repository as repository
-
-from . import configs
-
-
-class MakeWarning(unittest.TestCase):
-    def _warning(self, build_command):
-        stream = io.StringIO()
-        with mock.patch("sys.stderr", stream):
-            orchestrator.warn_if_not_make(build_command)
-        return stream.getvalue()
-
-    def test_make_is_silent(self):
-        self.assertEqual("", self._warning(["make"]))
-
-    def test_gmake_is_silent(self):
-        self.assertEqual("", self._warning(["gmake", "-j8"]))
-
-    def test_an_absolute_make_is_silent(self):
-        self.assertEqual("", self._warning(["/usr/bin/make", "-C", "sub"]))
-
-    def test_anything_else_warns_but_does_not_refuse(self):
-        warning = self._warning(["./build.sh"])
-        self.assertIn("./build.sh", warning)
-        self.assertIn("not make", warning)
-        self.assertIn("-B", warning)
-
-    def test_an_env_prefix_is_looked_past_not_objected_to(self):
-        self.assertEqual("", self._warning(["env", "V=1", "make"]))
-        self.assertEqual("", self._warning(["V=1", "make", "-j8"]))
-
-    def test_the_warning_names_the_word_that_is_not_make(self):
-        self.assertIn("'ninja' is not make", self._warning(["env", "V=1", "ninja"]))
-        self.assertIn("'cmake' is not make", self._warning(["cmake", "--build", "."]))
-
-    def test_a_command_of_nothing_but_assignments_says_nothing(self):
-        for build_command in ([], ["V=1"], ["env", "V=1"]):
-            self.assertEqual("", self._warning(build_command), build_command)
-
-    def test_an_env_prefix_around_something_else_still_warns(self):
-        self.assertIn("not make", self._warning(["env", "V=1", "ninja"]))
-
-    def test_the_warning_names_what_will_be_appended(self):
-        self.assertIn("-B", self._warning(["ninja"]))
-
-
-class Main(unittest.TestCase):
-    def _main(self, argv):
-        self.run_calls = []
-        with mock.patch("sys.stderr", io.StringIO()) as stream, mock.patch.object(
-            orchestrator,
-            "run_ssaf_workflow",
-            lambda *args: self.run_calls.append(args),
-        ):
-            return orchestrator.main(argv, {}), stream.getvalue()
-
-    def test_a_usage_error_stops_before_the_build(self):
-        status, message = self._main(["--extract-summaries=PointerFlow"])
-        self.assertEqual(options.USAGE_ERROR, status)
-        self.assertIn("no build command", message)
-        self.assertEqual([], self.run_calls)
-
-    def test_an_environment_error_stops_before_the_build(self):
-        status, message = self._main(
-            [
-                "--extract-summaries=PointerFlow",
-                "--ssaf-clang=/no/such/clang",
-                "--",
-                "make",
-            ]
-        )
-        self.assertEqual(options.ENVIRONMENT_ERROR, status)
-        self.assertIn("--ssaf-clang", message)
-        self.assertEqual([], self.run_calls)
-
-    def test_a_configured_run_is_handed_its_two_configurations(self):
-        configured = ("workflow", "analysis")
-        with mock.patch.object(
-            config_orchestrator, "configure", return_value=(configured, None)
-        ):
-            status, _ = self._main(["--extract-summaries=X", "--", "make"])
-        self.assertEqual(0, status)
-        self.assertEqual([configured], self.run_calls)
-
-
-class ClearOutputDir(unittest.TestCase):
-    def setUp(self):
-        self.tmp = tempfile.mkdtemp()
-        self.addCleanup(shutil.rmtree, self.tmp, True)
-
-    def test_what_a_previous_run_left_is_removed(self):
-        os.makedirs(os.path.join(self.tmp, "shims"))
-        open(os.path.join(self.tmp, "wpa.json"), "w").close()
-        orchestrator.clear_output_dir(self.tmp)
-        self.assertEqual([config.OUTPUT_DIR_MARKER], os.listdir(self.tmp))
-
-    def test_an_output_directory_that_is_not_there_yet_is_made(self):
-        output_dir = os.path.join(self.tmp, "out")
-        orchestrator.clear_output_dir(output_dir)
-        self.assertEqual([config.OUTPUT_DIR_MARKER], os.listdir(output_dir))
-
-
-class PassConfigFile(unittest.TestCase):
-    def setUp(self):
-        self.tmp = tempfile.mkdtemp()
-        self.addCleanup(shutil.rmtree, self.tmp, True)
-        self.workflow_config = config.SSAFWorkflowConfig(
-            output_dir=self.tmp,
-            installed_shim_dir_path="/libexec",
-            build_command=["make"],
-        )
-        self.analysis_config = config.SSAFAnalysisPassConfig(
-            ssaf_clang="/bin/clang",
-            extractors="PointerFlow",
-            ssaf_linker="/bin/clang-ssaf-linker",
-        )
-
-    def test_a_pass_is_written_under_the_output_directory(self):
-        path = orchestrator.write_pass_config(
-            self.workflow_config, self.analysis_config
-        )
-        self.assertEqual(os.path.join(self.tmp, self.analysis_config.file_name), path)
-        self.assertTrue(os.path.isfile(path))
-
-    def test_nothing_is_left_behind_by_the_write(self):
-        orchestrator.write_pass_config(self.workflow_config, self.analysis_config)
-        self.assertEqual(["config-analysis.json"], os.listdir(self.tmp))
-
-    def test_the_document_does_not_carry_its_own_path(self):
-        path = orchestrator.write_pass_config(
-            self.workflow_config, self.analysis_config
-        )
-        with open(path) as handle:
-            written = json.load(handle)
-        self.assertNotIn("serialized_config_path", written)
-        self.assertNotIn(path, written.values())
-
-    def test_an_output_directory_that_does_not_exist_is_not_silently_skipped(self):
-        workflow_config = configs.workflow_config(
-            output_dir=os.path.join(self.tmp, "absent")
-        )
-        with self.assertRaises(OSError):
-            orchestrator.write_pass_config(workflow_config, self.analysis_config)
-
-    def test_a_shim_reads_back_the_run_and_its_own_pass(self):
-        path = orchestrator.write_pass_config(
-            self.workflow_config, self.analysis_config
-        )
-        workflow_config, pass_config = config_shims.bootstrap_from_env(
-            {config.SSAF_CONFIG_ENV_VAR: path}
-        )
-        self.assertEqual(self.workflow_config.to_json(), workflow_config.to_json())
-        self.assertIsInstance(pass_config, config.SSAFAnalysisPassConfig)
-        self.assertEqual("PointerFlow", pass_config.extractors)
-
-
-class RunBuild(unittest.TestCase):
-    def setUp(self):
-        self.tmp = tempfile.mkdtemp()
-        self.addCleanup(shutil.rmtree, self.tmp, True)
-        self.workflow_config = configs.workflow_config(output_dir=self.tmp)
-        self.workflow_config.build_command = ["make", "-j8"]
-
-    def _run(self, **kwargs):
-        with mock.patch("subprocess.call", **kwargs) as called:
-            self.called = called
-            return orchestrator.run_build_with_toolchain_interposition(
-                self.workflow_config, "/out/config.json", "/out/shims", "build"
-            )
-
-    def test_a_build_that_succeeds_is_no_problem(self):
-        self.assertIsNone(self._run(return_value=0))
-
-    def test_the_rebuild_flag_is_appended_to_the_build_command(self):
-        self._run(return_value=0)
-        self.assertEqual(["make", "-j8", "-B"], self.called.call_args[0][0])
-
-    def test_the_build_runs_where_we_were_invoked_and_sees_the_shims(self):
-        self._run(return_value=0)
-        self.assertNotIn("cwd", self.called.call_args[1])
-        env = self.called.call_args[1]["env"]
-        self.assertTrue(env["PATH"].startswith("/out/shims"))
-        self.assertEqual("/out/config.json", env[config.SSAF_CONFIG_ENV_VAR])
-
-    def test_a_build_that_fails_carries_its_own_status(self):
-        problem = self._run(return_value=2)
-        self.assertEqual(2, problem.exit_status)
-        self.assertEqual("build failed (exit 2)", problem.message)
-
-    def test_a_build_killed_by_a_signal_exits_as_a_shell_would(self):
-        problem = self._run(return_value=-15)
-        self.assertEqual(143, problem.exit_status)
-
-    def test_a_build_command_that_cannot_be_run_at_all(self):
-        problem = self._run(side_effect=OSError(2, "No such file"))
-        self.assertEqual(127, problem.exit_status)
-        self.assertIn("cannot run 'make'", problem.message)
-
-    def test_the_description_names_which_build_failed(self):
-        with mock.patch("subprocess.call", return_value=1):
-            problem = orchestrator.run_build_with_toolchain_interposition(
-                self.workflow_config, "/c.json", "/s", "rebuild for something"
-            )
-        self.assertEqual("rebuild for something failed (exit 1)", problem.message)
-
-
-class TheAnalysisPass(unittest.TestCase):
-    def setUp(self):
-        self.tmp = tempfile.mkdtemp()
-        self.addCleanup(shutil.rmtree, self.tmp, True)
-        self.workflow_config = configs.workflow_config(output_dir=self.tmp)
-        self.ssaf_artifact_repo = configs.repository_for(self.tmp)
-        prg = build_graph.BuildArtifactId("/p/prg")
-        configs.build_graph_for(self.tmp).record_build_step(prg, [])
-        self.summary = utils.make_parents(
-            self.ssaf_artifact_repo.get_path_for_artifact(
-                repository.get_ssaf_artifact_id(
-                    prg, repository.SSAFArtifactKind.SUMMARY
-                )
-            )
-        )
-        with open(self.summary, "w") as handle:
-            json.dump({"lu_namespace": [{"kind": "LinkUnit", "name": "prg"}]}, handle)
-
-    def _run(self, analyses, status=0):
-        with mock.patch.object(
-            orchestrator, "run_build_with_toolchain_interposition", return_value=None
-        ), mock.patch("subprocess.call", return_value=status) as called, mock.patch(
-            "sys.stdout", io.StringIO()
-        ):
-            problem = orchestrator.run_ssaf_analysis_pass(
-                self.workflow_config,
-                configs.analysis_config(analyses=analyses),
-                self.ssaf_artifact_repo,
-                "/out/shims",
-            )
-        return problem, called
-
-    def test_without_an_analysis_no_analyzer_runs(self):
-        problem, called = self._run([])
-        self.assertIsNone(problem)
-        called.assert_not_called()
-
-    def test_the_analyzer_runs_every_analysis_over_the_link_unit_summary(self):
-        problem, called = self._run(["A", "B"])
-        self.assertIsNone(problem)
-        self.assertEqual(
-            [
-                "/bin/clang-ssaf-analyzer",
-                self.summary,
-                "-o",
-                config.wpa_result_path(self.tmp),
-                "-a",
-                "A",
-                "-a",
-                "B",
-            ],
-            called.call_args[0][0],
-        )
-
-    def test_a_failed_analysis_fails_the_run_with_its_own_status(self):
-        problem, _ = self._run(["A"], status=3)
-        self.assertEqual(3, problem.exit_status)
-        self.assertEqual("whole-program analysis failed (exit 3)", problem.message)
-
-    def test_an_analyzer_killed_by_a_signal_exits_as_a_shell_would(self):
-        problem, _ = self._run(["A"], status=-9)
-        self.assertEqual(137, problem.exit_status)
-
-
-class TopMostLinkUnit(unittest.TestCase):
-    def setUp(self):
-        self.tmp = tempfile.mkdtemp()
-        self.addCleanup(shutil.rmtree, self.tmp, True)
-        self.ssaf_artifact_repo = configs.repository_for(self.tmp)
-        self.graph = configs.build_graph_for(self.tmp)
-
-    def _record(self, output_path, inputs):
-        inputs = [build_graph.BuildArtifactId(each) for each in inputs]
-        self.graph.record_build_step(
-            build_graph.BuildArtifactId(output_path),
-            inputs,
-        )
-
-    def _summary(self, build_artifact_path):
-        path = utils.make_parents(
-            self.ssaf_artifact_repo.get_path_for_artifact(
-                repository.get_ssaf_artifact_id(
-                    build_graph.BuildArtifactId(build_artifact_path),
-                    repository.SSAFArtifactKind.SUMMARY,
-                )
-            )
-        )
-        document = {
-            "lu_namespace": [
-                {"kind": "LinkUnit", "name": os.path.basename(build_artifact_path)}
-            ]
-        }
-        with open(path, "w") as handle:
-            json.dump(document, handle)
-
-    def test_no_link_unit_at_all(self):
-        link_unit, _, problem = orchestrator.get_topmost_link_unit(
-            self.ssaf_artifact_repo, self.tmp
-        )
-        self.assertIsNone(link_unit)
-        self.assertIn("produced no link unit", problem.message)
-
-    def test_several_that_consume_none_of_each_other(self):
-        self._record("/p/one", ["a.o"])
-        self._record("/p/two", ["b.o"])
-        link_unit, _, problem = orchestrator.get_topmost_link_unit(
-            self.ssaf_artifact_repo, self.tmp
-        )
-        self.assertIsNone(link_unit)
-        self.assertIn("produced 2 unconsumed outputs", problem.message)
-        self.assertIn("p/one", problem.message)
-        self.assertIn("p/two", problem.message)
-
-    def test_one_whose_summary_was_never_written(self):
-        self._record("/p/prg", ["a.o"])
-        link_unit, _, problem = orchestrator.get_topmost_link_unit(
-            self.ssaf_artifact_repo, self.tmp
-        )
-        self.assertIsNone(link_unit)
-        self.assertIn("no summary", problem.message)
-        self.assertIn("p/prg", problem.message)
-
-    def test_one_with_its_summary_is_the_answer(self):
-        self._record("/p/prg", ["a.o"])
-        self._summary("/p/prg")
-        link_unit, _, problem = orchestrator.get_topmost_link_unit(
-            self.ssaf_artifact_repo, self.tmp
-        )
-        self.assertIsNone(problem)
-        self.assertEqual("/p/prg", link_unit.get_path())
-
-
-if __name__ == "__main__":
-    unittest.main()
diff --git a/clang/tools/clang-ssaf-orchestrator-make/tests/test_run.py b/clang/tools/clang-ssaf-orchestrator-make/tests/test_run.py
deleted file mode 100644
index bcfd52713c869..0000000000000
--- a/clang/tools/clang-ssaf-orchestrator-make/tests/test_run.py
+++ /dev/null
@@ -1,84 +0,0 @@
-# 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
-
-import io
-import shutil
-import tempfile
-import unittest
-from unittest import mock
-
-from clang_ssaf_orchestrator_make import config, failure_logs, orchestrator
-from clang_ssaf_orchestrator_make.shims import run
-from clang_ssaf_orchestrator_make.shims import shim as shim_module
-
-from . import configs
-
-
-class RunShim(unittest.TestCase):
-    def setUp(self):
-        self.tmp = tempfile.mkdtemp()
-        self.addCleanup(shutil.rmtree, self.tmp, True)
-        self.env = {
-            config.SSAF_CONFIG_ENV_VAR: orchestrator.write_pass_config(
-                configs.workflow_config(output_dir=self.tmp), configs.analysis_config()
-            )
-        }
-        self.binary_status = 0
-        self.binary_runs = []
-        self.ssaf_runs = []
-        patch = mock.patch.object(
-            shim_module.Shim, "run_bin_tool", lambda shim, path, cwd: self._binary(shim)
-        )
-        patch.start()
-        self.addCleanup(patch.stop)
-
-    def _binary(self, shim):
-        self.binary_runs.append(shim.argv)
-        return self.binary_status
-
-    def _run_shim(self, argv, work=lambda: None):
-        def invoke_ssaf_tools(shim, cwd):
-            self.ssaf_runs.append(shim.argv)
-            work()
-
-        return run.run_shim(invoke_ssaf_tools, argv, self.env)
-
-    def test_a_shim_reached_through_its_link_runs_the_tool_then_the_ssaf_half(self):
-        self.assertEqual(0, self._run_shim(["/out/shims/ld", "-o", "prg", "a.o"]))
-        self.assertEqual([["/out/shims/ld", "-o", "prg", "a.o"]], self.binary_runs)
-        self.assertEqual([["/out/shims/ld", "-o", "prg", "a.o"]], self.ssaf_runs)
-
-    def test_a_forwarded_job_does_not_run_the_tool_again(self):
-        argv = ["/out/shims/ld", "-o", "prg", "a.o"]
-        self.assertEqual(
-            0, self._run_shim(argv + [shim_module.SKIP_BINARY_TOOL_INVOCATION])
-        )
-        self.assertEqual([], self.binary_runs)
-        self.assertEqual([argv], self.ssaf_runs)
-
-    def test_a_tool_that_fails_is_the_shims_status_and_no_ssaf_step_runs(self):
-        self.binary_status = 2
-        self.assertEqual(2, self._run_shim(["ld", "-o", "prg"]))
-        self.assertEqual([], self.ssaf_runs)
-
-    def test_an_internal_error_lets_the_build_go_on_and_is_counted(self):
-        def explode():
-            raise ValueError("deliberate")
-
-        with mock.patch("sys.stderr", io.StringIO()):
-            self.assertEqual(0, self._run_shim(["ld", "-o", "prg"], explode))
-        self.assertEqual(1, failure_logs.count_failure_logs(self.tmp))
-
-    def test_outside_a_run_nothing_runs(self):
-        with mock.patch("sys.stderr", io.StringIO()):
-            status = run.run_shim(
-                lambda shim, cwd: self.ssaf_runs.append(shim.argv), ["ld"], {}
-            )
-        self.assertEqual(1, status)
-        self.assertEqual([], self.binary_runs)
-        self.assertEqual([], self.ssaf_runs)
-
-
-if __name__ == "__main__":
-    unittest.main()
diff --git a/clang/tools/clang-ssaf-orchestrator-make/tests/test_shim.py b/clang/tools/clang-ssaf-orchestrator-make/tests/test_shim.py
deleted file mode 100644
index aa9deb789b342..0000000000000
--- a/clang/tools/clang-ssaf-orchestrator-make/tests/test_shim.py
+++ /dev/null
@@ -1,414 +0,0 @@
-# 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
-
-import io
-import os
-import shutil
-import signal
-import stat
-import sys
-import tempfile
-import types
-import unittest
-from unittest import mock
-
-from clang_ssaf_orchestrator_make import config
-from clang_ssaf_orchestrator_make.shims import shim as shim_utils
-from clang_ssaf_orchestrator_make import build_graph
-from clang_ssaf_orchestrator_make import failure_logs
-from clang_ssaf_orchestrator_make.failure_logs import SSAFFailureKind
-
-from . import configs
-
-
-class BinaryTool(unittest.TestCase):
-    def setUp(self):
-        self.tmp = tempfile.mkdtemp()
-        self.addCleanup(shutil.rmtree, self.tmp, True)
-        self.shim_link_dir_path = os.path.join(self.tmp, "shims")
-        self.binary_tools = os.path.join(self.tmp, "binary")
-        for directory in (self.shim_link_dir_path, self.binary_tools):
-            os.makedirs(directory)
-        for name in ("cc", "clang", "c++", "clang++", "ld", "ar"):
-            self._executable(self.binary_tools, name)
-        self.workflow_config = configs.workflow_config(
-            output_dir=os.path.join(self.tmp, "out")
-        )
-        self.workflow_config.restored_path_env_var = self.binary_tools
-
-    def _executable(self, directory, name):
-        path = os.path.join(directory, name)
-        with open(path, "w") as handle:
-            handle.write("#!/bin/sh\n")
-        os.chmod(path, os.stat(path).st_mode | stat.S_IXUSR)
-        return path
-
-    def _shim(self, name, *extra):
-        argv = [os.path.join(self.shim_link_dir_path, name), "-c", "a.c"]
-        return shim_utils.Shim(
-            self.workflow_config,
-            config.SSAFAnalysisPassConfig(),
-            argv + list(extra),
-        )
-
-    def test_a_name_on_path_runs_that_same_name(self):
-        shim = self._shim("clang")
-        self.assertFalse(shim.skip_binary_tool_invocation)
-        self.assertEqual(os.path.join(self.binary_tools, "clang"), shim.bin_tool_path())
-
-    def test_a_name_on_path_is_resolved_off_our_own_path(self):
-        self.assertEqual(
-            os.path.join(self.binary_tools, "cc"),
-            self._shim("cc").bin_tool_path(),
-        )
-
-    def test_the_marker_says_the_binary_tool_has_already_run(self):
-        shim = self._shim("ld", shim_utils.SKIP_BINARY_TOOL_INVOCATION)
-        self.assertTrue(shim.skip_binary_tool_invocation)
-
-    def test_without_the_marker_the_shim_owns_the_binary_tool(self):
-        shim = self._shim("ld")
-        self.assertFalse(shim.skip_binary_tool_invocation)
-        self.assertEqual(os.path.join(self.binary_tools, "ld"), shim.bin_tool_path())
-
-    def test_the_marker_never_reaches_the_binary_tool(self):
-        shim = self._shim("ld", shim_utils.SKIP_BINARY_TOOL_INVOCATION)
-        self.assertEqual(["-c", "a.c"], shim.argv[1:])
-        self.assertNotIn(shim_utils.SKIP_BINARY_TOOL_INVOCATION, shim.argv)
-
-    def test_a_name_that_no_longer_resolves_yields_no_words(self):
-        os.remove(os.path.join(self.binary_tools, "ar"))
-        self.assertIsNone(self._shim("ar").bin_tool_path())
-
-
-class ShimEnvironment(unittest.TestCase):
-    def setUp(self):
-        self.workflow_config = config.SSAFWorkflowConfig(
-            installed_shim_dir_path="/libexec",
-            restored_path_env_var="/usr/bin",
-        )
-        self.shim = shim_utils.Shim(
-            self.workflow_config, config.SSAFAnalysisPassConfig(), ["cc"]
-        )
-
-    def test_the_binary_tool_sees_the_build_s_own_path(self):
-        env = {
-            config.SSAF_CONFIG_ENV_VAR: "/out/config-analysis.json",
-            "PATH": "/out/shims:/usr/bin",
-            "HOME": "/home/jan",
-        }
-        with mock.patch.dict(os.environ, env, clear=True):
-            cleaned = self.shim.get_unmodified_env()
-        self.assertNotIn(config.SSAF_CONFIG_ENV_VAR, cleaned)
-        self.assertEqual("/usr/bin", cleaned["PATH"])
-        self.assertEqual("/home/jan", cleaned["HOME"])
-
-
-class MissingSummary(unittest.TestCase):
-    def setUp(self):
-        self.tmp = tempfile.mkdtemp()
-        self.addCleanup(shutil.rmtree, self.tmp, True)
-        self.root = os.path.join(self.tmp, "project")
-        self.out = os.path.join(self.tmp, "out")
-        os.makedirs(os.path.join(self.root, "build"))
-        workflow_config = config.SSAFWorkflowConfig(output_dir=self.out)
-        self.shim = shim_utils.Shim(
-            workflow_config,
-            config.SSAFAnalysisPassConfig(),
-            ["ld", "-o", "build/prg"],
-        )
-
-    def _id(self, relative):
-        return build_graph.BuildArtifactId(os.path.join(self.root, relative))
-
-    def _report(self, path):
-        stream = io.StringIO()
-        with mock.patch("sys.stderr", stream):
-            self.shim.log_missing_summary(
-                self._id("build/prg"), build_graph.BuildArtifactId(path)
-            )
-        return stream.getvalue()
-
-    def _logs(self):
-        logs = config.failure_log_dir(self.out)
-        found = []
-        for directory, _, filenames in os.walk(logs):
-            found.extend(
-                os.path.relpath(os.path.join(directory, name), logs)
-                for name in filenames
-                if name.endswith(".log")
-            )
-        return sorted(found)
-
-    def _log(self, ssaf_failure_kind, build_artifact_id):
-        return os.path.relpath(
-            failure_logs.get_failure_log_path(
-                self.out, ssaf_failure_kind, None, build_artifact_id
-            ),
-            config.failure_log_dir(self.out),
-        )
-
-    def test_an_artifact_with_no_summary_is_a_counted_failure(self):
-        message = self._report(os.path.join(self.root, "build", "libx.a"))
-        self.assertEqual(
-            "clang-ssaf-orchestrator-make: error: no summary for %s, consumed "
-            "by %s; nothing it was assembled from was analysed\n"
-            % (
-                self._id("build/libx.a").get_path(),
-                self._id("build/prg").get_path(),
-            ),
-            message,
-        )
-        self.assertEqual(
-            [self._log(SSAFFailureKind.MISSING, self._id("build/libx.a"))],
-            self._logs(),
-        )
-
-    def test_where_the_artifact_lives_does_not_change_that(self):
-        slice_object = os.path.join(self.tmp, "slices", "a-arm64.o")
-        build_artifact_id = build_graph.BuildArtifactId(slice_object)
-        self.assertIn("no summary for", self._report(slice_object))
-        self.assertEqual(
-            [self._log(SSAFFailureKind.MISSING, build_artifact_id)],
-            self._logs(),
-        )
-
-    def test_an_already_reported_artifact_is_not_reported_twice(self):
-        obj = os.path.join(self.root, "build", "a.o")
-        existing = failure_logs.get_failure_log_path(
-            self.out, SSAFFailureKind.EXTRACT, None, self._id("build/a.o")
-        )
-        os.makedirs(os.path.dirname(existing))
-        with open(existing, "w") as handle:
-            handle.write("the SSAF compilation failed\n")
-        self.assertEqual("", self._report(obj))
-        self.assertEqual(
-            [self._log(SSAFFailureKind.EXTRACT, self._id("build/a.o"))],
-            self._logs(),
-        )
-
-
-class WithoutConfiguration(unittest.TestCase):
-    def test_a_shim_run_outside_a_run_says_so(self):
-        stream = io.StringIO()
-        with mock.patch("sys.stderr", stream):
-            status = shim_utils.error_no_config()
-        self.assertEqual(1, status)
-        self.assertEqual(
-            "clang-ssaf-orchestrator-make: error: missing configuration file\n"
-            "  %s is not set, so this is not an orchestrator run\n"
-            % config.SSAF_CONFIG_ENV_VAR,
-            stream.getvalue(),
-        )
-
-
-class Argv(unittest.TestCase):
-    def _shim(self, argv):
-        return shim_utils.Shim(configs.workflow_config(), None, argv)
-
-    def test_the_marker_is_taken_only_off_the_end(self):
-        shim = self._shim(["ld", shim_utils.SKIP_BINARY_TOOL_INVOCATION, "a.o"])
-        self.assertFalse(shim.skip_binary_tool_invocation)
-        self.assertIn(shim_utils.SKIP_BINARY_TOOL_INVOCATION, shim.argv)
-
-    def test_a_command_of_nothing_but_the_marker_keeps_it(self):
-        shim = self._shim([shim_utils.SKIP_BINARY_TOOL_INVOCATION])
-        self.assertFalse(shim.skip_binary_tool_invocation)
-
-    def test_the_tool_is_named_by_the_link_it_was_reached_through(self):
-        shim = self._shim(["/out/shims/c++", "-c", "a.c"])
-        self.assertEqual("c++", shim.invoked_as)
-
-    def test_the_artifact_repository_is_built_once(self):
-        shim = self._shim(["ld", "-o", "prg"])
-        self.assertIs(shim.ssaf_artifact_repo, shim.ssaf_artifact_repo)
-
-
-class RunBinaryTool(unittest.TestCase):
-    def setUp(self):
-        self.tmp = tempfile.mkdtemp()
-        self.addCleanup(shutil.rmtree, self.tmp, True)
-        self.shim = shim_utils.Shim(
-            configs.workflow_config(output_dir=self.tmp),
-            config.SSAFAnalysisPassConfig(),
-            ["ld", "-o", "prg"],
-        )
-
-    def _stderr(self, work):
-        stream = io.StringIO()
-        with mock.patch("sys.stderr", stream):
-            self.status = work()
-        return stream.getvalue()
-
-    def test_a_tool_that_cannot_be_found_is_a_missing_command(self):
-        message = self._stderr(lambda: self.shim.run_bin_tool(None, self.tmp))
-        self.assertEqual(127, self.status)
-        self.assertIn("cannot find the binary ld", message)
-
-    def test_a_tool_that_cannot_be_run_is_a_missing_command(self):
-        message = self._stderr(
-            lambda: self.shim.run_bin_tool(os.path.join(self.tmp, "nope"), self.tmp)
-        )
-        self.assertEqual(127, self.status)
-        self.assertIn("cannot run", message)
-
-    def test_the_tool_runs_as_the_build_asked_in_the_builds_environment(self):
-        self.shim.workflow_config.restored_path_env_var = "/usr/bin"
-        live = {config.SSAF_CONFIG_ENV_VAR: "/out/c.json", "PATH": "/out/shims"}
-        with mock.patch.dict(os.environ, live), mock.patch(
-            "subprocess.call", return_value=3
-        ) as called:
-            status = self.shim.run_bin_tool("/usr/bin/ld", self.tmp)
-        self.assertEqual(3, status)
-        self.assertEqual(["/usr/bin/ld", "-o", "prg"], called.call_args[0][0])
-        self.assertEqual(self.tmp, called.call_args[1]["cwd"])
-        env = called.call_args[1]["env"]
-        self.assertNotIn(config.SSAF_CONFIG_ENV_VAR, env)
-        self.assertEqual("/usr/bin", env["PATH"])
-
-    def test_a_signal_the_tool_died_of_is_re_raised(self):
-        killed = []
-        with mock.patch("signal.signal") as signalled, mock.patch(
-            "os.kill", side_effect=lambda pid, number: killed.append(number)
-        ):
-            status = self.shim._propagate_process_return_status(-signal.SIGTERM)
-        self.assertEqual([signal.SIGTERM], killed)
-        self.assertEqual((signal.SIGTERM, signal.SIG_DFL), signalled.call_args[0])
-        self.assertEqual(128 + signal.SIGTERM, status)
-
-    def test_a_signal_that_cannot_be_reset_is_not_raised_on_ourselves(self):
-        with mock.patch("signal.signal", side_effect=OSError(22, "bad")), mock.patch(
-            "os.kill"
-        ) as killed:
-            self.assertEqual(137, self.shim._propagate_process_return_status(-9))
-        killed.assert_not_called()
-
-
-class Protect(unittest.TestCase):
-    def setUp(self):
-        self.tmp = tempfile.mkdtemp()
-        self.addCleanup(shutil.rmtree, self.tmp, True)
-        self.shim = shim_utils.Shim(
-            configs.workflow_config(output_dir=self.tmp),
-            config.SSAFAnalysisPassConfig(),
-            ["ld", "-o", "prg"],
-        )
-
-    def test_work_that_succeeds_is_not_reported(self):
-        stream = io.StringIO()
-        with mock.patch("sys.stderr", stream):
-            self.assertEqual(0, self.shim.protect(lambda: None))
-        self.assertEqual("", stream.getvalue())
-
-    def test_an_internal_error_is_reported_logged_and_swallowed(self):
-        def explode():
-            raise ValueError("deliberate")
-
-        stream = io.StringIO()
-        with mock.patch("sys.stderr", stream):
-            self.assertEqual(0, self.shim.protect(explode))
-        self.assertIn("internal error in ld", stream.getvalue())
-        self.assertIn("deliberate", stream.getvalue())
-        log = failure_logs.get_failure_log_path(
-            self.tmp, SSAFFailureKind.INTERNAL, self.shim.argv, None
-        )
-        self.assertTrue(os.path.isfile(log))
-        with open(log) as handle:
-            self.assertIn("deliberate", handle.read())
-
-    def test_a_log_that_cannot_be_written_is_itself_reported(self):
-        def explode():
-            raise ValueError("deliberate")
-
-        stream = io.StringIO()
-        with mock.patch("sys.stderr", stream), mock.patch(
-            "clang_ssaf_orchestrator_make.utils.make_parents", side_effect=OSError
-        ):
-            self.assertEqual(0, self.shim.protect(explode))
-        self.assertIn("could not be written", stream.getvalue())
-
-
-class RunningAnSsafStep(unittest.TestCase):
-    def setUp(self):
-        self.tmp = tempfile.mkdtemp()
-        self.addCleanup(shutil.rmtree, self.tmp, True)
-        self.shim = shim_utils.Shim(
-            configs.workflow_config(output_dir=self.tmp),
-            config.SSAFAnalysisPassConfig(),
-            ["ld", "-o", "prg"],
-        )
-        self.build_artifact_id = build_graph.BuildArtifactId("/p/prg")
-
-    def _run(self, command):
-        stream = io.StringIO()
-        with mock.patch("sys.stderr", stream):
-            succeeded = self.shim.run(
-                command, SSAFFailureKind.LINK, self.build_artifact_id
-            )
-        return succeeded, stream.getvalue()
-
-    def test_what_a_step_says_is_kept_from_the_build_unless_relayed(self):
-        command = [sys.executable, "-c", "print('from the step')"]
-        _, quiet = self._run(command)
-        stream = io.StringIO()
-        with mock.patch("sys.stderr", stream):
-            self.shim.run(
-                command, SSAFFailureKind.FORWARD, self.build_artifact_id, True
-            )
-        self.assertNotIn("from the step", quiet)
-        self.assertIn("from the step", stream.getvalue())
-
-
-class FailureLog(unittest.TestCase):
-    def setUp(self):
-        self.tmp = tempfile.mkdtemp()
-        self.addCleanup(shutil.rmtree, self.tmp, True)
-        self.shim = shim_utils.Shim(
-            configs.workflow_config(output_dir=self.tmp),
-            config.SSAFAnalysisPassConfig(),
-            ["ld", "-o", "prg"],
-        )
-        self.build_artifact_id = build_graph.BuildArtifactId("/p/build/a.o")
-
-    def _log(self):
-        return failure_logs.get_failure_log_path(
-            self.tmp, SSAFFailureKind.EXTRACT, None, self.build_artifact_id
-        )
-
-    def _log_failure(self, command, completed):
-        self.shim.log_failure(
-            command, completed, SSAFFailureKind.EXTRACT, self.build_artifact_id
-        )
-
-    def test_the_command_and_its_output_are_recorded(self):
-        completed = types.SimpleNamespace(
-            returncode=2, stdout=b"it broke\n", stderr=None
-        )
-        stream = io.StringIO()
-        with mock.patch("sys.stderr", stream):
-            self._log_failure(["ssaf-clang", "a.c"], completed)
-        with open(self._log()) as handle:
-            self.assertEqual("$ ssaf-clang a.c\nit broke\n", handle.read())
-        self.assertIn("exit 2", stream.getvalue())
-        self.assertIn(self._log(), stream.getvalue())
-
-    def test_a_tool_that_said_nothing_still_gets_a_log(self):
-        completed = types.SimpleNamespace(returncode=1, stdout=None, stderr=None)
-        with mock.patch("sys.stderr", io.StringIO()):
-            self._log_failure(["ssaf-clang"], completed)
-        with open(self._log()) as handle:
-            self.assertEqual("$ ssaf-clang\n", handle.read())
-
-    def test_what_a_tool_wrote_on_its_own_stderr_is_recorded_too(self):
-        completed = types.SimpleNamespace(
-            returncode=1, stdout=b"", stderr=b"error: unknown argument\n"
-        )
-        with mock.patch("sys.stderr", io.StringIO()):
-            self._log_failure(["clang", "-###"], completed)
-        with open(self._log()) as handle:
-            self.assertEqual("$ clang -###\nerror: unknown argument\n", handle.read())
-
-
-if __name__ == "__main__":
-    unittest.main()
diff --git a/clang/tools/clang-ssaf-orchestrator-make/tests/test_ssaf_artifact_repository.py b/clang/tools/clang-ssaf-orchestrator-make/tests/test_ssaf_artifact_repository.py
deleted file mode 100644
index f8b63c9b1acff..0000000000000
--- a/clang/tools/clang-ssaf-orchestrator-make/tests/test_ssaf_artifact_repository.py
+++ /dev/null
@@ -1,102 +0,0 @@
-# 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
-
-import os
-import shutil
-import tempfile
-import unittest
-
-from clang_ssaf_orchestrator_make import build_graph, utils
-from clang_ssaf_orchestrator_make import ssaf_artifact_repository as repository
-
-from . import configs
-
-
-class OutputDirIsNeverLeft(unittest.TestCase):
-    def test_an_artifact_anywhere_stays_inside_the_output_directory(self):
-        ssaf_artifact_repo = configs.repository_for("/out")
-        build_artifact_id = build_graph.BuildArtifactId("/elsewhere/a.o")
-        self.assertTrue(
-            ssaf_artifact_repo.get_path_for_artifact(
-                repository.get_ssaf_artifact_id(
-                    build_artifact_id, repository.SSAFArtifactKind.SUMMARY
-                )
-            ).startswith("/out/ssaf-artifacts/")
-        )
-
-
-class Paths(unittest.TestCase):
-    def setUp(self):
-        self.ssaf_artifact_repo = configs.repository_for("/out")
-        self.graph = configs.build_graph_for("/out")
-
-    def test_artifact_paths(self):
-        self.assertEqual(
-            "/out/ssaf-artifacts/p/build/a.o.summary.json",
-            self.ssaf_artifact_repo.get_path_for_artifact(
-                repository.get_ssaf_artifact_id(
-                    build_graph.BuildArtifactId("/p/build/a.o"),
-                    repository.SSAFArtifactKind.SUMMARY,
-                )
-            ),
-        )
-        self.assertEqual(
-            "/out/ssaf-artifacts/p/prg.summary.json",
-            self.ssaf_artifact_repo.get_path_for_artifact(
-                repository.get_ssaf_artifact_id(
-                    build_graph.BuildArtifactId("/p/prg"),
-                    repository.SSAFArtifactKind.SUMMARY,
-                )
-            ),
-        )
-
-
-class Construction(unittest.TestCase):
-    def test_constructing_it_creates_no_directory(self):
-        output_dir = os.path.join(tempfile.mkdtemp(), "out")
-        self.addCleanup(shutil.rmtree, os.path.dirname(output_dir), True)
-        paths = repository.SSAFArtifactRepository(output_dir)
-        self.assertEqual(output_dir, paths.ssaf_artifact_dir)
-        self.assertFalse(os.path.exists(output_dir))
-
-
-class Counts(unittest.TestCase):
-    def setUp(self):
-        self.tmp = tempfile.mkdtemp()
-        self.addCleanup(shutil.rmtree, self.tmp, True)
-        self.ssaf_artifact_repo = configs.repository_for(self.tmp)
-        self.graph = configs.build_graph_for(self.tmp)
-
-    def _write(self, path):
-        open(utils.make_parents(path), "w").close()
-
-    def test_an_output_directory_that_does_not_exist_counts_nothing(self):
-        absent = configs.repository_for(os.path.join(self.tmp, "none"))
-        self.assertEqual(0, absent.count_summaries())
-
-    def test_each_kind_is_counted_apart_at_any_depth(self):
-        self._write(
-            self.ssaf_artifact_repo.get_path_for_artifact(
-                repository.get_ssaf_artifact_id(
-                    build_graph.BuildArtifactId("/p/a.o"),
-                    repository.SSAFArtifactKind.SUMMARY,
-                )
-            )
-        )
-        self._write(
-            self.ssaf_artifact_repo.get_path_for_artifact(
-                repository.get_ssaf_artifact_id(
-                    build_graph.BuildArtifactId("/p/deep/b.o"),
-                    repository.SSAFArtifactKind.SUMMARY,
-                )
-            )
-        )
-        self._write(
-            self.graph.get_buildstep_record_path(build_graph.BuildArtifactId("/p/prg"))
-        )
-        self.assertEqual(2, self.ssaf_artifact_repo.count_summaries())
-
-
-if __name__ == "__main__":
-    unittest.main()
diff --git a/clang/tools/clang-ssaf-orchestrator-make/tests/test_utils.py b/clang/tools/clang-ssaf-orchestrator-make/tests/test_utils.py
deleted file mode 100644
index f44d649fd8765..0000000000000
--- a/clang/tools/clang-ssaf-orchestrator-make/tests/test_utils.py
+++ /dev/null
@@ -1,94 +0,0 @@
-# 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
-
-import io
-import json
-import os
-import shutil
-import tempfile
-import unittest
-from unittest import mock
-
-from clang_ssaf_orchestrator_make import utils
-
-
-class MakeParents(unittest.TestCase):
-    def setUp(self):
-        self.tmp = tempfile.mkdtemp()
-        self.addCleanup(shutil.rmtree, self.tmp, True)
-
-    def test_it_returns_the_path_it_was_given(self):
-        path = os.path.join(self.tmp, "a", "b", "c.json")
-        self.assertEqual(path, utils.make_parents(path))
-        self.assertTrue(os.path.isdir(os.path.dirname(path)))
-
-    def test_an_existing_directory_is_not_an_error(self):
-        path = os.path.join(self.tmp, "a", "c.json")
-        utils.make_parents(path)
-        utils.make_parents(path)
-        self.assertTrue(os.path.isdir(os.path.dirname(path)))
-
-    def test_a_bare_name_has_no_parent_to_make(self):
-        self.assertEqual("c.json", utils.make_parents("c.json"))
-
-    def test_a_parent_that_cannot_be_made_is_not_swallowed(self):
-        blocked = os.path.join(self.tmp, "file")
-        open(blocked, "w").close()
-        with self.assertRaises(OSError):
-            utils.make_parents(os.path.join(blocked, "a", "c.json"))
-
-
-class Json(unittest.TestCase):
-    def setUp(self):
-        self.tmp = tempfile.mkdtemp()
-        self.addCleanup(shutil.rmtree, self.tmp, True)
-        self.path = os.path.join(self.tmp, "doc.json")
-
-    def test_a_document_round_trips(self):
-        utils.write_json(self.path, {"a": [1, 2]})
-        self.assertEqual({"a": [1, 2]}, utils.read_json(self.path))
-
-    def test_writing_leaves_no_temporary_behind(self):
-        utils.write_json(self.path, {})
-        self.assertEqual(["doc.json"], os.listdir(self.tmp))
-
-    def test_a_write_replaces_rather_than_appends(self):
-        utils.write_json(self.path, {"a": 1})
-        utils.write_json(self.path, {"b": 2})
-        self.assertEqual({"b": 2}, utils.read_json(self.path))
-
-    def test_an_absent_file_reads_as_nothing_and_says_nothing(self):
-        stream = io.StringIO()
-        with mock.patch("sys.stderr", stream):
-            self.assertIsNone(utils.read_json(os.path.join(self.tmp, "absent")))
-        self.assertEqual("", stream.getvalue())
-
-    def test_a_corrupt_file_reads_as_nothing_and_says_so(self):
-        with open(self.path, "w") as handle:
-            handle.write('{"a": ')
-        stream = io.StringIO()
-        with mock.patch("sys.stderr", stream):
-            self.assertIsNone(utils.read_json(self.path))
-        self.assertIn("is not valid JSON", stream.getvalue())
-        self.assertIn(self.path, stream.getvalue())
-
-    def test_the_two_cases_are_distinguishable(self):
-        absent = io.StringIO()
-        corrupt = io.StringIO()
-        with open(self.path, "w") as handle:
-            handle.write("{")
-        with mock.patch("sys.stderr", absent):
-            utils.read_json(os.path.join(self.tmp, "absent"))
-        with mock.patch("sys.stderr", corrupt):
-            utils.read_json(self.path)
-        self.assertNotEqual(absent.getvalue(), corrupt.getvalue())
-
-    def test_what_is_written_is_readable_json(self):
-        utils.write_json(self.path, {"kind": "link", "inputs": ["a.o"]})
-        with open(self.path) as handle:
-            self.assertEqual({"kind": "link", "inputs": ["a.o"]}, json.load(handle))
-
-
-if __name__ == "__main__":
-    unittest.main()



More information about the cfe-commits mailing list