zequanwu created this revision.
zequanwu added reviewers: vsk, efriedma, rnk, pirama.
Herald added a subscriber: lxfind.
zequanwu requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

This solves the problems that D85036 <https://reviews.llvm.org/D85036> tried to 
solve, but that patch introduced
new bugs and those bugs should be fixed in the clang coverage rather than
llvm-cov. I'll revert D85036 <https://reviews.llvm.org/D85036> after this is 
landed to avoid reintroduce the bugs.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D97101

Files:
  clang/lib/CodeGen/CoverageMappingGen.cpp
  clang/test/CoverageMapping/classtemplate.cpp
  clang/test/CoverageMapping/coroutine.cpp
  clang/test/CoverageMapping/deferred-region.cpp
  clang/test/CoverageMapping/label.cpp
  clang/test/CoverageMapping/moremacros.c
  clang/test/CoverageMapping/return.c
  clang/test/CoverageMapping/switch.cpp
  clang/test/CoverageMapping/switchmacro.c
  clang/test/CoverageMapping/terminate-statements.cpp
  clang/test/CoverageMapping/trycatch.cpp
  clang/test/CoverageMapping/unreachable-macro.c

Index: clang/test/CoverageMapping/unreachable-macro.c
===================================================================
--- clang/test/CoverageMapping/unreachable-macro.c
+++ clang/test/CoverageMapping/unreachable-macro.c
@@ -6,6 +6,7 @@
 void counters_in_macro_following_unreachable() {
   // CHECK-NEXT: File 0, [[@LINE-1]]:48 -> {{[0-9]+}}:2 = #0
   return;
+  // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:10 -> [[@LINE+3]]:3 = 0
   // CHECK-NEXT: Expansion,File 0, [[@LINE+2]]:3 -> [[@LINE+2]]:8 = 0
   // CHECK-NEXT: File 0, [[@LINE+1]]:8 -> [[@LINE+2]]:2 = 0
   WHILE
Index: clang/test/CoverageMapping/trycatch.cpp
===================================================================
--- clang/test/CoverageMapping/trycatch.cpp
+++ clang/test/CoverageMapping/trycatch.cpp
@@ -13,7 +13,7 @@
 void func(int i) {                    // CHECK-NEXT: File 0, [[@LINE]]:18 -> {{[0-9]+}}:2 = #0
                                       // CHECK-NEXT: File 0, [[@LINE+1]]:6 -> [[@LINE+1]]:11 = #0
   if(i % 2) {                         // CHECK: File 0, [[@LINE]]:13 -> [[@LINE+4]]:4 = #1
-    throw Error();
+    throw Error();                    // CHECK-NEXT: Gap,File 0, [[@LINE]]:19 -> [[@LINE+1]]:5 = 0
     int j = 0;                        // CHECK-NEXT: File 0, [[@LINE]]:5 -> [[@LINE+2]]:4 = 0
                                       // CHECK: File 0, [[@LINE+1]]:10 -> [[@LINE+2]]:27 = (#0 - #1)
   } else if(i == 8)                   // CHECK-NEXT: File 0, [[@LINE]]:13 -> [[@LINE]]:19 = (#0 - #1)
Index: clang/test/CoverageMapping/terminate-statements.cpp
===================================================================
--- /dev/null
+++ clang/test/CoverageMapping/terminate-statements.cpp
@@ -0,0 +1,130 @@
+// RUN: %clang_cc1 -mllvm -emptyline-comment-coverage=false -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -emit-llvm-only -main-file-name deferred-region.cpp -I %S/Inputs %s | FileCheck %s
+
+int f1() {
+  return 0;
+  return 0; // CHECK: Gap,File 0, [[@LINE-1]]:12 -> [[@LINE]]:3 = 0
+}
+
+int f2(int i) {
+  if (i)
+    return 0;
+  else
+    ;
+  return 1; // CHECK: Gap,File 0, [[@LINE-1]]:6 -> [[@LINE]]:3 = 0
+}
+
+int f3() {
+  for (int a = 1; a < 9; a--)
+    return a;
+  return 0; // CHECK: Gap,File 0, [[@LINE-1]]:14 -> [[@LINE]]:3 = 0
+}
+
+int f4(int i) {
+  while (i > 0) {
+    i++;
+    return i;
+  }
+  return 0; // CHECK: Gap,File 0, [[@LINE-1]]:4 -> [[@LINE]]:3 = 0
+}
+
+int f5(int i) {
+  do {
+    return i;
+  } while (i > 0);
+  return 0; // CHECK: Gap,File 0, [[@LINE-1]]:19 -> [[@LINE]]:3 = 0
+}
+
+int f6() {
+  int arr[] = {1, 2, 3, 4};
+  for (int i : arr) {
+    return i;
+  }
+  return 0; // CHECK: Gap,File 0, [[@LINE-1]]:4 -> [[@LINE]]:3 = 0
+}
+
+int f7() {
+  {
+    {
+      return 0;
+    }
+    return 0; // CHECK: Gap,File 0, [[@LINE-1]]:6 -> [[@LINE]]:5 = 0
+  }
+  return 0; // CHECK: Gap,File 0, [[@LINE-1]]:4 -> [[@LINE]]:3 = 0
+}
+
+int f8(int i) {
+  if (i == 1)
+    return 1;
+  if (i == 2) // CHECK: Gap,File 0, [[@LINE-1]]:14 -> [[@LINE]]:3 = 0
+    return 2;
+  if (i == 3) // CHECK: Gap,File 0, [[@LINE-1]]:14 -> [[@LINE]]:3 = 0
+    return 3;
+  return 4; // CHECK: Gap,File 0, [[@LINE-1]]:14 -> [[@LINE]]:3 = 0
+}
+
+int f9(int i) {
+  if (i == 1)
+    return 1;
+  else if (i == 2)
+    return 2;
+  return 3; // CHECK: Gap,File 0, [[@LINE-1]]:14 -> [[@LINE]]:3 = 0
+}
+
+int f10(int i) {
+  if (i == 1) {
+    return 0;
+    if (i == 2) // CHECK: Gap,File 0, [[@LINE-1]]:14 -> [[@LINE]]:5 = 0
+      return 0;
+  }
+  return 0; // CHECK: Gap,File 0, [[@LINE-1]]:4 -> [[@LINE]]:3 = 0
+}
+
+int f11(int i) {
+  if (i == 1)
+    i = 2;
+  else
+    return 0;
+  return 0; // CHECK: Gap,File 0, [[@LINE-1]]:14 -> [[@LINE]]:3 = 0
+}
+
+int f12(int i) {
+  int x = 1;
+  if (x == 1) {
+    if (x == 1) {
+      return 0;
+    }
+  } else if (x == 2) {
+    x = 2;
+  }
+  return 1; // CHECK: Gap,File 0, [[@LINE-1]]:4 -> [[@LINE]]:3 = 0
+}
+
+int f13(int i) {
+  if (i == 1) {
+    return 0;
+    if (i == 2) { // CHECK: Gap,File 0, [[@LINE-1]]:14 -> [[@LINE]]:5 = 0
+      i++;
+    }
+  }
+  return 0; // CHECK: Gap,File 0, [[@LINE-1]]:4 -> [[@LINE]]:3 = 0
+}
+
+int f14(int i) {
+  while (i == 0) {
+    while (i < 10) {
+      i++;
+      return 0;
+    }
+  }
+  return 0; // CHECK: Gap,File 0, [[@LINE-1]]:4 -> [[@LINE]]:3 = 0
+}
+
+int f15(int i) {
+  while (i == 0) {
+    return 0;
+    while (i < 10) { // CHECK: Gap,File 0, [[@LINE-1]]:14 -> [[@LINE]]:5 = 0
+      i++;
+    }
+  }
+  return 0; // CHECK: Gap,File 0, [[@LINE-1]]:4 -> [[@LINE]]:3 = 0
+}
Index: clang/test/CoverageMapping/switchmacro.c
===================================================================
--- clang/test/CoverageMapping/switchmacro.c
+++ clang/test/CoverageMapping/switchmacro.c
@@ -10,13 +10,13 @@
     if (i == 1)  // CHECK-NEXT: File 0, [[@LINE]]:9 -> [[@LINE]]:15 = #2
                  // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:9 -> [[@LINE-1]]:15 = #3, (#2 - #3)
       return 0;  // CHECK: File 0, [[@LINE]]:7 -> [[@LINE]]:15 = #3
-                 // CHECK-NEXT: File 0, [[@LINE-1]]:15 -> [[@LINE+3]]:5 = (#2 - #3)
+                 // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:16 -> [[@LINE+3]]:5 = 0
     // CHECK-NEXT: Expansion,File 0, [[@LINE+2]]:5 -> [[@LINE+2]]:8 = (#2 - #3) (Expanded file = 1)
     // CHECK-NEXT: File 0, [[@LINE+1]]:8 -> {{[0-9]+}}:11 = (#2 - #3)
     FOO(1);
   case 0:        // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+2]]:13 = ((#2 + #4) - #3)
                  // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #4, (#0 - #4)
-    return 2;    // CHECK-NEXT: Gap,File 0, [[@LINE]]:13 -> [[@LINE+6]]:3 = #5
+    return 2;    // CHECK-NEXT: Gap,File 0, [[@LINE]]:14 -> [[@LINE+4]]:3 = 0
 
   // CHECK-NEXT: Expansion,File 0, [[@LINE+2]]:3 -> [[@LINE+2]]:6 = 0
   // CHECK-NEXT: File 0, [[@LINE+1]]:6 -> {{[0-9]+}}:11 = 0
Index: clang/test/CoverageMapping/switch.cpp
===================================================================
--- clang/test/CoverageMapping/switch.cpp
+++ clang/test/CoverageMapping/switch.cpp
@@ -1,14 +1,16 @@
 // RUN: %clang_cc1 -mllvm -emptyline-comment-coverage=false -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -emit-llvm-only -std=c++1z -triple %itanium_abi_triple -main-file-name switch.cpp %s | FileCheck %s
 
 // CHECK: foo
-void foo(int i) {   // CHECK-NEXT: File 0, [[@LINE]]:17 -> [[@LINE+9]]:2 = #0
+void foo(int i) {   // CHECK-NEXT: File 0, [[@LINE]]:17 -> [[@LINE+11]]:2 = #0
   switch(i) {       // CHECK-NEXT: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:11 = ((#0 - #2) - #3), (#2 + #3)
-                    // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:13 -> [[@LINE+4]]:10 = 0
+                    // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:13 -> [[@LINE+5]]:10 = 0
   case 1:           // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+1]]:11 = #2
     return;         // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #2, (#0 - #2)
+                    // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:12 -> [[@LINE+1]]:3 = 0
   case 2:           // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+1]]:10 = #3
     break;          // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #3, (#0 - #3)
-  }                 // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:10 -> [[@LINE+1]]:3 = #1
+                    // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:10 -> [[@LINE+2]]:3 = #1
+  }                 // CHECK-NEXT: Gap,File 0, [[@LINE]]:4 -> [[@LINE+1]]:3 = 0
   int x = 0;        // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+1]]:2 = #1
 }
 
@@ -93,7 +95,7 @@
 
   case 1:            // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+1]]:13 = #2
     return 0;        // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #2, (#0 - #2)
-
+                     // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:14 -> [[@LINE+1]]:3 = 0
   default:           // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+1]]:13 = #3
     return 1;        // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:10 = #3, (#0 - #3)
   }
@@ -120,12 +122,14 @@
 
 void abort(void) __attribute((noreturn));
                    // CHECK: noret
-int noret(int x) { // CHECK-NEXT: File 0, [[@LINE]]:18 -> [[@LINE+9]]:2
-  switch (x) {     // CHECK-NEXT: Gap,File 0, [[@LINE]]:14 -> [[@LINE+6]]:14 = 0
+int noret(int x) { // CHECK-NEXT: File 0, [[@LINE]]:18 -> [[@LINE+11]]:2
+  switch (x) {     // CHECK-NEXT: Gap,File 0, [[@LINE]]:14 -> [[@LINE+8]]:14 = 0
   default:         // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+1]]:12
     abort();      // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:10 = #2, (#0 - #2)
+                  // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:13 -> [[@LINE+1]]:3 = 0
   case 1:         // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+1]]:13
     return 5;     // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #3, (#0 - #3)
+                  // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:14 -> [[@LINE+1]]:3 = 0
   case 2:         // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+1]]:14
     return 10;    // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #4, (#0 - #4)
   }
Index: clang/test/CoverageMapping/return.c
===================================================================
--- clang/test/CoverageMapping/return.c
+++ clang/test/CoverageMapping/return.c
@@ -2,7 +2,7 @@
 
 // CHECK: func
 void func() {                   // CHECK: File 0, [[@LINE]]:13 -> [[@LINE+3]]:2 = #0
-  return;
+  return;                       // CHECK-NEXT: Gap,File 0, [[@LINE]]:10 -> [[@LINE+1]]:3 = 0
   int i = 0;                    // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+1]]:2 = 0
 }
 
@@ -14,7 +14,7 @@
   for(int i = 0; i < 10; ++i) { // CHECK: File 0, [[@LINE]]:31 -> {{[0-9]+}}:4 = #1
                                 // CHECK-NEXT: File 0, [[@LINE+1]]:8 -> [[@LINE+1]]:13 = #1
     if(i > 2) {                 // CHECK: File 0, [[@LINE]]:15 -> [[@LINE+2]]:6 = #2
-      return;                   // CHECK-NEXT: File 0, [[@LINE+1]]:6 -> [[@LINE+3]]:5 = (#1 - #2)
+      return;                   // CHECK-NEXT: Gap,File 0, [[@LINE+1]]:6 -> [[@LINE+3]]:5 = 0
     }                           // CHECK-NEXT: File 0, [[@LINE+2]]:5 -> {{[0-9]+}}:4 = (#1 - #2)
                                 // CHECK-NEXT: File 0, [[@LINE+1]]:8 -> [[@LINE+1]]:14 = (#1 - #2)
     if(i == 3) {                // CHECK: File 0, [[@LINE]]:16 -> [[@LINE+2]]:6 = #3
@@ -28,13 +28,14 @@
                                // CHECK-NEXT: func3
 void func3(int x) {            // CHECK-NEXT: File 0, [[@LINE]]:19 -> {{[0-9]+}}:2 = #0
                                // CHECK-NEXT: File 0, [[@LINE+1]]:6 -> [[@LINE+1]]:11 = #0
-  if(x > 5) {                  // CHECK: File 0, [[@LINE]]:13 -> [[@LINE+6]]:4 = #1
+  if(x > 5) {                  // CHECK: File 0, [[@LINE]]:13 -> [[@LINE+7]]:4 = #1
     while(x >= 9) {            // CHECK-NEXT: File 0, [[@LINE]]:11 -> [[@LINE]]:17 = #1
-      return;                  // CHECK: File 0, [[@LINE-1]]:19 -> [[@LINE+2]]:6 = #2
+      return;                  // CHECK: File 0, [[@LINE-1]]:19 -> [[@LINE+3]]:6 = #2
+                               // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:14 -> [[@LINE+1]]:7 = 0
       --x;                     // CHECK-NEXT: File 0, [[@LINE]]:7 -> [[@LINE+1]]:6 = 0
-    }
+    }                          // CHECK-NEXT: Gap,File 0, [[@LINE]]:6 -> [[@LINE+1]]:5 = 0
     int i = 0;                 // CHECK-NEXT: File 0, [[@LINE]]:5 -> [[@LINE+1]]:4 = (#1 - #2)
-  }
+  }                            // CHECK-NEXT: Gap,File 0, [[@LINE]]:4 -> [[@LINE+1]]:3 = 0
   int j = 0;                   // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+1]]:2 = (#0 - #2)
 }
 
Index: clang/test/CoverageMapping/moremacros.c
===================================================================
--- clang/test/CoverageMapping/moremacros.c
+++ clang/test/CoverageMapping/moremacros.c
@@ -17,7 +17,7 @@
   if (!argc) LBRAC
     return 0;
   // CHECK-NEXT: Expansion,File 0, [[@LINE+1]]:3 -> [[@LINE+1]]:8 = #2
-  RBRAC // CHECK-NEXT: [[@LINE]]:8 -> [[@LINE+8]]:3 = (#0 - #2)
+  RBRAC // CHECK-NEXT: [[@LINE]]:8 -> [[@LINE+8]]:3 = 0
 
   // CHECK-NEXT: File 0, [[@LINE+6]]:3 -> [[@LINE+17]]:2 = (#0 - #2)
   // CHECK-NEXT: File 0, [[@LINE+5]]:7 -> [[@LINE+5]]:12 = (#0 - #2)
@@ -27,7 +27,7 @@
   // CHECK-NEXT: File 0, [[@LINE+1]]:19 -> [[@LINE+3]]:4 = #3
   if (!argc) LBRAC
     return 0;
-  } // CHECK-NEXT: [[@LINE]]:4 -> [[@LINE+5]]:3 = ((#0 - #2) - #3)
+  } // CHECK-NEXT: [[@LINE]]:4 -> [[@LINE+5]]:3 = 0
 
   // CHECK-NEXT: File 0, [[@LINE+3]]:3 -> [[@LINE+7]]:2 = ((#0 - #2) - #3)
   // CHECK-NEXT: File 0, [[@LINE+2]]:7 -> [[@LINE+2]]:12 = ((#0 - #2) - #3)
Index: clang/test/CoverageMapping/label.cpp
===================================================================
--- clang/test/CoverageMapping/label.cpp
+++ clang/test/CoverageMapping/label.cpp
@@ -13,10 +13,10 @@
           int j = 1;
       }
       int m = 2;
-    } else
-      goto x;                // CHECK: File 0, [[@LINE]]:7 -> [[@LINE]]:13 = (#1 - #2)
-    int k = 3;               // CHECK-NEXT: File 0, [[@LINE-1]]:13 -> [[@LINE]]:5 = #3
-  }                          // CHECK-NEXT: File 0, [[@LINE-1]]:5 -> [[@LINE]]:4 = #3
+    } else                   // CHECK: File 0, [[@LINE+1]]:7 -> [[@LINE+1]]:13 = (#1 - #2)
+      goto x;                // CHECK-NEXT: Gap,File 0, [[@LINE]]:14 -> [[@LINE+1]]:5 = 0
+    int k = 3;               // CHECK-NEXT: File 0, [[@LINE]]:5 -> [[@LINE+1]]:4 = #3
+  }                          // CHECK-NEXT: Gap,File 0, [[@LINE]]:4 -> [[@LINE+1]]:3 = 0
   static int j = 0;          // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+4]]:2 = ((#0 + #3) - #1)
   ++j;
   if(j == 1)                 // CHECK-NEXT: File 0, [[@LINE]]:6 -> [[@LINE]]:12 = ((#0 + #3) - #1)
