From: Vedant Kumar Date: Tue, 17 Oct 2017 07:47:39 +0000 (+0000) Subject: [Coverage] Discard deferred region in closing if-else X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=fe8249cb5c936a6f1c0990923044319d283a9624;p=clang [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 --- 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(Body)) { + Stmt *LastStmt = CS->body_back(); + if (auto *IfElse = dyn_cast(LastStmt)) { + if (auto *Else = dyn_cast_or_null(IfElse->getElse())) + LastStmt = Else->body_back(); + else + LastStmt = IfElse->getElse(); + } + return dyn_cast_or_null(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(Body)) - if (dyn_cast_or_null(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) { diff --git a/test/CoverageMapping/deferred-region.cpp b/test/CoverageMapping/deferred-region.cpp index 743b635a90..3504588a6c 100644 --- a/test/CoverageMapping/deferred-region.cpp +++ b/test/CoverageMapping/deferred-region.cpp @@ -31,11 +31,28 @@ void baz() { // CHECK: [[@LINE]]:12 -> [[@LINE+2]]:2 // CHECK-LABEL: _Z3mazv: void maz() { if (true) - return; // CHECK: Gap,File 0, [[@LINE]]:11 -> 36:3 = (#0 - #1) + return; // CHECK: Gap,File 0, [[@LINE]]:11 -> [[@LINE+2]]:3 = (#0 - #1) return; // CHECK-NOT: Gap } +// CHECK-LABEL: _Z4maazv: +void maaz() { + if (true) + return; // CHECK: Gap,File 0, [[@LINE]]:11 + else + return; // CHECK-NOT: Gap,File 0, [[@LINE]] +} + +// CHECK-LABEL: _Z5maaazv: +void maaaz() { + if (true) { + return; + } else { // CHECK: Gap,File 0, [[@LINE]]:4 -> [[@LINE]]:10 + return; // CHECK-NOT: Gap,File 0, [[@LINE]] + } +} + // CHECK-LABEL: _Z3bari: void bar(int x) { IF (x) @@ -158,6 +175,9 @@ int main() { foo(1); fooo(0); fooo(1); + maz(); + maaz(); + maaaz(); baz(); bar(0); bar(1);