diff options
author | Vedant Kumar <vsk@apple.com> | 2017-11-09 02:33:39 +0000 |
---|---|---|
committer | Vedant Kumar <vsk@apple.com> | 2017-11-09 02:33:39 +0000 |
commit | 1d4f0c6913374711c79d2c08bddf7c0bd86617cd (patch) | |
tree | d43299f884d4c1752b244be42b7872901a4094ad /lib/CodeGen/CoverageMappingGen.cpp | |
parent | 04811d180e622d85a8a6b878f59a61967a12add1 (diff) |
[Coverage] Complete top-level deferred regions before labels
The area immediately after a terminated region in the function top-level
should have the same count as the label it precedes.
This solves another problem with wrapped segments. Consider:
1| a:
2| return 0;
3| b:
4| return 1;
Without a gap area starting after the first return, the wrapped segment
from line 2 would make it look like line 3 is executed, when it's not.
rdar://35373009
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@317759 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CoverageMappingGen.cpp')
-rw-r--r-- | lib/CodeGen/CoverageMappingGen.cpp | 41 |
1 files changed, 38 insertions, 3 deletions
diff --git a/lib/CodeGen/CoverageMappingGen.cpp b/lib/CodeGen/CoverageMappingGen.cpp index 2b6e6deb55..26236b72ff 100644 --- a/lib/CodeGen/CoverageMappingGen.cpp +++ b/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()); } |