@@ -27,9 +27,9 @@
 void test1(int x) {          // CHECK-NEXT: File 0, [[@LINE]]:19 -> {{[0-9]+}}:2 = #0
   if(x == 0)                 // CHECK-NEXT: File 0, [[@LINE]]:6 -> [[@LINE]]:12 = #0
     goto a;                  // CHECK: File 0, [[@LINE]]:5 -> [[@LINE]]:11 = #1
-                             // CHECK-NEXT: File 0, [[@LINE-1]]:11 -> [[@LINE+1]]:3 = (#0 - #1)
-  goto b;                    // CHECK: File 0, [[@LINE]]:3 -> [[@LINE+5]]:2 = (#0 - #1)
-                             // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:9 -> [[@LINE+1]]:1 = #2
+                             // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:12 -> [[@LINE+1]]:3 = 0
+  goto b;                    // CHECK: File 0, [[@LINE]]:3 -> [[@LINE]]:9 = (#0 - #1)
+                             // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:10 -> [[@LINE+1]]:1 = 0
 a:                           // CHECK-NEXT: File 0, [[@LINE]]:1 -> [[@LINE+3]]:2 = #2
 b:                           // CHECK-NEXT: File 0, [[@LINE]]:1 -> [[@LINE+2]]:2 = #3
   x = x + 1;
@@ -39,11 +39,11 @@
 void test2(int x) {          // CHECK-NEXT: File 0, [[@LINE]]:19 -> {{[0-9]+}}:2 = #0
   if(x == 0)                 // CHECK-NEXT: File 0, [[@LINE]]:6 -> [[@LINE]]:12 = #0
     goto a;                  // CHECK: File 0, [[@LINE]]:5 -> [[@LINE]]:11 = #1
-                             // CHECK: Gap,File 0, [[@LINE-1]]:12 -> [[@LINE+3]]:8 = (#0 - #1)
+                             // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:12 -> [[@LINE+3]]:8 = (#0 - #1)
                              // CHECK-NEXT: File 0, [[@LINE+2]]:8 -> [[@LINE+3]]:11 = (#0 - #1)
                              // CHECK-NEXT: File 0, [[@LINE+1]]:11 -> [[@LINE+1]]:17 = (#0 - #1)
   else if(x == 1)            // CHECK: File 0, [[@LINE+1]]:5 -> [[@LINE+1]]:11 = #2
-    goto b;                  // CHECK-NEXT: File 0, [[@LINE]]:11 -> [[@LINE+1]]:1 = #3
+    goto b;                  // CHECK-NEXT: Gap,File 0, [[@LINE]]:12 -> [[@LINE+1]]:1 = 0
 a:                           // CHECK-NEXT: File 0, [[@LINE]]:1 -> [[@LINE+3]]:2 = #3
 b:                           // CHECK-NEXT: File 0, [[@LINE]]:1 -> [[@LINE+2]]:2 = #4
   x = x + 1;
@@ -53,8 +53,8 @@
 #define a b
 void test3() {
   if (0)
-    goto b; // CHECK: Gap,File 0, [[@LINE]]:11 -> [[@LINE+1]]:1 = [[retnCount:#[0-9]+]]
-a: // CHECK-NEXT: Expansion,File 0, [[@LINE]]:1 -> [[@LINE]]:2 = [[retnCount]] (Expanded file = 1)
+    goto b; // CHECK: Gap,File 0, [[@LINE]]:12 -> [[@LINE+1]]:1 = 0
+a: // CHECK-NEXT: Expansion,File 0, [[@LINE]]:1 -> [[@LINE]]:2 = [[retnCount:#[0-9]+]] (Expanded file = 1)
   return; // CHECK-NEXT: File 0, [[@LINE-1]]:2 -> [[@LINE]]:9 = [[retnCount]]
 }
 #undef a
@@ -66,16 +66,16 @@
   a:                         // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+12]]:4 = #2
     if(i < 3)                // CHECK-NEXT: File 0, [[@LINE]]:8 -> [[@LINE]]:13 = #2
       goto e;                // CHECK: File 0, [[@LINE]]:7 -> [[@LINE]]:13 = #3
-                             // CHECK-NEXT: File 0, [[@LINE-1]]:13 -> [[@LINE+1]]:5 = (#2 - #3)
-    goto c;                  // CHECK-NEXT: File 0, [[@LINE]]:5 -> [[@LINE+8]]:4 = (#2 - #3)
-                             // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:11 -> [[@LINE+1]]:3 = #4
+                             // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:14 -> [[@LINE+1]]:5 = 0
+    goto c;                  // CHECK-NEXT: File 0, [[@LINE]]:5 -> [[@LINE]]:11 = (#2 - #3)
+                             // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:12 -> [[@LINE+1]]:3 = 0
   b:                         // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+6]]:4 = #4
     j = 2;
   c:                         // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+4]]:4 = #5
     j = 1;
                              // CHECK-NEXT: File 0, [[@LINE+1]]:3 -> [[@LINE+2]]:4 = #6
   e: f: ;                    // CHECK-NEXT: File 0, [[@LINE]]:6 -> [[@LINE+1]]:4 = #7
-  }
+  }                          // CHECK-NEXT: Gap,File 0, [[@LINE]]:4 -> [[@LINE+1]]:3 = 0
   func();                    // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+3]]:2 = ((#0 + #7) - #1)
   test1(0);
   test2(2);
