Squashed 'third_party/llvm-7.0/llvm/' content from commit 65ce2e56889

git-subtree-dir: third_party/llvm-7.0/llvm
git-subtree-split: 65ce2e56889af84e8be8e311f484a4dfe4b62d7a
diff --git a/test/tools/llvm-cov/Inputs/README b/test/tools/llvm-cov/Inputs/README
new file mode 100644
index 0000000..3773ba3
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/README
@@ -0,0 +1,21 @@
+These inputs were pre-generated to allow for easier testing of llvm-cov.
+
+The files used to test the gcov compatible code coverage tool were generated
+using the following method:
+
+  test.gcno and test.gcda were create by running clang:
+    clang++ -g -ftest-coverage -fprofile-arcs test.cpp
+
+  test.cpp.gcov was created by running gcov 4.2.1:
+    gcov test.cpp
+
+The 'covmapping' files that are used to test llvm-cov contain raw sections
+with the coverage mapping data generated by the compiler and linker. They are
+created by running clang and llvm-cov:
+  clang++ -fprofile-instr-generate -fcoverage-mapping -o test test.cpp
+  llvm-cov convert-for-testing -o test.covmapping test
+
+The 'profdata' files were generated by running an instrumented version of the
+program and merging the raw profile data using llvm-profdata.
+  ./test
+  llvm-profdata merge -o test.profdata default.profraw
diff --git a/test/tools/llvm-cov/Inputs/binary-formats.canonical.json b/test/tools/llvm-cov/Inputs/binary-formats.canonical.json
new file mode 100644
index 0000000..19147e2
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/binary-formats.canonical.json
@@ -0,0 +1,39 @@
+// Metadata section
+// CHECK: {"version":"{{[0-9]\.[0-9]\.[0-9]}}","type":"llvm.coverage.json.export","data":[
+
+// Open Export
+// CHECK-SAME: {"files":[
+
+// File Object
+// CHECK-SAME: {"filename":"{{[^"]+}}binary-formats.c",
+// CHECK-SAME: "segments":[
+// CHECK-SAME: [4,40,100,1,1],[4,42,0,0,0]],
+// CHECK-SAME: "expansions":[],
+
+// Verify the Summary Section for the first file
+// CHECK-SAME: "summary":{
+// CHECK-SAME: "lines":{"count":1,"covered":1,"percent":100},
+// CHECK-SAME: "functions":{"count":1,"covered":1,"percent":100},
+// CHECK-SAME: "regions":{"count":1,"covered":1,"notcovered":0,"percent":100}}}
+
+// Close Files Array
+// CHECK-SAME: ],
+
+// Functions List
+// CHECK-SAME: "functions":[
+// CHECK-SAME: {"name":"main","count":100,"regions":[
+// CHECK-SAME: [4,40,4,42,100,0,0,0]
+// CHECK-SAME: ],
+// CHECK-SAME: "filenames":["{{[^"]+}}binary-formats.c"]
+// CHECK-SAME: }],
+
+
+// Full Export Summary
+// CHECK-SAME: "totals":{
+// CHECK-SAME: "lines":{"count":1,"covered":1,"percent":100},
+// CHECK-SAME: "functions":{"count":1,"covered":1,"percent":100},
+// CHECK-SAME: "instantiations":{"count":1,"covered":1,"percent":100},
+// CHECK-SAME: "regions":{"count":1,"covered":1,"notcovered":0,"percent":100}}
+
+// Close the export object, data array, and root object
+// CHECK-SAME: }]}
diff --git a/test/tools/llvm-cov/Inputs/binary-formats.macho32b b/test/tools/llvm-cov/Inputs/binary-formats.macho32b
new file mode 100755
index 0000000..bb9f356
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/binary-formats.macho32b
Binary files differ
diff --git a/test/tools/llvm-cov/Inputs/binary-formats.macho32l b/test/tools/llvm-cov/Inputs/binary-formats.macho32l
new file mode 100755
index 0000000..2dd4c44
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/binary-formats.macho32l
Binary files differ
diff --git a/test/tools/llvm-cov/Inputs/binary-formats.macho64l b/test/tools/llvm-cov/Inputs/binary-formats.macho64l
new file mode 100755
index 0000000..0045c43
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/binary-formats.macho64l
Binary files differ
diff --git a/test/tools/llvm-cov/Inputs/binary-formats.proftext b/test/tools/llvm-cov/Inputs/binary-formats.proftext
new file mode 100644
index 0000000..97816c2
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/binary-formats.proftext
@@ -0,0 +1,4 @@
+main
+0x0
+1
+100
diff --git a/test/tools/llvm-cov/Inputs/binary-formats.v1.linux64l b/test/tools/llvm-cov/Inputs/binary-formats.v1.linux64l
new file mode 100755
index 0000000..319322d
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/binary-formats.v1.linux64l
Binary files differ
diff --git a/test/tools/llvm-cov/Inputs/binary-formats.v2.linux32l b/test/tools/llvm-cov/Inputs/binary-formats.v2.linux32l
new file mode 100755
index 0000000..6ea83e5
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/binary-formats.v2.linux32l
Binary files differ
diff --git a/test/tools/llvm-cov/Inputs/binary-formats.v2.linux64l b/test/tools/llvm-cov/Inputs/binary-formats.v2.linux64l
new file mode 100755
index 0000000..9c6835c
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/binary-formats.v2.linux64l
Binary files differ
diff --git a/test/tools/llvm-cov/Inputs/combine_expansions.covmapping b/test/tools/llvm-cov/Inputs/combine_expansions.covmapping
new file mode 100644
index 0000000..744bb29
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/combine_expansions.covmapping
Binary files differ
diff --git a/test/tools/llvm-cov/Inputs/combine_expansions.proftext b/test/tools/llvm-cov/Inputs/combine_expansions.proftext
new file mode 100644
index 0000000..5419d23
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/combine_expansions.proftext
@@ -0,0 +1,8 @@
+main
+# Func Hash:
+0
+# Num Counters:
+1
+# Counter Values:
+1
+
diff --git a/test/tools/llvm-cov/Inputs/copy_block_helper.gcda b/test/tools/llvm-cov/Inputs/copy_block_helper.gcda
new file mode 100644
index 0000000..d7ff469
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/copy_block_helper.gcda
Binary files differ
diff --git a/test/tools/llvm-cov/Inputs/copy_block_helper.gcno b/test/tools/llvm-cov/Inputs/copy_block_helper.gcno
new file mode 100644
index 0000000..a9d1084
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/copy_block_helper.gcno
Binary files differ
diff --git a/test/tools/llvm-cov/Inputs/deferred-regions.covmapping b/test/tools/llvm-cov/Inputs/deferred-regions.covmapping
new file mode 100644
index 0000000..750dd81
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/deferred-regions.covmapping
Binary files differ
diff --git a/test/tools/llvm-cov/Inputs/deferred-regions.profdata b/test/tools/llvm-cov/Inputs/deferred-regions.profdata
new file mode 100644
index 0000000..423f1f0
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/deferred-regions.profdata
Binary files differ
diff --git a/test/tools/llvm-cov/Inputs/dir-with-filtering.covmapping b/test/tools/llvm-cov/Inputs/dir-with-filtering.covmapping
new file mode 100644
index 0000000..0f52ba8
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/dir-with-filtering.covmapping
Binary files differ
diff --git a/test/tools/llvm-cov/Inputs/dir-with-filtering.proftext b/test/tools/llvm-cov/Inputs/dir-with-filtering.proftext
new file mode 100644
index 0000000..6457ad1
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/dir-with-filtering.proftext
@@ -0,0 +1,32 @@
+main
+# Func Hash:
+0
+# Num Counters:
+1
+# Counter Values:
+1
+
+_Z2f1v
+# Func Hash:
+0
+# Num Counters:
+1
+# Counter Values:
+1
+
+_Z2f2v
+# Func Hash:
+0
+# Num Counters:
+1
+# Counter Values:
+0
+
+_Z2f3v
+# Func Hash:
+0
+# Num Counters:
+1
+# Counter Values:
+0
+
diff --git a/test/tools/llvm-cov/Inputs/dir-with-filtering1.cpp b/test/tools/llvm-cov/Inputs/dir-with-filtering1.cpp
new file mode 100644
index 0000000..b6a308f
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/dir-with-filtering1.cpp
@@ -0,0 +1,8 @@
+int f1() {
+  return 1;
+}
+
+int main() {
+  f1();
+  return 0;
+}
diff --git a/test/tools/llvm-cov/Inputs/dir-with-filtering2.cpp b/test/tools/llvm-cov/Inputs/dir-with-filtering2.cpp
new file mode 100644
index 0000000..2fa2c4e
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/dir-with-filtering2.cpp
@@ -0,0 +1,8 @@
+int f2() {
+  return 2;
+}
+
+int f3() {
+  return 3;
+}
+
diff --git a/test/tools/llvm-cov/Inputs/double_dots.covmapping b/test/tools/llvm-cov/Inputs/double_dots.covmapping
new file mode 100644
index 0000000..b03e19e
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/double_dots.covmapping
Binary files differ
diff --git a/test/tools/llvm-cov/Inputs/double_dots.proftext b/test/tools/llvm-cov/Inputs/double_dots.proftext
new file mode 100644
index 0000000..5419d23
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/double_dots.proftext
@@ -0,0 +1,8 @@
+main
+# Func Hash:
+0
+# Num Counters:
+1
+# Counter Values:
+1
+
diff --git a/test/tools/llvm-cov/Inputs/elf_binary_comdat.profdata b/test/tools/llvm-cov/Inputs/elf_binary_comdat.profdata
new file mode 100644
index 0000000..ef80e56
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/elf_binary_comdat.profdata
Binary files differ
diff --git a/test/tools/llvm-cov/Inputs/gcov47_compatibility.gcda b/test/tools/llvm-cov/Inputs/gcov47_compatibility.gcda
new file mode 100644
index 0000000..825156b
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/gcov47_compatibility.gcda
Binary files differ
diff --git a/test/tools/llvm-cov/Inputs/gcov47_compatibility.gcno b/test/tools/llvm-cov/Inputs/gcov47_compatibility.gcno
new file mode 100644
index 0000000..90e3bd2
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/gcov47_compatibility.gcno
Binary files differ
diff --git a/test/tools/llvm-cov/Inputs/hideUnexecutedSubviews.proftext b/test/tools/llvm-cov/Inputs/hideUnexecutedSubviews.proftext
new file mode 100644
index 0000000..8ef6eae
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/hideUnexecutedSubviews.proftext
@@ -0,0 +1,16 @@
+_Z4funcIbEiT_
+10
+2
+0
+0
+
+_Z4funcIiEiT_
+10
+2
+0
+0
+
+main
+0
+1
+1
diff --git a/test/tools/llvm-cov/Inputs/highlightedRanges.covmapping b/test/tools/llvm-cov/Inputs/highlightedRanges.covmapping
new file mode 100644
index 0000000..5c3d67f
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/highlightedRanges.covmapping
Binary files differ
diff --git a/test/tools/llvm-cov/Inputs/highlightedRanges.json b/test/tools/llvm-cov/Inputs/highlightedRanges.json
new file mode 100644
index 0000000..cff6ab3
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/highlightedRanges.json
@@ -0,0 +1,51 @@
+// Metadata section
+// CHECK: {"version":"{{[0-9]\.[0-9]\.[0-9]}}","type":"llvm.coverage.json.export","data":[
+
+// Open Export
+// CHECK-SAME: {"files":[
+
+// File Object
+// CHECK-SAME: {"filename":"{{[^"]+}}showHighlightedRanges.cpp",
+// CHECK-SAME: "segments":[
+// CHECK-SAME: {{(\[[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+\],?)+}}],
+// CHECK-SAME: "expansions":[],
+
+// Verify the Summary Section for the first file
+// CHECK-SAME: "summary":{
+// CHECK-SAME: "lines":{"count":40,"covered":33,"percent":82},
+// CHECK-SAME: "functions":{"count":4,"covered":4,"percent":100},
+// CHECK-SAME: "regions":{"count":21,"covered":13,"notcovered":8,"percent":61}}}
+
+// Close Files Array
+// CHECK-SAME: ],
+
+// Functions List
+// CHECK-SAME: "functions":[
+// CHECK-SAME: {"name":"_Z4funcv","count":1,"regions":[
+// CHECK-SAME: {{(\[[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+\],?)+}}
+// CHECK-SAME: ],
+// CHECK-SAME: "filenames":["{{[^"]+}}showHighlightedRanges.cpp"]
+// CHECK-SAME: },
+// CHECK-SAME: {"name":"_Z5func2i","count":1,"regions":[
+// CHECK-SAME: {{(\[[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+\],?)+}}
+// CHECK-SAME: ],
+// CHECK-SAME: "filenames":["{{[^"]+}}showHighlightedRanges.cpp"]
+// CHECK-SAME: }
+// CHECK-SAME: {"name":"_Z4testv","count":1,"regions":[
+// CHECK-SAME: {{(\[[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+\],?)+}}
+// CHECK-SAME: ],
+// CHECK-SAME: "filenames":["{{[^"]+}}showHighlightedRanges.cpp"]
+// CHECK-SAME: }
+// CHECK-SAME: {"name":"main","count":1,"regions":[
+// CHECK-SAME: {{(\[[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+\],?)+}}
+// CHECK-SAME: ],
+// CHECK-SAME: "filenames":["{{.*}}showHighlightedRanges.cpp"]
+// CHECK-SAME: }],
+
+
+// Full Export Summary
+// CHECK-SAME: "totals":{
+// CHECK-SAME: "lines":{"count":40,"covered":33,"percent":82},
+// CHECK-SAME: "functions":{"count":4,"covered":4,"percent":100},
+// CHECK-SAME: "instantiations":{"count":4,"covered":4,"percent":100},
+// CHECK-SAME: "regions":{"count":21,"covered":13,"notcovered":8,"percent":61}}}
diff --git a/test/tools/llvm-cov/Inputs/highlightedRanges.profdata b/test/tools/llvm-cov/Inputs/highlightedRanges.profdata
new file mode 100644
index 0000000..b465b00
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/highlightedRanges.profdata
Binary files differ
diff --git a/test/tools/llvm-cov/Inputs/ifdef.covmapping b/test/tools/llvm-cov/Inputs/ifdef.covmapping
new file mode 100644
index 0000000..212a1ba
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/ifdef.covmapping
Binary files differ
diff --git a/test/tools/llvm-cov/Inputs/ifdef.profdata b/test/tools/llvm-cov/Inputs/ifdef.profdata
new file mode 100644
index 0000000..e71240b
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/ifdef.profdata
Binary files differ
diff --git a/test/tools/llvm-cov/Inputs/instrprof-comdat.h b/test/tools/llvm-cov/Inputs/instrprof-comdat.h
new file mode 100644
index 0000000..07941f9
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/instrprof-comdat.h
@@ -0,0 +1,28 @@
+template <class T> class FOO {
+public:
+  FOO() : t(0) {}
+
+  T DoIt(T ti);
+
+private:
+  T t;
+};
+
+template <class T> T FOO<T>::DoIt(T ti) { // HEADER: [[@LINE]]|  2|template
+  for (T I = 0; I < ti; I++) {            // HEADER: [[@LINE]]| 22|  for (T
+    t += I;                               // HEADER: [[@LINE]]| 20|   t += I;
+    if (I > ti / 2)                       // HEADER: [[@LINE]]| 20|   if (I > ti
+      t -= 1;                             // HEADER: [[@LINE]]| 20|     t -= 1;
+  }                                       // HEADER: [[@LINE]]| 20| }
+                                          // HEADER: [[@LINE]]|  2|
+  return t;                               // HEADER: [[@LINE]]|  2|  return t;
+}
+
+// To generate the binaries which correspond to this file, you must first
+// compile a program with two calls to Foo<int>::DoIt(10) for each desired
+// architecture. Collect a raw profile from any one of these binaries, index
+// it, and check it in along with the executables.
+
+// Note:
+// The line execution count on line 14 is incorrect because of a bug in the
+// checked-in coverage mappings, which has subsequently been fixed in clang.
diff --git a/test/tools/llvm-cov/Inputs/lineExecutionCounts.covmapping b/test/tools/llvm-cov/Inputs/lineExecutionCounts.covmapping
new file mode 100644
index 0000000..0b2458a
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/lineExecutionCounts.covmapping
Binary files differ
diff --git a/test/tools/llvm-cov/Inputs/lineExecutionCounts.json b/test/tools/llvm-cov/Inputs/lineExecutionCounts.json
new file mode 100644
index 0000000..07f39e7
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/lineExecutionCounts.json
@@ -0,0 +1,39 @@
+// Metadata section
+// CHECK: {"version":"{{[0-9]\.[0-9]\.[0-9]}}","type":"llvm.coverage.json.export","data":[
+
+// Open Export
+// CHECK-SAME: {"files":[
+
+// File Object
+// CHECK-SAME: {"filename":"{{[^"]+}}showLineExecutionCounts.cpp",
+// CHECK-SAME: "segments":[
+// CHECK-SAME: {{(\[[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+\],?)+}}],
+// CHECK-SAME: "expansions":[],
+
+// Verify the Summary Section for the first file
+// CHECK-SAME: "summary":{
+// CHECK-SAME: "lines":{"count":20,"covered":18,"percent":90},
+// CHECK-SAME: "functions":{"count":1,"covered":1,"percent":100},
+// CHECK-SAME: "regions":{"count":11,"covered":8,"notcovered":3,"percent":72}}}
+
+// Close Files Array
+// CHECK-SAME: ],
+
+// Functions List
+// CHECK-SAME: "functions":[
+// CHECK-SAME: {"name":"main","count":161,"regions":[
+// CHECK-SAME: {{(\[[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+\],?)+}}
+// CHECK-SAME: ],
+// CHECK-SAME: "filenames":["{{[^"]+}}showLineExecutionCounts.cpp"]
+// CHECK-SAME: }],
+
+
+// Full Export Summary
+// CHECK-SAME: "totals":{
+// CHECK-SAME: "lines":{"count":20,"covered":18,"percent":90},
+// CHECK-SAME: "functions":{"count":1,"covered":1,"percent":100},
+// CHECK-SAME: "instantiations":{"count":1,"covered":1,"percent":100},
+// CHECK-SAME: "regions":{"count":11,"covered":8,"notcovered":3,"percent":72}}
+
+// Close the export object, data array, and root object
+// CHECK-SAME: }]}
diff --git a/test/tools/llvm-cov/Inputs/lineExecutionCounts.proftext b/test/tools/llvm-cov/Inputs/lineExecutionCounts.proftext
new file mode 100644
index 0000000..38387a6
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/lineExecutionCounts.proftext
@@ -0,0 +1,8 @@
+main
+0x000000000028434d
+5
+161
+0
+16100
+161
+0
diff --git a/test/tools/llvm-cov/Inputs/malformedRegions.covmapping b/test/tools/llvm-cov/Inputs/malformedRegions.covmapping
new file mode 100644
index 0000000..20d6abf
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/malformedRegions.covmapping
Binary files differ
diff --git a/test/tools/llvm-cov/Inputs/multiple-files.covmapping b/test/tools/llvm-cov/Inputs/multiple-files.covmapping
new file mode 100644
index 0000000..3e229a8
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/multiple-files.covmapping
Binary files differ
diff --git a/test/tools/llvm-cov/Inputs/multiple-files.proftext b/test/tools/llvm-cov/Inputs/multiple-files.proftext
new file mode 100644
index 0000000..1be93b7
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/multiple-files.proftext
@@ -0,0 +1,19 @@
+f1
+0x0
+1
+1
+
+f2
+0x0
+1
+1
+
+f3
+0x0
+1
+1
+
+f4
+0x0
+1
+1
diff --git a/test/tools/llvm-cov/Inputs/multiple-files2.covmapping b/test/tools/llvm-cov/Inputs/multiple-files2.covmapping
new file mode 100644
index 0000000..770817a
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/multiple-files2.covmapping
Binary files differ
diff --git a/test/tools/llvm-cov/Inputs/multiple_objects/header.h b/test/tools/llvm-cov/Inputs/multiple_objects/header.h
new file mode 100644
index 0000000..03b37cd
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/multiple_objects/header.h
@@ -0,0 +1,29 @@
+static inline void f1() {
+#ifdef DEF
+  if (false && false)
+    return;
+
+  if (true || false || true)
+    return;
+
+  if (true && false)
+    return;
+#endif
+}
+
+template<typename T>
+void f2(T **x) {
+#ifdef DEF
+  if (false && false)
+    *x = nullptr;
+
+  if (true || false || true)
+    *x = nullptr;
+
+  if (true && false)
+    *x = nullptr;
+#endif
+}
+
+static inline void f3() {
+}
diff --git a/test/tools/llvm-cov/Inputs/multiple_objects/merged.profdata b/test/tools/llvm-cov/Inputs/multiple_objects/merged.profdata
new file mode 100644
index 0000000..eeaa4eb
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/multiple_objects/merged.profdata
Binary files differ
diff --git a/test/tools/llvm-cov/Inputs/multiple_objects/use_1.cc b/test/tools/llvm-cov/Inputs/multiple_objects/use_1.cc
new file mode 100644
index 0000000..835db29
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/multiple_objects/use_1.cc
@@ -0,0 +1,14 @@
+#define DEF
+#include "header.h"
+
+int main() {
+  f1();
+
+  int *x;
+  f2(&x);
+
+  float *y;
+  f2(&y);
+
+  return 0;
+}
diff --git a/test/tools/llvm-cov/Inputs/multiple_objects/use_1.covmapping b/test/tools/llvm-cov/Inputs/multiple_objects/use_1.covmapping
new file mode 100644
index 0000000..641bdb4
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/multiple_objects/use_1.covmapping
Binary files differ
diff --git a/test/tools/llvm-cov/Inputs/multiple_objects/use_2.cc b/test/tools/llvm-cov/Inputs/multiple_objects/use_2.cc
new file mode 100644
index 0000000..5296559
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/multiple_objects/use_2.cc
@@ -0,0 +1,20 @@
+#undef DEF
+#include "header.h"
+
+static int foo() {
+  return 0;
+}
+
+int main() {
+  f1();
+
+  long *x;
+  f2(&x);
+
+  double *y;
+  f2(&y);
+
+  f3();
+
+  return foo();
+}
diff --git a/test/tools/llvm-cov/Inputs/multiple_objects/use_2.covmapping b/test/tools/llvm-cov/Inputs/multiple_objects/use_2.covmapping
new file mode 100644
index 0000000..f26caea
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/multiple_objects/use_2.covmapping
Binary files differ
diff --git a/test/tools/llvm-cov/Inputs/multithreaded_report/abs.h b/test/tools/llvm-cov/Inputs/multithreaded_report/abs.h
new file mode 100644
index 0000000..41eb2b0
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/multithreaded_report/abs.h
@@ -0,0 +1,7 @@
+template<typename T>
+T abs(T x) {
+  if (x < 0) {
+    return -x;
+  }
+  return x;
+}
diff --git a/test/tools/llvm-cov/Inputs/multithreaded_report/bytes.cc b/test/tools/llvm-cov/Inputs/multithreaded_report/bytes.cc
new file mode 100644
index 0000000..7df13d8
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/multithreaded_report/bytes.cc
@@ -0,0 +1,15 @@
+#include "abs.h"
+#include "bytes.h"
+#include "pow.h"
+
+bool loopBytes() {
+  uint64_t totalInt = 0;
+  double totalFloat = 0;
+  for (uint8_t i = 1; i != 0; ++i) {
+    double a = logarithm(i);
+    a = abs(a);
+    totalInt += abs(pow(i, static_cast<uint8_t>(a)));
+    totalFloat += pow(static_cast<decltype(a)>(i), a);
+  }
+  return totalInt > totalFloat;
+}
diff --git a/test/tools/llvm-cov/Inputs/multithreaded_report/bytes.h b/test/tools/llvm-cov/Inputs/multithreaded_report/bytes.h
new file mode 100644
index 0000000..c239bb6
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/multithreaded_report/bytes.h
@@ -0,0 +1,8 @@
+#include <cmath>
+#include <cstdint>
+
+inline double logarithm(uint8_t v) {
+  return log(v);
+}
+
+bool loopBytes();
diff --git a/test/tools/llvm-cov/Inputs/multithreaded_report/main.cc b/test/tools/llvm-cov/Inputs/multithreaded_report/main.cc
new file mode 100644
index 0000000..b5bc654
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/multithreaded_report/main.cc
@@ -0,0 +1,15 @@
+#include "bytes.h"
+#include "words.h"
+
+int main() {
+  bool result = false;
+  if (loopBytes())
+    result |= true;
+  if (loopWords())
+    result |= true;
+
+  if (result)
+    return 0;
+
+  return result;
+}
diff --git a/test/tools/llvm-cov/Inputs/multithreaded_report/main.covmapping b/test/tools/llvm-cov/Inputs/multithreaded_report/main.covmapping
new file mode 100644
index 0000000..75bd4cb
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/multithreaded_report/main.covmapping
Binary files differ
diff --git a/test/tools/llvm-cov/Inputs/multithreaded_report/main.profdata b/test/tools/llvm-cov/Inputs/multithreaded_report/main.profdata
new file mode 100644
index 0000000..21dfdcf
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/multithreaded_report/main.profdata
Binary files differ
diff --git a/test/tools/llvm-cov/Inputs/multithreaded_report/pow.h b/test/tools/llvm-cov/Inputs/multithreaded_report/pow.h
new file mode 100644
index 0000000..303d114
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/multithreaded_report/pow.h
@@ -0,0 +1,11 @@
+template<typename T>
+T pow(T b, T p) {
+  if (!p)
+    return 1;
+
+  while (--p) {
+    b *= b;
+  }
+
+  return b;
+}
diff --git a/test/tools/llvm-cov/Inputs/multithreaded_report/words.cc b/test/tools/llvm-cov/Inputs/multithreaded_report/words.cc
new file mode 100644
index 0000000..7d2b47c
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/multithreaded_report/words.cc
@@ -0,0 +1,15 @@
+#include "abs.h"
+#include "bytes.h"
+#include "pow.h"
+
+bool loopWords() {
+  uint64_t totalInt = 0;
+  double totalFloat = 0;
+  for (uint16_t i = 1; i != 0; ++i) {
+    double a = logarithm(i);
+    a = abs(a);
+    totalInt += abs(pow(i, static_cast<uint16_t>(a)));
+    totalFloat += pow(static_cast<decltype(a)>(i), a);
+  }
+  return totalInt > totalFloat;
+}
diff --git a/test/tools/llvm-cov/Inputs/multithreaded_report/words.h b/test/tools/llvm-cov/Inputs/multithreaded_report/words.h
new file mode 100644
index 0000000..855f7b3
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/multithreaded_report/words.h
@@ -0,0 +1,8 @@
+#include <cmath>
+#include <cstdint>
+
+inline double logarithm(uint16_t v) {
+  return log(v);
+}
+
+bool loopWords();
diff --git a/test/tools/llvm-cov/Inputs/name_whitelist.covmapping b/test/tools/llvm-cov/Inputs/name_whitelist.covmapping
new file mode 100644
index 0000000..6c067ab
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/name_whitelist.covmapping
Binary files differ
diff --git a/test/tools/llvm-cov/Inputs/name_whitelist.cpp b/test/tools/llvm-cov/Inputs/name_whitelist.cpp
new file mode 100644
index 0000000..dec10ea
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/name_whitelist.cpp
@@ -0,0 +1,18 @@
+int func1() {
+    return 1;
+}
+int func2() {
+    return 1;
+}
+int func3() {
+    return 1;
+}
+int func4() {
+    return 1;
+}
+int func5() {
+    return 1;
+}
+int func6() {
+    return 1;
+}
diff --git a/test/tools/llvm-cov/Inputs/name_whitelist.proftext b/test/tools/llvm-cov/Inputs/name_whitelist.proftext
new file mode 100644
index 0000000..c806d15
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/name_whitelist.proftext
@@ -0,0 +1,56 @@
+_Z5func1v
+# Func Hash:
+0
+# Num Counters:
+1
+# Counter Values:
+0
+
+_Z5func2v
+# Func Hash:
+0
+# Num Counters:
+1
+# Counter Values:
+0
+
+_Z5func3v
+# Func Hash:
+0
+# Num Counters:
+1
+# Counter Values:
+0
+
+_Z5func4v
+# Func Hash:
+0
+# Num Counters:
+1
+# Counter Values:
+0
+
+main
+# Func Hash:
+0
+# Num Counters:
+1
+# Counter Values:
+1
+
+_Z5func5v
+# Func Hash:
+0
+# Num Counters:
+1
+# Counter Values:
+0
+
+_Z5func6v
+# Func Hash:
+0
+# Num Counters:
+1
+# Counter Values:
+0
+
diff --git a/test/tools/llvm-cov/Inputs/native_separators.covmapping b/test/tools/llvm-cov/Inputs/native_separators.covmapping
new file mode 100644
index 0000000..ce8d6bb
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/native_separators.covmapping
Binary files differ
diff --git a/test/tools/llvm-cov/Inputs/path_equivalence.covmapping b/test/tools/llvm-cov/Inputs/path_equivalence.covmapping
new file mode 100644
index 0000000..ea09bf3
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/path_equivalence.covmapping
Binary files 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
index 0000000..5419d23
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/path_equivalence.proftext
@@ -0,0 +1,8 @@
+main
+# Func Hash:
+0
+# Num Counters:
+1
+# Counter Values:
+1
+
diff --git a/test/tools/llvm-cov/Inputs/prefer_used_to_unused.covmapping b/test/tools/llvm-cov/Inputs/prefer_used_to_unused.covmapping
new file mode 100644
index 0000000..c4e1c80
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/prefer_used_to_unused.covmapping
Binary files differ
diff --git a/test/tools/llvm-cov/Inputs/prefer_used_to_unused.cpp b/test/tools/llvm-cov/Inputs/prefer_used_to_unused.cpp
new file mode 100644
index 0000000..a0892b1
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/prefer_used_to_unused.cpp
@@ -0,0 +1,5 @@
+#include "prefer_used_to_unused.h"
+
+int main() {
+  return sampleFunc(5) + simpleFunc(5);
+}
diff --git a/test/tools/llvm-cov/Inputs/prefer_used_to_unused.proftext b/test/tools/llvm-cov/Inputs/prefer_used_to_unused.proftext
new file mode 100644
index 0000000..dd3e704
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/prefer_used_to_unused.proftext
@@ -0,0 +1,25 @@
+_Z10sampleFunci
+# Func Hash:
+10
+# Num Counters:
+2
+# Counter Values:
+1
+1
+
+main
+# Func Hash:
+0
+# Num Counters:
+1
+# Counter Values:
+1
+
+_Z10simpleFunci
+# Func Hash:
+0
+# Num Counters:
+1
+# Counter Values:
+1
+
diff --git a/test/tools/llvm-cov/Inputs/prevent_false_instantiations.covmapping b/test/tools/llvm-cov/Inputs/prevent_false_instantiations.covmapping
new file mode 100644
index 0000000..bbaefe5
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/prevent_false_instantiations.covmapping
Binary files differ
diff --git a/test/tools/llvm-cov/Inputs/prevent_false_instantiations.cpp b/test/tools/llvm-cov/Inputs/prevent_false_instantiations.cpp
new file mode 100644
index 0000000..2a84f1d
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/prevent_false_instantiations.cpp
@@ -0,0 +1,15 @@
+#include "prevent_false_instantiations.h"
+
+void func1() {
+  DO_SOMETHING();
+}
+
+void func2() {
+  DO_SOMETHING();
+}
+
+int main() {
+  func1();
+  func2();
+  return 0;
+}
diff --git a/test/tools/llvm-cov/Inputs/prevent_false_instantiations.proftext b/test/tools/llvm-cov/Inputs/prevent_false_instantiations.proftext
new file mode 100644
index 0000000..ad5362e
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/prevent_false_instantiations.proftext
@@ -0,0 +1,26 @@
+_Z5func1v
+# Func Hash:
+3
+# Num Counters:
+2
+# Counter Values:
+1
+0
+
+_Z5func2v
+# Func Hash:
+3
+# Num Counters:
+2
+# Counter Values:
+1
+0
+
+main
+# Func Hash:
+0
+# Num Counters:
+1
+# Counter Values:
+1
+
diff --git a/test/tools/llvm-cov/Inputs/range_based_for.gcda b/test/tools/llvm-cov/Inputs/range_based_for.gcda
new file mode 100644
index 0000000..df51888
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/range_based_for.gcda
Binary files differ
diff --git a/test/tools/llvm-cov/Inputs/range_based_for.gcno b/test/tools/llvm-cov/Inputs/range_based_for.gcno
new file mode 100644
index 0000000..5f30acf
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/range_based_for.gcno
Binary files differ
diff --git a/test/tools/llvm-cov/Inputs/regionMarkers.covmapping b/test/tools/llvm-cov/Inputs/regionMarkers.covmapping
new file mode 100644
index 0000000..af920c2
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/regionMarkers.covmapping
Binary files differ
diff --git a/test/tools/llvm-cov/Inputs/regionMarkers.json b/test/tools/llvm-cov/Inputs/regionMarkers.json
new file mode 100644
index 0000000..c996433
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/regionMarkers.json
@@ -0,0 +1,35 @@
+// Metadata section
+// CHECK: {"version":"{{[0-9]\.[0-9]\.[0-9]}}","type":"llvm.coverage.json.export","data":[
+
+// Open Export
+// CHECK-SAME: {"files":[
+
+// File Object
+// CHECK-SAME: {"filename":"{{[^"]+}}showRegionMarkers.cpp",
+// CHECK-SAME: "segments":[
+// CHECK-SAME: {{(\[[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+\],?)+}}],
+// CHECK-SAME: "expansions":[],
+
+// Verify the Summary Section for the first file
+// CHECK-SAME: "summary":{
+// CHECK-SAME: "lines":{"count":21,"covered":19,"percent":90},
+// CHECK-SAME: "functions":{"count":1,"covered":1,"percent":100},
+// CHECK-SAME: "regions":{"count":11,"covered":8,"notcovered":3,"percent":72}}
+
+// Close Files Array
+// CHECK-SAME: ],
+
+// Functions List
+// CHECK-SAME: "functions":[
+// CHECK-SAME: {"name":"main","count":1111000,"regions":[
+// CHECK-SAME: {{(\[[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+\],?)+}}
+// CHECK-SAME: ],
+// CHECK-SAME: "filenames":["{{[^"]+}}showRegionMarkers.cpp"]
+// CHECK-SAME: }],
+
+// Full Export Summary
+// CHECK-SAME: "totals":{
+// CHECK-SAME: "lines":{"count":21,"covered":19,"percent":90},
+// CHECK-SAME: "functions":{"count":1,"covered":1,"percent":100},
+// CHECK-SAME: "instantiations":{"count":1,"covered":1,"percent":100},
+// CHECK-SAME: "regions":{"count":11,"covered":8,"notcovered":3,"percent":72}}
diff --git a/test/tools/llvm-cov/Inputs/regionMarkers.proftext b/test/tools/llvm-cov/Inputs/regionMarkers.proftext
new file mode 100644
index 0000000..5199edc
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/regionMarkers.proftext
@@ -0,0 +1,8 @@
+main
+0x000000000028434d
+5
+1111000
+0
+111100000
+1111000
+0
diff --git a/test/tools/llvm-cov/Inputs/report.covmapping b/test/tools/llvm-cov/Inputs/report.covmapping
new file mode 100644
index 0000000..f9858ed
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/report.covmapping
Binary files differ
diff --git a/test/tools/llvm-cov/Inputs/report.profdata b/test/tools/llvm-cov/Inputs/report.profdata
new file mode 100644
index 0000000..aa47be0
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/report.profdata
Binary files differ
diff --git a/test/tools/llvm-cov/Inputs/showExpansions.covmapping b/test/tools/llvm-cov/Inputs/showExpansions.covmapping
new file mode 100644
index 0000000..d4eb527
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/showExpansions.covmapping
Binary files differ
diff --git a/test/tools/llvm-cov/Inputs/showExpansions.json b/test/tools/llvm-cov/Inputs/showExpansions.json
new file mode 100644
index 0000000..d145f7d
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/showExpansions.json
@@ -0,0 +1,52 @@
+// Metadata section
+// CHECK: {"version":"{{[0-9]\.[0-9]\.[0-9]}}","type":"llvm.coverage.json.export","data":[
+
+// Open Export
+// CHECK-SAME: {"files":[
+
+// File Object
+// CHECK-SAME: {"filename":"{{[^"]+}}showExpansions.cpp",
+// CHECK-SAME: "segments":[
+// CHECK-SAME: {{(\[[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+\],?)+}}],
+// CHECK-SAME: "expansions":[
+// CHECK-SAME: {"source_region":[24,5,24,17,100,0,1,1],
+// CHECK-SAME: "target_regions":[
+// CHECK-SAME: {{(\[[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+\],?)+}}
+// CHECK-SAME: ],
+
+// Yes, 4 of the same filename in a row
+// CHECK-SAME: "filenames":[
+// CHECK-SAME: "{{[^"]+}}showExpansions.cpp","{{[^"]+}}showExpansions.cpp",
+// CHECK-SAME: "{{[^"]+}}showExpansions.cpp","{{[^"]+}}showExpansions.cpp"]
+// CHECK-SAME: }],
+
+// Verify the Summary Section for the first file
+// CHECK-SAME: "summary":{
+// CHECK-SAME: "lines":{"count":5,"covered":5,"percent":100},
+// CHECK-SAME: "functions":{"count":1,"covered":1,"percent":100},
+// CHECK-SAME: "regions":{"count":13,"covered":12,"notcovered":1,"percent":92}}
+
+// Close Files Array
+// CHECK-SAME: ],
+
+// Functions List
+// CHECK-SAME: "functions":[
+// CHECK-SAME: {"name":"main","count":1,"regions":[
+// CHECK-SAME: {{(\[[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+\],?)+}}
+// CHECK-SAME: ],
+// CHECK-SAME: "filenames":[
+// CHECK-SAME: "{{[^"]+}}showExpansions.cpp",
+// CHECK-SAME: "{{[^"]+}}showExpansions.cpp",
+// CHECK-SAME: "{{[^"]+}}showExpansions.cpp",
+// CHECK-SAME: "{{[^"]+}}showExpansions.cpp"]
+// CHECK-SAME: }],
+
+// Full Export Summary
+// CHECK-SAME: "totals":{
+// CHECK-SAME: "lines":{"count":5,"covered":5,"percent":100},
+// CHECK-SAME: "functions":{"count":1,"covered":1,"percent":100},
+// CHECK-SAME: "instantiations":{"count":1,"covered":1,"percent":100},
+// CHECK-SAME: "regions":{"count":13,"covered":12,"notcovered":1,"percent":92}}
+
+// Close the export object, data array, and root object
+// CHECK-SAME: }]}
diff --git a/test/tools/llvm-cov/Inputs/showExpansions.profdata b/test/tools/llvm-cov/Inputs/showExpansions.profdata
new file mode 100644
index 0000000..7925c60
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/showExpansions.profdata
Binary files differ
diff --git a/test/tools/llvm-cov/Inputs/showProjectSummary.covmapping b/test/tools/llvm-cov/Inputs/showProjectSummary.covmapping
new file mode 100644
index 0000000..d95caf2
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/showProjectSummary.covmapping
Binary files differ
diff --git a/test/tools/llvm-cov/Inputs/showProjectSummary.proftext b/test/tools/llvm-cov/Inputs/showProjectSummary.proftext
new file mode 100644
index 0000000..b3cdcc7
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/showProjectSummary.proftext
@@ -0,0 +1,10 @@
+main
+# Func Hash:
+266
+# Num Counters:
+3
+# Counter Values:
+1
+20
+0
+
diff --git a/test/tools/llvm-cov/Inputs/showProjectSummary.test b/test/tools/llvm-cov/Inputs/showProjectSummary.test
new file mode 100644
index 0000000..eb02226
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/showProjectSummary.test
@@ -0,0 +1,15 @@
+TEXT-TITLE: Test Suite
+TEXT-NOT: Coverage Report
+TEXT-NOT: Created:
+TEXT-FUNCTION: main:
+TEXT-FOOTER: Generated by llvm-cov
+
+HTML-TITLE: <h1>Test Suite</h1>
+HTML: <h2>Coverage Report</h2>
+HTML: <h4>Created:{{.*}}</h4>
+HTML-FILE: <pre>{{.*}}showProjectSummary.cpp</pre>
+HTML-FUNCTION: <pre>main</pre>
+HTML-HEADER: <td><pre>Line</pre></td>
+HTML-HEADER: <td><pre>Count</pre></td>
+HTML-HEADER: <td><pre>Source (<a href='#L8'>jump to first uncovered line</a>)</pre></td>
+HTML-FOOTER: <h5>Generated by llvm-cov{{.*}}</h5>
diff --git a/test/tools/llvm-cov/Inputs/showTabsHTML.covmapping b/test/tools/llvm-cov/Inputs/showTabsHTML.covmapping
new file mode 100644
index 0000000..96df49d
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/showTabsHTML.covmapping
Binary files differ
diff --git a/test/tools/llvm-cov/Inputs/showTabsHTML.proftext b/test/tools/llvm-cov/Inputs/showTabsHTML.proftext
new file mode 100644
index 0000000..5419d23
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/showTabsHTML.proftext
@@ -0,0 +1,8 @@
+main
+# Func Hash:
+0
+# Num Counters:
+1
+# Counter Values:
+1
+
diff --git a/test/tools/llvm-cov/Inputs/sources_specified/abs.h b/test/tools/llvm-cov/Inputs/sources_specified/abs.h
new file mode 100644
index 0000000..f13c517
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/sources_specified/abs.h
@@ -0,0 +1,5 @@
+int abs(int x) {
+  if (x < 0)
+    return -x;
+  return x;
+}
diff --git a/test/tools/llvm-cov/Inputs/sources_specified/extra/dec.h b/test/tools/llvm-cov/Inputs/sources_specified/extra/dec.h
new file mode 100644
index 0000000..178e1ea
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/sources_specified/extra/dec.h
@@ -0,0 +1,3 @@
+int dec(int x) {
+  return x + 1;
+}
diff --git a/test/tools/llvm-cov/Inputs/sources_specified/extra/inc.h b/test/tools/llvm-cov/Inputs/sources_specified/extra/inc.h
new file mode 100644
index 0000000..5086aaa
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/sources_specified/extra/inc.h
@@ -0,0 +1,3 @@
+int inc(int x) {
+  return x + 1;
+}
diff --git a/test/tools/llvm-cov/Inputs/sources_specified/main.cc b/test/tools/llvm-cov/Inputs/sources_specified/main.cc
new file mode 100644
index 0000000..cda21f1
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/sources_specified/main.cc
@@ -0,0 +1,9 @@
+#include "abs.h"
+#include "extra/dec.h"
+#include "extra/inc.h"
+
+int main() {
+  int x = 0;
+  inc(x);
+  return abs(x);
+}
diff --git a/test/tools/llvm-cov/Inputs/sources_specified/main.covmapping b/test/tools/llvm-cov/Inputs/sources_specified/main.covmapping
new file mode 100644
index 0000000..440d59a
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/sources_specified/main.covmapping
Binary files differ
diff --git a/test/tools/llvm-cov/Inputs/sources_specified/main.profdata b/test/tools/llvm-cov/Inputs/sources_specified/main.profdata
new file mode 100644
index 0000000..aeee1ab
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/sources_specified/main.profdata
Binary files differ
diff --git a/test/tools/llvm-cov/Inputs/templateInstantiations.covmapping b/test/tools/llvm-cov/Inputs/templateInstantiations.covmapping
new file mode 100644
index 0000000..b604e06
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/templateInstantiations.covmapping
Binary files differ
diff --git a/test/tools/llvm-cov/Inputs/templateInstantiations.profdata b/test/tools/llvm-cov/Inputs/templateInstantiations.profdata
new file mode 100644
index 0000000..6ccf526
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/templateInstantiations.profdata
Binary files differ
diff --git a/test/tools/llvm-cov/Inputs/test.cpp b/test/tools/llvm-cov/Inputs/test.cpp
new file mode 100644
index 0000000..e580e5a
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/test.cpp
@@ -0,0 +1,74 @@
+#include "test.h"
+#include <cstdlib>
+
+bool on = false;
+int len = 42;
+double grid[10][10] = {0};
+const char * hello = "world";
+const char * world = "hello";
+
+void A::B() {}
+
+void useless() {}
+
+double more_useless() {
+  return 0;
+}
+
+int foo() {
+  on = true;
+  return 3;
+}
+
+int bar() {
+  len--;
+  return foo() + 45;
+}
+
+void assign(int ii, int jj) {
+  grid[ii][jj] = (ii+1) * (jj+1);
+}
+
+void initialize_grid() {
+  for (int ii = 0; ii < 2; ii++)
+    for (int jj = 0; jj < 2; jj++)
+      assign(ii, jj);
+}
+
+int main() {
+  initialize_grid();
+
+  int a = 2;
+  on = rand() % 2;
+  if (on) {
+    foo();
+    ++a;
+  } else {
+    bar();
+    a += rand();
+  }
+
+  for (int ii = 0; ii < 10; ++ii) {
+    switch (rand() % 5) {
+      case 0:
+        a += rand();
+        break;
+      case 1:
+      case 2:
+        a += rand() / rand();
+        break;
+      case 3:
+        a -= rand();
+        break;
+      default:
+        a = -1;
+    }
+  }
+
+  A thing;
+  for (uint64_t ii = 0; ii < 4294967296; ++ii)
+    thing.B();
+
+  return a + 8 + grid[2][3] + len;
+  return more_useless();
+}
diff --git a/test/tools/llvm-cov/Inputs/test.gcda b/test/tools/llvm-cov/Inputs/test.gcda
new file mode 100644
index 0000000..613e3a8
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/test.gcda
Binary files differ
diff --git a/test/tools/llvm-cov/Inputs/test.gcno b/test/tools/llvm-cov/Inputs/test.gcno
new file mode 100644
index 0000000..24f1c82
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/test.gcno
Binary files differ
diff --git a/test/tools/llvm-cov/Inputs/test.h b/test/tools/llvm-cov/Inputs/test.h
new file mode 100644
index 0000000..55d9c6a
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/test.h
@@ -0,0 +1,3 @@
+struct A {
+  virtual void B();
+};
diff --git a/test/tools/llvm-cov/Inputs/test_-a.cpp.gcov b/test/tools/llvm-cov/Inputs/test_-a.cpp.gcov
new file mode 100644
index 0000000..c2210d5
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/test_-a.cpp.gcov
@@ -0,0 +1,111 @@
+        -:    0:Source:test.cpp
+        -:    0:Graph:test.gcno
+        -:    0:Data:test.gcda
+        -:    0:Runs:2
+        -:    0:Programs:1
+        -:    1:#include "test.h"
+        -:    2:#include <cstdlib>
+        -:    3:
+        -:    4:bool on = false;
+        -:    5:int len = 42;
+        -:    6:double grid[10][10] = {0};
+        -:    7:const char * hello = "world";
+        -:    8:const char * world = "hello";
+        -:    9:
+8589934592:   10:void A::B() {}
+8589934592:   10-block  0
+        -:   11:
+    #####:   12:void useless() {}
+    $$$$$:   12-block  0
+        -:   13:
+        -:   14:double more_useless() {
+    #####:   15:  return 0;
+    $$$$$:   15-block  0
+        -:   16:}
+        -:   17:
+        -:   18:int foo() {
+        2:   19:  on = true;
+        2:   20:  return 3;
+        2:   20-block  0
+        -:   21:}
+        -:   22:
+        -:   23:int bar() {
+    #####:   24:  len--;
+    #####:   25:  return foo() + 45;
+    $$$$$:   25-block  0
+        -:   26:}
+        -:   27:
+        8:   28:void assign(int ii, int jj) {
+        8:   29:  grid[ii][jj] = (ii+1) * (jj+1);
+        8:   30:}
+        8:   30-block  0
+        -:   31:
+        -:   32:void initialize_grid() {
+        6:   33:  for (int ii = 0; ii < 2; ii++)
+        2:   33-block  0
+        6:   33-block  1
+        4:   33-block  2
+       12:   34:    for (int jj = 0; jj < 2; jj++)
+        4:   34-block  0
+       12:   34-block  1
+        8:   34-block  2
+        8:   35:      assign(ii, jj);
+        8:   35-block  0
+        4:   35-block  1
+        2:   36:}
+        2:   36-block  0
+        -:   37:
+        -:   38:int main() {
+        2:   39:  initialize_grid();
+        -:   40:
+        2:   41:  int a = 2;
+        2:   42:  on = rand() % 2;
+        2:   43:  if (on) {
+        2:   43-block  0
+        2:   44:    foo();
+        2:   45:    ++a;
+        2:   46:  } else {
+        2:   46-block  0
+    #####:   47:    bar();
+    #####:   48:    a += rand();
+    $$$$$:   48-block  0
+        -:   49:  }
+        -:   50:
+       22:   51:  for (int ii = 0; ii < 10; ++ii) {
+        2:   51-block  0
+       22:   51-block  1
+       20:   51-block  2
+       20:   52:    switch (rand() % 5) {
+       20:   52-block  0
+        -:   53:      case 0:
+        4:   54:        a += rand();
+        4:   55:        break;
+        4:   55-block  0
+        -:   56:      case 1:
+        -:   57:      case 2:
+        2:   58:        a += rand() / rand();
+        2:   59:        break;
+        2:   59-block  0
+        -:   60:      case 3:
+        6:   61:        a -= rand();
+        6:   62:        break;
+        6:   62-block  0
+        -:   63:      default:
+        8:   64:        a = -1;
+        8:   65:    }
+        8:   65-block  0
+       20:   66:  }
+       20:   66-block  0
+        -:   67:
+        2:   68:  A thing;
+8589934594:   69:  for (uint64_t ii = 0; ii < 4294967296; ++ii)
+        2:   69-block  0
+8589934594:   69-block  1
+8589934592:   69-block  2
+8589934592:   70:    thing.B();
+8589934592:   70-block  0
+        -:   71:
+        2:   72:  return a + 8 + grid[2][3] + len;
+        2:   72-block  0
+        -:   73:  return more_useless();
+        -:   74:}
diff --git a/test/tools/llvm-cov/Inputs/test_-a.h.gcov b/test/tools/llvm-cov/Inputs/test_-a.h.gcov
new file mode 100644
index 0000000..a5fe62b
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/test_-a.h.gcov
@@ -0,0 +1,10 @@
+        -:    0:Source:./test.h
+        -:    0:Graph:test.gcno
+        -:    0:Data:test.gcda
+        -:    0:Runs:2
+        -:    0:Programs:1
+        2:    1:struct A {
+        2:    1-block  0
+        2:    1-block  1
+        -:    2:  virtual void B();
+        -:    3:};
diff --git a/test/tools/llvm-cov/Inputs/test_-a_-b.cpp.gcov b/test/tools/llvm-cov/Inputs/test_-a_-b.cpp.gcov
new file mode 100644
index 0000000..ae21037
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/test_-a_-b.cpp.gcov
@@ -0,0 +1,134 @@
+        -:    0:Source:test.cpp
+        -:    0:Graph:test.gcno
+        -:    0:Data:test.gcda
+        -:    0:Runs:2
+        -:    0:Programs:1
+        -:    1:#include "test.h"
+        -:    2:#include <cstdlib>
+        -:    3:
+        -:    4:bool on = false;
+        -:    5:int len = 42;
+        -:    6:double grid[10][10] = {0};
+        -:    7:const char * hello = "world";
+        -:    8:const char * world = "hello";
+        -:    9:
+function _ZN1A1BEv called 8589934592 returned 100% blocks executed 100%
+8589934592:   10:void A::B() {}
+8589934592:   10-block  0
+        -:   11:
+function _Z7uselessv called 0 returned 0% blocks executed 0%
+    #####:   12:void useless() {}
+    $$$$$:   12-block  0
+        -:   13:
+function _Z12more_uselessv called 0 returned 0% blocks executed 0%
+        -:   14:double more_useless() {
+    #####:   15:  return 0;
+    $$$$$:   15-block  0
+        -:   16:}
+        -:   17:
+function _Z3foov called 2 returned 100% blocks executed 100%
+        -:   18:int foo() {
+        2:   19:  on = true;
+        2:   20:  return 3;
+        2:   20-block  0
+        -:   21:}
+        -:   22:
+function _Z3barv called 0 returned 0% blocks executed 0%
+        -:   23:int bar() {
+    #####:   24:  len--;
+    #####:   25:  return foo() + 45;
+    $$$$$:   25-block  0
+        -:   26:}
+        -:   27:
+function _Z6assignii called 8 returned 100% blocks executed 100%
+        8:   28:void assign(int ii, int jj) {
+        8:   29:  grid[ii][jj] = (ii+1) * (jj+1);
+        8:   30:}
+        8:   30-block  0
+        -:   31:
+function _Z15initialize_gridv called 2 returned 100% blocks executed 100%
+        -:   32:void initialize_grid() {
+        6:   33:  for (int ii = 0; ii < 2; ii++)
+        2:   33-block  0
+        6:   33-block  1
+branch  0 taken 67%
+branch  1 taken 33%
+        4:   33-block  2
+       12:   34:    for (int jj = 0; jj < 2; jj++)
+        4:   34-block  0
+       12:   34-block  1
+branch  0 taken 67%
+branch  1 taken 33%
+        8:   34-block  2
+        8:   35:      assign(ii, jj);
+        8:   35-block  0
+        4:   35-block  1
+        2:   36:}
+        2:   36-block  0
+        -:   37:
+function main called 2 returned 100% blocks executed 94%
+        -:   38:int main() {
+        2:   39:  initialize_grid();
+        -:   40:
+        2:   41:  int a = 2;
+        2:   42:  on = rand() % 2;
+        2:   43:  if (on) {
+        2:   43-block  0
+branch  0 taken 100%
+branch  1 taken 0%
+        2:   44:    foo();
+        2:   45:    ++a;
+        2:   46:  } else {
+        2:   46-block  0
+    #####:   47:    bar();
+    #####:   48:    a += rand();
+    $$$$$:   48-block  0
+        -:   49:  }
+        -:   50:
+       22:   51:  for (int ii = 0; ii < 10; ++ii) {
+        2:   51-block  0
+       22:   51-block  1
+branch  0 taken 91%
+branch  1 taken 9%
+       20:   51-block  2
+       20:   52:    switch (rand() % 5) {
+       20:   52-block  0
+branch  0 taken 20%
+branch  1 taken 0%
+branch  2 taken 10%
+branch  3 taken 30%
+branch  4 taken 40%
+        -:   53:      case 0:
+        4:   54:        a += rand();
+        4:   55:        break;
+        4:   55-block  0
+        -:   56:      case 1:
+        -:   57:      case 2:
+        2:   58:        a += rand() / rand();
+        2:   59:        break;
+        2:   59-block  0
+        -:   60:      case 3:
+        6:   61:        a -= rand();
+        6:   62:        break;
+        6:   62-block  0
+        -:   63:      default:
+        8:   64:        a = -1;
+        8:   65:    }
+        8:   65-block  0
+       20:   66:  }
+       20:   66-block  0
+        -:   67:
+        2:   68:  A thing;
+8589934594:   69:  for (uint64_t ii = 0; ii < 4294967296; ++ii)
+        2:   69-block  0
+8589934594:   69-block  1
+branch  0 taken 99%
+branch  1 taken 1%
+8589934592:   69-block  2
+8589934592:   70:    thing.B();
+8589934592:   70-block  0
+        -:   71:
+        2:   72:  return a + 8 + grid[2][3] + len;
+        2:   72-block  0
+        -:   73:  return more_useless();
+        -:   74:}
diff --git a/test/tools/llvm-cov/Inputs/test_-a_-b.h.gcov b/test/tools/llvm-cov/Inputs/test_-a_-b.h.gcov
new file mode 100644
index 0000000..f3dabcb
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/test_-a_-b.h.gcov
@@ -0,0 +1,12 @@
+        -:    0:Source:./test.h
+        -:    0:Graph:test.gcno
+        -:    0:Data:test.gcda
+        -:    0:Runs:2
+        -:    0:Programs:1
+function _ZN1AC1Ev called 2 returned 100% blocks executed 100%
+function _ZN1AC2Ev called 2 returned 100% blocks executed 100%
+        2:    1:struct A {
+        2:    1-block  0
+        2:    1-block  1
+        -:    2:  virtual void B();
+        -:    3:};
diff --git a/test/tools/llvm-cov/Inputs/test_-a_-b_-c_-u.cpp.gcov b/test/tools/llvm-cov/Inputs/test_-a_-b_-c_-u.cpp.gcov
new file mode 100644
index 0000000..cc5940f
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/test_-a_-b_-c_-u.cpp.gcov
@@ -0,0 +1,160 @@
+        -:    0:Source:test.cpp
+        -:    0:Graph:test.gcno
+        -:    0:Data:test.gcda
+        -:    0:Runs:2
+        -:    0:Programs:1
+        -:    1:#include "test.h"
+        -:    2:#include <cstdlib>
+        -:    3:
+        -:    4:bool on = false;
+        -:    5:int len = 42;
+        -:    6:double grid[10][10] = {0};
+        -:    7:const char * hello = "world";
+        -:    8:const char * world = "hello";
+        -:    9:
+function _ZN1A1BEv called 8589934592 returned 100% blocks executed 100%
+8589934592:   10:void A::B() {}
+8589934592:   10-block  0
+unconditional  0 taken 8589934592
+        -:   11:
+function _Z7uselessv called 0 returned 0% blocks executed 0%
+    #####:   12:void useless() {}
+    $$$$$:   12-block  0
+unconditional  0 never executed
+        -:   13:
+function _Z12more_uselessv called 0 returned 0% blocks executed 0%
+        -:   14:double more_useless() {
+    #####:   15:  return 0;
+    $$$$$:   15-block  0
+unconditional  0 never executed
+        -:   16:}
+        -:   17:
+function _Z3foov called 2 returned 100% blocks executed 100%
+        -:   18:int foo() {
+        2:   19:  on = true;
+        2:   20:  return 3;
+        2:   20-block  0
+unconditional  0 taken 2
+        -:   21:}
+        -:   22:
+function _Z3barv called 0 returned 0% blocks executed 0%
+        -:   23:int bar() {
+    #####:   24:  len--;
+    #####:   25:  return foo() + 45;
+    $$$$$:   25-block  0
+unconditional  0 never executed
+        -:   26:}
+        -:   27:
+function _Z6assignii called 8 returned 100% blocks executed 100%
+        8:   28:void assign(int ii, int jj) {
+        8:   29:  grid[ii][jj] = (ii+1) * (jj+1);
+        8:   30:}
+        8:   30-block  0
+unconditional  0 taken 8
+        -:   31:
+function _Z15initialize_gridv called 2 returned 100% blocks executed 100%
+        -:   32:void initialize_grid() {
+        6:   33:  for (int ii = 0; ii < 2; ii++)
+        2:   33-block  0
+unconditional  0 taken 2
+        6:   33-block  1
+branch  1 taken 4
+branch  2 taken 2
+        4:   33-block  2
+unconditional  3 taken 4
+       12:   34:    for (int jj = 0; jj < 2; jj++)
+        4:   34-block  0
+unconditional  0 taken 4
+       12:   34-block  1
+branch  1 taken 8
+branch  2 taken 4
+        8:   34-block  2
+unconditional  3 taken 8
+        8:   35:      assign(ii, jj);
+        8:   35-block  0
+unconditional  0 taken 8
+        4:   35-block  1
+unconditional  1 taken 4
+        2:   36:}
+        2:   36-block  0
+unconditional  0 taken 2
+        -:   37:
+function main called 2 returned 100% blocks executed 94%
+        -:   38:int main() {
+        2:   39:  initialize_grid();
+        -:   40:
+        2:   41:  int a = 2;
+        2:   42:  on = rand() % 2;
+        2:   43:  if (on) {
+        2:   43-block  0
+branch  0 taken 2
+branch  1 taken 0
+        2:   44:    foo();
+        2:   45:    ++a;
+        2:   46:  } else {
+        2:   46-block  0
+unconditional  0 taken 2
+    #####:   47:    bar();
+    #####:   48:    a += rand();
+    $$$$$:   48-block  0
+unconditional  0 never executed
+        -:   49:  }
+        -:   50:
+       22:   51:  for (int ii = 0; ii < 10; ++ii) {
+        2:   51-block  0
+unconditional  0 taken 2
+       22:   51-block  1
+branch  1 taken 20
+branch  2 taken 2
+       20:   51-block  2
+unconditional  3 taken 20
+       20:   52:    switch (rand() % 5) {
+       20:   52-block  0
+branch  0 taken 4
+branch  1 taken 0
+branch  2 taken 2
+branch  3 taken 6
+branch  4 taken 8
+        -:   53:      case 0:
+        4:   54:        a += rand();
+        4:   55:        break;
+        4:   55-block  0
+unconditional  0 taken 4
+        -:   56:      case 1:
+        -:   57:      case 2:
+        2:   58:        a += rand() / rand();
+        2:   59:        break;
+        2:   59-block  0
+unconditional  0 taken 2
+        -:   60:      case 3:
+        6:   61:        a -= rand();
+        6:   62:        break;
+        6:   62-block  0
+unconditional  0 taken 6
+        -:   63:      default:
+        8:   64:        a = -1;
+        8:   65:    }
+        8:   65-block  0
+unconditional  0 taken 8
+       20:   66:  }
+       20:   66-block  0
+unconditional  0 taken 20
+        -:   67:
+        2:   68:  A thing;
+8589934594:   69:  for (uint64_t ii = 0; ii < 4294967296; ++ii)
+        2:   69-block  0
+unconditional  0 taken 2
+8589934594:   69-block  1
+branch  1 taken 8589934592
+branch  2 taken 2
+8589934592:   69-block  2
+unconditional  3 taken 8589934592
+8589934592:   70:    thing.B();
+8589934592:   70-block  0
+unconditional  0 taken 8589934592
+        -:   71:
+        2:   72:  return a + 8 + grid[2][3] + len;
+        2:   72-block  0
+unconditional  0 taken 2
+        -:   73:  return more_useless();
+        -:   74:}
diff --git a/test/tools/llvm-cov/Inputs/test_-a_-b_-c_-u.h.gcov b/test/tools/llvm-cov/Inputs/test_-a_-b_-c_-u.h.gcov
new file mode 100644
index 0000000..840324e
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/test_-a_-b_-c_-u.h.gcov
@@ -0,0 +1,14 @@
+        -:    0:Source:./test.h
+        -:    0:Graph:test.gcno
+        -:    0:Data:test.gcda
+        -:    0:Runs:2
+        -:    0:Programs:1
+function _ZN1AC1Ev called 2 returned 100% blocks executed 100%
+function _ZN1AC2Ev called 2 returned 100% blocks executed 100%
+        2:    1:struct A {
+        2:    1-block  0
+unconditional  0 taken 2
+        2:    1-block  1
+unconditional  1 taken 2
+        -:    2:  virtual void B();
+        -:    3:};
diff --git a/test/tools/llvm-cov/Inputs/test_-a_-b_-u.cpp.gcov b/test/tools/llvm-cov/Inputs/test_-a_-b_-u.cpp.gcov
new file mode 100644
index 0000000..0d2c6b3
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/test_-a_-b_-u.cpp.gcov
@@ -0,0 +1,160 @@
+        -:    0:Source:test.cpp
+        -:    0:Graph:test.gcno
+        -:    0:Data:test.gcda
+        -:    0:Runs:2
+        -:    0:Programs:1
+        -:    1:#include "test.h"
+        -:    2:#include <cstdlib>
+        -:    3:
+        -:    4:bool on = false;
+        -:    5:int len = 42;
+        -:    6:double grid[10][10] = {0};
+        -:    7:const char * hello = "world";
+        -:    8:const char * world = "hello";
+        -:    9:
+function _ZN1A1BEv called 8589934592 returned 100% blocks executed 100%
+8589934592:   10:void A::B() {}
+8589934592:   10-block  0
+unconditional  0 taken 100%
+        -:   11:
+function _Z7uselessv called 0 returned 0% blocks executed 0%
+    #####:   12:void useless() {}
+    $$$$$:   12-block  0
+unconditional  0 never executed
+        -:   13:
+function _Z12more_uselessv called 0 returned 0% blocks executed 0%
+        -:   14:double more_useless() {
+    #####:   15:  return 0;
+    $$$$$:   15-block  0
+unconditional  0 never executed
+        -:   16:}
+        -:   17:
+function _Z3foov called 2 returned 100% blocks executed 100%
+        -:   18:int foo() {
+        2:   19:  on = true;
+        2:   20:  return 3;
+        2:   20-block  0
+unconditional  0 taken 100%
+        -:   21:}
+        -:   22:
+function _Z3barv called 0 returned 0% blocks executed 0%
+        -:   23:int bar() {
+    #####:   24:  len--;
+    #####:   25:  return foo() + 45;
+    $$$$$:   25-block  0
+unconditional  0 never executed
+        -:   26:}
+        -:   27:
+function _Z6assignii called 8 returned 100% blocks executed 100%
+        8:   28:void assign(int ii, int jj) {
+        8:   29:  grid[ii][jj] = (ii+1) * (jj+1);
+        8:   30:}
+        8:   30-block  0
+unconditional  0 taken 100%
+        -:   31:
+function _Z15initialize_gridv called 2 returned 100% blocks executed 100%
+        -:   32:void initialize_grid() {
+        6:   33:  for (int ii = 0; ii < 2; ii++)
+        2:   33-block  0
+unconditional  0 taken 100%
+        6:   33-block  1
+branch  1 taken 67%
+branch  2 taken 33%
+        4:   33-block  2
+unconditional  3 taken 100%
+       12:   34:    for (int jj = 0; jj < 2; jj++)
+        4:   34-block  0
+unconditional  0 taken 100%
+       12:   34-block  1
+branch  1 taken 67%
+branch  2 taken 33%
+        8:   34-block  2
+unconditional  3 taken 100%
+        8:   35:      assign(ii, jj);
+        8:   35-block  0
+unconditional  0 taken 100%
+        4:   35-block  1
+unconditional  1 taken 100%
+        2:   36:}
+        2:   36-block  0
+unconditional  0 taken 100%
+        -:   37:
+function main called 2 returned 100% blocks executed 94%
+        -:   38:int main() {
+        2:   39:  initialize_grid();
+        -:   40:
+        2:   41:  int a = 2;
+        2:   42:  on = rand() % 2;
+        2:   43:  if (on) {
+        2:   43-block  0
+branch  0 taken 100%
+branch  1 taken 0%
+        2:   44:    foo();
+        2:   45:    ++a;
+        2:   46:  } else {
+        2:   46-block  0
+unconditional  0 taken 100%
+    #####:   47:    bar();
+    #####:   48:    a += rand();
+    $$$$$:   48-block  0
+unconditional  0 never executed
+        -:   49:  }
+        -:   50:
+       22:   51:  for (int ii = 0; ii < 10; ++ii) {
+        2:   51-block  0
+unconditional  0 taken 100%
+       22:   51-block  1
+branch  1 taken 91%
+branch  2 taken 9%
+       20:   51-block  2
+unconditional  3 taken 100%
+       20:   52:    switch (rand() % 5) {
+       20:   52-block  0
+branch  0 taken 20%
+branch  1 taken 0%
+branch  2 taken 10%
+branch  3 taken 30%
+branch  4 taken 40%
+        -:   53:      case 0:
+        4:   54:        a += rand();
+        4:   55:        break;
+        4:   55-block  0
+unconditional  0 taken 100%
+        -:   56:      case 1:
+        -:   57:      case 2:
+        2:   58:        a += rand() / rand();
+        2:   59:        break;
+        2:   59-block  0
+unconditional  0 taken 100%
+        -:   60:      case 3:
+        6:   61:        a -= rand();
+        6:   62:        break;
+        6:   62-block  0
+unconditional  0 taken 100%
+        -:   63:      default:
+        8:   64:        a = -1;
+        8:   65:    }
+        8:   65-block  0
+unconditional  0 taken 100%
+       20:   66:  }
+       20:   66-block  0
+unconditional  0 taken 100%
+        -:   67:
+        2:   68:  A thing;
+8589934594:   69:  for (uint64_t ii = 0; ii < 4294967296; ++ii)
+        2:   69-block  0
+unconditional  0 taken 100%
+8589934594:   69-block  1
+branch  1 taken 99%
+branch  2 taken 1%
+8589934592:   69-block  2
+unconditional  3 taken 100%
+8589934592:   70:    thing.B();
+8589934592:   70-block  0
+unconditional  0 taken 100%
+        -:   71:
+        2:   72:  return a + 8 + grid[2][3] + len;
+        2:   72-block  0
+unconditional  0 taken 100%
+        -:   73:  return more_useless();
+        -:   74:}
diff --git a/test/tools/llvm-cov/Inputs/test_-a_-b_-u.h.gcov b/test/tools/llvm-cov/Inputs/test_-a_-b_-u.h.gcov
new file mode 100644
index 0000000..e7fa658
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/test_-a_-b_-u.h.gcov
@@ -0,0 +1,14 @@
+        -:    0:Source:./test.h
+        -:    0:Graph:test.gcno
+        -:    0:Data:test.gcda
+        -:    0:Runs:2
+        -:    0:Programs:1
+function _ZN1AC1Ev called 2 returned 100% blocks executed 100%
+function _ZN1AC2Ev called 2 returned 100% blocks executed 100%
+        2:    1:struct A {
+        2:    1-block  0
+unconditional  0 taken 100%
+        2:    1-block  1
+unconditional  1 taken 100%
+        -:    2:  virtual void B();
+        -:    3:};
diff --git a/test/tools/llvm-cov/Inputs/test_-b.output b/test/tools/llvm-cov/Inputs/test_-b.output
new file mode 100644
index 0000000..a6495fd
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/test_-b.output
@@ -0,0 +1,13 @@
+File './test.h'
+Lines executed:100.00% of 1
+No branches
+No calls
+./test.h:creating 'test.h.gcov'
+
+File 'test.cpp'
+Lines executed:84.21% of 38
+Branches executed:100.00% of 15
+Taken at least once:86.67% of 15
+No calls
+test.cpp:creating 'test.cpp.gcov'
+
diff --git a/test/tools/llvm-cov/Inputs/test_-b_-f.output b/test/tools/llvm-cov/Inputs/test_-b_-f.output
new file mode 100644
index 0000000..c3ccd05
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/test_-b_-f.output
@@ -0,0 +1,65 @@
+Function '_ZN1A1BEv'
+Lines executed:100.00% of 1
+No branches
+No calls
+
+Function '_Z7uselessv'
+Lines executed:0.00% of 1
+No branches
+No calls
+
+Function '_Z12more_uselessv'
+Lines executed:0.00% of 1
+No branches
+No calls
+
+Function '_Z3foov'
+Lines executed:100.00% of 2
+No branches
+No calls
+
+Function '_Z3barv'
+Lines executed:0.00% of 2
+No branches
+No calls
+
+Function '_Z6assignii'
+Lines executed:100.00% of 3
+No branches
+No calls
+
+Function '_Z15initialize_gridv'
+Lines executed:100.00% of 4
+Branches executed:100.00% of 4
+Taken at least once:100.00% of 4
+No calls
+
+Function 'main'
+Lines executed:91.67% of 24
+Branches executed:100.00% of 11
+Taken at least once:81.82% of 11
+No calls
+
+Function '_ZN1AC1Ev'
+Lines executed:100.00% of 1
+No branches
+No calls
+
+Function '_ZN1AC2Ev'
+No executable lines
+No branches
+No calls
+
+File 'test.cpp'
+Lines executed:84.21% of 38
+Branches executed:100.00% of 15
+Taken at least once:86.67% of 15
+No calls
+test.cpp:creating 'test.cpp.gcov'
+
+File './test.h'
+Lines executed:100.00% of 1
+No branches
+No calls
+./test.h:creating 'test.h.gcov'
+
diff --git a/test/tools/llvm-cov/Inputs/test_-f.output b/test/tools/llvm-cov/Inputs/test_-f.output
new file mode 100644
index 0000000..b0a73ea
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/test_-f.output
@@ -0,0 +1,38 @@
+Function '_ZN1AC1Ev'
+Lines executed:100.00% of 1
+
+Function '_ZN1AC2Ev'
+Lines executed:100.00% of 1
+
+Function '_ZN1A1BEv'
+Lines executed:100.00% of 1
+
+Function '_Z7uselessv'
+Lines executed:0.00% of 1
+
+Function '_Z12more_uselessv'
+Lines executed:0.00% of 1
+
+Function '_Z3foov'
+Lines executed:100.00% of 2
+
+Function '_Z3barv'
+Lines executed:0.00% of 2
+
+Function '_Z6assignii'
+Lines executed:100.00% of 3
+
+Function '_Z15initialize_gridv'
+Lines executed:100.00% of 4
+
+Function 'main'
+Lines executed:91.67% of 24
+
+File './test.h'
+Lines executed:100.00% of 1
+./test.h:creating 'test.h.gcov'
+
+File 'test.cpp'
+Lines executed:84.21% of 38
+test.cpp:creating 'test.cpp.gcov'
+
diff --git a/test/tools/llvm-cov/Inputs/test_exit_block_arcs.gcda b/test/tools/llvm-cov/Inputs/test_exit_block_arcs.gcda
new file mode 100644
index 0000000..3ca483d
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/test_exit_block_arcs.gcda
Binary files differ
diff --git a/test/tools/llvm-cov/Inputs/test_exit_block_arcs.gcno b/test/tools/llvm-cov/Inputs/test_exit_block_arcs.gcno
new file mode 100644
index 0000000..d453566
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/test_exit_block_arcs.gcno
Binary files differ
diff --git a/test/tools/llvm-cov/Inputs/test_file_checksum_fail.gcda b/test/tools/llvm-cov/Inputs/test_file_checksum_fail.gcda
new file mode 100644
index 0000000..8bfd82c
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/test_file_checksum_fail.gcda
Binary files differ
diff --git a/test/tools/llvm-cov/Inputs/test_func_checksum_fail.gcda b/test/tools/llvm-cov/Inputs/test_func_checksum_fail.gcda
new file mode 100644
index 0000000..4c729a8
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/test_func_checksum_fail.gcda
Binary files differ
diff --git a/test/tools/llvm-cov/Inputs/test_long_file_names.output b/test/tools/llvm-cov/Inputs/test_long_file_names.output
new file mode 100644
index 0000000..e74b636
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/test_long_file_names.output
@@ -0,0 +1,8 @@
+File 'srcdir/./nested_dir/../test.cpp'
+Lines executed:84.21% of 38
+srcdir/./nested_dir/../test.cpp:creating 'test_paths.cpp##test.cpp.gcov'
+
+File 'srcdir/./nested_dir/../test.h'
+Lines executed:100.00% of 1
+srcdir/./nested_dir/../test.h:creating 'test_paths.cpp##test.h.gcov'
+
diff --git a/test/tools/llvm-cov/Inputs/test_long_paths.output b/test/tools/llvm-cov/Inputs/test_long_paths.output
new file mode 100644
index 0000000..faf3d8a
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/test_long_paths.output
@@ -0,0 +1,8 @@
+File 'srcdir/./nested_dir/../test.cpp'
+Lines executed:84.21% of 38
+srcdir/./nested_dir/../test.cpp:creating 'srcdir#^#test_paths.cpp##srcdir#nested_dir#^#test.cpp.gcov'
+
+File 'srcdir/./nested_dir/../test.h'
+Lines executed:100.00% of 1
+srcdir/./nested_dir/../test.h:creating 'srcdir#^#test_paths.cpp##srcdir#nested_dir#^#test.h.gcov'
+
diff --git a/test/tools/llvm-cov/Inputs/test_missing.cpp.gcov b/test/tools/llvm-cov/Inputs/test_missing.cpp.gcov
new file mode 100644
index 0000000..1c138e4
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/test_missing.cpp.gcov
@@ -0,0 +1,77 @@
+        -:    0:Source:srcdir/./nested_dir/../test.cpp
+        -:    0:Graph:test_paths.gcno
+        -:    0:Data:test_paths.gcda
+        -:    0:Runs:3
+        -:    0:Programs:1
+        -:    1:/*EOF*/
+        -:    2:/*EOF*/
+        -:    3:/*EOF*/
+        -:    4:/*EOF*/
+        -:    5:/*EOF*/
+        -:    6:/*EOF*/
+        -:    7:/*EOF*/
+        -:    8:/*EOF*/
+        -:    9:/*EOF*/
+12884901888:   10:/*EOF*/
+        -:   11:/*EOF*/
+    #####:   12:/*EOF*/
+        -:   13:/*EOF*/
+        -:   14:/*EOF*/
+    #####:   15:/*EOF*/
+        -:   16:/*EOF*/
+        -:   17:/*EOF*/
+        -:   18:/*EOF*/
+        3:   19:/*EOF*/
+        3:   20:/*EOF*/
+        -:   21:/*EOF*/
+        -:   22:/*EOF*/
+        -:   23:/*EOF*/
+    #####:   24:/*EOF*/
+    #####:   25:/*EOF*/
+        -:   26:/*EOF*/
+        -:   27:/*EOF*/
+       12:   28:/*EOF*/
+       12:   29:/*EOF*/
+       12:   30:/*EOF*/
+        -:   31:/*EOF*/
+        -:   32:/*EOF*/
+       21:   33:/*EOF*/
+       36:   34:/*EOF*/
+       18:   35:/*EOF*/
+        3:   36:/*EOF*/
+        -:   37:/*EOF*/
+        -:   38:/*EOF*/
+        3:   39:/*EOF*/
+        -:   40:/*EOF*/
+        3:   41:/*EOF*/
+        3:   42:/*EOF*/
+        3:   43:/*EOF*/
+        3:   44:/*EOF*/
+        3:   45:/*EOF*/
+        3:   46:/*EOF*/
+    #####:   47:/*EOF*/
+    #####:   48:/*EOF*/
+        -:   49:/*EOF*/
+        -:   50:/*EOF*/
+       66:   51:/*EOF*/
+       30:   52:/*EOF*/
+        -:   53:/*EOF*/
+        6:   54:/*EOF*/
+        6:   55:/*EOF*/
+        -:   56:/*EOF*/
+        -:   57:/*EOF*/
+        3:   58:/*EOF*/
+        3:   59:/*EOF*/
+        -:   60:/*EOF*/
+        9:   61:/*EOF*/
+        9:   62:/*EOF*/
+        -:   63:/*EOF*/
+       12:   64:/*EOF*/
+       12:   65:/*EOF*/
+       30:   66:/*EOF*/
+        -:   67:/*EOF*/
+        3:   68:/*EOF*/
+25769803782:   69:/*EOF*/
+12884901888:   70:/*EOF*/
+        -:   71:/*EOF*/
+        3:   72:/*EOF*/
diff --git a/test/tools/llvm-cov/Inputs/test_missing.h.gcov b/test/tools/llvm-cov/Inputs/test_missing.h.gcov
new file mode 100644
index 0000000..d500e86
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/test_missing.h.gcov
@@ -0,0 +1,6 @@
+        -:    0:Source:srcdir/./nested_dir/../test.h
+        -:    0:Graph:test_paths.gcno
+        -:    0:Data:test_paths.gcda
+        -:    0:Runs:3
+        -:    0:Programs:1
+        6:    1:/*EOF*/
diff --git a/test/tools/llvm-cov/Inputs/test_missing.output b/test/tools/llvm-cov/Inputs/test_missing.output
new file mode 100644
index 0000000..a3e32dd
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/test_missing.output
@@ -0,0 +1,8 @@
+File 'srcdir/./nested_dir/../test.cpp'
+Lines executed:84.21% of 38
+srcdir/./nested_dir/../test.cpp:creating 'test.cpp.gcov'
+
+File 'srcdir/./nested_dir/../test.h'
+Lines executed:100.00% of 1
+srcdir/./nested_dir/../test.h:creating 'test.h.gcov'
+
diff --git a/test/tools/llvm-cov/Inputs/test_no_gcda.cpp.gcov b/test/tools/llvm-cov/Inputs/test_no_gcda.cpp.gcov
new file mode 100644
index 0000000..31353ca
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/test_no_gcda.cpp.gcov
@@ -0,0 +1,79 @@
+        -:    0:Source:test.cpp
+        -:    0:Graph:test.gcno
+        -:    0:Data:-
+        -:    0:Runs:0
+        -:    0:Programs:0
+        -:    1:#include "test.h"
+        -:    2:#include <cstdlib>
+        -:    3:
+        -:    4:bool on = false;
+        -:    5:int len = 42;
+        -:    6:double grid[10][10] = {0};
+        -:    7:const char * hello = "world";
+        -:    8:const char * world = "hello";
+        -:    9:
+    #####:   10:void A::B() {}
+        -:   11:
+    #####:   12:void useless() {}
+        -:   13:
+        -:   14:double more_useless() {
+    #####:   15:  return 0;
+        -:   16:}
+        -:   17:
+        -:   18:int foo() {
+    #####:   19:  on = true;
+    #####:   20:  return 3;
+        -:   21:}
+        -:   22:
+        -:   23:int bar() {
+    #####:   24:  len--;
+    #####:   25:  return foo() + 45;
+        -:   26:}
+        -:   27:
+    #####:   28:void assign(int ii, int jj) {
+    #####:   29:  grid[ii][jj] = (ii+1) * (jj+1);
+    #####:   30:}
+        -:   31:
+        -:   32:void initialize_grid() {
+    #####:   33:  for (int ii = 0; ii < 2; ii++)
+    #####:   34:    for (int jj = 0; jj < 2; jj++)
+    #####:   35:      assign(ii, jj);
+    #####:   36:}
+        -:   37:
+        -:   38:int main() {
+    #####:   39:  initialize_grid();
+        -:   40:
+    #####:   41:  int a = 2;
+    #####:   42:  on = rand() % 2;
+    #####:   43:  if (on) {
+    #####:   44:    foo();
+    #####:   45:    ++a;
+    #####:   46:  } else {
+    #####:   47:    bar();
+    #####:   48:    a += rand();
+        -:   49:  }
+        -:   50:
+    #####:   51:  for (int ii = 0; ii < 10; ++ii) {
+    #####:   52:    switch (rand() % 5) {
+        -:   53:      case 0:
+    #####:   54:        a += rand();
+    #####:   55:        break;
+        -:   56:      case 1:
+        -:   57:      case 2:
+    #####:   58:        a += rand() / rand();
+    #####:   59:        break;
+        -:   60:      case 3:
+    #####:   61:        a -= rand();
+    #####:   62:        break;
+        -:   63:      default:
+    #####:   64:        a = -1;
+    #####:   65:    }
+    #####:   66:  }
+        -:   67:
+    #####:   68:  A thing;
+    #####:   69:  for (uint64_t ii = 0; ii < 4294967296; ++ii)
+    #####:   70:    thing.B();
+        -:   71:
+    #####:   72:  return a + 8 + grid[2][3] + len;
+        -:   73:  return more_useless();
+        -:   74:}
diff --git a/test/tools/llvm-cov/Inputs/test_no_gcda.h.gcov b/test/tools/llvm-cov/Inputs/test_no_gcda.h.gcov
new file mode 100644
index 0000000..c0a45c6
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/test_no_gcda.h.gcov
@@ -0,0 +1,8 @@
+        -:    0:Source:./test.h
+        -:    0:Graph:test.gcno
+        -:    0:Data:-
+        -:    0:Runs:0
+        -:    0:Programs:0
+    #####:    1:struct A {
+        -:    2:  virtual void B();
+        -:    3:};
diff --git a/test/tools/llvm-cov/Inputs/test_no_gcda.output b/test/tools/llvm-cov/Inputs/test_no_gcda.output
new file mode 100644
index 0000000..46efaca
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/test_no_gcda.output
@@ -0,0 +1,8 @@
+File './test.h'
+Lines executed:0.00% of 1
+./test.h:creating 'test.h.gcov'
+
+File 'test.cpp'
+Lines executed:0.00% of 38
+test.cpp:creating 'test.cpp.gcov'
+
diff --git a/test/tools/llvm-cov/Inputs/test_no_options.cpp.gcov b/test/tools/llvm-cov/Inputs/test_no_options.cpp.gcov
new file mode 100644
index 0000000..871e3ba
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/test_no_options.cpp.gcov
@@ -0,0 +1,79 @@
+        -:    0:Source:test.cpp
+        -:    0:Graph:test.gcno
+        -:    0:Data:test.gcda
+        -:    0:Runs:2
+        -:    0:Programs:1
+        -:    1:#include "test.h"
+        -:    2:#include <cstdlib>
+        -:    3:
+        -:    4:bool on = false;
+        -:    5:int len = 42;
+        -:    6:double grid[10][10] = {0};
+        -:    7:const char * hello = "world";
+        -:    8:const char * world = "hello";
+        -:    9:
+8589934592:   10:void A::B() {}
+        -:   11:
+    #####:   12:void useless() {}
+        -:   13:
+        -:   14:double more_useless() {
+    #####:   15:  return 0;
+        -:   16:}
+        -:   17:
+        -:   18:int foo() {
+        2:   19:  on = true;
+        2:   20:  return 3;
+        -:   21:}
+        -:   22:
+        -:   23:int bar() {
+    #####:   24:  len--;
+    #####:   25:  return foo() + 45;
+        -:   26:}
+        -:   27:
+        8:   28:void assign(int ii, int jj) {
+        8:   29:  grid[ii][jj] = (ii+1) * (jj+1);
+        8:   30:}
+        -:   31:
+        -:   32:void initialize_grid() {
+       12:   33:  for (int ii = 0; ii < 2; ii++)
+       24:   34:    for (int jj = 0; jj < 2; jj++)
+       12:   35:      assign(ii, jj);
+        2:   36:}
+        -:   37:
+        -:   38:int main() {
+        2:   39:  initialize_grid();
+        -:   40:
+        2:   41:  int a = 2;
+        2:   42:  on = rand() % 2;
+        2:   43:  if (on) {
+        2:   44:    foo();
+        2:   45:    ++a;
+        2:   46:  } else {
+    #####:   47:    bar();
+    #####:   48:    a += rand();
+        -:   49:  }
+        -:   50:
+       44:   51:  for (int ii = 0; ii < 10; ++ii) {
+       20:   52:    switch (rand() % 5) {
+        -:   53:      case 0:
+        4:   54:        a += rand();
+        4:   55:        break;
+        -:   56:      case 1:
+        -:   57:      case 2:
+        2:   58:        a += rand() / rand();
+        2:   59:        break;
+        -:   60:      case 3:
+        6:   61:        a -= rand();
+        6:   62:        break;
+        -:   63:      default:
+        8:   64:        a = -1;
+        8:   65:    }
+       20:   66:  }
+        -:   67:
+        2:   68:  A thing;
+17179869188:   69:  for (uint64_t ii = 0; ii < 4294967296; ++ii)
+8589934592:   70:    thing.B();
+        -:   71:
+        2:   72:  return a + 8 + grid[2][3] + len;
+        -:   73:  return more_useless();
+        -:   74:}
diff --git a/test/tools/llvm-cov/Inputs/test_no_options.h.gcov b/test/tools/llvm-cov/Inputs/test_no_options.h.gcov
new file mode 100644
index 0000000..4ba58c9
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/test_no_options.h.gcov
@@ -0,0 +1,8 @@
+        -:    0:Source:./test.h
+        -:    0:Graph:test.gcno
+        -:    0:Data:test.gcda
+        -:    0:Runs:2
+        -:    0:Programs:1
+        4:    1:struct A {
+        -:    2:  virtual void B();
+        -:    3:};
diff --git a/test/tools/llvm-cov/Inputs/test_no_options.output b/test/tools/llvm-cov/Inputs/test_no_options.output
new file mode 100644
index 0000000..dd76811
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/test_no_options.output
@@ -0,0 +1,8 @@
+File './test.h'
+Lines executed:100.00% of 1
+./test.h:creating 'test.h.gcov'
+
+File 'test.cpp'
+Lines executed:84.21% of 38
+test.cpp:creating 'test.cpp.gcov'
+
diff --git a/test/tools/llvm-cov/Inputs/test_no_output.output b/test/tools/llvm-cov/Inputs/test_no_output.output
new file mode 100644
index 0000000..b41e20e
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/test_no_output.output
@@ -0,0 +1,6 @@
+File './test.h'
+Lines executed:100.00% of 1
+
+File 'test.cpp'
+Lines executed:84.21% of 38
+
diff --git a/test/tools/llvm-cov/Inputs/test_no_preserve_paths.output b/test/tools/llvm-cov/Inputs/test_no_preserve_paths.output
new file mode 100644
index 0000000..a3e32dd
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/test_no_preserve_paths.output
@@ -0,0 +1,8 @@
+File 'srcdir/./nested_dir/../test.cpp'
+Lines executed:84.21% of 38
+srcdir/./nested_dir/../test.cpp:creating 'test.cpp.gcov'
+
+File 'srcdir/./nested_dir/../test.h'
+Lines executed:100.00% of 1
+srcdir/./nested_dir/../test.h:creating 'test.h.gcov'
+
diff --git a/test/tools/llvm-cov/Inputs/test_objdir.cpp.gcov b/test/tools/llvm-cov/Inputs/test_objdir.cpp.gcov
new file mode 100644
index 0000000..abf8856
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/test_objdir.cpp.gcov
@@ -0,0 +1,79 @@
+        -:    0:Source:test.cpp
+        -:    0:Graph:objdir/test.gcno
+        -:    0:Data:objdir/test.gcda
+        -:    0:Runs:2
+        -:    0:Programs:1
+        -:    1:#include "test.h"
+        -:    2:#include <cstdlib>
+        -:    3:
+        -:    4:bool on = false;
+        -:    5:int len = 42;
+        -:    6:double grid[10][10] = {0};
+        -:    7:const char * hello = "world";
+        -:    8:const char * world = "hello";
+        -:    9:
+8589934592:   10:void A::B() {}
+        -:   11:
+    #####:   12:void useless() {}
+        -:   13:
+        -:   14:double more_useless() {
+    #####:   15:  return 0;
+        -:   16:}
+        -:   17:
+        -:   18:int foo() {
+        2:   19:  on = true;
+        2:   20:  return 3;
+        -:   21:}
+        -:   22:
+        -:   23:int bar() {
+    #####:   24:  len--;
+    #####:   25:  return foo() + 45;
+        -:   26:}
+        -:   27:
+        8:   28:void assign(int ii, int jj) {
+        8:   29:  grid[ii][jj] = (ii+1) * (jj+1);
+        8:   30:}
+        -:   31:
+        -:   32:void initialize_grid() {
+       12:   33:  for (int ii = 0; ii < 2; ii++)
+       24:   34:    for (int jj = 0; jj < 2; jj++)
+       12:   35:      assign(ii, jj);
+        2:   36:}
+        -:   37:
+        -:   38:int main() {
+        2:   39:  initialize_grid();
+        -:   40:
+        2:   41:  int a = 2;
+        2:   42:  on = rand() % 2;
+        2:   43:  if (on) {
+        2:   44:    foo();
+        2:   45:    ++a;
+        2:   46:  } else {
+    #####:   47:    bar();
+    #####:   48:    a += rand();
+        -:   49:  }
+        -:   50:
+       44:   51:  for (int ii = 0; ii < 10; ++ii) {
+       20:   52:    switch (rand() % 5) {
+        -:   53:      case 0:
+        4:   54:        a += rand();
+        4:   55:        break;
+        -:   56:      case 1:
+        -:   57:      case 2:
+        2:   58:        a += rand() / rand();
+        2:   59:        break;
+        -:   60:      case 3:
+        6:   61:        a -= rand();
+        6:   62:        break;
+        -:   63:      default:
+        8:   64:        a = -1;
+        8:   65:    }
+       20:   66:  }
+        -:   67:
+        2:   68:  A thing;
+17179869188:   69:  for (uint64_t ii = 0; ii < 4294967296; ++ii)
+8589934592:   70:    thing.B();
+        -:   71:
+        2:   72:  return a + 8 + grid[2][3] + len;
+        -:   73:  return more_useless();
+        -:   74:}
diff --git a/test/tools/llvm-cov/Inputs/test_objdir.h.gcov b/test/tools/llvm-cov/Inputs/test_objdir.h.gcov
new file mode 100644
index 0000000..8208d25
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/test_objdir.h.gcov
@@ -0,0 +1,8 @@
+        -:    0:Source:./test.h
+        -:    0:Graph:objdir/test.gcno
+        -:    0:Data:objdir/test.gcda
+        -:    0:Runs:2
+        -:    0:Programs:1
+        4:    1:struct A {
+        -:    2:  virtual void B();
+        -:    3:};
diff --git a/test/tools/llvm-cov/Inputs/test_paths.cpp.gcov b/test/tools/llvm-cov/Inputs/test_paths.cpp.gcov
new file mode 100644
index 0000000..3982ddf
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/test_paths.cpp.gcov
@@ -0,0 +1,79 @@
+        -:    0:Source:srcdir/./nested_dir/../test.cpp
+        -:    0:Graph:test_paths.gcno
+        -:    0:Data:test_paths.gcda
+        -:    0:Runs:3
+        -:    0:Programs:1
+        -:    1:#include "test.h"
+        -:    2:#include <cstdlib>
+        -:    3:
+        -:    4:bool on = false;
+        -:    5:int len = 42;
+        -:    6:double grid[10][10] = {0};
+        -:    7:const char * hello = "world";
+        -:    8:const char * world = "hello";
+        -:    9:
+12884901888:   10:void A::B() {}
+        -:   11:
+    #####:   12:void useless() {}
+        -:   13:
+        -:   14:double more_useless() {
+    #####:   15:  return 0;
+        -:   16:}
+        -:   17:
+        -:   18:int foo() {
+        3:   19:  on = true;
+        3:   20:  return 3;
+        -:   21:}
+        -:   22:
+        -:   23:int bar() {
+    #####:   24:  len--;
+    #####:   25:  return foo() + 45;
+        -:   26:}
+        -:   27:
+       12:   28:void assign(int ii, int jj) {
+       12:   29:  grid[ii][jj] = (ii+1) * (jj+1);
+       12:   30:}
+        -:   31:
+        -:   32:void initialize_grid() {
+       21:   33:  for (int ii = 0; ii < 2; ii++)
+       36:   34:    for (int jj = 0; jj < 2; jj++)
+       18:   35:      assign(ii, jj);
+        3:   36:}
+        -:   37:
+        -:   38:int main() {
+        3:   39:  initialize_grid();
+        -:   40:
+        3:   41:  int a = 2;
+        3:   42:  on = rand() % 2;
+        3:   43:  if (on) {
+        3:   44:    foo();
+        3:   45:    ++a;
+        3:   46:  } else {
+    #####:   47:    bar();
+    #####:   48:    a += rand();
+        -:   49:  }
+        -:   50:
+       66:   51:  for (int ii = 0; ii < 10; ++ii) {
+       30:   52:    switch (rand() % 5) {
+        -:   53:      case 0:
+        6:   54:        a += rand();
+        6:   55:        break;
+        -:   56:      case 1:
+        -:   57:      case 2:
+        3:   58:        a += rand() / rand();
+        3:   59:        break;
+        -:   60:      case 3:
+        9:   61:        a -= rand();
+        9:   62:        break;
+        -:   63:      default:
+       12:   64:        a = -1;
+       12:   65:    }
+       30:   66:  }
+        -:   67:
+        3:   68:  A thing;
+25769803782:   69:  for (uint64_t ii = 0; ii < 4294967296; ++ii)
+12884901888:   70:    thing.B();
+        -:   71:
+        3:   72:  return a + 8 + grid[2][3] + len;
+        -:   73:  return more_useless();
+        -:   74:}
diff --git a/test/tools/llvm-cov/Inputs/test_paths.gcda b/test/tools/llvm-cov/Inputs/test_paths.gcda
new file mode 100644
index 0000000..7e2cf9e
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/test_paths.gcda
Binary files differ
diff --git a/test/tools/llvm-cov/Inputs/test_paths.gcno b/test/tools/llvm-cov/Inputs/test_paths.gcno
new file mode 100644
index 0000000..aada974
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/test_paths.gcno
Binary files differ
diff --git a/test/tools/llvm-cov/Inputs/test_paths.h.gcov b/test/tools/llvm-cov/Inputs/test_paths.h.gcov
new file mode 100644
index 0000000..95e90ca
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/test_paths.h.gcov
@@ -0,0 +1,8 @@
+        -:    0:Source:srcdir/./nested_dir/../test.h
+        -:    0:Graph:test_paths.gcno
+        -:    0:Data:test_paths.gcda
+        -:    0:Runs:3
+        -:    0:Programs:1
+        6:    1:struct A {
+        -:    2:  virtual void B();
+        -:    3:};
diff --git a/test/tools/llvm-cov/Inputs/test_preserve_paths.output b/test/tools/llvm-cov/Inputs/test_preserve_paths.output
new file mode 100644
index 0000000..0164f2d
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/test_preserve_paths.output
@@ -0,0 +1,8 @@
+File 'srcdir/./nested_dir/../test.cpp'
+Lines executed:84.21% of 38
+srcdir/./nested_dir/../test.cpp:creating 'srcdir#nested_dir#^#test.cpp.gcov'
+
+File 'srcdir/./nested_dir/../test.h'
+Lines executed:100.00% of 1
+srcdir/./nested_dir/../test.h:creating 'srcdir#nested_dir#^#test.h.gcov'
+
diff --git a/test/tools/llvm-cov/Inputs/test_read_fail.gcno b/test/tools/llvm-cov/Inputs/test_read_fail.gcno
new file mode 100644
index 0000000..88073f1
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/test_read_fail.gcno
Binary files differ
diff --git a/test/tools/llvm-cov/Inputs/universal-binary b/test/tools/llvm-cov/Inputs/universal-binary
new file mode 100755
index 0000000..aad5758
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/universal-binary
Binary files differ
diff --git a/test/tools/llvm-cov/Inputs/universal-binary.json b/test/tools/llvm-cov/Inputs/universal-binary.json
new file mode 100644
index 0000000..54b9e22
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/universal-binary.json
@@ -0,0 +1,37 @@
+// Metadata section
+// CHECK: {"version":"{{[0-9]\.[0-9]\.[0-9]}}","type":"llvm.coverage.json.export","data":[
+
+// Open Export
+// CHECK-SAME: {"files":[
+
+// File Object
+// CHECK-SAME: {"filename":"{{[^"]+}}universal-binary.c",
+// CHECK-SAME: "segments":[
+// CHECK-SAME: {{(\[[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+\],?)+}}],
+// CHECK-SAME: "expansions":[],
+
+// Verify the Summary Section for the first file
+// CHECK-SAME: "summary":{
+// CHECK-SAME: "lines":{"count":1,"covered":1,"percent":100},
+// CHECK-SAME: "functions":{"count":1,"covered":1,"percent":100},
+// CHECK-SAME: "regions":{"count":1,"covered":1,"notcovered":0,"percent":100}}
+
+// Close Files Array
+// CHECK-SAME: ],
+
+// Functions List
+// CHECK-SAME: "functions":[
+// CHECK-SAME: {"name":"main","count":100,"regions":[
+// CHECK-SAME: {{(\[[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+\],?)+}}],
+// CHECK-SAME: "filenames":["{{[^"]+}}universal-binary.c"]
+// CHECK-SAME: }],
+
+// Full Export Summary
+// CHECK-SAME: "totals":{
+// CHECK-SAME: "lines":{"count":1,"covered":1,"percent":100},
+// CHECK-SAME: "functions":{"count":1,"covered":1,"percent":100},
+// CHECK-SAME: "instantiations":{"count":1,"covered":1,"percent":100},
+// CHECK-SAME: "regions":{"count":1,"covered":1,"notcovered":0,"percent":100}
+
+// Close the export object, data array, and root object
+// CHECK-SAME: }]}
diff --git a/test/tools/llvm-cov/Inputs/universal-binary.proftext b/test/tools/llvm-cov/Inputs/universal-binary.proftext
new file mode 100644
index 0000000..97816c2
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/universal-binary.proftext
@@ -0,0 +1,4 @@
+main
+0x0
+1
+100
diff --git a/test/tools/llvm-cov/Inputs/whitelist1.txt b/test/tools/llvm-cov/Inputs/whitelist1.txt
new file mode 100644
index 0000000..2646323
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/whitelist1.txt
@@ -0,0 +1,4 @@
+# Comment
+
+whitelist_fun:*func1*
+whitelist_fun:*func2*
diff --git a/test/tools/llvm-cov/Inputs/whitelist2.txt b/test/tools/llvm-cov/Inputs/whitelist2.txt
new file mode 100644
index 0000000..5809820
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/whitelist2.txt
@@ -0,0 +1,2 @@
+whitelist_fun:*func3*
+whitelist_fun:*func4*
diff --git a/test/tools/llvm-cov/Inputs/zeroFunctionFile.covmapping b/test/tools/llvm-cov/Inputs/zeroFunctionFile.covmapping
new file mode 100644
index 0000000..b2c198a
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/zeroFunctionFile.covmapping
Binary files differ
diff --git a/test/tools/llvm-cov/Inputs/zeroFunctionFile.h b/test/tools/llvm-cov/Inputs/zeroFunctionFile.h
new file mode 100644
index 0000000..1703e8e
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/zeroFunctionFile.h
@@ -0,0 +1,3 @@
+// This header has no functions
+
+#define NOFUNCTIONS(x) (x) > 0 ? 0 : 1
diff --git a/test/tools/llvm-cov/Inputs/zeroFunctionFile.proftext b/test/tools/llvm-cov/Inputs/zeroFunctionFile.proftext
new file mode 100644
index 0000000..55187c1
--- /dev/null
+++ b/test/tools/llvm-cov/Inputs/zeroFunctionFile.proftext
@@ -0,0 +1,16 @@
+foo
+# Func Hash:
+13
+# Num Counters:
+2
+# Counter Values:
+1
+1
+
+main
+# Func Hash:
+0
+# Num Counters:
+1
+# Counter Values:
+1