diff options
author | Eli Friedman <efriedma@codeaurora.org> | 2017-08-03 22:27:36 +0000 |
---|---|---|
committer | Eli Friedman <efriedma@codeaurora.org> | 2017-08-03 22:27:36 +0000 |
commit | 54657e3db73cad36112c1a6e72d440f98eccba05 (patch) | |
tree | 14b8ff0a682fbc6ee20e344e0dadae5a3f7e048c | |
parent | 764e1d8251b12447aee69092a851e46c0eb63c7d (diff) |
[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
-rw-r--r-- | lib/CodeGen/CoverageMappingGen.cpp | 12 | ||||
-rw-r--r-- | test/CoverageMapping/switch.cpp | 13 |
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; + } +} |