diff options
-rw-r--r-- | clang/lib/CodeGen/CoverageMappingGen.cpp | 41 | ||||
-rw-r--r-- | clang/test/CoverageMapping/label.cpp | 6 | ||||
-rw-r--r-- | clang/test/CoverageMapping/switchmacro.c | 2 |
3 files changed, 42 insertions, 7 deletions
diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp index 2b6e6deb554..26236b72ff7 100644 --- a/clang/lib/CodeGen/CoverageMappingGen.cpp +++ b/clang/lib/CodeGen/CoverageMappingGen.cpp @@ -445,6 +445,9 @@ struct CounterCoverageMappingBuilder /// expressions cross file or macro boundaries. SourceLocation MostRecentLocation; + /// Location of the last terminated region. + Optional<std::pair<SourceLocation, size_t>> LastTerminatedRegion; + /// \brief Return a counter for the subtraction of \c RHS from \c LHS Counter subtractCounters(Counter LHS, Counter RHS) { return Builder.subtract(LHS, RHS); @@ -520,6 +523,27 @@ struct CounterCoverageMappingBuilder return Index; } + /// Complete a deferred region created after a terminated region at the + /// top-level. + void completeTopLevelDeferredRegion(Counter Count, + SourceLocation DeferredEndLoc) { + if (DeferredRegion || !LastTerminatedRegion) + return; + + if (LastTerminatedRegion->second != RegionStack.size()) + return; + + SourceLocation Start = LastTerminatedRegion->first; + if (SM.getFileID(Start) != SM.getMainFileID()) + return; + + SourceMappingRegion DR = RegionStack.back(); + DR.setStartLoc(Start); + DR.setDeferred(false); + DeferredRegion = DR; + completeDeferred(Count, DeferredEndLoc); + } + /// \brief Pop regions from the stack into the function's list of regions. /// /// Adds all regions from \c ParentIndex to the top of the stack to the @@ -576,6 +600,12 @@ struct CounterCoverageMappingBuilder ParentOfDeferredRegion = true; } RegionStack.pop_back(); + + // If the zero region pushed after the last terminated region no longer + // exists, clear its cached information. + if (LastTerminatedRegion && + RegionStack.size() < LastTerminatedRegion->second) + LastTerminatedRegion = None; } assert(!ParentOfDeferredRegion && "Deferred region with no parent"); } @@ -712,10 +742,13 @@ struct CounterCoverageMappingBuilder void terminateRegion(const Stmt *S) { extendRegion(S); SourceMappingRegion &Region = getRegion(); + SourceLocation EndLoc = getEnd(S); if (!Region.hasEndLoc()) - Region.setEndLoc(getEnd(S)); + Region.setEndLoc(EndLoc); pushRegion(Counter::getZero()); - getRegion().setDeferred(true); + auto &ZeroRegion = getRegion(); + ZeroRegion.setDeferred(true); + LastTerminatedRegion = {EndLoc, RegionStack.size()}; } /// Emit a gap region between \p StartLoc and \p EndLoc with the given count. @@ -826,10 +859,12 @@ struct CounterCoverageMappingBuilder void VisitGotoStmt(const GotoStmt *S) { terminateRegion(S); } void VisitLabelStmt(const LabelStmt *S) { + Counter LabelCount = getRegionCounter(S); SourceLocation Start = getStart(S); + completeTopLevelDeferredRegion(LabelCount, Start); // We can't extendRegion here or we risk overlapping with our new region. handleFileExit(Start); - pushRegion(getRegionCounter(S), Start); + pushRegion(LabelCount, Start); Visit(S->getSubStmt()); } diff --git a/clang/test/CoverageMapping/label.cpp b/clang/test/CoverageMapping/label.cpp index 6e8a078fe6c..a0bd4fd352c 100644 --- a/clang/test/CoverageMapping/label.cpp +++ b/clang/test/CoverageMapping/label.cpp @@ -28,8 +28,8 @@ void test1(int x) { // CHECK-NEXT: File 0, [[@LINE]]:19 -> {{[0-9]+}}:2 if(x == 0) // CHECK-NEXT: File 0, [[@LINE]]:6 -> [[@LINE]]:12 = #0 goto a; // CHECK: File 0, [[@LINE]]:5 -> [[@LINE]]:11 = #1 // CHECK-NEXT: File 0, [[@LINE-1]]:11 -> [[@LINE+1]]:3 = (#0 - #1) - goto b; // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+5]]:2 = (#0 - #1) - // CHECK-NEXT: File 0, [[@LINE-1]]:3 -> [[@LINE+4]]:2 = #3 + goto b; // CHECK: Gap,File 0, [[@LINE]]:3 -> [[@LINE+5]]:2 = #3 + // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:9 -> [[@LINE+1]]:1 = #2 a: // CHECK-NEXT: File 0, [[@LINE]]:1 -> [[@LINE+3]]:2 = #2 b: // CHECK-NEXT: File 0, [[@LINE]]:1 -> [[@LINE+2]]:2 = #3 x = x + 1; @@ -58,7 +58,7 @@ int main() { // CHECK-NEXT: File 0, [[@LINE]]:12 -> {{[0-9]+}}:2 goto e; // CHECK: File 0, [[@LINE]]:7 -> [[@LINE]]:13 = #3 // CHECK-NEXT: File 0, [[@LINE-1]]:13 -> [[@LINE+1]]:5 = (#2 - #3) goto c; // CHECK-NEXT: File 0, [[@LINE]]:5 -> [[@LINE+8]]:4 = (#2 - #3) - + // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:11 -> [[@LINE+1]]:3 = #4 b: // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+6]]:4 = #4 j = 2; c: // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+4]]:4 = #5 diff --git a/clang/test/CoverageMapping/switchmacro.c b/clang/test/CoverageMapping/switchmacro.c index 29f99af697d..f4c14f798f0 100644 --- a/clang/test/CoverageMapping/switchmacro.c +++ b/clang/test/CoverageMapping/switchmacro.c @@ -13,7 +13,7 @@ int foo(int i) { // CHECK-NEXT: File 0, [[@LINE]]:16 -> {{[0-9]+}}:2 = #0 // CHECK-NEXT: File 0, [[@LINE+1]]:8 -> {{[0-9]+}}:11 = (#2 - #3) FOO(1); case 0: // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+1]]:13 = ((#2 + #4) - #3) - return 2; + return 2; // CHECK-NEXT: Gap,File 0, [[@LINE]]:13 -> [[@LINE+6]]:3 = #5 // CHECK-NEXT: Expansion,File 0, [[@LINE+2]]:3 -> [[@LINE+2]]:6 = 0 // CHECK-NEXT: File 0, [[@LINE+1]]:6 -> {{[0-9]+}}:11 = 0 |