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 | 341bf4299182938ba021acfac82b8e7845a65f1f (patch) | |
tree | 1f93d70eb1d7b2e459a7b1b47b9b5985fd8d7cb7 /clang/lib/CodeGen/CoverageMappingGen.cpp | |
parent | e5f06a81a870a6c3e1caa5203d9fceed45c1d0e1 (diff) | |
download | bcm5719-llvm-341bf4299182938ba021acfac82b8e7845a65f1f.tar.gz bcm5719-llvm-341bf4299182938ba021acfac82b8e7845a65f1f.zip |
[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.
llvm-svn: 315982
Diffstat (limited to 'clang/lib/CodeGen/CoverageMappingGen.cpp')
-rw-r--r-- | clang/lib/CodeGen/CoverageMappingGen.cpp | 30 |
1 files changed, 23 insertions, 7 deletions
diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp index 15c81945e0b..08b8c2ec544 100644 --- a/clang/lib/CodeGen/CoverageMappingGen.cpp +++ b/clang/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) { |