Index: test/tools/llvm-cov/deferred-region.cpp =================================================================== --- /dev/null +++ test/tools/llvm-cov/deferred-region.cpp @@ -0,0 +1,79 @@ +// RUN: llvm-cov show %S/Inputs/deferred-regions.covmapping -instr-profile %S/Inputs/deferred-regions.profdata -show-line-counts-or-regions -dump -filename-equivalence %s 2>&1 | FileCheck %s + +void foo(int x) { + if (x == 0) { + return; // CHECK: [[@LINE]]|{{ +}}1| + } + +} // CHECK: [[@LINE]]|{{ +}}2| + +void bar() { + return; + +} // CHECK: [[@LINE]]|{{ +}}1| + +void for_loop() { + if (false) + return; // CHECK: [[@LINE]]|{{ +}}0| + + for (int i = 0; i < 10; ++i) { // CHECK: [[@LINE]]|{{ +}}2| + if (i % 2 == 0) + continue; // CHECK: [[@LINE]]|{{ +}}1| + + if (i % 5 == 0) + break; // CHECK: [[@LINE]]|{{ +}}0| + + int x = i; + return; // CHECK: [[@LINE]]|{{ +}}1| + + } // CHECK: [[@LINE]]|{{ +}}1| +} + +struct Error {}; + +void while_loop() { + if (false) + return; // CHECK: [[@LINE]]|{{ +}}0| + + int x = 0; + while (++x < 10) { // CHECK: [[@LINE]]|{{ +}}3| + if (x == 1) + continue; // CHECK: [[@LINE]]|{{ +}}1| + + while (++x < 4) { // CHECK: [[@LINE]]|{{ +}}1| + if (x == 3) + break; // CHECK: [[@LINE]]|{{ +}}1| + // CHECK: [[@LINE]]|{{ +}}0| + while (++x < 5) {} // CHECK: [[@LINE]]|{{ +}}0| + } // CHECK: [[@LINE]]|{{ +}}1| + + if (x == 0) + throw Error(); // CHECK: [[@LINE]]|{{ +}}0| + + while (++x < 9) { // CHECK: [[@LINE]]|{{ +}}6| + if (x == 0) // CHECK: [[@LINE]]|{{ +}}5| + break; // CHECK: [[@LINE]]|{{ +}}0| + + } + } +} + +void gotos() { + if (false) + goto out; // CHECK: [[@LINE]]|{{ +}}0| + + return; + +out: // CHECK: [[@LINE]]|{{ +}}1| + return; +} + +int main() { + foo(0); + foo(1); + bar(); + for_loop(); + while_loop(); + gotos(); + return 0; +} Index: test/tools/llvm-cov/showLineExecutionCounts.cpp =================================================================== --- test/tools/llvm-cov/showLineExecutionCounts.cpp +++ test/tools/llvm-cov/showLineExecutionCounts.cpp @@ -6,7 +6,7 @@ int main() { // TEXT: [[@LINE]]| 161|int main( int x = 0; // TEXT: [[@LINE]]| 161| int x // TEXT: [[@LINE]]| 161| - if (x) { // TEXT: [[@LINE]]| 0| if (x) + if (x) { // TEXT: [[@LINE]]| 161| if (x) x = 0; // TEXT: [[@LINE]]| 0| x = 0 } else { // TEXT: [[@LINE]]| 161| } else x = 1; // TEXT: [[@LINE]]| 161| x = 1 @@ -50,7 +50,7 @@ // HTML:
[[@LINE-44]]
161
int main() {
 // HTML: 
[[@LINE-44]]
161
  int x = 0
 // HTML: 
[[@LINE-44]]
161
-// HTML: 
[[@LINE-44]]
0
  if (x) {
+// HTML: 
[[@LINE-44]]
161
  if (x) {
 // HTML: 
[[@LINE-44]]
0
 // HTML: 
[[@LINE-44]]
161
  }
 // HTML: 
[[@LINE-44]]
161
    x = 1;
Index: tools/llvm-cov/SourceCoverageView.h
===================================================================
--- tools/llvm-cov/SourceCoverageView.h
+++ tools/llvm-cov/SourceCoverageView.h
@@ -67,25 +67,15 @@
 /// \brief Coverage statistics for a single line.
 struct LineCoverageStats {
   uint64_t ExecutionCount;
-  unsigned RegionCount;
+  bool HasMultipleRegions;
   bool Mapped;
 
-  LineCoverageStats() : ExecutionCount(0), RegionCount(0), Mapped(false) {}
+  LineCoverageStats(ArrayRef LineSegments,
+                    const coverage::CoverageSegment *WrappedSegment);
 
   bool isMapped() const { return Mapped; }
 
-  bool hasMultipleRegions() const { return RegionCount > 1; }
-
-  void addRegionStartCount(uint64_t Count) {
-    // The max of all region starts is the most interesting value.
-    addRegionCount(RegionCount ? std::max(ExecutionCount, Count) : Count);
-    ++RegionCount;
-  }
-
-  void addRegionCount(uint64_t Count) {
-    Mapped = true;
-    ExecutionCount = Count;
-  }
+  bool hasMultipleRegions() const { return HasMultipleRegions; }
 };
 
 /// \brief A file manager that handles format-aware file creation.
Index: tools/llvm-cov/SourceCoverageView.cpp
===================================================================
--- tools/llvm-cov/SourceCoverageView.cpp
+++ tools/llvm-cov/SourceCoverageView.cpp
@@ -83,6 +83,41 @@
   llvm_unreachable("Unknown coverage output format!");
 }
 
+LineCoverageStats::LineCoverageStats(
+    ArrayRef LineSegments,
+    const coverage::CoverageSegment *WrappedSegment) {
+  // Find the minimum number of regions which start in this line.
+  unsigned MinRegionCount = 0;
+  auto isStartOfRegion = [](const coverage::CoverageSegment *S) {
+    return S->HasCount && S->IsRegionEntry;
+  };
+  for (unsigned I = 0; I < LineSegments.size() && MinRegionCount < 2; ++I)
+    if (isStartOfRegion(LineSegments[I]))
+      ++MinRegionCount;
+
+  ExecutionCount = 0;
+  HasMultipleRegions = MinRegionCount > 1;
+  Mapped = (WrappedSegment && WrappedSegment->HasCount) || (MinRegionCount > 0);
+
+  if (!Mapped)
+    return;
+
+  // Pick the max count among regions which start and end on this line, to
+  // avoid erroneously using the wrapped count, and to avoid picking region
+  // counts which come from deferred regions.
+  if (LineSegments.size() > 1) {
+    for (unsigned I = 0; I < LineSegments.size() - 1; ++I)
+      ExecutionCount = std::max(ExecutionCount, LineSegments[I]->Count);
+    return;
+  }
+
+  // Just pick the maximum count.
+  if (WrappedSegment && WrappedSegment->HasCount)
+    ExecutionCount = WrappedSegment->Count;
+  if (!LineSegments.empty())
+    ExecutionCount = std::max(ExecutionCount, LineSegments[0]->Count);
+}
+
 unsigned SourceCoverageView::getFirstUncoveredLineNo() {
   auto CheckIfUncovered = [](const coverage::CoverageSegment &S) {
     return S.HasCount && S.Count == 0;
@@ -207,17 +242,11 @@
     while (NextSegment != EndSegment && NextSegment->Line == LI.line_number())
       LineSegments.push_back(&*NextSegment++);
 
-    // Calculate a count to be for the line as a whole.
-    LineCoverageStats LineCount;
-    if (WrappedSegment && WrappedSegment->HasCount)
-      LineCount.addRegionCount(WrappedSegment->Count);
-    for (const auto *S : LineSegments)
-      if (S->HasCount && S->IsRegionEntry)
-        LineCount.addRegionStartCount(S->Count);
-
     renderLinePrefix(OS, ViewDepth);
     if (getOptions().ShowLineNumbers)
       renderLineNumberColumn(OS, LI.line_number());
+
+    LineCoverageStats LineCount{LineSegments, WrappedSegment};
     if (getOptions().ShowLineStats)
       renderLineCoverageColumn(OS, LineCount);