[llvm-cov] Track function and instantiation coverage separately

These are distinct statistics which are useful to look at separately.

Example: say you have a template function "foo" with 5 instantiations
and only 3 of them are covered. Then this contributes (1/1) to the total
function coverage and (3/5) to the total instantiation coverage. I.e,
the old "Function Coverage" column has been renamed to "Instantiation
Coverage", and the new "Function Coverage" aggregates information from
the various instantiations of a function.

One benefit of making this switch is that the Line and Region coverage
columns will start making sense. Let's continue the example and assume
that the 5 instantiations of "foo" cover {2, 4, 6, 8, 10} out of 10
lines respectively. The new line coverage for "foo" is (10/10), not
(30/50).  The old scenario got confusing because we'd report that there
were more lines in a file than what was actually possible.

llvm-svn: 281875
diff --git a/llvm/tools/llvm-cov/CoverageReport.cpp b/llvm/tools/llvm-cov/CoverageReport.cpp
index 332268a..e70cce4 100644
--- a/llvm/tools/llvm-cov/CoverageReport.cpp
+++ b/llvm/tools/llvm-cov/CoverageReport.cpp
@@ -13,6 +13,7 @@
 
 #include "CoverageReport.h"
 #include "RenderingSupport.h"
+#include "llvm/ADT/DenseMap.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/Format.h"
 #include "llvm/Support/Path.h"
@@ -85,7 +86,8 @@
 }
 
 // Specify the default column widths.
-size_t FileReportColumns[] = {25, 12, 18, 10, 12, 18, 10, 12, 18, 10};
+size_t FileReportColumns[] = {25, 12, 18, 10, 12, 18, 10,
+                              16, 16, 10, 12, 18, 10};
 size_t FunctionReportColumns[] = {25, 10, 8, 8, 10, 8, 8};
 
 /// \brief Adjust column widths to fit long file paths and function names.
@@ -139,6 +141,8 @@
       determineCoveragePercentageColor(File.RegionCoverage);
   auto FuncCoverageColor =
       determineCoveragePercentageColor(File.FunctionCoverage);
+  auto InstantiationCoverageColor =
+      determineCoveragePercentageColor(File.InstantiationCoverage);
   auto LineCoverageColor = determineCoveragePercentageColor(File.LineCoverage);
   SmallString<256> FileName = File.Name;
   sys::path::remove_dots(FileName, /*remove_dot_dots=*/true);
@@ -162,11 +166,20 @@
                 File.FunctionCoverage.getPercentCovered())
       << '%';
   OS << format("%*u", FileReportColumns[7],
+               (unsigned)File.InstantiationCoverage.NumFunctions);
+  OS << format("%*u", FileReportColumns[8],
+               (unsigned)(File.InstantiationCoverage.NumFunctions -
+                          File.InstantiationCoverage.Executed));
+  Options.colored_ostream(OS, InstantiationCoverageColor)
+      << format("%*.2f", FileReportColumns[9] - 1,
+                File.InstantiationCoverage.getPercentCovered())
+      << '%';
+  OS << format("%*u", FileReportColumns[10],
                (unsigned)File.LineCoverage.NumLines);
   Options.colored_ostream(OS, LineCoverageColor) << format(
-      "%*u", FileReportColumns[8], (unsigned)File.LineCoverage.NotCovered);
+      "%*u", FileReportColumns[11], (unsigned)File.LineCoverage.NotCovered);
   Options.colored_ostream(OS, LineCoverageColor)
-      << format("%*.2f", FileReportColumns[9] - 1,
+      << format("%*.2f", FileReportColumns[12] - 1,
                 File.LineCoverage.getPercentCovered())
       << '%';
   OS << "\n";
@@ -255,11 +268,28 @@
 
   for (StringRef Filename : Files) {
     FileCoverageSummary Summary(Filename.drop_front(LCP));
+
+    // Map source locations to aggregate function coverage summaries.
+    DenseMap<std::pair<unsigned, unsigned>, FunctionCoverageSummary> Summaries;
+
     for (const auto &F : Coverage.getCoveredFunctions(Filename)) {
       FunctionCoverageSummary Function = FunctionCoverageSummary::get(F);
-      Summary.addFunction(Function);
-      Totals.addFunction(Function);
+      auto StartLoc = F.CountedRegions[0].startLoc();
+
+      auto UniquedSummary = Summaries.insert({StartLoc, Function});
+      if (!UniquedSummary.second)
+        UniquedSummary.first->second.update(Function);
+
+      Summary.addInstantiation(Function);
+      Totals.addInstantiation(Function);
     }
+
+    for (const auto &UniquedSummary : Summaries) {
+      const FunctionCoverageSummary &FCS = UniquedSummary.second;
+      Summary.addFunction(FCS);
+      Totals.addFunction(FCS);
+    }
+
     FileReports.push_back(Summary);
   }
 
@@ -288,9 +318,12 @@
      << column("Functions", FileReportColumns[4], Column::RightAlignment)
      << column("Missed Functions", FileReportColumns[5], Column::RightAlignment)
      << column("Executed", FileReportColumns[6], Column::RightAlignment)
-     << column("Lines", FileReportColumns[7], Column::RightAlignment)
-     << column("Missed Lines", FileReportColumns[8], Column::RightAlignment)
-     << column("Cover", FileReportColumns[9], Column::RightAlignment) << "\n";
+     << column("Instantiations", FileReportColumns[7], Column::RightAlignment)
+     << column("Missed Insts.", FileReportColumns[8], Column::RightAlignment)
+     << column("Executed", FileReportColumns[9], Column::RightAlignment)
+     << column("Lines", FileReportColumns[10], Column::RightAlignment)
+     << column("Missed Lines", FileReportColumns[11], Column::RightAlignment)
+     << column("Cover", FileReportColumns[12], Column::RightAlignment) << "\n";
   renderDivider(FileReportColumns, OS);
   OS << "\n";