Index: clang/test/CoverageMapping/deferred-region.cpp
===================================================================
--- clang/test/CoverageMapping/deferred-region.cpp
+++ clang/test/CoverageMapping/deferred-region.cpp
@@ -16,7 +16,7 @@
 void fooo(int x) {
   if (x == 0) {
     return;
-  } // CHECK: Gap,File 0, [[@LINE]]:4 -> [[@LINE+2]]:3 = (#0 - #1)
+  } // CHECK: Gap,File 0, [[@LINE]]:4 -> [[@LINE+2]]:3 = 0
 
   if (x == 1) {
     return;
@@ -32,7 +32,7 @@
 // CHECK-LABEL: _Z3mazv:
 void maz() {
   if (true)
-    return; // CHECK: Gap,File 0, [[@LINE]]:11 -> [[@LINE+2]]:3 = (#0 - #1)
+    return; // CHECK: Gap,File 0, [[@LINE]]:12 -> [[@LINE+2]]:3 = 0
 
   return; // CHECK-NOT: Gap
 }
@@ -40,7 +40,7 @@
 // CHECK-LABEL: _Z4maazv:
 void maaz() {
   if (true)
-    return; // CHECK: Gap,File 0, [[@LINE]]:11
+    return;
   else
     return; // CHECK-NOT: Gap,File 0, [[@LINE]]
 }
@@ -49,7 +49,7 @@
 void maaaz() {
   if (true) {
     return;
-  } else {  // CHECK: Gap,File 0, [[@LINE]]:4 -> [[@LINE]]:10
+  } else {
     return; // CHECK-NOT: Gap,File 0, [[@LINE]]
   }
 }
@@ -57,10 +57,10 @@
 // CHECK-LABEL: _Z3bari:
 void bar(int x) {
   IF (x)
-    return; // CHECK: Gap,File 0, [[@LINE]]:11 -> [[@LINE+2]]:3 = (#0 - #1)
+    return; // CHECK: Gap,File 0, [[@LINE]]:12 -> [[@LINE+2]]:3 = 0
 
   IF (!x)
-    return; // CHECK: Gap,File 0, [[@LINE]]:11 -> [[@LINE+2]]:3 = ((#0 - #1) - #2)
+    return; // CHECK: Gap,File 0, [[@LINE]]:12 -> [[@LINE+2]]:3 = 0
 
   foo(x);
 }
@@ -95,18 +95,18 @@
   int i = 0;
 
   if (false)
-    return; // CHECK: Gap,File 0, [[@LINE]]:11 -> [[@LINE+2]]:3 = (#0 - #1)
+    return; // CHECK: Gap,File 0, [[@LINE]]:12 -> [[@LINE+2]]:3 = 0
 
   if (false)
     i++;
 
   if (i + 100 > 0) { // CHECK: [[@LINE]]:20 -> [[@LINE+6]]:4 = #3
     if (false)       // CHECK: [[@LINE+1]]:7 -> [[@LINE+1]]:13 = #4
-      return;        // CHECK: Gap,File 0, [[@LINE]]:13 -> [[@LINE+2]]:5 = (#3 - #4)
-                     // CHECK: [[@LINE+1]]:5 -> [[@LINE+3]]:4 = (#3 - #4)
-    return;          // CHECK: Gap,File 0, [[@LINE]]:5 -> [[@LINE+4]]:3 = ((#0 - #1) - #3)
+      return;        // CHECK: Gap,File 0, [[@LINE]]:14 -> [[@LINE+2]]:5 = 0
+                     // CHECK: [[@LINE+1]]:5 -> [[@LINE+1]]:11 = (#3 - #4)
+    return;
 
-  }
+  }                  // CHECK: Gap,File 0, [[@LINE]]:4 -> [[@LINE+2]]:3 = 0
 
   if (false)
     return; // CHECK-NOT: Gap,File 0, [[@LINE]]:11
