diff --git a/clang/include/clang/Lex/PPCallbacks.h b/clang/include/clang/Lex/PPCallbacks.h --- a/clang/include/clang/Lex/PPCallbacks.h +++ b/clang/include/clang/Lex/PPCallbacks.h @@ -319,6 +319,10 @@ virtual void SourceRangeSkipped(SourceRange Range, SourceLocation EndifLoc) { } + /// Hood called when the source range is comment, which should be skipped. + /// \param Range The SourceRange that is comment. + virtual void CommentSkipped(SourceRange Range) {} + enum ConditionValueKind { CVK_NotEvaluated, CVK_False, CVK_True }; @@ -565,6 +569,11 @@ Second->SourceRangeSkipped(Range, EndifLoc); } + void CommentSkipped(SourceRange Range) override { + First->CommentSkipped(Range); + Second->CommentSkipped(Range); + } + /// Hook called whenever an \#if is seen. void If(SourceLocation Loc, SourceRange ConditionRange, ConditionValueKind ConditionValue) override { diff --git a/clang/lib/CodeGen/CoverageMappingGen.h b/clang/lib/CodeGen/CoverageMappingGen.h --- a/clang/lib/CodeGen/CoverageMappingGen.h +++ b/clang/lib/CodeGen/CoverageMappingGen.h @@ -38,6 +38,8 @@ ArrayRef getSkippedRanges() const { return SkippedRanges; } void SourceRangeSkipped(SourceRange Range, SourceLocation EndifLoc) override; + + void CommentSkipped(SourceRange Range) override; }; namespace CodeGen { diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp --- a/clang/lib/CodeGen/CoverageMappingGen.cpp +++ b/clang/lib/CodeGen/CoverageMappingGen.cpp @@ -39,6 +39,10 @@ SkippedRanges.push_back(Range); } +void CoverageSourceInfo::CommentSkipped(SourceRange Range) { + SkippedRanges.push_back(Range); +} + namespace { /// A region of source code that can be mapped to a counter. diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp --- a/clang/lib/Parse/Parser.cpp +++ b/clang/lib/Parse/Parser.cpp @@ -34,6 +34,7 @@ explicit ActionCommentHandler(Sema &S) : S(S) { } bool HandleComment(Preprocessor &PP, SourceRange Comment) override { + PP.getPPCallbacks()->CommentSkipped(Comment); S.ActOnComment(Comment); return false; } diff --git a/llvm/lib/ProfileData/Coverage/CoverageMappingWriter.cpp b/llvm/lib/ProfileData/Coverage/CoverageMappingWriter.cpp --- a/llvm/lib/ProfileData/Coverage/CoverageMappingWriter.cpp +++ b/llvm/lib/ProfileData/Coverage/CoverageMappingWriter.cpp @@ -148,6 +148,41 @@ encodeULEB128(encodeCounter(Expressions, C), OS); } +static MutableArrayRef +mergeSkippedRegions(MutableArrayRef MappingRegions) { + SmallVector MergedRegions; + for (size_t I = 0; I < MappingRegions.size() - 1; I++) { + CounterMappingRegion First = MappingRegions[I]; + CounterMappingRegion Second = MappingRegions[I+1]; + if (First.FileID != Second.FileID || + First.Kind != CounterMappingRegion::SkippedRegion || + First.Kind != Second.Kind) { + MergedRegions.push_back(First); + continue; + } + + if (First.LineEnd > Second.LineEnd || + (First.LineEnd == Second.LineEnd && + First.ColumnEnd >= Second.ColumnEnd)) { + // When second region is inside first region, discard second region. + MergedRegions.push_back(First); + I++; + } else if (Second.LineStart >= First.LineStart && + Second.LineStart <= First.LineEnd) { + // When the start location of second region is inside first region and the + // end location is outside first region. + MergedRegions.push_back(CounterMappingRegion::makeSkipped( + First.FileID, First.LineStart, First.ColumnStart, Second.LineEnd, + Second.ColumnEnd)); + } else { + // When there is no overlapping. + MergedRegions.push_back(First); + } + } + + return MergedRegions; +} + void CoverageMappingWriter::write(raw_ostream &OS) { // Check that we don't have any bogus regions. assert(all_of(MappingRegions, @@ -167,6 +202,9 @@ return LHS.Kind < RHS.Kind; }); + // Merge overlapped regions. + MappingRegions = mergeSkippedRegions(MappingRegions); + // Write out the fileid -> filename mapping. encodeULEB128(VirtualFileMapping.size(), OS); for (const auto &FileID : VirtualFileMapping)