From 54657e3db73cad36112c1a6e72d440f98eccba05 Mon Sep 17 00:00:00 2001
From: Eli Friedman <efriedma@codeaurora.org>
Date: Thu, 3 Aug 2017 22:27:36 +0000
Subject: [PATCH] [coverage] Special-case calls to noreturn functions.

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).

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



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@309995 91177308-0d34-0410-b5e6-96231b3b80d8
---
 lib/CodeGen/CoverageMappingGen.cpp | 12 ++++++++++++
 test/CoverageMapping/switch.cpp    | 13 +++++++++++++
 2 files changed, 25 insertions(+)

diff --git a/lib/CodeGen/CoverageMappingGen.cpp b/lib/CodeGen/CoverageMappingGen.cpp
index 1484ec78b88..28aabd0f071 100644
--- a/lib/CodeGen/CoverageMappingGen.cpp
+++ b/lib/CodeGen/CoverageMappingGen.cpp
@@ -716,6 +716,18 @@ struct CounterCoverageMappingBuilder
     terminateRegion(S);
   }
 
+  void VisitCallExpr(const CallExpr *E) {
+    extendRegion(E);
+    for (const Stmt *Child : E->children())
+      this->Visit(Child);
+
+    // 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);
 
diff --git a/test/CoverageMapping/switch.cpp b/test/CoverageMapping/switch.cpp
index 17aa53bb486..52f22e8eda1 100644
--- a/test/CoverageMapping/switch.cpp
+++ b/test/CoverageMapping/switch.cpp
@@ -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;
+  }
+}
-- 
GitLab