]> granicus.if.org Git - clang/commitdiff
[coverage] Special-case calls to noreturn functions.
authorEli Friedman <efriedma@codeaurora.org>
Tue, 8 Aug 2017 20:10:14 +0000 (20:10 +0000)
committerEli Friedman <efriedma@codeaurora.org>
Tue, 8 Aug 2017 20:10:14 +0000 (20:10 +0000)
The code after a noreturn call doesn't execute.

The pattern in the testcase is pretty common in LLVM (a switch with
a default case that calls llvm_unreachable).

The original version of this patch was reverted in r309995 due to a
crash. This version includes a fix for that crash (testcase in
test/CoverageMapping/md.cpp).

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

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

lib/CodeGen/CoverageMappingGen.cpp
test/CoverageMapping/md.cpp
test/CoverageMapping/switch.cpp

index 1484ec78b88638c88222ebfc187b2fd50f56c96d..f2e051c615b52f003805de743d26a4d0ee63b768 100644 (file)
@@ -716,6 +716,16 @@ struct CounterCoverageMappingBuilder
     terminateRegion(S);
   }
 
+  void VisitCallExpr(const CallExpr *E) {
+    VisitStmt(E);
+
+    // 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())
+      terminateRegion(E);
+  }
+
   void VisitWhileStmt(const WhileStmt *S) {
     extendRegion(S);
 
index 20c696c7dfbba52b8313a2c4e68c6bd66809d705..5f2b2d61224fbb0c04fdcfec21cb8ed87d2ee90a 100644 (file)
@@ -27,6 +27,17 @@ void foo(MD i) {
   #include "Inputs/md.def"
 }
 
+// CHECK: bar
+// CHECK-NEXT: File 0, [[@LINE+3]]:12 -> [[@LINE+8]]:2 = #0
+bool isVal1();
+bool isVal2();
+bool bar() {
+ #define HANDLE_MD(X) is##X() ||
+  return
+#include "Inputs/md.def"
+  0;
+}
+
 int main(int argc, const char *argv[]) {
   foo(MD::Val1);
   return 0;
index 17aa53bb48600231fb7cc570c7c1cf695d2d4237..52f22e8eda1fe8ae07188734ad47592d75f29a4f 100644 (file)
@@ -97,3 +97,16 @@ int fallthrough(int i) { // CHECK-NEXT: File 0, [[@LINE]]:24 -> [[@LINE+12]]:2 =
     break;
   }
 }
+
+void abort(void) __attribute((noreturn));
+                   // CHECK: noret
+int noret(int x) { // CHECK-NEXT: File 0, [[@LINE]]:18 -> [[@LINE+9]]:2
+  switch (x) {
+  default:         // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+1]]:12
+    abort();
+  case 1:         // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+1]]:13
+    return 5;
+  case 2:         // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+1]]:14
+    return 10;
+  }
+}