summaryrefslogtreecommitdiffstats
path: root/lib/CodeGen/CoverageMappingGen.cpp
diff options
context:
space:
mode:
authorVedant Kumar <vsk@apple.com>2017-10-17 07:47:39 +0000
committerVedant Kumar <vsk@apple.com>2017-10-17 07:47:39 +0000
commitfe8249cb5c936a6f1c0990923044319d283a9624 (patch)
tree5a20229554bc75a324af673dd3b6d5b3a9f19b78 /lib/CodeGen/CoverageMappingGen.cpp
parent762d1e77cbcec32f272b58e412d4bca839626f95 (diff)
[Coverage] Discard deferred region in closing if-else
A trailing deferred region isn't necessary in a function that ends with this pattern: ... else { ... return; } Special-case this pattern so that the closing curly brace of the function isn't marked as uncovered. This issue came up in PR34962. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@315982 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CoverageMappingGen.cpp')
-rw-r--r--lib/CodeGen/CoverageMappingGen.cpp30
1 files changed, 23 insertions, 7 deletions
diff --git a/lib/CodeGen/CoverageMappingGen.cpp b/lib/CodeGen/CoverageMappingGen.cpp
index 15c81945e0..08b8c2ec54 100644
--- a/lib/CodeGen/CoverageMappingGen.cpp
+++ b/lib/CodeGen/CoverageMappingGen.cpp
@@ -758,6 +758,22 @@ struct CounterCoverageMappingBuilder
handleFileExit(getEnd(S));
}
+ /// Determine whether the final deferred region emitted in \p Body should be
+ /// discarded.
+ static bool discardFinalDeferredRegionInDecl(Stmt *Body) {
+ if (auto *CS = dyn_cast<CompoundStmt>(Body)) {
+ Stmt *LastStmt = CS->body_back();
+ if (auto *IfElse = dyn_cast<IfStmt>(LastStmt)) {
+ if (auto *Else = dyn_cast_or_null<CompoundStmt>(IfElse->getElse()))
+ LastStmt = Else->body_back();
+ else
+ LastStmt = IfElse->getElse();
+ }
+ return dyn_cast_or_null<ReturnStmt>(LastStmt);
+ }
+ return false;
+ }
+
void VisitDecl(const Decl *D) {
assert(!DeferredRegion && "Deferred region never completed");
@@ -770,14 +786,14 @@ struct CounterCoverageMappingBuilder
Counter ExitCount = propagateCounts(getRegionCounter(Body), Body);
assert(RegionStack.empty() && "Regions entered but never exited");
- // Special case: if the last statement is a return, throw away the
- // deferred region. This allows the closing brace to have a count.
- if (auto *CS = dyn_cast_or_null<CompoundStmt>(Body))
- if (dyn_cast_or_null<ReturnStmt>(CS->body_back()))
+ if (DeferredRegion) {
+ // Complete (or discard) any deferred regions introduced by the last
+ // statement.
+ if (discardFinalDeferredRegionInDecl(Body))
DeferredRegion = None;
-
- // Complete any deferred regions introduced by the last statement.
- popRegions(completeDeferred(ExitCount, getEnd(Body)));
+ else
+ popRegions(completeDeferred(ExitCount, getEnd(Body)));
+ }
}
void VisitReturnStmt(const ReturnStmt *S) {