diff options
author | Vedant Kumar <vsk@apple.com> | 2017-10-17 07:47:39 +0000 |
---|---|---|
committer | Vedant Kumar <vsk@apple.com> | 2017-10-17 07:47:39 +0000 |
commit | fe8249cb5c936a6f1c0990923044319d283a9624 (patch) | |
tree | 5a20229554bc75a324af673dd3b6d5b3a9f19b78 /lib/CodeGen/CoverageMappingGen.cpp | |
parent | 762d1e77cbcec32f272b58e412d4bca839626f95 (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.cpp | 30 |
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) { |