]> granicus.if.org Git - llvm/commitdiff
[llvm-cov] Add an option which maps the location of source directories on another...
authorSean Eveson <eveson.sean@gmail.com>
Mon, 14 Aug 2017 10:20:12 +0000 (10:20 +0000)
committerSean Eveson <eveson.sean@gmail.com>
Mon, 14 Aug 2017 10:20:12 +0000 (10:20 +0000)
Summary:
This patch adds the -path-equivalence option (example: llvm-cov show -path-equivalence=/origin/path,/local/path) which maps the source code path from one machine to another when using `llvm-cov show`. This is similar to the -filename-equivalence option, but doesn't require you to specify all the source files on the command line.

This allows you to generate the coverage data on one machine (e.g. in a CI system), and then use llvm-cov on another machine where you have the same code base on a different path.

Reviewers: vsk

Reviewed By: vsk

Subscribers: llvm-commits

Differential Revision: https://reviews.llvm.org/D36391

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@310827 91177308-0d34-0410-b5e6-96231b3b80d8

27 files changed:
docs/CommandGuide/llvm-cov.rst
test/tools/llvm-cov/Inputs/path_equivalence.covmapping [new file with mode: 0644]
test/tools/llvm-cov/Inputs/path_equivalence.proftext [new file with mode: 0644]
test/tools/llvm-cov/binary-formats.c
test/tools/llvm-cov/combine_expansions.cpp
test/tools/llvm-cov/cov-comdat.test
test/tools/llvm-cov/deferred-region.cpp
test/tools/llvm-cov/demangle.test
test/tools/llvm-cov/hideUnexecutedSubviews.test
test/tools/llvm-cov/native_separators.c
test/tools/llvm-cov/path_equivalence.c [new file with mode: 0644]
test/tools/llvm-cov/prefer_used_to_unused.h
test/tools/llvm-cov/prevent_false_instantiations.h
test/tools/llvm-cov/report.cpp
test/tools/llvm-cov/scan-directory.test
test/tools/llvm-cov/showExpansions.cpp
test/tools/llvm-cov/showHighlightedRanges.cpp
test/tools/llvm-cov/showLineExecutionCounts.cpp
test/tools/llvm-cov/showProjectSummary.cpp
test/tools/llvm-cov/showRegionMarkers.cpp
test/tools/llvm-cov/showTabsHTML.cpp
test/tools/llvm-cov/showTemplateInstantiations.cpp
test/tools/llvm-cov/style.test
test/tools/llvm-cov/threads.c
test/tools/llvm-cov/universal-binary.c
test/tools/llvm-cov/warnings.h
tools/llvm-cov/CodeCoverage.cpp

index 97064c82cf4a2b03d418eddf64cb08e66296df72..082f510375169b2db8453877f7dfd70b484ae8ff 100644 (file)
@@ -290,6 +290,12 @@ OPTIONS
  Show code coverage only for functions with region coverage less than the given
  threshold.
 
+.. option:: -path-equivalence=<from>,<to>
+
+ Map the paths in the coverage data to local source file paths. This allows you
+ to generate the coverage data on one machine, and then use llvm-cov on a
+ different machine where you have the same files on a different path.
+
 .. program:: llvm-cov report
 
 .. _llvm-cov-report:
diff --git a/test/tools/llvm-cov/Inputs/path_equivalence.covmapping b/test/tools/llvm-cov/Inputs/path_equivalence.covmapping
new file mode 100644 (file)
index 0000000..ea09bf3
Binary files /dev/null and b/test/tools/llvm-cov/Inputs/path_equivalence.covmapping differ
diff --git a/test/tools/llvm-cov/Inputs/path_equivalence.proftext b/test/tools/llvm-cov/Inputs/path_equivalence.proftext
new file mode 100644 (file)
index 0000000..5419d23
--- /dev/null
@@ -0,0 +1,8 @@
+main
+# Func Hash:
+0
+# Num Counters:
+1
+# Counter Values:
+1
+
index 0b4187d7b54518252609ed308e2138f891e882aa..3c2fa26afa39d535858bc3f18cd444fe86eec456 100644 (file)
@@ -4,9 +4,9 @@
 int main(int argc, const char *argv[]) {}
 
 // RUN: llvm-profdata merge %S/Inputs/binary-formats.proftext -o %t.profdata
-// RUN: llvm-cov show %S/Inputs/binary-formats.macho32l -instr-profile %t.profdata -filename-equivalence %s | FileCheck %s
-// RUN: llvm-cov show %S/Inputs/binary-formats.macho64l -instr-profile %t.profdata -filename-equivalence %s | FileCheck %s
-// RUN: llvm-cov show %S/Inputs/binary-formats.macho32b -instr-profile %t.profdata -filename-equivalence %s | FileCheck %s
+// RUN: llvm-cov show %S/Inputs/binary-formats.macho32l -instr-profile %t.profdata -path-equivalence=/tmp,%S %s | FileCheck %s
+// RUN: llvm-cov show %S/Inputs/binary-formats.macho64l -instr-profile %t.profdata -path-equivalence=/tmp,%S %s | FileCheck %s
+// RUN: llvm-cov show %S/Inputs/binary-formats.macho32b -instr-profile %t.profdata -path-equivalence=/tmp,%S %s | FileCheck %s
 
 // RUN: llvm-cov export %S/Inputs/binary-formats.macho32l -instr-profile %t.profdata | FileCheck %S/Inputs/binary-formats.canonical.json
 // RUN: llvm-cov export %S/Inputs/binary-formats.macho64l -instr-profile %t.profdata | FileCheck %S/Inputs/binary-formats.canonical.json
index 1c99bf0d85dac4930edddc04473617b591a979cc..b870d61f232326e877e22d3a4ead0b815d1542fe 100644 (file)
@@ -1,7 +1,7 @@
 // Check that we combine expansion regions.
 
 // RUN: llvm-profdata merge %S/Inputs/combine_expansions.proftext -o %t.profdata
-// RUN: llvm-cov show %S/Inputs/combine_expansions.covmapping -instr-profile %t.profdata -filename-equivalence %s | FileCheck %s
+// RUN: llvm-cov show %S/Inputs/combine_expansions.covmapping -instr-profile %t.profdata -path-equivalence=/tmp/ec,%S %s | FileCheck %s
 
 #define SIMPLE_OP \
   ++x
index de52323014fc5af60fc4254fef4c5cc5023f2ec9..1545f9921e99c4df0bcecbba92c1294bedae74ec 100644 (file)
@@ -7,6 +7,6 @@ REQUIRES: shell
 # of the same template function are properly merged in show
 # output.
 
