llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang-static-analyzer-1 Author: Jan Korous (jkorous-apple) <details> <summary>Changes</summary> 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. --- Patch is 33.76 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/231731.diff 19 Files Affected: - (modified) clang/docs/ScalableStaticAnalysis/user-docs/SourceEditGeneration.md (+12) - (added) clang/test/Analysis/Scalable/ssaf-merge-conflict-report/Inputs/conflicts-a.sarif (+118) - (added) clang/test/Analysis/Scalable/ssaf-merge-conflict-report/Inputs/conflicts-b.sarif (+118) - (added) clang/test/Analysis/Scalable/ssaf-merge-conflict-report/Inputs/conflicts-c.sarif (+67) - (added) clang/test/Analysis/Scalable/ssaf-merge-conflict-report/Inputs/no-conflicts.sarif (+15) - (added) clang/test/Analysis/Scalable/ssaf-merge-conflict-report/Inputs/other-tool.sarif (+15) - (added) clang/test/Analysis/Scalable/ssaf-merge-conflict-report/Inputs/two-runs.sarif (+24) - (added) clang/test/Analysis/Scalable/ssaf-merge-conflict-report/cli-errors.test (+69) - (added) clang/test/Analysis/Scalable/ssaf-merge-conflict-report/empty.test (+14) - (added) clang/test/Analysis/Scalable/ssaf-merge-conflict-report/help.test (+19) - (added) clang/test/Analysis/Scalable/ssaf-merge-conflict-report/merge.test (+28) - (added) clang/test/Analysis/Scalable/ssaf-merge-conflict-report/nested.test (+17) - (added) clang/test/Analysis/Scalable/ssaf-merge-conflict-report/order-invariance.test (+8) - (added) clang/test/Analysis/Scalable/ssaf-merge-conflict-report/src-edit-merge-reports.test (+26) - (added) clang/test/Analysis/Scalable/ssaf-merge-conflict-report/version.test (+5) - (modified) clang/test/CMakeLists.txt (+1) - (modified) clang/tools/CMakeLists.txt (+1) - (added) clang/tools/clang-ssaf-merge-conflict-report/CMakeLists.txt (+12) - (added) clang/tools/clang-ssaf-merge-conflict-report/MergeConflictReport.cpp (+249) ``````````diff diff --git a/clang/docs/ScalableStaticAnalysis/user-docs/SourceEditGeneration.md b/clang/docs/ScalableStaticAnalysis/user-docs/SourceEditGeneration.md index a0b52b3f7df38..842238730a106 100644 --- a/clang/docs/ScalableStaticAnalysis/user-docs/SourceEditGeneration.md +++ b/clang/docs/ScalableStaticAnalysis/user-docs/SourceEditGeneration.md @@ -81,3 +81,15 @@ 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 new file mode 100644 index 0000000000000..110b144a6d266 --- /dev/null +++ b/clang/test/Analysis/Scalable/ssaf-merge-conflict-report/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-merge-conflict-report/Inputs/conflicts-b.sarif b/clang/test/Analysis/Scalable/ssaf-merge-conflict-report/Inputs/conflicts-b.sarif new file mode 100644 index 0000000000000..7a7a92bb92921 --- /dev/null +++ b/clang/test/Analysis/Scalable/ssaf-merge-conflict-report/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-merge-conflict-report/Inputs/conflicts-c.sarif b/clang/test/Analysis/Scalable/ssaf-merge-conflict-report/Inputs/conflicts-c.sarif new file mode 100644 index 0000000000000..dc5b1c020be8d --- /dev/null +++ b/clang/test/Analysis/Scalable/ssaf-merge-conflict-report/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-merge-conflict-report/Inputs/no-conflicts.sarif b/clang/test/Analysis/Scalable/ssaf-merge-conflict-report/Inputs/no-conflicts.sarif new file mode 100644 index 0000000000000..da2d8c6941462 --- /dev/null +++ b/clang/test/Analysis/Scalable/ssaf-merge-conflict-report/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-merge-conflict-report/Inputs/other-tool.sarif b/clang/test/Analysis/Scalable/ssaf-merge-conflict-report/Inputs/other-tool.sarif new file mode 100644 index 0000000000000..1c2ea28ea3ad4 --- /dev/null +++ b/clang/test/Analysis/Scalable/ssaf-merge-conflict-report/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-merge-conflict-report/Inputs/two-runs.sarif b/clang/test/Analysis/Scalable/ssaf-merge-conflict-report/Inputs/two-runs.sarif new file mode 100644 index 0000000000000..cda78d1c4282d --- /dev/null +++ b/clang/test/Analysis/Scalable/ssaf-merge-conflict-report/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-merge-conflict-report/cli-errors.test b/clang/test/Analysis/Scalable/ssaf-merge-conflict-report/cli-errors.test new file mode 100644 index 0000000000000..05a17c2f6cfab --- /dev/null +++ b/clang/test/Analysis/Scalable/ssaf-merge-conflict-report/cli-errors.test @@ -0,0 +1,69 @@ +// 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 new file mode 100644 index 0000000000000..948cdfd95cedd --- /dev/null +++ b/clang/test/Analysis/Scalable/ssaf-merge-conflict-report/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-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 new file mode 100644 index 0000000000000..c8f0884255f9c --- /dev/null +++ b/clang/test/Analysis/Scalable/ssaf-merge-conflict-report/help.test @@ -0,0 +1,19 @@ +// 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 new file mode 100644 index 0000000000000..e54317ff9b809 --- /dev/null +++ b/clang/test/Analysis/Scalable/ssaf-merge-conflict-report/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-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 new file mode 100644 index 0000000000000..7f7bce20c8dac --- /dev/null +++ b/clang/test/Analysis/Scalable/ssaf-m... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/231731 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
