[clang] [llvm] [clang][ssaf] Add clang-ssaf-conflict-merge (PR #235192)

via cfe-commits cfe-commits at lists.llvm.org
Fri Oct 23 19:49:15 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang-ssaf

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

Author: Jan Korous (jkorous-apple)

<details>
<summary>Changes</summary>

clang-ssaf-src-edit-merge reports the edits it drops because they
overlap, but only those of the one merge it ran. Add a tool that merges
such reports, so that the conflicts found while merging the edits of an
archive can be carried into the report of the program it is linked into.

This relands f32ac72b4f1e (#<!-- -->231731), reverted with its stack in
782610a701b4 (#<!-- -->232274), under a shorter name that matches
clang-ssaf-src-edit-merge. The GN build files come from
1c563eafd44e (#<!-- -->232115).

Assisted-by: Claude




---

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


21 Files Affected:

- (modified) clang/docs/ScalableStaticAnalysis/user-docs/SourceEditGeneration.md (+13) 
- (added) clang/test/Analysis/Scalable/ssaf-conflict-merge/Inputs/conflicts-a.sarif (+118) 
- (added) clang/test/Analysis/Scalable/ssaf-conflict-merge/Inputs/conflicts-b.sarif (+118) 
- (added) clang/test/Analysis/Scalable/ssaf-conflict-merge/Inputs/conflicts-c.sarif (+67) 
- (added) clang/test/Analysis/Scalable/ssaf-conflict-merge/Inputs/no-conflicts.sarif (+15) 
- (added) clang/test/Analysis/Scalable/ssaf-conflict-merge/Inputs/other-tool.sarif (+15) 
- (added) clang/test/Analysis/Scalable/ssaf-conflict-merge/Inputs/two-runs.sarif (+24) 
- (added) clang/test/Analysis/Scalable/ssaf-conflict-merge/cli-errors.test (+69) 
- (added) clang/test/Analysis/Scalable/ssaf-conflict-merge/empty.test (+14) 
- (added) clang/test/Analysis/Scalable/ssaf-conflict-merge/help.test (+19) 
- (added) clang/test/Analysis/Scalable/ssaf-conflict-merge/merge.test (+28) 
- (added) clang/test/Analysis/Scalable/ssaf-conflict-merge/nested.test (+17) 
- (added) clang/test/Analysis/Scalable/ssaf-conflict-merge/order-invariance.test (+8) 
- (added) clang/test/Analysis/Scalable/ssaf-conflict-merge/src-edit-merge-reports.test (+26) 
- (added) clang/test/Analysis/Scalable/ssaf-conflict-merge/version.test (+5) 
- (modified) clang/test/CMakeLists.txt (+1) 
- (modified) clang/tools/CMakeLists.txt (+1) 
- (added) clang/tools/clang-ssaf-conflict-merge/CMakeLists.txt (+12) 
- (added) clang/tools/clang-ssaf-conflict-merge/ConflictMerge.cpp (+247) 
- (modified) llvm/utils/gn/secondary/clang/test/BUILD.gn (+1) 
- (added) llvm/utils/gn/secondary/clang/tools/clang-ssaf-conflict-merge/BUILD.gn (+8) 


``````````diff
diff --git a/clang/docs/ScalableStaticAnalysis/user-docs/SourceEditGeneration.md b/clang/docs/ScalableStaticAnalysis/user-docs/SourceEditGeneration.md
index af7fc7f56aa8ca..bb580c1bdc2042 100644
--- a/clang/docs/ScalableStaticAnalysis/user-docs/SourceEditGeneration.md
+++ b/clang/docs/ScalableStaticAnalysis/user-docs/SourceEditGeneration.md
@@ -65,3 +65,16 @@ $ clang-apply-replacements --remove-change-desc-files <dir-with-yaml>
 
 The transformation report can be consumed by any SARIF viewer.
 
+
+## Merging conflict reports
+
+`clang-ssaf-src-edit-merge --sarif-conflicts-out=` reports the overlapping
+edits it dropped while merging. `clang-ssaf-conflict-merge` merges such
+reports, 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-conflict-merge 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-conflict-merge/Inputs/conflicts-a.sarif b/clang/test/Analysis/Scalable/ssaf-conflict-merge/Inputs/conflicts-a.sarif
new file mode 100644
index 00000000000000..110b144a6d266b
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-conflict-merge/Inputs/conflicts-a.sarif
@@ -0,0 +1,118 @@
+{
+  "$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-conflict-merge/Inputs/conflicts-b.sarif b/clang/test/Analysis/Scalable/ssaf-conflict-merge/Inputs/conflicts-b.sarif
new file mode 100644
index 00000000000000..7a7a92bb92921e
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-conflict-merge/Inputs/conflicts-b.sarif
@@ -0,0 +1,118 @@
+{
+  "$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-conflict-merge/Inputs/conflicts-c.sarif b/clang/test/Analysis/Scalable/ssaf-conflict-merge/Inputs/conflicts-c.sarif
new file mode 100644
index 00000000000000..dc5b1c020be8d5
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-conflict-merge/Inputs/conflicts-c.sarif
@@ -0,0 +1,67 @@
+{
+  "$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-conflict-merge/Inputs/no-conflicts.sarif b/clang/test/Analysis/Scalable/ssaf-conflict-merge/Inputs/no-conflicts.sarif
new file mode 100644
index 00000000000000..da2d8c69414628
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-conflict-merge/Inputs/no-conflicts.sarif
@@ -0,0 +1,15 @@
+{
+  "$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-conflict-merge/Inputs/other-tool.sarif b/clang/test/Analysis/Scalable/ssaf-conflict-merge/Inputs/other-tool.sarif
new file mode 100644
index 00000000000000..1c2ea28ea3ad42
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-conflict-merge/Inputs/other-tool.sarif
@@ -0,0 +1,15 @@
+{
+  "$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-conflict-merge/Inputs/two-runs.sarif b/clang/test/Analysis/Scalable/ssaf-conflict-merge/Inputs/two-runs.sarif
new file mode 100644
index 00000000000000..cda78d1c4282dc
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-conflict-merge/Inputs/two-runs.sarif
@@ -0,0 +1,24 @@
+{
+  "$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-conflict-merge/cli-errors.test b/clang/test/Analysis/Scalable/ssaf-conflict-merge/cli-errors.test
new file mode 100644
index 00000000000000..675cb5c42e5dd3
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-conflict-merge/cli-errors.test
@@ -0,0 +1,69 @@
+// Tests for clang-ssaf-conflict-merge errors.
+
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+
+// ============================================================================
+// CLI error: no arguments
+// ============================================================================
+
+// RUN: not clang-ssaf-conflict-merge 2>&1 \
+// RUN:   | FileCheck %s --check-prefix=NO-ARGS
+// NO-ARGS: clang-ssaf-conflict-merge{{(\.exe)?}}: Not enough positional command line arguments specified!
+
+// ============================================================================
+// CLI error: missing -o
+// ============================================================================
+
+// RUN: not clang-ssaf-conflict-merge %S/Inputs/conflicts-a.sarif 2>&1 \
+// RUN:   | FileCheck %s --check-prefix=NO-OUTPUT
+// NO-OUTPUT: clang-ssaf-conflict-merge{{(\.exe)?}}: for the -o option: must be specified at least once!
+
+// ============================================================================
+// Error: nonexistent input
+// ============================================================================
+
+// RUN: not clang-ssaf-conflict-merge %t/missing.sarif \
+// RUN:   -o %t/out.sarif 2>&1 \
+// RUN:   | FileCheck %s --check-prefix=MISSING -DPATH=%t/missing.sarif
+// MISSING: clang-ssaf-conflict-merge: error: failed to read '[[PATH]]': {{.*}}
+
+// ============================================================================
+// Error: input is not JSON
+// ============================================================================
+
+// RUN: echo 'not json' > %t/not-json.sarif
+// RUN: not clang-ssaf-conflict-merge %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-conflict-merge: error: failed to parse '[[PATH]]': {{.*}}
+
+// ============================================================================
+// Error: input does not have exactly one run
+// ============================================================================
+
+// RUN: not clang-ssaf-conflict-merge %S/Inputs/two-runs.sarif \
+// RUN:   -o %t/out.sarif 2>&1 \
+// RUN:   | FileCheck %s --check-prefix=TWO-RUNS
+// TWO-RUNS: clang-ssaf-conflict-merge: error: '{{.*}}two-runs.sarif' is not a SARIF log with exactly one run
+
+// ============================================================================
+// Error: inputs written by different tools
+// ============================================================================
+
+// RUN: not clang-ssaf-conflict-merge %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-conflict-merge: 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-conflict-merge %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-conflict-merge: 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-conflict-merge/empty.test b/clang/test/Analysis/Scalable/ssaf-conflict-merge/empty.test
new file mode 100644
index 00000000000000..dfa2d927a9020b
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-conflict-merge/empty.test
@@ -0,0 +1,14 @@
+// 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-conflict-merge %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-conflict-merge %S/Inputs/conflicts-a.sarif \
+// RUN:   -o %t/a.sarif
+// RUN: clang-ssaf-conflict-merge %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-conflict-merge/help.test b/clang/test/Analysis/Scalable/ssaf-conflict-merge/help.test
new file mode 100644
index 00000000000000..de1262800c6944
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-conflict-merge/help.test
@@ -0,0 +1,19 @@
+// Test clang-ssaf-conflict-merge help option
+
+// RUN: clang-ssaf-conflict-merge --help-list-hidden \
+// RUN:           | FileCheck %s --match-full-lines
+
+// CHECK:      OVERVIEW: SSAF Conflict Report Merger
+// CHECK-EMPTY:
+// CHECK-NEXT: USAGE: clang-ssaf-conflict-merge{{(\.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-conflict-merge/merge.test b/clang/test/Analysis/Scalable/ssaf-conflict-merge/merge.test
new file mode 100644
index 00000000000000..c0823b5e514410
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-conflict-merge/merge.test
@@ -0,0 +1,28 @@
+// Two conflict reports that share a conflict merge into one run.
+
+// RUN: rm -rf %t && mkdir -p %t
+// RUN: clang-ssaf-conflict-merge %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-conflict-merge %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-conflict-merge/nested.test b/clang/test/Analysis/Scalable/ssaf-conflict-merge/nested.test
new file mode 100644
index 00000000000000..6a3fa47bdf8195
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-conflict-merge/nested.test
@@ -0,0 +1,17 @@
+// 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-conflict-merge %S/Inputs/conflicts-a.sarif \
+// RUN:   %S/Inputs/conflicts-b.sarif -o %t/ab.sarif
+// RUN: clang-ssaf-conflict-merge %t/ab.sarif \
+// RU...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/235192


More information about the cfe-commits mailing list