summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/CodeGen/CoverageMappingGen.cpp12
-rw-r--r--test/CoverageMapping/switch.cpp13
2 files changed, 25 insertions, 0 deletions
diff --git a/lib/CodeGen/CoverageMappingGen.cpp b/lib/CodeGen/CoverageMappingGen.cpp
index 1484ec78b8..28aabd0f07 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 17aa53bb48..52f22e8eda 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;
+ }
+}