Index: lib/CodeGen/CoverageMappingGen.cpp =================================================================== --- lib/CodeGen/CoverageMappingGen.cpp +++ lib/CodeGen/CoverageMappingGen.cpp @@ -552,6 +552,15 @@ completeDeferred(Count, DeferredEndLoc); } + size_t locationDepth(SourceLocation Loc) { + size_t Depth = 0; + while (Loc.isValid()) { + Loc = getIncludeOrExpansionLoc(Loc); + Depth++; + } + return Depth; + } + /// 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 @@ -566,19 +575,41 @@ SourceLocation EndLoc = Region.hasEndLoc() ? Region.getEndLoc() : RegionStack[ParentIndex].getEndLoc(); + size_t StartDepth = locationDepth(StartLoc); + size_t EndDepth = locationDepth(EndLoc); while (!SM.isWrittenInSameFile(StartLoc, EndLoc)) { - // The region ends in a nested file or macro expansion. Create a - // separate region for each expansion. - SourceLocation NestedLoc = getStartOfFileOrMacro(EndLoc); - assert(SM.isWrittenInSameFile(NestedLoc, EndLoc)); - - if (!isRegionAlreadyAdded(NestedLoc, EndLoc)) - SourceRegions.emplace_back(Region.getCounter(), NestedLoc, EndLoc); - - EndLoc = getPreciseTokenLocEnd(getIncludeOrExpansionLoc(EndLoc)); - if (EndLoc.isInvalid()) - llvm::report_fatal_error("File exit not handled before popRegions"); + bool UnnestStart = StartDepth >= EndDepth; + bool UnnestEnd = EndDepth >= StartDepth; + if (UnnestEnd) { + // The region ends in a nested file or macro expansion. Create a + // separate region for each expansion. + SourceLocation NestedLoc = getStartOfFileOrMacro(EndLoc); + assert(SM.isWrittenInSameFile(NestedLoc, EndLoc)); + + if (!isRegionAlreadyAdded(NestedLoc, EndLoc)) + SourceRegions.emplace_back(Region.getCounter(), NestedLoc, EndLoc); + + EndLoc = getPreciseTokenLocEnd(getIncludeOrExpansionLoc(EndLoc)); + if (EndLoc.isInvalid()) + llvm::report_fatal_error("File exit not handled before popRegions"); + EndDepth--; + } + if (UnnestStart) { + // The region begins in a nested file or macro expansion. Create a + // separate region for each expansion. + SourceLocation NestedLoc = getEndOfFileOrMacro(StartLoc); + assert(SM.isWrittenInSameFile(StartLoc, NestedLoc)); + + if (!isRegionAlreadyAdded(StartLoc, NestedLoc)) + SourceRegions.emplace_back(Region.getCounter(), StartLoc, NestedLoc); + + StartLoc = getIncludeOrExpansionLoc(StartLoc); + if (StartLoc.isInvalid()) + llvm::report_fatal_error("File exit not handled before popRegions"); + StartDepth--; + } } + Region.setStartLoc(StartLoc); Region.setEndLoc(EndLoc); MostRecentLocation = EndLoc; Index: test/CoverageMapping/macros.c =================================================================== --- test/CoverageMapping/macros.c +++ test/CoverageMapping/macros.c @@ -4,6 +4,7 @@ #define MACRO_2 bar() #define MACRO_1 return; MACRO_2 #define MACRO_3 MACRO_2 +#define GOTO goto void bar() {} @@ -56,6 +57,15 @@ // CHECK-NEXT: Expansion,File 1, 6:17 -> 6:24 = #1 // CHECK-NEXT: File 2, 4:17 -> 4:22 = #1 +// CHECK-NEXT: func6 +void func6(unsigned count) { // CHECK-NEXT: File 0, [[@LINE]]:28 -> [[@LINE+4]]:2 = #0 +begin: // CHECK-NEXT: File 0, [[@LINE]]:1 -> [[@LINE+3]]:2 = #1 + if (count--) // CHECK-NEXT: File 0, [[@LINE]]:9 -> [[@LINE]]:16 = #1 + GOTO begin; // CHECK-NEXT: File 0, [[@LINE]]:9 -> [[@LINE]]:19 = #2 +} +// CHECK-NEXT: Expansion,File 0, 64:9 -> 64:13 = #2 +// CHECK-NEXT: File 1, 7:14 -> 7:18 = #2 + int main(int argc, const char *argv[]) { func(); func2();