@@ -115,7 +115,7 @@
 // CHECK-LABEL: _Z8for_loopv:
 void for_loop() {
   if (false)
-    return; // CHECK: Gap,File 0, [[@LINE]]:11 -> [[@LINE+2]]:3 = (#0 - #1)
+    return; // CHECK: Gap,File 0, [[@LINE]]:12 -> [[@LINE+2]]:3 = 0
 
   for (int i = 0; i < 10; ++i) {
     if (i % 2 == 0)
@@ -135,7 +135,7 @@
 // CHECK-LABEL: _Z10while_loopv:
 void while_loop() {
   if (false)
-    return; // CHECK: Gap,File 0, [[@LINE]]:11 -> [[@LINE+2]]:3 = (#0 - #1)
+    return; // CHECK: Gap,File 0, [[@LINE]]:12 -> [[@LINE+2]]:3 = 0
 
   int x = 0;
   while (++x < 10) {
@@ -150,7 +150,7 @@
     }
 
     if (x == 0)
-      throw Error(); // CHECK: Gap,File 0, [[@LINE]]:20 -> [[@LINE+2]]:5 = ((#2 - #3) - #7)
+      throw Error(); // CHECK: Gap,File 0, [[@LINE]]:21 -> [[@LINE+2]]:5 = 0
 
     while (++x < 9) {
       if (x == 0)
@@ -163,9 +163,9 @@
 // CHECK-LABEL: _Z5gotosv:
 void gotos() {
   if (false)
-    goto out; // CHECK: Gap,File 0, [[@LINE]]:13 -> [[@LINE+2]]:3 = (#0 - #1)
+    goto out; // CHECK: Gap,File 0, [[@LINE]]:14 -> [[@LINE+2]]:3 = 0
 
-  return; // CHECK: [[@LINE]]:3 -> [[@LINE+4]]:2 = (#0 - #1)
+  return; // CHECK: [[@LINE]]:3 -> [[@LINE]]:9 = (#0 - #1)
 
 out:
 	return; // CHECK-NOT: Gap,File 0, [[@LINE]]:8
@@ -185,7 +185,7 @@
 #include "deferred-region-helper.h"
 // CHECK-LABEL: _Z13included_funcv:
 // CHECK:  Gap,File 0, 2:13 -> 3:5 = #1
-// CHECK:  Gap,File 0, 3:11 -> 4:3 = (#0 - #1)
+// CHECK:  Gap,File 0, 3:12 -> 4:3 = 0
 
 // CHECK-LABEL: _Z7includev:
 void include() {
Index: clang/test/CoverageMapping/coroutine.cpp
===================================================================
--- clang/test/CoverageMapping/coroutine.cpp
+++ clang/test/CoverageMapping/coroutine.cpp
@@ -44,5 +44,5 @@
   } else {            // CHECK-NEXT: File 0, [[@LINE-3]]:15 -> [[@LINE]]:4 = #1
     co_return x + 42; // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:4 -> [[@LINE-1]]:10 = (#0 - #1)
   }                   // CHECK-NEXT: File 0, [[@LINE-2]]:10 -> [[@LINE]]:4 = (#0 - #1)
-  co_return x;        // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:4 -> [[@LINE]]:3 = #1
-} // CHECK-NEXT: File 0, [[@LINE-1]]:3 -> [[@LINE]]:2 = #1
+  co_return x;        // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:4 -> [[@LINE]]:3 = 0
+} // CHECK-NEXT: File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:14 = #1
Index: clang/test/CoverageMapping/classtemplate.cpp
===================================================================
--- clang/test/CoverageMapping/classtemplate.cpp
+++ clang/test/CoverageMapping/classtemplate.cpp
@@ -80,7 +80,7 @@
 
 // CHECK-INIT-LIST-LABEL: _Z5Test4v:
 std::map<int, int> Test4() { // CHECK-INIT-LIST: File 0, [[@LINE]]:28 -> [[@LINE+3]]:2 = #0
-  abort();
+  abort();                           // CHECK-INIT-LIST-NEXT: Gap,File 0, [[@LINE]]:11 -> [[@LINE+1]]:3 = 0
   return std::map<int, int>{{0, 0}}; // CHECK-INIT-LIST-NEXT: [[@LINE]]:3 -> [[@LINE]]:36 = 0
 }
 
Index: clang/lib/CodeGen/CoverageMappingGen.cpp
===================================================================
--- clang/lib/CodeGen/CoverageMappingGen.cpp
+++ clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -556,8 +556,8 @@
   /// expressions cross file or macro boundaries.
   SourceLocation MostRecentLocation;
 
-  /// Location of the last terminated region.
-  Optional<std::pair<SourceLocation, size_t>> LastTerminatedRegion;
+  /// If there is a return, co_return, goto or throw inside.
+  bool HasTerminateStmt = false;
 
   /// Return a counter for the subtraction of \c RHS from \c LHS
   Counter subtractCounters(Counter LHS, Counter RHS) {
@@ -590,7 +590,6 @@
 
     if (StartLoc && !FalseCount.hasValue()) {
       MostRecentLocation = *StartLoc;
-      completeDeferred(Count, MostRecentLocation);
     }
 
     RegionStack.emplace_back(Count, FalseCount, StartLoc, EndLoc,
@@ -640,27 +639,6 @@
     return Index;
   }
 
-  /// Complete a deferred region created after a terminated region at the
-  /// top-level.
-  void completeTopLevelDeferredRegion(Counter Count,
-                                      SourceLocation DeferredEndLoc) {
-    if (DeferredRegion || !LastTerminatedRegion)
-      return;
-
-    if (LastTerminatedRegion->second != RegionStack.size())
-      return;
-
-    SourceLocation Start = LastTerminatedRegion->first;
-    if (SM.getFileID(Start) != SM.getMainFileID())
-      return;
-
-    SourceMappingRegion DR = RegionStack.back();
-    DR.setStartLoc(Start);
-    DR.setDeferred(false);
-    DeferredRegion = DR;
-    completeDeferred(Count, DeferredEndLoc);
-  }
-
   size_t locationDepth(SourceLocation Loc) {
     size_t Depth = 0;
     while (Loc.isValid()) {
@@ -764,12 +742,6 @@
         ParentOfDeferredRegion = true;
       }
       RegionStack.pop_back();
-
-      // If the zero region pushed after the last terminated region no longer
-      // exists, clear its cached information.
-      if (LastTerminatedRegion &&
-          RegionStack.size() < LastTerminatedRegion->second)
-        LastTerminatedRegion = None;
     }
     assert(!ParentOfDeferredRegion && "Deferred region with no parent");
   }
@@ -967,9 +939,10 @@
     if (!Region.hasEndLoc())
       Region.setEndLoc(EndLoc);
     pushRegion(Counter::getZero());
-    auto &ZeroRegion = getRegion();
-    ZeroRegion.setDeferred(true);
-    LastTerminatedRegion = {EndLoc, RegionStack.size()};
+    if (!HasTerminateStmt) {
+      auto &ZeroRegion = getRegion();
+      ZeroRegion.setDeferred(true);
+    }
   }
 
   /// Find a valid gap range between \p AfterLoc and \p BeforeLoc.
@@ -1004,7 +977,8 @@
     // file, the range may not be in source order.
     if (AfterLoc.isMacroID() || BeforeLoc.isMacroID())
       return None;
-    if (!SM.isWrittenInSameFile(AfterLoc, BeforeLoc))
+    if (!SM.isWrittenInSameFile(AfterLoc, BeforeLoc) ||
+        !SpellingRegion(SM, AfterLoc, BeforeLoc).isInSourceOrder())
       return None;
     return {{AfterLoc, BeforeLoc}};
   }
@@ -1056,9 +1030,31 @@
   void VisitStmt(const Stmt *S) {
     if (S->getBeginLoc().isValid())
       extendRegion(S);
+    const Stmt *LastStmt = nullptr;
+    bool LastStmtHasTerminateStmt = false;
+    bool SaveTerminateStmt = HasTerminateStmt;
+    HasTerminateStmt = false;
     for (const Stmt *Child : S->children())
-      if (Child)
+      if (Child) {
+        // If last statement contains terminate statements, add a gap area
+        // between the two statements. Skipping attributed statements, because
+        // they don't have valid start location.
+        if (LastStmt && LastStmtHasTerminateStmt &&
+            !dyn_cast<AttributedStmt>(Child)) {
+          auto Gap = findGapAreaBetween(getEnd(LastStmt), getStart(Child));
+          if (Gap)
+            fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(),
+                                 Counter::getZero());
+          LastStmtHasTerminateStmt = false;
+          SaveTerminateStmt = HasTerminateStmt;
+          HasTerminateStmt = false;
+        }
         this->Visit(Child);
+        LastStmt = Child;
+        LastStmtHasTerminateStmt = HasTerminateStmt;
+      }
+    if (SaveTerminateStmt)
+      HasTerminateStmt = true;
     handleFileExit(getEnd(S));
   }
 
