Author: Ziqing Luo Date: 2026-09-13T14:08:56-07:00 New Revision: 4b08871f7ffe6ad818147145f8b6103e6c9b2c95
URL: https://github.com/llvm/llvm-project/commit/4b08871f7ffe6ad818147145f8b6103e6c9b2c95 DIFF: https://github.com/llvm/llvm-project/commit/4b08871f7ffe6ad818147145f8b6103e6c9b2c95.diff LOG: [SSAF][SourceEdit] Wire in 'clang-ssaf-src-edit-merge' and add multi-TU tests (#220372) With 'clang-ssaf-src-edit-merge', we can test source edits over multiple translation units: their Replacements are merged before apply. This covers both clean merges and conflicts. Added: clang/test/Analysis/Scalable/source-edit-generation/multi-tu-conflict-edits-merge.cpp clang/test/Analysis/Scalable/source-edit-generation/multi-tu-edits-merge.cpp Modified: Removed: ################################################################################ diff --git a/clang/test/Analysis/Scalable/source-edit-generation/multi-tu-conflict-edits-merge.cpp b/clang/test/Analysis/Scalable/source-edit-generation/multi-tu-conflict-edits-merge.cpp new file mode 100644 index 0000000000000..27998e17b773d --- /dev/null +++ b/clang/test/Analysis/Scalable/source-edit-generation/multi-tu-conflict-edits-merge.cpp @@ -0,0 +1,288 @@ +// Tests clang-ssaf-src-edit-merge against real multi-TU source. +// Specifically, this file tests conflicting and duplicating source +// edits across multiple-TUs. + +// RUN: rm -rf %t && mkdir -p %t +// RUN: split-file %s %t + +// DEFINE: %{casedir} = unset +// DEFINE: %{testname} = unset +// DEFINE: %{tu_json} = %{casedir}/%{testname}.tu.json +// DEFINE: %{lu_json} = %{casedir}/%{testname}.lu.json +// DEFINE: %{wpa_json} = %{casedir}/%{testname}.wpa.json +// DEFINE: %{apply_dir} = %{casedir}/%{testname}_apply +// DEFINE: %{edits_yaml} = %{apply_dir}/%{testname}.edits.yaml +// DEFINE: %{extract} = %clang -fsyntax-only %{casedir}/%{testname}.cpp \ +// DEFINE: --ssaf-extract-summaries=PointerFlow,UnsafeBufferUsage \ +// DEFINE: --ssaf-compilation-unit-id=%{testname}.cu --ssaf-tu-summary-file=%{tu_json} +// DEFINE: %{link} = clang-ssaf-linker %{tu_json} -o %{lu_json} +// DEFINE: %{analyze} = clang-ssaf-analyzer %{lu_json} -o %{wpa_json} -a UnsafeBufferReachableAnalysisResult +// DEFINE: %{transform} = mkdir -p %{apply_dir} && %clang -fsyntax-only %{casedir}/%{testname}.cpp \ +// DEFINE: --ssaf-source-transformation=cpp-bounded-buffers \ +// DEFINE: --ssaf-global-scope-analysis-result=%{wpa_json} \ +// DEFINE: --ssaf-src-edit-file=%{edits_yaml} \ +// DEFINE: --ssaf-transformation-report-file=%{casedir}/%{testname}.report.sarif \ +// DEFINE: --ssaf-compilation-unit-id=%{testname}.cu --ssaf-link-unit-id=%{testname}.lu +// DEFINE: %{pipeline} = %{extract} && %{link} && %{analyze} && %{transform} +// DEFINE: %{merge_inputs} = unset +// DEFINE: %{merge} = clang-ssaf-src-edit-merge %{merge_inputs} -o %{casedir}/merged.yaml --sarif-conflicts-out=%{casedir}/conflicts.sarif 2> %{casedir}/merge.stderr + +//--- dedup/shared.h +int *g; + +//--- dedup/a.cpp +#include "shared.h" +void use_a() { g[5] = 0; } + +//--- dedup/b.cpp +#include "shared.h" +void use_b() { g[7] = 0; } + +// REDEFINE: %{casedir} = %t/dedup +// REDEFINE: %{testname} = a +// RUN: %{pipeline} +// REDEFINE: %{testname} = b +// RUN: %{pipeline} + +// Both TUs really produced the same replacement. +// RUN: FileCheck --check-prefix=DEDUP_A --input-file=%t/dedup/a_apply/a.edits.yaml %s +// DEDUP_A: Offset: 0 +// DEDUP_A-NEXT: Length: 5 +// DEDUP_A-NEXT: ReplacementText: 'bounded_ptr<int> ' +// RUN: FileCheck --check-prefix=DEDUP_B --input-file=%t/dedup/b_apply/b.edits.yaml %s +// DEDUP_B: Offset: 0 +// DEDUP_B-NEXT: Length: 5 +// DEDUP_B-NEXT: ReplacementText: 'bounded_ptr<int> ' + +// REDEFINE: %{merge_inputs} = %t/dedup/a_apply/a.edits.yaml %t/dedup/b_apply/b.edits.yaml +// RUN: %{merge} + +// Exactly one survivor: +// RUN: FileCheck --check-prefix=DEDUP_MERGED --input-file=%t/dedup/merged.yaml %s +// DEDUP_MERGED: Replacements: +// DEDUP_MERGED-NEXT: - FilePath: +// DEDUP_MERGED-SAME: shared.h +// DEDUP_MERGED-NEXT: Offset: 0 +// DEDUP_MERGED-NEXT: Length: 5 +// DEDUP_MERGED-NEXT: ReplacementText: 'bounded_ptr<int> ' +// DEDUP_MERGED-NOT: FilePath: + +// A dedup is not a conflict: +// RUN: FileCheck --check-prefix=DEDUP_NOSTDERR --input-file=%t/dedup/merge.stderr --allow-empty %s +// DEDUP_NOSTDERR-NOT: conflict: + +// The SARIF document is still written (its presence just signals reporting +// was requested), but with no results. +// RUN: FileCheck --check-prefix=DEDUP_SARIF --input-file=%t/dedup/conflicts.sarif %s +// DEDUP_SARIF: "results": [] + + +//--- two-way-conflict/shared.h +#if USE_LONG +long +#else +int +#endif +*g; + +//--- two-way-conflict/a.cpp +#include "shared.h" +void use_a() { g[5] = 0; } + +//--- two-way-conflict/b.cpp +#define USE_LONG 11 +#include "shared.h" +void use_b() { g[7] = 0; } + +// REDEFINE: %{casedir} = %t/two-way-conflict +// REDEFINE: %{testname} = a +// RUN: %{pipeline} +// REDEFINE: %{testname} = b +// RUN: %{pipeline} + +// Before merging: both real per-TU replacements exist and disagree. +// RUN: FileCheck --check-prefix=TWC_A --input-file=%t/two-way-conflict/a_apply/a.edits.yaml %s +// TWC_A: Offset: 24 +// TWC_A-NEXT: Length: 12 +// TWC_A-NEXT: ReplacementText: 'bounded_ptr<int> ' +// RUN: FileCheck --check-prefix=TWC_B --input-file=%t/two-way-conflict/b_apply/b.edits.yaml %s +// TWC_B: Offset: 13 +// TWC_B-NEXT: Length: 23 +// TWC_B-NEXT: ReplacementText: 'bounded_ptr<long> ' + +// REDEFINE: %{merge_inputs} = %t/two-way-conflict/a_apply/a.edits.yaml %t/two-way-conflict/b_apply/b.edits.yaml +// RUN: %{merge} + +// After merging: gone, and reported. +// RUN: FileCheck --check-prefix=TWC_MERGED --input-file=%t/two-way-conflict/merged.yaml %s +// TWC_MERGED: Replacements: [] + +// RUN: FileCheck --check-prefix=TWC_STDERR --input-file=%t/two-way-conflict/merge.stderr %s +// TWC_STDERR: conflict: +// TWC_STDERR-SAME: skipped +// TWC_STDERR-SAME: 2 +// TWC_STDERR-SAME: shared.h:13 + +// RUN: FileCheck --check-prefix=TWC_SARIF --input-file=%t/two-way-conflict/conflicts.sarif %s +// TWC_SARIF: "level": "error" +// TWC_SARIF: "uri": "file://{{.*}}shared.h" +// TWC_SARIF: "byteOffset": 13 +// TWC_SARIF: "relatedLocations": +// TWC_SARIF: "id": 1 +// TWC_SARIF: "text": "candidate edit: \"bounded_ptr<int> \"" +// TWC_SARIF: "id": 2 +// TWC_SARIF: "text": "candidate edit: \"bounded_ptr<long> \"" +// TWC_SARIF: "ruleId": "clang-reforge-replacement-conflict" + + + +//--- three-way-conflict/shared.h +#if VARIANT == 1 +long +#elif VARIANT == 2 +char +#else +int +#endif +*g; + +//--- three-way-conflict/a.cpp +#include "shared.h" +void use_a() { g[5] = 0; } + +//--- three-way-conflict/b.cpp +#define VARIANT 1 +#include "shared.h" +void use_b() { g[7] = 0; } + +//--- three-way-conflict/c.cpp +#define VARIANT 2 +#include "shared.h" +void use_c() { g[9] = 0; } + +// REDEFINE: %{casedir} = %t/three-way-conflict +// REDEFINE: %{testname} = a +// RUN: %{pipeline} +// REDEFINE: %{testname} = b +// RUN: %{pipeline} +// REDEFINE: %{testname} = c +// RUN: %{pipeline} + +// All three real per-TU replacements exist and disagree. +// RUN: FileCheck --check-prefix=THW_A --input-file=%t/three-way-conflict/a_apply/a.edits.yaml %s +// THW_A: Offset: 52 +// THW_A-NEXT: Length: 12 +// THW_A-NEXT: ReplacementText: 'bounded_ptr<int> ' +// RUN: FileCheck --check-prefix=THW_B --input-file=%t/three-way-conflict/b_apply/b.edits.yaml %s +// THW_B: Offset: 17 +// THW_B-NEXT: Length: 47 +// THW_B-NEXT: ReplacementText: 'bounded_ptr<long> ' +// RUN: FileCheck --check-prefix=THW_C --input-file=%t/three-way-conflict/c_apply/c.edits.yaml %s +// THW_C: Offset: 41 +// THW_C-NEXT: Length: 23 +// THW_C-NEXT: ReplacementText: 'bounded_ptr<char> ' + +// REDEFINE: %{merge_inputs} = %t/three-way-conflict/a_apply/a.edits.yaml %t/three-way-conflict/b_apply/b.edits.yaml %t/three-way-conflict/c_apply/c.edits.yaml +// RUN: %{merge} + +// All three dropped as one cluster, not "two conflict and one wins". +// RUN: FileCheck --check-prefix=THW_MERGED --input-file=%t/three-way-conflict/merged.yaml %s +// THW_MERGED: Replacements: [] + +// RUN: FileCheck --check-prefix=THW_STDERR --input-file=%t/three-way-conflict/merge.stderr %s +// THW_STDERR: conflict: +// THW_STDERR-SAME: skipped +// THW_STDERR-SAME: 3 +// THW_STDERR-SAME: shared.h:17 + +// The SARIF report names all three dropped candidates, not just two. +// RUN: FileCheck --check-prefix=THW_SARIF --input-file=%t/three-way-conflict/conflicts.sarif %s +// THW_SARIF: "level": "error" +// THW_SARIF: "uri": "file://{{.*}}shared.h" +// THW_SARIF: "byteOffset": 17 +// THW_SARIF: "relatedLocations": +// THW_SARIF: "id": 1 +// THW_SARIF: "text": "candidate edit: \"bounded_ptr<int> \"" +// THW_SARIF: "id": 2 +// THW_SARIF: "text": "candidate edit: \"bounded_ptr<char> \"" +// THW_SARIF: "id": 3 +// THW_SARIF: "text": "candidate edit: \"bounded_ptr<long> \"" +// THW_SARIF: "ruleId": "clang-reforge-replacement-conflict" + + +// In order to create conflicts that diff er only in text, copy 'v1.h' +// and 'v2.h' to 'shared.h' to create diff erent content in 'shared.h' +// for 'a.cpp' and 'b.cpp'. + +// FIXME: This test reveals a bug. If the array element edit is +// dropped, the bracket removal edit must be too. + +//--- array-length-conflict/v1.h +int arr[3]; + +//--- array-length-conflict/v2.h +int arr[5]; + +//--- array-length-conflict/a.cpp +#include "shared.h" +void use_a() { arr[5] = 0; } + +//--- array-length-conflict/b.cpp +#include "shared.h" +void use_b() { arr[7] = 0; } + +// REDEFINE: %{casedir} = %t/array-length-conflict +// RUN: cp %t/array-length-conflict/v1.h %t/array-length-conflict/shared.h +// REDEFINE: %{testname} = a +// RUN: %{pipeline} +// RUN: cp %t/array-length-conflict/v2.h %t/array-length-conflict/shared.h +// REDEFINE: %{testname} = b +// RUN: %{pipeline} + +// RUN: FileCheck --check-prefix=ARRLEN_A --input-file=%t/array-length-conflict/a_apply/a.edits.yaml %s +// ARRLEN_A: Offset: 0 +// ARRLEN_A-NEXT: Length: 3 +// ARRLEN_A-NEXT: ReplacementText: 'bounded_array<int, 3>' +// ARRLEN_A: Offset: 7 +// ARRLEN_A-NEXT: Length: 3 +// ARRLEN_A-NEXT: ReplacementText: '' +// RUN: FileCheck --check-prefix=ARRLEN_B --input-file=%t/array-length-conflict/b_apply/b.edits.yaml %s +// ARRLEN_B: Offset: 0 +// ARRLEN_B-NEXT: Length: 3 +// ARRLEN_B-NEXT: ReplacementText: 'bounded_array<int, 5>' +// ARRLEN_B: Offset: 7 +// ARRLEN_B-NEXT: Length: 3 +// ARRLEN_B-NEXT: ReplacementText: '' + +// REDEFINE: %{merge_inputs} = %t/array-length-conflict/a_apply/a.edits.yaml %t/array-length-conflict/b_apply/b.edits.yaml +// RUN: %{merge} + +// RUN: FileCheck --check-prefix=ARRLEN_MERGED --input-file=%t/array-length-conflict/merged.yaml %s +// ARRLEN_MERGED: Replacements: +// ARRLEN_MERGED-NEXT: - FilePath: +// ARRLEN_MERGED-SAME: shared.h +// ARRLEN_MERGED-NEXT: Offset: 7 +// ARRLEN_MERGED-NEXT: Length: 3 +// ARRLEN_MERGED-NEXT: ReplacementText: '' +// ARRLEN_MERGED-NOT: FilePath: + + +// RUN: FileCheck --check-prefix=ARRLEN_STDERR --input-file=%t/array-length-conflict/merge.stderr %s +// ARRLEN_STDERR: conflict: +// ARRLEN_STDERR-SAME: skipped +// ARRLEN_STDERR-SAME: 2 +// ARRLEN_STDERR-SAME: shared.h:0 +// ARRLEN_STDERR-NOT: conflict: + +// RUN: FileCheck --check-prefix=ARRLEN_SARIF --input-file=%t/array-length-conflict/conflicts.sarif %s +// ARRLEN_SARIF: "level": "error" +// ARRLEN_SARIF: "uri": "file://{{.*}}shared.h" +// ARRLEN_SARIF: "byteOffset": 0 +// ARRLEN_SARIF: "relatedLocations": +// ARRLEN_SARIF: "id": 1 +// ARRLEN_SARIF: "text": "candidate edit: \"bounded_array<int, 3>\"" +// ARRLEN_SARIF: "id": 2 +// ARRLEN_SARIF: "text": "candidate edit: \"bounded_array<int, 5>\"" +// ARRLEN_SARIF: "ruleId": "clang-reforge-replacement-conflict" + + diff --git a/clang/test/Analysis/Scalable/source-edit-generation/multi-tu-edits-merge.cpp b/clang/test/Analysis/Scalable/source-edit-generation/multi-tu-edits-merge.cpp new file mode 100644 index 0000000000000..7057a2a6ed078 --- /dev/null +++ b/clang/test/Analysis/Scalable/source-edit-generation/multi-tu-edits-merge.cpp @@ -0,0 +1,206 @@ +// Tests clang-ssaf-src-edit-merge against real multi-TU source. +// Specifically, this file tests non-conflicting merges across multiple TUs. + +// RUN: rm -rf %t && mkdir -p %t +// RUN: split-file %s %t + +// DEFINE: %{casedir} = unset +// DEFINE: %{testname} = unset +// DEFINE: %{tu_json} = %{casedir}/%{testname}.tu.json +// DEFINE: %{lu_json} = %{casedir}/%{testname}.lu.json +// DEFINE: %{wpa_json} = %{casedir}/%{testname}.wpa.json +// DEFINE: %{apply_dir} = %{casedir}/%{testname}_apply +// DEFINE: %{edits_yaml} = %{apply_dir}/%{testname}.edits.yaml +// DEFINE: %{extract} = %clang -fsyntax-only %{casedir}/%{testname}.cpp \ +// DEFINE: --ssaf-extract-summaries=PointerFlow,UnsafeBufferUsage \ +// DEFINE: --ssaf-compilation-unit-id=%{testname}.cu --ssaf-tu-summary-file=%{tu_json} +// DEFINE: %{link} = clang-ssaf-linker %{tu_json} -o %{lu_json} +// DEFINE: %{analyze} = clang-ssaf-analyzer %{lu_json} -o %{wpa_json} -a UnsafeBufferReachableAnalysisResult +// DEFINE: %{transform} = mkdir -p %{apply_dir} && %clang -fsyntax-only %{casedir}/%{testname}.cpp \ +// DEFINE: --ssaf-source-transformation=cpp-bounded-buffers \ +// DEFINE: --ssaf-global-scope-analysis-result=%{wpa_json} \ +// DEFINE: --ssaf-src-edit-file=%{edits_yaml} \ +// DEFINE: --ssaf-transformation-report-file=%{casedir}/%{testname}.report.sarif \ +// DEFINE: --ssaf-compilation-unit-id=%{testname}.cu --ssaf-link-unit-id=%{testname}.lu +// DEFINE: %{pipeline} = %{extract} && %{link} && %{analyze} && %{transform} +// DEFINE: %{merge_inputs} = unset +// DEFINE: %{merge} = mkdir -p %{casedir}/merge_apply && clang-ssaf-src-edit-merge %{merge_inputs} -o %{casedir}/merge_apply/merged.yaml --sarif-conflicts-out=%{casedir}/conflicts.sarif 2> %{casedir}/merge.stderr +// DEFINE: %{apply} = clang-apply-replacements %{casedir}/merge_apply + +//--- distinct-files/a.h +int *ga; + +//--- distinct-files/b.h +int *gb; + +//--- distinct-files/a.cpp +#include "a.h" +void use_a() { ga[5] = 0; } + +//--- distinct-files/b.cpp +#include "b.h" +void use_b() { gb[7] = 0; } + +// REDEFINE: %{casedir} = %t/distinct-files +// REDEFINE: %{testname} = a +// RUN: %{pipeline} +// REDEFINE: %{testname} = b +// RUN: %{pipeline} + +// REDEFINE: %{merge_inputs} = %t/distinct-files/a_apply/a.edits.yaml %t/distinct-files/b_apply/b.edits.yaml +// RUN: %{merge} + +// Both survive, diff erent files: +// RUN: FileCheck --check-prefix=DF_MERGED --input-file=%t/distinct-files/merge_apply/merged.yaml %s +// DF_MERGED: FilePath: +// DF_MERGED-SAME: a.h +// DF_MERGED: FilePath: +// DF_MERGED-SAME: b.h + +// RUN: FileCheck --check-prefix=DF_NOSTDERR --input-file=%t/distinct-files/merge.stderr --allow-empty %s +// DF_NOSTDERR-NOT: conflict: + +// RUN: %if clang-apply-replacements %{ %{apply} %} +// RUN: %if clang-apply-replacements %{ FileCheck --check-prefix=DF_A_APPLIED --input-file=%t/distinct-files/a.h %s %} +// DF_A_APPLIED: bounded_ptr<int> ga; +// RUN: %if clang-apply-replacements %{ FileCheck --check-prefix=DF_B_APPLIED --input-file=%t/distinct-files/b.h %s %} +// DF_B_APPLIED: bounded_ptr<int> gb; + + +//--- distinct-locations/shared.h +int *g1; +int *g2; + +//--- distinct-locations/a.cpp +#include "shared.h" +void use_a() { g1[5] = 0; } + +//--- distinct-locations/b.cpp +#include "shared.h" +void use_b() { g2[7] = 0; } + +// REDEFINE: %{casedir} = %t/distinct-locations +// REDEFINE: %{testname} = a +// RUN: %{pipeline} +// REDEFINE: %{testname} = b +// RUN: %{pipeline} + +// REDEFINE: %{merge_inputs} = %t/distinct-locations/a_apply/a.edits.yaml %t/distinct-locations/b_apply/b.edits.yaml +// RUN: %{merge} + +// Both survive, same file, distinct offsets: +// RUN: FileCheck --check-prefix=DL_MERGED --input-file=%t/distinct-locations/merge_apply/merged.yaml %s +// DL_MERGED: Offset: 0 +// DL_MERGED-NEXT: Length: 5 +// DL_MERGED-NEXT: ReplacementText: 'bounded_ptr<int> ' +// DL_MERGED: Offset: 9 +// DL_MERGED-NEXT: Length: 5 +// DL_MERGED-NEXT: ReplacementText: 'bounded_ptr<int> ' + +// RUN: FileCheck --check-prefix=DL_NOSTDERR --input-file=%t/distinct-locations/merge.stderr --allow-empty %s +// DL_NOSTDERR-NOT: conflict: + +// RUN: %if clang-apply-replacements %{ %{apply} %} +// RUN: %if clang-apply-replacements %{ FileCheck --check-prefix=DL_APPLIED --input-file=%t/distinct-locations/shared.h %s %} +// DL_APPLIED: bounded_ptr<int> g1; +// DL_APPLIED-NEXT: bounded_ptr<int> g2; + + +//--- three-tu-distinct/shared.h +int *g1;int *g2;int *g3; + +//--- three-tu-distinct/a.cpp +#include "shared.h" +void use_a() { g1[5] = 0; } + +//--- three-tu-distinct/b.cpp +#include "shared.h" +void use_b() { g2[7] = 0; } + +//--- three-tu-distinct/c.cpp +#include "shared.h" +void use_c() { g3[9] = 0; } + +// REDEFINE: %{casedir} = %t/three-tu-distinct +// REDEFINE: %{testname} = a +// RUN: %{pipeline} +// REDEFINE: %{testname} = b +// RUN: %{pipeline} +// REDEFINE: %{testname} = c +// RUN: %{pipeline} + +// REDEFINE: %{merge_inputs} = %t/three-tu-distinct/a_apply/a.edits.yaml %t/three-tu-distinct/b_apply/b.edits.yaml %t/three-tu-distinct/c_apply/c.edits.yaml +// RUN: %{merge} + +// All three survive: +// RUN: FileCheck --check-prefix=TTD_MERGED --input-file=%t/three-tu-distinct/merge_apply/merged.yaml %s +// TTD_MERGED: Offset: 0 +// TTD_MERGED: Offset: 8 +// TTD_MERGED: Offset: 16 + +// RUN: FileCheck --check-prefix=TTD_NOSTDERR --input-file=%t/three-tu-distinct/merge.stderr --allow-empty %s +// TTD_NOSTDERR-NOT: conflict: + +// RUN: %if clang-apply-replacements %{ %{apply} %} +// RUN: %if clang-apply-replacements %{ FileCheck --check-prefix=TTD_APPLIED --input-file=%t/three-tu-distinct/shared.h %s %} +// TTD_APPLIED: bounded_ptr<int> g1;bounded_ptr<int> g2;bounded_ptr<int> g3; + + +//--- static-inline-fun-dedup/shared.h +static inline int * foo(int *p) { + return p; +} + +//--- static-inline-fun-dedup/a.cpp +#include "shared.h" +void caller(int * p) { int * q = foo(p); q[5] = 0; } + +//--- static-inline-fun-dedup/b.cpp +#include "shared.h" +void caller(int * p) { int * q = foo(p); q[5] = 0; } + +// REDEFINE: %{casedir} = %t/static-inline-fun-dedup +// REDEFINE: %{testname} = a +// RUN: %{pipeline} +// REDEFINE: %{testname} = b +// RUN: %{pipeline} + +// REDEFINE: %{merge_inputs} = %t/static-inline-fun-dedup/a_apply/a.edits.yaml %t/static-inline-fun-dedup/b_apply/b.edits.yaml +// RUN: %{merge} + +// Shared static-linkage function's rewrite dedups; each caller's own file +// still survives on its own: +// RUN: FileCheck --check-prefix=SIF_MERGED --input-file=%t/static-inline-fun-dedup/merge_apply/merged.yaml %s +// SIF_MERGED: FilePath: +// SIF_MERGED-SAME: a.cpp +// SIF_MERGED: FilePath: +// SIF_MERGED-SAME: a.cpp +// SIF_MERGED: FilePath: +// SIF_MERGED-SAME: b.cpp +// SIF_MERGED: FilePath: +// SIF_MERGED-SAME: b.cpp +// SIF_MERGED: FilePath: +// SIF_MERGED-SAME: shared.h +// SIF_MERGED-NEXT: Offset: 14 +// SIF_MERGED-NEXT: Length: 5 +// SIF_MERGED-NEXT: ReplacementText: 'bounded_ptr<int> ' +// SIF_MERGED: FilePath: +// SIF_MERGED-SAME: shared.h +// SIF_MERGED-NEXT: Offset: 24 +// SIF_MERGED-NEXT: Length: 5 +// SIF_MERGED-NEXT: ReplacementText: 'bounded_ptr<int> ' +// SIF_MERGED-NOT: FilePath: + +// RUN: FileCheck --check-prefix=SIF_NOSTDERR --input-file=%t/static-inline-fun-dedup/merge.stderr --allow-empty %s +// SIF_NOSTDERR-NOT: conflict: + +// RUN: %if clang-apply-replacements %{ %{apply} %} +// RUN: %if clang-apply-replacements %{ FileCheck --check-prefix=SIF_H_APPLIED --input-file=%t/static-inline-fun-dedup/shared.h %s %} +// SIF_H_APPLIED: static inline bounded_ptr<int> foo(bounded_ptr<int> p) { +// RUN: %if clang-apply-replacements %{ FileCheck --check-prefix=SIF_A_APPLIED --input-file=%t/static-inline-fun-dedup/a.cpp %s %} +// SIF_A_APPLIED: void caller(bounded_ptr<int> p) { bounded_ptr<int> q = foo(p); q[5] = 0; } +// RUN: %if clang-apply-replacements %{ FileCheck --check-prefix=SIF_B_APPLIED --input-file=%t/static-inline-fun-dedup/b.cpp %s %} +// SIF_B_APPLIED: void caller(bounded_ptr<int> p) { bounded_ptr<int> q = foo(p); q[5] = 0; } + + + _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
