From b5f1f3cacdb0ba272db85083a72495d6b76d6093 Mon Sep 17 00:00:00 2001 From: Igor Kudrin Date: Wed, 4 May 2016 15:38:26 +0000 Subject: [PATCH] [Coverage] Fix an issue where a coverage region might not be created for a macro containing a loop statement. The issue happened when a macro contained a full for or while statement, which body ended at the end of the macro. Differential Revision: http://reviews.llvm.org/D19725 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@268511 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CoverageMappingGen.cpp | 22 +++++++++++++++++++--- test/CoverageMapping/macroscopes.cpp | 23 +++++++++++++++++++++++ 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/lib/CodeGen/CoverageMappingGen.cpp b/lib/CodeGen/CoverageMappingGen.cpp index 820ba1b8f7..d3fd19c174 100644 --- a/lib/CodeGen/CoverageMappingGen.cpp +++ b/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); } diff --git a/test/CoverageMapping/macroscopes.cpp b/test/CoverageMapping/macroscopes.cpp index 7aed39d282..f5fd55c731 100644 --- a/test/CoverageMapping/macroscopes.cpp +++ b/test/CoverageMapping/macroscopes.cpp @@ -22,6 +22,17 @@ #define starts_a_while while (x < 5) #define simple_stmt ++x +#define macro_with_for \ + x = 3; \ + for (int i = 0; i < x; ++i) { \ + } + +#define macro_with_while \ + x = 4; \ + while (x < 5) { \ + ++x; \ + } + // CHECK: main // CHECK-NEXT: File 0, [[@LINE+1]]:12 -> {{[0-9]+}}:2 = #0 int main() { @@ -64,6 +75,11 @@ int main() { simple_stmt; ends_a_scope + // CHECK-NEXT: Expansion,File 0, [[@LINE+1]]:3 -> [[@LINE+1]]:17 = #0 + macro_with_for + // CHECK-NEXT: Expansion,File 0, [[@LINE+1]]:3 -> [[@LINE+1]]:19 = #0 + macro_with_while + return 0; } @@ -103,3 +119,10 @@ int main() { // CHECK-NEXT: File 11, 22:31 -> 22:36 = (#0 + #9) // CHECK-NEXT: File 12, 23:21 -> 23:24 = #9 // CHECK-NEXT: File 13, 6:3 -> 7:4 = #9 +// CHECK-NEXT: File 14, 26:3 -> 28:4 = #0 +// CHECK-NEXT: File 14, 27:19 -> 27:24 = (#0 + #10) +// CHECK-NEXT: File 14, 27:26 -> 27:29 = #10 +// CHECK-NEXT: File 14, 27:31 -> 28:4 = #10 +// CHECK-NEXT: File 15, 31:3 -> 34:4 = #0 +// CHECK-NEXT: File 15, 32:10 -> 32:15 = (#0 + #11) +// CHECK-NEXT: File 15, 32:17 -> 34:4 = #11 -- 2.40.0