@@ -1093,6 +1089,7 @@
     extendRegion(S);
     if (S->getRetValue())
       Visit(S->getRetValue());
+    HasTerminateStmt = true;
     terminateRegion(S);
   }
 
@@ -1105,6 +1102,7 @@
     extendRegion(S);
     if (S->getOperand())
       Visit(S->getOperand());
+    HasTerminateStmt = true;
     terminateRegion(S);
   }
 
@@ -1112,16 +1110,18 @@
     extendRegion(E);
     if (E->getSubExpr())
       Visit(E->getSubExpr());
+    HasTerminateStmt = true;
     terminateRegion(E);
   }
 
-  void VisitGotoStmt(const GotoStmt *S) { terminateRegion(S); }
+  void VisitGotoStmt(const GotoStmt *S) {
+    HasTerminateStmt = true;
+    terminateRegion(S);
+  }
 
   void VisitLabelStmt(const LabelStmt *S) {
     Counter LabelCount = getRegionCounter(S);
     SourceLocation Start = getStart(S);
-    completeTopLevelDeferredRegion(LabelCount, Start);
-    completeDeferred(LabelCount, Start);
     // We can't extendRegion here or we risk overlapping with our new region.
     handleFileExit(Start);
     pushRegion(LabelCount, Start);
@@ -1150,8 +1150,10 @@
     // Terminate the region when we hit a noreturn function.
     // (This is helpful dealing with switch statements.)
     QualType CalleeType = E->getCallee()->getType();
-    if (getFunctionExtInfo(*CalleeType).getNoReturn())
+    if (getFunctionExtInfo(*CalleeType).getNoReturn()) {
+      HasTerminateStmt = true;
       terminateRegion(E);
+    }
   }
 
   void VisitWhileStmt(const WhileStmt *S) {
@@ -1166,6 +1168,9 @@
     Counter BackedgeCount = propagateCounts(BodyCount, S->getBody());
     BreakContinue BC = BreakContinueStack.pop_back_val();
 
+    bool BodyHasTerminateStmt = HasTerminateStmt;
+    HasTerminateStmt = false;
+
     // Go back to handle the condition.
     Counter CondCount =
         addCounters(ParentCount, BackedgeCount, BC.ContinueCount);
@@ -1185,6 +1190,9 @@
     // Create Branch Region around condition.
     createBranchRegion(S->getCond(), BodyCount,
                        subtractCounters(CondCount, BodyCount));
+
+    if (BodyHasTerminateStmt)
+      HasTerminateStmt = true;
   }
 
   void VisitDoStmt(const DoStmt *S) {
@@ -1199,6 +1207,9 @@
         propagateCounts(addCounters(ParentCount, BodyCount), S->getBody());
     BreakContinue BC = BreakContinueStack.pop_back_val();
 
+    bool BodyHasTerminateStmt = HasTerminateStmt;
+    HasTerminateStmt = false;
+
     Counter CondCount = addCounters(BackedgeCount, BC.ContinueCount);
     propagateCounts(CondCount, S->getCond());
 
@@ -1210,6 +1221,9 @@
     // Create Branch Region around condition.
     createBranchRegion(S->getCond(), BodyCount,
                        subtractCounters(CondCount, BodyCount));
+
+    if (BodyHasTerminateStmt)
+      HasTerminateStmt = true;
   }
 
   void VisitForStmt(const ForStmt *S) {
@@ -1230,6 +1244,9 @@
     Counter BackedgeCount = propagateCounts(BodyCount, S->getBody());
     BreakContinue BodyBC = BreakContinueStack.pop_back_val();
 
+    bool BodyHasTerminateStmt = HasTerminateStmt;
+    HasTerminateStmt = false;
+
     // The increment is essentially part of the body but it needs to include
     // the count for all the continue statements.
     BreakContinue IncrementBC;
@@ -1260,6 +1277,9 @@
     // Create Branch Region around condition.
     createBranchRegion(S->getCond(), BodyCount,
                        subtractCounters(CondCount, BodyCount));
+
+    if (BodyHasTerminateStmt)
+      HasTerminateStmt = true;
   }
 
   void VisitCXXForRangeStmt(const CXXForRangeStmt *S) {
@@ -1277,6 +1297,9 @@
     Counter BackedgeCount = propagateCounts(BodyCount, S->getBody());
     BreakContinue BC = BreakContinueStack.pop_back_val();
 
+    bool BodyHasTerminateStmt = HasTerminateStmt;
+    HasTerminateStmt = false;
+
     // The body count applies to the area immediately after the range.
     auto Gap = findGapAreaBetween(S->getRParenLoc(), getStart(S->getBody()));
     if (Gap)
@@ -1292,6 +1315,9 @@
     // Create Branch Region around condition.
     createBranchRegion(S->getCond(), BodyCount,
                        subtractCounters(LoopCount, BodyCount));
+
+    if (BodyHasTerminateStmt)
+      HasTerminateStmt = true;
   }
 
   void VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S) {
@@ -1336,8 +1362,7 @@
         // the unreachable code at the beginning of the switch body.
         size_t Index = pushRegion(Counter::getZero(), getStart(CS));
         getRegion().setGap(true);
-        for (const auto *Child : CS->children())
-          Visit(Child);
+        Visit(Body);
 
         // Set the end for the body of the switch, if it isn't already set.
         for (size_t i = RegionStack.size(); i != Index; --i) {
@@ -1435,12 +1460,18 @@
 
     Counter ElseCount = subtractCounters(ParentCount, ThenCount);
     if (const Stmt *Else = S->getElse()) {
+      bool ThenHasTerminateStmt = HasTerminateStmt;
+      HasTerminateStmt = false;
+
       // The 'else' count applies to the area immediately after the 'then'.
       Gap = findGapAreaBetween(getEnd(S->getThen()), getStart(Else));
       if (Gap)
         fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), ElseCount);
       extendRegion(Else);
       OutCount = addCounters(OutCount, propagateCounts(ElseCount, Else));
+
+      if (ThenHasTerminateStmt)
+        HasTerminateStmt = true;
     } else
       OutCount = addCounters(OutCount, ElseCount);
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to