return strcmp(SM.getBufferName(SM.getSpellingLoc(Loc)), "<built-in>") == 0;
}
+ /// \brief Check whether \c Loc is included or expanded from \c Parent.
+ bool isNestedIn(SourceLocation Loc, FileID Parent) {
+ do {
+ Loc = getIncludeOrExpansionLoc(Loc);
+ if (Loc.isInvalid())
+ return false;
+ } while (!SM.isInFileID(Loc, Parent));
+ return true;
+ }
+
/// \brief Get the start of \c S ignoring macro arguments and builtin macros.
SourceLocation getStart(const Stmt *S) {
SourceLocation Loc = S->getLocStart();
if (!D->hasBody())
return;
auto Body = D->getBody();
- SourceRegions.emplace_back(Counter(), getStart(Body), getEnd(Body));
+ SourceLocation Start = getStart(Body);
+ SourceLocation End = getEnd(Body);
+ if (!SM.isWrittenInSameFile(Start, End)) {
+ // Walk up to find the common ancestor.
+ // Correct the locations accordingly.
+ FileID StartFileID = SM.getFileID(Start);
+ FileID EndFileID = SM.getFileID(End);
+ while (StartFileID != EndFileID && !isNestedIn(End, StartFileID)) {
+ Start = getIncludeOrExpansionLoc(Start);
+ assert(Start.isValid() &&
+ "Declaration start location not nested within a known region");
+ StartFileID = SM.getFileID(Start);
+ }
+ while (StartFileID != EndFileID) {
+ End = getPreciseTokenLocEnd(getIncludeOrExpansionLoc(End));
+ assert(End.isValid() &&
+ "Declaration end location not nested within a known region");
+ EndFileID = SM.getFileID(End);
+ }
+ }
+ SourceRegions.emplace_back(Counter(), Start, End);
}
/// \brief Write the mapping data to the output stream
MostRecentLocation = getIncludeOrExpansionLoc(MostRecentLocation);
}
- /// \brief Check whether \c Loc is included or expanded from \c Parent.
- bool isNestedIn(SourceLocation Loc, FileID Parent) {
- do {
- Loc = getIncludeOrExpansionLoc(Loc);
- if (Loc.isInvalid())
- return false;
- } while (!SM.isInFileID(Loc, Parent));
- return true;
- }
-
/// \brief Adjust regions and state when \c NewLoc exits a file.
///
/// If moving from our most recently tracked location to \c NewLoc exits any
--- /dev/null
+// RUN: %clang_cc1 -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -emit-llvm-only %s | FileCheck %s
+
+#define START_SCOPE {
+#define END_SCOPE }
+
+// CHECK: {{_Z2f0v|\?f0@@YAXXZ}}:
+// CHECK-NEXT: File 0, [[@LINE+1]]:18 -> [[@LINE+1]]:20 = 0
+inline void f0() {}
+
+// CHECK: {{_Z2f1v|\?f1@@YAXXZ}}:
+// CHECK-NEXT: File 0, [[@LINE+1]]:18 -> [[@LINE+1]]:31 = 0
+inline void f1() START_SCOPE }
+
+// CHECK: {{_Z2f2v|\?f2@@YAXXZ}}:
+// CHECK-NEXT: File 0, [[@LINE+1]]:18 -> [[@LINE+1]]:29 = 0
+inline void f2() { END_SCOPE
+
+// CHECK: {{_Z2f3v|\?f3@@YAXXZ}}:
+// CHECK-NEXT: File 0, [[@LINE+1]]:18 -> [[@LINE+1]]:39 = 0
+inline void f3() START_SCOPE END_SCOPE
+
+// CHECK: {{_Z2f4v|\?f4@@YAXXZ}}:
+// CHECK-NEXT: File 0, [[@LINE+2]]:10 -> [[@LINE+3]]:2 = 0
+inline void f4()
+#include "Inputs/starts_a_scope_only"
+}
+
+// CHECK: {{_Z2f5v|\?f5@@YAXXZ}}:
+// CHECK-NEXT: File 0, [[@LINE+1]]:18 -> [[@LINE+2]]:36 = 0
+inline void f5() {
+#include "Inputs/ends_a_scope_only"
+
+// CHECK: {{_Z2f6v|\?f6@@YAXXZ}}:
+// CHECK-NEXT: File 0, [[@LINE+2]]:10 -> [[@LINE+3]]:36 = 0
+inline void f6()
+#include "Inputs/starts_a_scope_only"
+#include "Inputs/ends_a_scope_only"