diff options
Diffstat (limited to 'clang/lib/CodeGen/CoverageMappingGen.cpp')
-rw-r--r-- | clang/lib/CodeGen/CoverageMappingGen.cpp | 22 |
1 files changed, 19 insertions, 3 deletions
diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp index 820ba1b..d3fd19c 100644 --- a/clang/lib/CodeGen/CoverageMappingGen.cpp +++ b/clang/lib/CodeGen/CoverageMappingGen.cpp @@ -443,15 +443,31 @@ struct CounterCoverageMappingBuilder return ExitCount; } + /// \brief Check whether a region with bounds \c StartLoc and \c EndLoc + /// is already added to \c SourceRegions. + bool isRegionAlreadyAdded(SourceLocation StartLoc, SourceLocation EndLoc) { + return SourceRegions.rend() != + std::find_if(SourceRegions.rbegin(), SourceRegions.rend(), + [&](const SourceMappingRegion &Region) { + return Region.getStartLoc() == StartLoc && + Region.getEndLoc() == EndLoc; + }); + } + /// \brief Adjust the most recently visited location to \c EndLoc. /// /// This should be used after visiting any statements in non-source order. void adjustForOutOfOrderTraversal(SourceLocation EndLoc) { MostRecentLocation = EndLoc; - // Avoid adding duplicate regions if we have a completed region on the top - // of the stack and are adjusting to the end of a virtual file. + // The code region for a whole macro is created in handleFileExit() when + // it detects exiting of the virtual file of that macro. If we visited + // statements in non-source order, we might already have such a region + // added, for example, if a body of a loop is divided among multiple + // macros. Avoid adding duplicate regions in such case. if (getRegion().hasEndLoc() && - MostRecentLocation == getEndOfFileOrMacro(MostRecentLocation)) + MostRecentLocation == getEndOfFileOrMacro(MostRecentLocation) && + isRegionAlreadyAdded(getStartOfFileOrMacro(MostRecentLocation), + MostRecentLocation)) MostRecentLocation = getIncludeOrExpansionLoc(MostRecentLocation); } |