diff options
Diffstat (limited to 'clang/lib/CodeGen/CoverageMappingGen.cpp')
-rw-r--r-- | clang/lib/CodeGen/CoverageMappingGen.cpp | 28 |
1 files changed, 23 insertions, 5 deletions
diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp index 080525c8e6c..e008f44fc6f 100644 --- a/clang/lib/CodeGen/CoverageMappingGen.cpp +++ b/clang/lib/CodeGen/CoverageMappingGen.cpp @@ -92,6 +92,14 @@ public: /// \brief The source mapping regions for this function. std::vector<SourceMappingRegion> SourceRegions; + /// \brief A set of regions which can be used as a filter. + /// + /// It is produced by emitExpansionRegions() and is used in + /// emitSourceRegions() to suppress producing code regions if + /// the same area is covered by expansion regions. + typedef llvm::SmallSet<std::pair<SourceLocation, SourceLocation>, 8> + SourceRegionFilter; + CoverageMappingBuilder(CoverageMappingModuleGen &CVM, SourceManager &SM, const LangOptions &LangOpts) : CVM(CVM), SM(SM), LangOpts(LangOpts) {} @@ -249,7 +257,7 @@ public: /// \brief Generate the coverage counter mapping regions from collected /// source regions. - void emitSourceRegions() { + void emitSourceRegions(const SourceRegionFilter &Filter) { for (const auto &Region : SourceRegions) { assert(Region.hasEndLoc() && "incomplete region"); @@ -269,6 +277,13 @@ public: assert(SM.isWrittenInSameFile(LocStart, LocEnd) && "region spans multiple files"); + // Don't add code regions for the area covered by expansion regions. + // This not only suppresses redundant regions, but sometimes prevents + // creating regions with wrong counters if, for example, a statement's + // body ends at the end of a nested macro. + if (Filter.count(std::make_pair(LocStart, LocEnd))) + continue; + // Find the spilling locations for the mapping region. unsigned LineStart = SM.getSpellingLineNumber(LocStart); unsigned ColumnStart = SM.getSpellingColumnNumber(LocStart); @@ -283,7 +298,8 @@ public: } /// \brief Generate expansion regions for each virtual file we've seen. - void emitExpansionRegions() { + SourceRegionFilter emitExpansionRegions() { + SourceRegionFilter Filter; for (const auto &FM : FileIDMapping) { SourceLocation ExpandedLoc = FM.second.second; SourceLocation ParentLoc = getIncludeOrExpansionLoc(ExpandedLoc); @@ -299,6 +315,7 @@ public: SourceLocation LocEnd = getPreciseTokenLocEnd(ParentLoc); assert(SM.isWrittenInSameFile(ParentLoc, LocEnd) && "region spans multiple files"); + Filter.insert(std::make_pair(ParentLoc, LocEnd)); unsigned LineStart = SM.getSpellingLineNumber(ParentLoc); unsigned ColumnStart = SM.getSpellingColumnNumber(ParentLoc); @@ -309,6 +326,7 @@ public: *ParentFileID, *ExpandedFileID, LineStart, ColumnStart, LineEnd, ColumnEnd)); } + return Filter; } }; @@ -350,7 +368,7 @@ struct EmptyCoverageMappingBuilder : public CoverageMappingBuilder { void write(llvm::raw_ostream &OS) { SmallVector<unsigned, 16> FileIDMapping; gatherFileIDs(FileIDMapping); - emitSourceRegions(); + emitSourceRegions(SourceRegionFilter()); if (MappingRegions.empty()) return; @@ -605,8 +623,8 @@ struct CounterCoverageMappingBuilder void write(llvm::raw_ostream &OS) { llvm::SmallVector<unsigned, 8> VirtualFileMapping; gatherFileIDs(VirtualFileMapping); - emitSourceRegions(); - emitExpansionRegions(); + SourceRegionFilter Filter = emitExpansionRegions(); + emitSourceRegions(Filter); gatherSkippedRegions(); if (MappingRegions.empty()) |