diff options
-rw-r--r-- | clang/lib/CodeGen/CoverageMappingGen.cpp | 28 | ||||
-rw-r--r-- | clang/test/CoverageMapping/macroception.c | 6 | ||||
-rw-r--r-- | clang/test/CoverageMapping/macros.c | 11 |
3 files changed, 33 insertions, 12 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()) diff --git a/clang/test/CoverageMapping/macroception.c b/clang/test/CoverageMapping/macroception.c index 78487416418..7c142ef5afd 100644 --- a/clang/test/CoverageMapping/macroception.c +++ b/clang/test/CoverageMapping/macroception.c @@ -11,7 +11,6 @@ int main() M1 return 0; } -// CHECK-NEXT: File 1, 4:12 -> 4:14 = #0 // CHECK-NEXT: Expansion,File 1, 4:12 -> 4:14 = #0 // CHECK-NEXT: File 2, 3:12 -> 3:13 = #0 @@ -21,7 +20,6 @@ int main() M1 void func2() { int x = 0; M11 -// CHECK-NEXT: File 1, 6:13 -> 6:16 = #0 // CHECK-NEXT: Expansion,File 1, 6:13 -> 6:16 = #0 // CHECK-NEXT: File 2, 5:13 -> 5:14 = #0 @@ -32,9 +30,7 @@ M11 void func3() M1 int x = 0; M11 -// CHECK-NEXT: File 1, 4:12 -> 4:14 = #0 // CHECK-NEXT: Expansion,File 1, 4:12 -> 4:14 = #0 -// CHECK-NEXT: File 2, 6:13 -> 6:16 = #0 // CHECK-NEXT: Expansion,File 2, 6:13 -> 6:16 = #0 // CHECK-NEXT: File 3, 3:12 -> 3:13 = #0 // CHECK-NEXT: File 4, 5:13 -> 5:14 = #0 @@ -44,9 +40,7 @@ M11 // CHECK-NEXT: File 0, [[@LINE+2]]:16 -> [[@LINE+2]]:20 = #0 // CHECK-NEXT: Expansion,File 0, [[@LINE+1]]:17 -> [[@LINE+1]]:20 = #0 void func4() M1 M11 -// CHECK-NEXT: File 1, 4:12 -> 4:14 = #0 // CHECK-NEXT: Expansion,File 1, 4:12 -> 4:14 = #0 -// CHECK-NEXT: File 2, 6:13 -> 6:16 = #0 // CHECK-NEXT: Expansion,File 2, 6:13 -> 6:16 = #0 // CHECK-NEXT: File 3, 3:12 -> 3:13 = #0 // CHECK-NEXT: File 4, 5:13 -> 5:14 = #0 diff --git a/clang/test/CoverageMapping/macros.c b/clang/test/CoverageMapping/macros.c index 8e2355b1ab4..60164be91d7 100644 --- a/clang/test/CoverageMapping/macros.c +++ b/clang/test/CoverageMapping/macros.c @@ -3,6 +3,7 @@ #define MACRO return; bar() #define MACRO_2 bar() #define MACRO_1 return; MACRO_2 +#define MACRO_3 MACRO_2 void bar() {} @@ -24,7 +25,6 @@ void func2() { // CHECK-NEXT: File 0, [[@LINE]]:14 -> [[@LINE+5]]:2 = #0 i = 2; } // CHECK-NEXT: File 1, 5:17 -> 5:32 = #0 -// CHECK-NEXT: File 1, 5:25 -> 5:32 = 0 // CHECK-NEXT: Expansion,File 1, 5:25 -> 5:32 = 0 // CHECK-NEXT: File 2, 4:17 -> 4:22 = 0 @@ -47,6 +47,15 @@ void func4() { // CHECK-NEXT: File 0, [[@LINE]]:14 -> [[@LINE+6]]:2 = #0 // CHECK-NEXT: File 1, 4:17 -> 4:22 = #2 // CHECK-NOT: File 1 +// CHECK-NEXT: func5 +void func5() { // CHECK-NEXT: File 0, [[@LINE]]:14 -> [[@LINE+4]]:2 = #0 + int i = 0; + if (i > 5) // CHECK-NEXT: File 0, [[@LINE]]:7 -> [[@LINE]]:12 = #0 + MACRO_3; // CHECK-NEXT: Expansion,File 0, [[@LINE]]:5 -> [[@LINE]]:12 = #1 +} +// CHECK-NEXT: Expansion,File 1, 6:17 -> 6:24 = #1 +// CHECK-NEXT: File 2, 4:17 -> 4:22 = #1 + int main(int argc, const char *argv[]) { func(); func2(); |