-// RUN: llvm-cov show %S/Inputs/binary-formats.v1.linux64l -instr-profile %S/Inputs/elf_binary_comdat.profdata -filename-equivalence %S/Inputs/instrprof-comdat.h | FileCheck --check-prefix=HEADER %S/Inputs/instrprof-comdat.h
-// RUN: llvm-cov show %S/Inputs/binary-formats.v2.linux64l -instr-profile %S/Inputs/elf_binary_comdat.profdata -filename-equivalence %S/Inputs/instrprof-comdat.h | FileCheck --check-prefix=HEADER %S/Inputs/instrprof-comdat.h
-// RUN: llvm-cov show %S/Inputs/binary-formats.v2.linux32l -instr-profile %S/Inputs/elf_binary_comdat.profdata -filename-equivalence %S/Inputs/instrprof-comdat.h | FileCheck --check-prefix=HEADER %S/Inputs/instrprof-comdat.h
+// RUN: llvm-cov show %S/Inputs/binary-formats.v1.linux64l -instr-profile %S/Inputs/elf_binary_comdat.profdata -path-equivalence=/tmp,%S/Inputs %S/Inputs/instrprof-comdat.h | FileCheck --check-prefix=HEADER %S/Inputs/instrprof-comdat.h
+// RUN: llvm-cov show %S/Inputs/binary-formats.v2.linux64l -instr-profile %S/Inputs/elf_binary_comdat.profdata -path-equivalence=/root/llvm/test/tools,%S/.. %S/Inputs/instrprof-comdat.h | FileCheck --check-prefix=HEADER %S/Inputs/instrprof-comdat.h
+// RUN: llvm-cov show %S/Inputs/binary-formats.v2.linux32l -instr-profile %S/Inputs/elf_binary_comdat.profdata -path-equivalence=/root/llvm/R/../test/tools,%S/.. %S/Inputs/instrprof-comdat.h | FileCheck --check-prefix=HEADER %S/Inputs/instrprof-comdat.h
index 3704d0ed5151e8382bf2320498bb76a53dc5e9f7..a11ad64e6001a9dfd5a6040f0841fb6aad4992af 100644 (file)
@@ -1,4 +1,4 @@
-// RUN: llvm-cov show %S/Inputs/deferred-regions.covmapping -instr-profile %S/Inputs/deferred-regions.profdata -show-line-counts-or-regions -dump -filename-equivalence %s 2>&1 | FileCheck %s
+// RUN: llvm-cov show %S/Inputs/deferred-regions.covmapping -instr-profile %S/Inputs/deferred-regions.profdata -show-line-counts-or-regions -dump -path-equivalence=/Users/vk/src/llvm.org-coverage-braces/llvm/test/tools,%S/.. %s 2>&1 | FileCheck %s
 
 void foo(int x) {
   if (x == 0) {
index 5ca113262e409700e60db2ac5d52345bd097f5af..a6d2cb353b33f8f26ce3f0fe6c14e963b0d8e258 100644 (file)
@@ -1,11 +1,11 @@
-RUN: llvm-cov show %S/Inputs/templateInstantiations.covmapping -instr-profile %S/Inputs/templateInstantiations.profdata -Xdemangler sed -Xdemangler 's/_/X/g' -filename-equivalence %S/showTemplateInstantiations.cpp | FileCheck %s
+RUN: llvm-cov show %S/Inputs/templateInstantiations.covmapping -instr-profile %S/Inputs/templateInstantiations.profdata -Xdemangler sed -Xdemangler 's/_/X/g' -path-equivalence=/tmp,%S %S/showTemplateInstantiations.cpp | FileCheck %s
 
 // Check that we demangle names even if the sub-view will be hidden.
 RUN: llvm-profdata merge %S/Inputs/hideUnexecutedSubviews.proftext -o %t.profdata
-RUN: llvm-cov show %S/Inputs/templateInstantiations.covmapping -instr-profile %t.profdata -Xdemangler sed -Xdemangler 's/_/X/g' -filename-equivalence %S/showTemplateInstantiations.cpp | FileCheck %s
+RUN: llvm-cov show %S/Inputs/templateInstantiations.covmapping -instr-profile %t.profdata -Xdemangler sed -Xdemangler 's/_/X/g' -path-equivalence=/tmp,%S %S/showTemplateInstantiations.cpp | FileCheck %s
 
 // Check that we demangle names when printing out function summaries.
-RUN: llvm-cov report -show-functions %S/Inputs/templateInstantiations.covmapping -instr-profile %S/Inputs/templateInstantiations.profdata -Xdemangler sed -Xdemangler 's/_/X/g' -filename-equivalence %S/showTemplateInstantiations.cpp | FileCheck %s
+RUN: llvm-cov report -show-functions %S/Inputs/templateInstantiations.covmapping -instr-profile %S/Inputs/templateInstantiations.profdata -Xdemangler sed -Xdemangler 's/_/X/g' -path-equivalence=/tmp,%S %S/showTemplateInstantiations.cpp | FileCheck %s
 
 CHECK-DAG: XZ4funcIbEiTX
 CHECK-DAG: XZ4funcIiEiTX
index 646c6e5aec479dbae76427bc8b6109d781e15a69..f97c0ff176a5a23fbf669bdcd6fdd1125cdbd49c 100644 (file)
@@ -1,8 +1,8 @@
 RUN: llvm-profdata merge %S/Inputs/hideUnexecutedSubviews.proftext -o %t.profdata
 
-RUN: llvm-cov show %S/Inputs/templateInstantiations.covmapping -instr-profile %t.profdata -filename-equivalence %S/showTemplateInstantiations.cpp | FileCheck -check-prefix=FILE %s
+RUN: llvm-cov show %S/Inputs/templateInstantiations.covmapping -instr-profile %t.profdata -path-equivalence=/tmp,%S %S/showTemplateInstantiations.cpp | FileCheck -check-prefix=FILE %s
 
-RUN: llvm-cov show %S/Inputs/templateInstantiations.covmapping -instr-profile %t.profdata -format html -o %t.html.dir -filename-equivalence %S/showTemplateInstantiations.cpp
+RUN: llvm-cov show %S/Inputs/templateInstantiations.covmapping -instr-profile %t.profdata -format html -o %t.html.dir -path-equivalence=/tmp,%S %S/showTemplateInstantiations.cpp
 RUN: FileCheck -check-prefix=FILE %s -input-file %t.html.dir/coverage/tmp/showTemplateInstantiations.cpp.html
 
 FILE: Unexecuted instantiation: _Z4funcIbEiT_
index adc167bf3d7eb8803c32a1cc1072556b1b27b9eb..8ab1a732b995107af8cb21a26b750767040f913d 100644 (file)
@@ -8,9 +8,9 @@
 // RUN: llvm-profdata merge %S/Inputs/double_dots.proftext -o %t.profdata
 // RUN: llvm-cov show %S/Inputs/native_separators.covmapping -instr-profile=%t.profdata -o %t.dir
 // RUN: FileCheck -check-prefixes=TEXT-INDEX -input-file=%t.dir/index.txt %s
-// RUN: llvm-cov show -format=html %S/Inputs/native_separators.covmapping -instr-profile=%t.profdata -filename-equivalence ../llvm-"config"/../llvm-"cov"/native_separators.c -o %t.dir
+// RUN: llvm-cov show -format=html %S/Inputs/native_separators.covmapping -instr-profile=%t.profdata -path-equivalence=/tmp,%S ../llvm-"config"/../llvm-"cov"/native_separators.c -o %t.dir
 // RUN: FileCheck -check-prefixes=HTML-INDEX -input-file=%t.dir/index.html %s
-// RUN: llvm-cov show -format=html %S/Inputs/native_separators.covmapping -instr-profile=%t.profdata -filename-equivalence %s -o %t.dir
+// RUN: llvm-cov show -format=html %S/Inputs/native_separators.covmapping -instr-profile=%t.profdata -path-equivalence=/tmp,%S %s -o %t.dir
 // RUN: FileCheck -check-prefixes=HTML -input-file=%t.dir/coverage/tmp/native_separators.c.html %s
 
 // TEXT-INDEX: \tmp\native_separators.c
diff --git a/test/tools/llvm-cov/path_equivalence.c b/test/tools/llvm-cov/path_equivalence.c
new file mode 100644 (file)
index 0000000..ba62360
--- /dev/null
@@ -0,0 +1,4 @@
+// RUN: llvm-profdata merge %S/Inputs/path_equivalence.proftext -o %t.profdata
+// RUN: llvm-cov show %S/Inputs/path_equivalence.covmapping -instr-profile=%t.profdata -path-equivalence=/tmp,%S | FileCheck %s
+
+int main() {} // CHECK: [[@LINE]]|      1|int main() {}
index ef4d5f0b5441809decf4ad181f0f3bf149281772..852eb927a5c0cb0c0202738d9d71836e2ffcbcfc 100644 (file)
@@ -9,7 +9,7 @@
 // llvm-cov convert-for-testing -o prefer_used_to_unused.covmapping tmp
 
 // RUN: llvm-profdata merge %S/Inputs/prefer_used_to_unused.proftext -o %t.profdata
-// RUN: llvm-cov show %S/Inputs/prefer_used_to_unused.covmapping -instr-profile %t.profdata -filename-equivalence %s | FileCheck %s
+// RUN: llvm-cov show %S/Inputs/prefer_used_to_unused.covmapping -instr-profile %t.profdata -path-equivalence=/tmp/uu/./,%S %s | FileCheck %s
 
 // Coverage data for this function has a non-zero hash value if it is used in the translation unit.
 inline int sampleFunc(int A) { // CHECK:      [[@LINE]]| 1|inline int sampleFunc(int A) {
index 1cb216ca48e9371afea44c2803a08b722c4021a1..22f14260204ca79f9522426385b61e4ee007ad74 100644 (file)
@@ -4,7 +4,7 @@
 // NAN-NOT: {{[ \t]+}}nan%
 
 // RUN: llvm-profdata merge %S/Inputs/prevent_false_instantiations.proftext -o %t.profdata
-// RUN: llvm-cov show -format text %S/Inputs/prevent_false_instantiations.covmapping -instr-profile %t.profdata -filename-equivalence %s | FileCheck %s -check-prefix=INSTANTIATION
+// RUN: llvm-cov show -format text %S/Inputs/prevent_false_instantiations.covmapping -instr-profile %t.profdata -path-equivalence=/tmp/false_instantiations/./,%S %s | FileCheck %s -check-prefix=INSTANTIATION
 // RUN: llvm-cov report %S/Inputs/prevent_false_instantiations.covmapping -instr-profile %t.profdata | FileCheck %s -check-prefix=NAN
 
 #define DO_SOMETHING() \
index 49425eb5f62415b525703d9f3591f6c53417bb3a..92f8158db584f24f468be065bc514891cf29ae8d 100644 (file)
@@ -1,6 +1,6 @@
-// RUN: llvm-cov report %S/Inputs/report.covmapping -instr-profile %S/Inputs/report.profdata -filename-equivalence 2>&1 | FileCheck %s
-// RUN: llvm-cov report -show-functions %S/Inputs/report.covmapping -instr-profile %S/Inputs/report.profdata -filename-equivalence report.cpp 2>&1 | FileCheck -check-prefix=FILT %s
-// RUN: llvm-cov report -show-functions %S/Inputs/report.covmapping -instr-profile %S/Inputs/report.profdata -filename-equivalence report.cpp does-not-exist.cpp 2>&1 | FileCheck -check-prefix=FILT %s
+// RUN: llvm-cov report %S/Inputs/report.covmapping -instr-profile %S/Inputs/report.profdata -path-equivalence=,%S 2>&1 | FileCheck %s
+// RUN: llvm-cov report -show-functions %S/Inputs/report.covmapping -instr-profile %S/Inputs/report.profdata -path-equivalence=,%S %s 2>&1 | FileCheck -check-prefix=FILT %s
+// RUN: llvm-cov report -show-functions %S/Inputs/report.covmapping -instr-profile %S/Inputs/report.profdata -path-equivalence=,%S %s does-not-exist.cpp 2>&1 | FileCheck -check-prefix=FILT %s
 
 // CHECK: Regions    Missed Regions     Cover   Functions  Missed Functions  Executed  Instantiations   Missed Insts.  Executed       Lines      Missed Lines     Cover
 // CHECK-NEXT: ---
@@ -36,7 +36,7 @@ int main() {
 }
 
 // Test that listing multiple functions in a function view works.
-// RUN: llvm-cov show -o %t.dir %S/Inputs/report.covmapping -instr-profile=%S/Inputs/report.profdata -filename-equivalence -name-regex=".*" %s
+// RUN: llvm-cov show -o %t.dir %S/Inputs/report.covmapping -instr-profile=%S/Inputs/report.profdata -path-equivalence=,%S -name-regex=".*" %s
 // RUN: FileCheck -check-prefix=FUNCTIONS -input-file %t.dir/functions.txt %s
 // FUNCTIONS: _Z3foob
 // FUNCTIONS: _Z3barv
index b7f2858426780f50177808a30526e4d8537cfe74..f9959d4a978bbeefb44b50c222ebee1d200ab4e2 100644 (file)
@@ -8,7 +8,8 @@ RUN: llvm-cov show /dev/null -instr-profile /dev/null -dump-collected-paths %t/a
 REAL-DAG: {{.*}}c.tmp
 REAL-DAG: {{.*}}d.tmp
 
-RUN: llvm-cov show /dev/null -instr-profile /dev/null -dump-collected-paths -filename-equivalence %t a b c d e f | FileCheck %s --check-prefix=EQUIV
+// NEEDS FIX.
+RUN: llvm-cov show /dev/null -instr-profile /dev/null -dump-collected-paths -path-equivalence=%t,%S %t a b c d e f | FileCheck %s --check-prefix=EQUIV
 EQUIV-DAG: {{.*}}c.tmp
 EQUIV-DAG: {{.*}}d.tmp
 EQUIV-DAG: a
index 818c0e16c57b7fc5f79900339943aa0f48b4f6ac..f9d63e95e75048522d20520c345efa8d93314b29 100644 (file)
@@ -1,4 +1,4 @@
-// RUN: llvm-cov show %S/Inputs/showExpansions.covmapping -instr-profile %S/Inputs/showExpansions.profdata -dump -show-expansions -filename-equivalence %s 2>&1 | FileCheck %s
+// RUN: llvm-cov show %S/Inputs/showExpansions.covmapping -instr-profile %S/Inputs/showExpansions.profdata -dump -show-expansions -path-equivalence="/Users/bogner/code/llvm/test/tools,%S/.." %s 2>&1 | FileCheck %s
 
 #define DO_SOMETHING_ELSE() \
   do {                      \
index 4ed3f17e58f4ffb2e86e93a1022a0801a28eb002..3b457faccd23d877740793b0e339622ddfd186be 100644 (file)
@@ -1,4 +1,4 @@
-// RUN: llvm-cov show %S/Inputs/highlightedRanges.covmapping -instr-profile %S/Inputs/highlightedRanges.profdata -dump -filename-equivalence %s 2>&1 | FileCheck %s -check-prefixes=TEXT,SHARED
+// RUN: llvm-cov show %S/Inputs/highlightedRanges.covmapping -instr-profile %S/Inputs/highlightedRanges.profdata -dump -path-equivalence=/Users/bogner/code/llvm/test/tools,%S/.. %s 2>&1 | FileCheck %s -check-prefixes=TEXT,SHARED
 
 void func() {
   return;
@@ -44,5 +44,5 @@ int main() {
   return 0;
 }
 
-// RUN: llvm-cov show %S/Inputs/highlightedRanges.covmapping -instr-profile %S/Inputs/highlightedRanges.profdata -format html -dump -filename-equivalence %s 2>&1 | FileCheck %s -check-prefixes=HTML,SHARED
+// RUN: llvm-cov show %S/Inputs/highlightedRanges.covmapping -instr-profile %S/Inputs/highlightedRanges.profdata -format html -dump -path-equivalence=/Users/bogner/code/llvm/test/tools,%S/.. %s 2>&1 | FileCheck %s -check-prefixes=HTML,SHARED
 // RUN: llvm-cov export %S/Inputs/highlightedRanges.covmapping -instr-profile %S/Inputs/highlightedRanges.profdata 2>&1 | FileCheck %S/Inputs/highlightedRanges.json
index 4bc3ad5dfdc0a2aa4c8b5310b2a026e978416930..48460b3d2fd96a944e909df1a1e14b5f41406d6c 100644 (file)
@@ -26,12 +26,12 @@ int main() {                              // TEXT: [[@LINE]]|   161|int main(
 // after coverage                   // WHOLE-FILE: [[@LINE]]|      |// after
                                     // FILTER-NOT: [[@LINE-1]]|    |// after
 
-// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -instr-profile %t.profdata -filename-equivalence %s | FileCheck -check-prefixes=TEXT,WHOLE-FILE %s
-// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -instr-profile %t.profdata -filename-equivalence -name=main %s | FileCheck -check-prefixes=TEXT,FILTER %s
+// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -instr-profile %t.profdata -path-equivalence=/tmp,%S %s | FileCheck -check-prefixes=TEXT,WHOLE-FILE %s
+// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -instr-profile %t.profdata -path-equivalence=/tmp,%S -name=main %s | FileCheck -check-prefixes=TEXT,FILTER %s
 
 // Test -output-dir.
-// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -o %t.dir -instr-profile %t.profdata -filename-equivalence %s
-// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -output-dir %t.dir -instr-profile %t.profdata -filename-equivalence -name=main %s
+// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -o %t.dir -instr-profile %t.profdata -path-equivalence=/tmp,%S %s
+// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -output-dir %t.dir -instr-profile %t.profdata -path-equivalence=/tmp,%S -name=main %s
 // RUN: FileCheck -check-prefixes=TEXT,WHOLE-FILE -input-file %t.dir/coverage/tmp/showLineExecutionCounts.cpp.txt %s
 // RUN: FileCheck -check-prefixes=TEXT,FILTER -input-file %t.dir/functions.txt %s
 //
@@ -40,8 +40,8 @@ int main() {                              // TEXT: [[@LINE]]|   161|int main(
 // RUN: cat %t.export.json | %python -c "import json, sys; json.loads(sys.stdin.read())"
 //
 // Test html output.
-// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -format html -o %t.html.dir -instr-profile %t.profdata -filename-equivalence %s
-// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -format html -o %t.html.dir -instr-profile %t.profdata -filename-equivalence -name=main %s
+// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -format html -o %t.html.dir -instr-profile %t.profdata -path-equivalence=/tmp,%S %s
+// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -format html -o %t.html.dir -instr-profile %t.profdata -path-equivalence=/tmp,%S -name=main %s
 // RUN: FileCheck -check-prefixes=HTML,HTML-WHOLE-FILE -input-file %t.html.dir/coverage/tmp/showLineExecutionCounts.cpp.html %s
 // RUN: FileCheck -check-prefixes=HTML,HTML-FILTER -input-file %t.html.dir/functions.html %s
 //
index 604c7730cc76d8288c854ca24604ebb9c64947f7..4d0b4f18b51b7ec145d9cc7eb0a3535d131f6fc4 100644 (file)
@@ -12,17 +12,17 @@ int main(int argc, char ** argv) {
 }
 
 // Test console output.
-// RUN: llvm-cov show %S/Inputs/showProjectSummary.covmapping -instr-profile %t.profdata -filename-equivalence %s | FileCheck -check-prefixes=TEXT,TEXT-FILE,TEXT-HEADER %S/Inputs/showProjectSummary.test
-// RUN: llvm-cov show %S/Inputs/showProjectSummary.covmapping -instr-profile %t.profdata -project-title "Test Suite" -filename-equivalence %s | FileCheck -check-prefixes=TEXT-TITLE,TEXT,TEXT-FILE,TEXT-HEADER %S/Inputs/showProjectSummary.test
-// RUN: llvm-cov show %S/Inputs/showProjectSummary.covmapping -instr-profile %t.profdata -project-title "Test Suite" -name=main -filename-equivalence %s | FileCheck -check-prefixes=TEXT-FUNCTION,TEXT-HEADER %S/Inputs/showProjectSummary.test
-// RUN: llvm-cov show %S/Inputs/showProjectSummary.covmapping -instr-profile=%t.profdata -o %t.dir -filename-equivalence %s
+// RUN: llvm-cov show %S/Inputs/showProjectSummary.covmapping -instr-profile %t.profdata -path-equivalence=/tmp,%S %s | FileCheck -check-prefixes=TEXT,TEXT-FILE,TEXT-HEADER %S/Inputs/showProjectSummary.test
+// RUN: llvm-cov show %S/Inputs/showProjectSummary.covmapping -instr-profile %t.profdata -project-title "Test Suite" -path-equivalence=/tmp,%S %s | FileCheck -check-prefixes=TEXT-TITLE,TEXT,TEXT-FILE,TEXT-HEADER %S/Inputs/showProjectSummary.test
+// RUN: llvm-cov show %S/Inputs/showProjectSummary.covmapping -instr-profile %t.profdata -project-title "Test Suite" -name=main -path-equivalence=/tmp,%S %s | FileCheck -check-prefixes=TEXT-FUNCTION,TEXT-HEADER %S/Inputs/showProjectSummary.test
+// RUN: llvm-cov show %S/Inputs/showProjectSummary.covmapping -instr-profile=%t.profdata -o %t.dir -path-equivalence=/tmp,%S %s
 // RUN: FileCheck -check-prefixes=TEXT-FOOTER -input-file=%t.dir/index.txt %S/Inputs/showProjectSummary.test
 
 // Test html output.
-// RUN: llvm-cov show %S/Inputs/showProjectSummary.covmapping -format=html -o %t.dir -instr-profile %t.profdata -filename-equivalence %s
+// RUN: llvm-cov show %S/Inputs/showProjectSummary.covmapping -format=html -o %t.dir -instr-profile %t.profdata -path-equivalence=/tmp,%S %s
 // RUN: FileCheck -check-prefixes=HTML,HTML-FILE,HTML-HEADER -input-file %t.dir/coverage/tmp/showProjectSummary.cpp.html %S/Inputs/showProjectSummary.test
-// RUN: llvm-cov show %S/Inputs/showProjectSummary.covmapping -format=html -o %t.dir -instr-profile %t.profdata -project-title "Test Suite" -filename-equivalence %s
+// RUN: llvm-cov show %S/Inputs/showProjectSummary.covmapping -format=html -o %t.dir -instr-profile %t.profdata -project-title "Test Suite" -path-equivalence=/tmp,%S %s
 // RUN: FileCheck -check-prefixes=HTML-TITLE,HTML,HTML-FILE,HTML-HEADER -input-file %t.dir/coverage/tmp/showProjectSummary.cpp.html %S/Inputs/showProjectSummary.test
 // RUN: FileCheck -check-prefixes=HTML-TITLE,HTML,HTML-FOOTER -input-file %t.dir/index.html %S/Inputs/showProjectSummary.test
-// RUN: llvm-cov show %S/Inputs/showProjectSummary.covmapping -format=html -o %t.dir -instr-profile %t.profdata  -project-title "Test Suite" -filename-equivalence -name=main %s
+// RUN: llvm-cov show %S/Inputs/showProjectSummary.covmapping -format=html -o %t.dir -instr-profile %t.profdata  -project-title "Test Suite" -path-equivalence=/tmp,%S -name=main %s
 // RUN: FileCheck -check-prefixes=HTML-FUNCTION,HTML-HEADER -input-file %t.dir/functions.html %S/Inputs/showProjectSummary.test
index 6c25cdbfd587b826e08c8ac404b946f204323d7b..c1d9e0c9167df29774b9c50fc00793e0830efbfc 100644 (file)
@@ -22,6 +22,6 @@ int main() {                      // CHECK: Marker at [[@LINE]]:12 = 1.11M
   return 0;
 }
 
-// RUN: llvm-cov show %S/Inputs/regionMarkers.covmapping -instr-profile %t.profdata -show-regions -dump -filename-equivalence %s 2>&1 | FileCheck %s
+// RUN: llvm-cov show %S/Inputs/regionMarkers.covmapping -instr-profile %t.profdata -show-regions -dump -path-equivalence=/Users/bogner/code/llvm/test/tools,%S/.. %s 2>&1 | FileCheck %s
 
 // RUN: llvm-cov export %S/Inputs/regionMarkers.covmapping -instr-profile %t.profdata 2>&1 | FileCheck %S/Inputs/regionMarkers.json
index c092841aeb22701f02fe6ad606f63e7b6698e1bf..6f10c3b539fed327220351f09a989d792f782609 100644 (file)
@@ -1,5 +1,5 @@
 // RUN: llvm-profdata merge -o %t.profdata %S/Inputs/showTabsHTML.proftext
-// RUN: llvm-cov show %S/Inputs/showTabsHTML.covmapping -format html -instr-profile %t.profdata -filename-equivalence %s | FileCheck %s
+// RUN: llvm-cov show %S/Inputs/showTabsHTML.covmapping -format html -instr-profile %t.profdata -path-equivalence=/tmp,%S %s | FileCheck %s
 
 int main(int argc, char ** argv) {
        (void) "This tab starts at column 0";            // CHECK: &nbsp;&nbsp;(void) &quot;This tab starts at column 0&quot;;
@@ -9,7 +9,7 @@ int main(int argc, char ** argv) {
   return 0;
 }
 
-// RUN: llvm-cov show %S/Inputs/showTabsHTML.covmapping -format html -tab-size=3 -instr-profile %t.profdata -filename-equivalence %s | FileCheck -check-prefix=CHECK-TABSIZE %s
+// RUN: llvm-cov show %S/Inputs/showTabsHTML.covmapping -format html -tab-size=3 -instr-profile %t.profdata -path-equivalence=/tmp,%S %s | FileCheck -check-prefix=CHECK-TABSIZE %s
 
 // CHECK-TABSIZE: &nbsp;&nbsp;&nbsp;(void) &quot;This tab starts at column 0&quot;;
 // CHECK-TABSIZE: (void) &quot;&nbsp;&nbsp;This tab starts at column 10&quot;;
index 326eb99f10b7002d59d776889776627cd6ee3247..e164e97f7031cfcdf90b0ffa6958f66ec4faeff1 100644 (file)
@@ -1,5 +1,5 @@
-// RUN: llvm-cov show %S/Inputs/templateInstantiations.covmapping -instr-profile %S/Inputs/templateInstantiations.profdata -filename-equivalence %s | FileCheck -check-prefixes=SHARED,ALL %s
-// RUN: llvm-cov show %S/Inputs/templateInstantiations.covmapping -instr-profile %S/Inputs/templateInstantiations.profdata -filename-equivalence -name=_Z4funcIbEiT_ %s | FileCheck -check-prefixes=SHARED,FILTER %s
+// RUN: llvm-cov show %S/Inputs/templateInstantiations.covmapping -instr-profile %S/Inputs/templateInstantiations.profdata -path-equivalence=/tmp,%S %s | FileCheck -check-prefixes=SHARED,ALL %s
+// RUN: llvm-cov show %S/Inputs/templateInstantiations.covmapping -instr-profile %S/Inputs/templateInstantiations.profdata -path-equivalence=/tmp,%S -name=_Z4funcIbEiT_ %s | FileCheck -check-prefixes=SHARED,FILTER %s
 
 // before coverage   // ALL:         [[@LINE]]|  |// before
                      // FILTER-NOT:[[@LINE-1]]|  |// before
@@ -40,8 +40,8 @@ int main() {         // ALL:         [[@LINE]]| 1|int main() {
                      // FILTER-NOT:[[@LINE-1]]|  |// after
 
 // Test html output.
-// RUN: llvm-cov show %S/Inputs/templateInstantiations.covmapping -instr-profile %S/Inputs/templateInstantiations.profdata -filename-equivalence %s -format html -o %t.html.dir
-// RUN: llvm-cov show %S/Inputs/templateInstantiations.covmapping -instr-profile %S/Inputs/templateInstantiations.profdata -filename-equivalence -name=_Z4funcIbEiT_ %s -format html -o %t.html.dir
+// RUN: llvm-cov show %S/Inputs/templateInstantiations.covmapping -instr-profile %S/Inputs/templateInstantiations.profdata -path-equivalence=/tmp,%S %s -format html -o %t.html.dir
+// RUN: llvm-cov show %S/Inputs/templateInstantiations.covmapping -instr-profile %S/Inputs/templateInstantiations.profdata -path-equivalence=/tmp,%S -name=_Z4funcIbEiT_ %s -format html -o %t.html.dir
 // RUN: FileCheck -check-prefixes=HTML-SHARED,HTML-ALL -input-file=%t.html.dir/coverage/tmp/showTemplateInstantiations.cpp.html %s
 // RUN: FileCheck -check-prefixes=HTML-SHARED,HTML-FILTER -input-file=%t.html.dir/functions.html %s
 
@@ -88,6 +88,6 @@ int main() {         // ALL:         [[@LINE]]| 1|int main() {
 // HTML-JUMP: <pre>Source (<a href='#L{{[0-9]+}}'>jump to first uncovered line</a>)</pre>
 // HTML-JUMP-NOT: <pre>Source (<a href='#L{{[0-9]+}}'>jump to first uncovered line</a>)</pre>
 
-// RUN: llvm-cov show %S/Inputs/templateInstantiations.covmapping -instr-profile %S/Inputs/templateInstantiations.profdata -show-instantiations=false -filename-equivalence %s | FileCheck -check-prefix=NO_INSTS %s
+// RUN: llvm-cov show %S/Inputs/templateInstantiations.covmapping -instr-profile %S/Inputs/templateInstantiations.profdata -show-instantiations=false -path-equivalence=/tmp,%S %s | FileCheck -check-prefix=NO_INSTS %s
 // NO_INSTS-NOT: {{^ *}}| _Z4funcIbEiT_:
 // NO_INSTS-NOT: {{^ *}}| _Z4funcIiEiT_:
index a37ad857ade27b6bf26a5cbf55137715fd6c02bc..579189b9e034aabdb01f9a4dfbda62d33991e357 100644 (file)
@@ -1,8 +1,8 @@
-RUN: llvm-cov show %S/Inputs/templateInstantiations.covmapping -instr-profile %S/Inputs/templateInstantiations.profdata -filename-equivalence %S/showTemplateInstantiations.cpp -format html -o %t.dir
+RUN: llvm-cov show %S/Inputs/templateInstantiations.covmapping -instr-profile %S/Inputs/templateInstantiations.profdata -path-equivalence=/tmp,%S %S/showTemplateInstantiations.cpp -format html -o %t.dir
 
-RUN: llvm-cov show %S/Inputs/templateInstantiations.covmapping -instr-profile %S/Inputs/templateInstantiations.profdata -filename-equivalence -name=_Z4funcIbEiT_ %S/showTemplateInstantiations.cpp -format html -o %t.dir
+RUN: llvm-cov show %S/Inputs/templateInstantiations.covmapping -instr-profile %S/Inputs/templateInstantiations.profdata -path-equivalence=/tmp,%S -name=_Z4funcIbEiT_ %S/showTemplateInstantiations.cpp -format html -o %t.dir
 
-RUN: llvm-cov show %S/Inputs/templateInstantiations.covmapping -instr-profile %S/Inputs/templateInstantiations.profdata -filename-equivalence %S/showTemplateInstantiations.cpp -format html | FileCheck %s -check-prefix=NODIR
+RUN: llvm-cov show %S/Inputs/templateInstantiations.covmapping -instr-profile %S/Inputs/templateInstantiations.profdata -path-equivalence=/tmp,%S %S/showTemplateInstantiations.cpp -format html | FileCheck %s -check-prefix=NODIR
 
 RUN: FileCheck %s -input-file=%t.dir/style.css -check-prefix=STYLE
 RUN: FileCheck %s -input-file=%t.dir/functions.html -check-prefix=TOPLEVEL
index 00a85edb7ce8b001a374b3cd48040d43ac5da74c..b162b6ac5a8011cd32ff9558ac32ec0df2bd07c6 100644 (file)
@@ -1,9 +1,9 @@
 // Coverage/profile data recycled from the showLineExecutionCounts.cpp test.
 //
 // RUN: llvm-profdata merge %S/Inputs/lineExecutionCounts.proftext -o %t.profdata
-// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -j 1 -o %t1.dir -instr-profile %t.profdata -filename-equivalence %S/showLineExecutionCounts.cpp
-// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -num-threads 2 -o %t2.dir -instr-profile %t.profdata -filename-equivalence %S/showLineExecutionCounts.cpp
-// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -o %t3.dir -instr-profile %t.profdata -filename-equivalence %S/showLineExecutionCounts.cpp
+// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -j 1 -o %t1.dir -instr-profile %t.profdata -path-equivalence=/tmp,%S %S/showLineExecutionCounts.cpp
+// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -num-threads 2 -o %t2.dir -instr-profile %t.profdata -path-equivalence=/tmp,%S %S/showLineExecutionCounts.cpp
+// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -o %t3.dir -instr-profile %t.profdata -path-equivalence=/tmp,%S %S/showLineExecutionCounts.cpp
 //
 // RUN: diff %t1.dir/index.txt %t2.dir/index.txt
 // RUN: diff %t1.dir/coverage/tmp/showLineExecutionCounts.cpp.txt %t2.dir/coverage/tmp/showLineExecutionCounts.cpp.txt
index 00f3e87b6014ef4f236f0c79ccd5740bd116090f..39fc22b7ce74eecc4c2336b7b07d7523bf95e819 100644 (file)
@@ -4,20 +4,20 @@
 int main(int argc, const char *argv[]) {}
 
 // RUN: llvm-profdata merge %S/Inputs/universal-binary.proftext -o %t.profdata
-// RUN: llvm-cov show %S/Inputs/universal-binary -instr-profile %t.profdata -filename-equivalence %s -arch x86_64 | FileCheck %s
+// RUN: llvm-cov show %S/Inputs/universal-binary -instr-profile %t.profdata -path-equivalence=/tmp,%S %s -arch x86_64 | FileCheck %s
 // RUN: llvm-cov export %S/Inputs/universal-binary -instr-profile %t.profdata -arch x86_64 2>&1 | FileCheck %S/Inputs/universal-binary.json
 
 // RUN: llvm-cov report %S/Inputs/universal-binary -arch x86_64 -object %S/Inputs/templateInstantiations.covmapping -arch i386 -instr-profile %t.profdata 2>&1 | FileCheck %s --check-prefix=COMBINED
 // COMBINED: showTemplateInstantiations.cpp
 // COMBINED-NEXT: universal-binary.c
 
-// RUN: not llvm-cov show %S/Inputs/universal-binary -instr-profile %t.profdata -filename-equivalence %s -arch i386 2>&1 | FileCheck --check-prefix=WRONG-ARCH %s
+// RUN: not llvm-cov show %S/Inputs/universal-binary -instr-profile %t.profdata -path-equivalence=/tmp,%S %s -arch i386 2>&1 | FileCheck --check-prefix=WRONG-ARCH %s
 // WRONG-ARCH: Failed to load coverage
 
-// RUN: not llvm-cov show %S/Inputs/universal-binary -instr-profile %t.profdata -filename-equivalence %s -arch definitly_a_made_up_architecture 2>&1 | FileCheck --check-prefix=MADE-UP-ARCH %s
+// RUN: not llvm-cov show %S/Inputs/universal-binary -instr-profile %t.profdata -path-equivalence=/tmp,%S %s -arch definitly_a_made_up_architecture 2>&1 | FileCheck --check-prefix=MADE-UP-ARCH %s
 // MADE-UP-ARCH: Unknown architecture: definitly_a_made_up_architecture
 
-// RUN: not llvm-cov show %S/Inputs/universal-binary -instr-profile %t.profdata -filename-equivalence %s -arch=x86_64 -arch=x86_64 2>&1 | FileCheck --check-prefix=TOO-MANY-ARCH %s
+// RUN: not llvm-cov show %S/Inputs/universal-binary -instr-profile %t.profdata -path-equivalence=/tmp,%S %s -arch=x86_64 -arch=x86_64 2>&1 | FileCheck --check-prefix=TOO-MANY-ARCH %s
 // TOO-MANY-ARCH: Number of architectures doesn't match the number of objects
 //
 // RUN: not llvm-cov report -instr-profile %t.profdata 2>&1 | FileCheck --check-prefix=MISSING-BINARY %s
index a06e02f92d56e3d674ed9ebfec5ff69506daebf7..a7826e8bcc84bdaf17741c6d162a0f66ba9bbd7f 100644 (file)
@@ -1,13 +1,13 @@
-// RUN: llvm-cov show %S/Inputs/prevent_false_instantiations.covmapping -instr-profile %S/Inputs/elf_binary_comdat.profdata -filename-equivalence /dev/null | FileCheck %s -allow-empty -check-prefix=FAKE-FILE-STDOUT
-// RUN: llvm-cov show %S/Inputs/prevent_false_instantiations.covmapping -instr-profile %S/Inputs/elf_binary_comdat.profdata -filename-equivalence /dev/null 2>&1 | FileCheck %s -check-prefix=FAKE-FILE-STDERR
+// RUN: llvm-cov show %S/Inputs/prevent_false_instantiations.covmapping -instr-profile %S/Inputs/elf_binary_comdat.profdata -path-equivalence=/tmp,%S /dev/null | FileCheck %s -allow-empty -check-prefix=FAKE-FILE-STDOUT
+// RUN: llvm-cov show %S/Inputs/prevent_false_instantiations.covmapping -instr-profile %S/Inputs/elf_binary_comdat.profdata -path-equivalence=/tmp,%S /dev/null 2>&1 | FileCheck %s -check-prefix=FAKE-FILE-STDERR
 // RUN: not llvm-cov report %S/Inputs/prevent_false_instantiations.covmapping -instr-profile %S/Inputs/elf_binary_comdat.profdata -format=html
 // RUN: not llvm-cov export %S/Inputs/prevent_false_instantiations.covmapping -instr-profile %S/Inputs/elf_binary_comdat.profdata -format=html
 
 // FAKE-FILE-STDOUT-NOT: warning: The file '{{.*}}' isn't covered.
 // FAKE-FILE-STDERR: warning: The file '{{.*}}' isn't covered.
 
-// RUN: llvm-cov show %S/Inputs/prevent_false_instantiations.covmapping -instr-profile %S/Inputs/elf_binary_comdat.profdata -filename-equivalence -name ".*" /dev/null | FileCheck %s -allow-empty -check-prefix=FAKE-FUNC-STDOUT
-// RUN: llvm-cov show %S/Inputs/prevent_false_instantiations.covmapping -instr-profile %S/Inputs/elf_binary_comdat.profdata -filename-equivalence -name-regex ".*" /dev/null 2>&1 | FileCheck %s -check-prefix=FAKE-FUNC-STDERR
+// RUN: llvm-cov show %S/Inputs/prevent_false_instantiations.covmapping -instr-profile %S/Inputs/elf_binary_comdat.profdata -path-equivalence=/tmp,%S -name ".*" /dev/null | FileCheck %s -allow-empty -check-prefix=FAKE-FUNC-STDOUT
+// RUN: llvm-cov show %S/Inputs/prevent_false_instantiations.covmapping -instr-profile %S/Inputs/elf_binary_comdat.profdata -path-equivalence=/tmp,%S -name-regex ".*" /dev/null 2>&1 | FileCheck %s -check-prefix=FAKE-FUNC-STDERR
 
 // FAKE-FUNC-STDOUT-NOT: warning: Could not read coverage for '{{.*}}'.
 // FAKE-FUNC-STDERR: Could not read coverage for '{{.*}}'.
index 8afae2294ebed7beee444a912589ed48429bc406..e5878df6c154fc88ce66b57ed77ed6fa40d16a6d 100644 (file)
@@ -94,6 +94,10 @@ private:
   /// \brief Load the coverage mapping data. Return nullptr if an error occurred.
   std::unique_ptr<CoverageMapping> load();
 
+  /// \brief Create a mapping from files in the Coverage data to local copies
+  /// (path-equivalence).
+  void remapPathNames(const CoverageMapping &Coverage);
+
   /// \brief Remove input source files which aren't mapped by \p Coverage.
   void removeUnmappedInputs(const CoverageMapping &Coverage);
 
@@ -125,13 +129,14 @@ private:
   /// A list of input source files.
   std::vector<std::string> SourceFiles;
 
-  /// Whether or not we're in -filename-equivalence mode.
-  bool CompareFilenamesOnly;
-
-  /// In -filename-equivalence mode, this maps absolute paths from the
-  /// coverage mapping data to input source files.
+  /// In -path-equivalence mode, this maps the absolute paths from the coverage
+  /// mapping data to the input source files.
   StringMap<std::string> RemappedFilenames;
 
+  /// The coverage data path to be remapped from, and the source path to be
+  /// remapped to, when using -path-equivalence.
+  Optional<std::pair<std::string, std::string>> PathRemapping;
+
   /// The architecture the coverage mapping data targets.
   std::vector<StringRef> CoverageArches;
 
@@ -171,24 +176,20 @@ void CodeCoverageTool::warning(const Twine &Message, StringRef Whence) {
 }
 
 void CodeCoverageTool::addCollectedPath(const std::string &Path) {
-  if (CompareFilenamesOnly) {
-    SourceFiles.emplace_back(Path);
-  } else {
-    SmallString<128> EffectivePath(Path);
-    if (std::error_code EC = sys::fs::make_absolute(EffectivePath)) {
-      error(EC.message(), Path);
-      return;
-    }
-    sys::path::remove_dots(EffectivePath, /*remove_dot_dots=*/true);
-    SourceFiles.emplace_back(EffectivePath.str());
+  SmallString<128> EffectivePath(Path);
+  if (std::error_code EC = sys::fs::make_absolute(EffectivePath)) {
+    error(EC.message(), Path);
+    return;
   }
+  sys::path::remove_dots(EffectivePath, /*remove_dot_dots=*/true);
+  SourceFiles.emplace_back(EffectivePath.str());
 }
 
 void CodeCoverageTool::collectPaths(const std::string &Path) {
   llvm::sys::fs::file_status Status;
   llvm::sys::fs::status(Path, Status);
   if (!llvm::sys::fs::exists(Status)) {
-    if (CompareFilenamesOnly)
+    if (PathRemapping)
       addCollectedPath(Path);
     else
       error("Missing source file", Path);
@@ -348,6 +349,8 @@ std::unique_ptr<CoverageMapping> CodeCoverageTool::load() {
   if (Mismatched)
     warning(utostr(Mismatched) + " functions have mismatched data");
 
+  remapPathNames(*Coverage);
+
   if (!SourceFiles.empty())
     removeUnmappedInputs(*Coverage);
 
@@ -356,33 +359,58 @@ std::unique_ptr<CoverageMapping> CodeCoverageTool::load() {
   return Coverage;
 }
 
+void CodeCoverageTool::remapPathNames(const CoverageMapping &Coverage) {
+  if (!PathRemapping)
+    return;
+
+  // Convert remapping paths to native paths with trailing seperators.
+  auto nativeWithTrailing = [](StringRef Path) -> std::string {
+    if (Path.empty())
+      return "";
+    SmallString<128> NativePath;
+    sys::path::native(Path, NativePath);
+    if (!sys::path::is_separator(NativePath.back()))
+      NativePath += sys::path::get_separator();
+    return NativePath.c_str();
+  };
+  std::string RemapFrom = nativeWithTrailing(PathRemapping->first);
+  std::string RemapTo = nativeWithTrailing(PathRemapping->second);
+
+  // Create a mapping from coverage data file paths to local paths.
+  for (StringRef Filename : Coverage.getUniqueSourceFiles()) {
+    SmallString<128> NativeFilename;
+    sys::path::native(Filename, NativeFilename);
+    if (NativeFilename.startswith(RemapFrom)) {
+      RemappedFilenames[Filename] =
+          RemapTo + NativeFilename.substr(RemapFrom.size()).str();
+    }
+  }
+
+  // Convert input files from local paths to coverage data file paths.
+  StringMap<std::string> InvRemappedFilenames;
+  for (const auto &RemappedFilename : RemappedFilenames)
+    InvRemappedFilenames[RemappedFilename.getValue()] = RemappedFilename.getKey();
+
+  for (std::string &Filename : SourceFiles) {
+    SmallString<128> NativeFilename;
+    sys::path::native(Filename, NativeFilename);
+    auto CovFileName = InvRemappedFilenames.find(NativeFilename);
+    if (CovFileName != InvRemappedFilenames.end())
+      Filename = CovFileName->second;
+  }
+}
+
 void CodeCoverageTool::removeUnmappedInputs(const CoverageMapping &Coverage) {
   std::vector<StringRef> CoveredFiles = Coverage.getUniqueSourceFiles();
 
   auto UncoveredFilesIt = SourceFiles.end();
-  if (!CompareFilenamesOnly) {
-    // The user may have specified source files which aren't in the coverage
-    // mapping. Filter these files away.
-    UncoveredFilesIt = std::remove_if(
-        SourceFiles.begin(), SourceFiles.end(), [&](const std::string &SF) {
-          return !std::binary_search(CoveredFiles.begin(), CoveredFiles.end(),
-                                     SF);
-        });
-  } else {
-    for (auto &SF : SourceFiles) {
-      StringRef SFBase = sys::path::filename(SF);
-      for (const auto &CF : CoveredFiles) {
-        if (SFBase == sys::path::filename(CF)) {
-          RemappedFilenames[CF] = SF;
-          SF = CF;
-          break;
-        }
-      }
-    }
-    UncoveredFilesIt = std::remove_if(
-        SourceFiles.begin(), SourceFiles.end(),
-        [&](const std::string &SF) { return !RemappedFilenames.count(SF); });
-  }
+  // The user may have specified source files which aren't in the coverage
+  // mapping. Filter these files away.
+  UncoveredFilesIt = std::remove_if(
+      SourceFiles.begin(), SourceFiles.end(), [&](const std::string &SF) {
+        return !std::binary_search(CoveredFiles.begin(), CoveredFiles.end(),
+                                   SF);
+      });
 
   SourceFiles.erase(UncoveredFilesIt, SourceFiles.end());
 }
@@ -521,10 +549,10 @@ int CodeCoverageTool::run(Command Cmd, int argc, const char **argv) {
                             "HTML output")),
       cl::init(CoverageViewOptions::OutputFormat::Text));
 
-  cl::opt<bool> FilenameEquivalence(
-      "filename-equivalence", cl::Optional,
-      cl::desc("Treat source files as equivalent to paths in the coverage data "
-               "when the file names match, even if the full paths do not"));
+  cl::opt<std::string> PathRemap(
+      "path-equivalence", cl::Optional,
+      cl::desc("<from>,<to> Map coverage data paths to local source file "
+               "paths"));
 
   cl::OptionCategory FilteringCategory("Function filtering options");
 
@@ -573,7 +601,6 @@ int CodeCoverageTool::run(Command Cmd, int argc, const char **argv) {
   auto commandLineParser = [&, this](int argc, const char **argv) -> int {
     cl::ParseCommandLineOptions(argc, argv, "LLVM code coverage tool\n");
     ViewOpts.Debug = DebugDump;
-    CompareFilenamesOnly = FilenameEquivalence;
 
     if (!CovFilename.empty())
       ObjectFilenames.emplace_back(CovFilename);
@@ -598,6 +625,12 @@ int CodeCoverageTool::run(Command Cmd, int argc, const char **argv) {
       break;
     }
 
+    // If path-equivalence was given and is a comma seperated pair then set
+    // PathRemapping.
+    auto EquivPair = StringRef(PathRemap).split(',');
+    if (!(EquivPair.first.empty() && EquivPair.second.empty()))
+      PathRemapping = EquivPair;
+
     // If a demangler is supplied, check if it exists and register it.
     if (DemanglerOpts.size()) {
       auto DemanglerPathOrErr = sys::findProgramByName(DemanglerOpts[0]);