https://github.com/ChuanqiXu9 created 
https://github.com/llvm/llvm-project/pull/204517

Motivation: there are some macro likes:

```C++
#define CHECK(X) if (!X) { log_something(); exit(1); } 
```

Then the branch coverage for such cases may always under 50%. It is enough if 
we can make sure `CHECK(X)` is covered.

To implement this, this is more complicated than I thought. As we already have 
ExpansionRegion, but we can't distinguish #include expansion and macro 
expansion. So I have to introduce a new MacroExpansionRegion type.

This enables the new
--ignore-branch-in-macro flag to filter out branches inside macro expansions 
(e.g. CHECK, ASSERT, VERIFY macros) from branch coverage statistics while 
preserving branches from #include'd files.

Changes:
- Add MacroExpansionRegion (Type=6) to CoverageMapping
- Clang CodeGen emits MacroExpansionRegion for macro expansions
- llvm-cov: add --ignore-branch-in-macro to show/report/export subcommands
- Filter branches by FileID matching in branch counting logic
- Apply to LCOV/JSON exporters, summary info, and report views
- Update existing coverage mapping tests for new region type
- Add new tests for macro vs #include branch filtering

AI assisted.

>From 5f8d4c62b56b7e2938f2fdc7cbf3b4e2556f6c2d Mon Sep 17 00:00:00 2001
From: Chuanqi Xu <[email protected]>
Date: Wed, 17 Jun 2026 10:28:33 +0800
Subject: [PATCH] [Coverage] Add MacroExpansionRegion and
 --ignore-branch-in-macro

Motivation: there are some macro likes:

```C++
```

Then the branch coverage for such cases may always under 50%. It is enough
if we can make sure `CHECK(X)` is covered.

To implement this, this is more complicated than I thought. As we already
have ExpansionRegion, but we can't distinguish #include expansion and
macro expansion. So I have to introduce a new MacroExpansionRegion type.

This enables the new
--ignore-branch-in-macro flag to filter out branches inside macro
expansions (e.g. CHECK, ASSERT, VERIFY macros) from branch coverage
statistics while preserving branches from #include'd files.

Changes:
- Add MacroExpansionRegion (Type=6) to CoverageMapping
- Clang CodeGen emits MacroExpansionRegion for macro expansions
- llvm-cov: add --ignore-branch-in-macro to show/report/export subcommands
- Filter branches by FileID matching in branch counting logic
- Apply to LCOV/JSON exporters, summary info, and report views
- Update existing coverage mapping tests for new region type
- Add new tests for macro vs #include branch filtering

AI assisted.
---
 clang/lib/CodeGen/CoverageMappingGen.cpp      |   8 +-
 clang/test/CoverageMapping/comment-in-macro.c |   4 +-
 .../test/CoverageMapping/control-flow-macro.c |   4 +-
 clang/test/CoverageMapping/if.cpp             |   8 +-
 clang/test/CoverageMapping/label.cpp          |   2 +-
 clang/test/CoverageMapping/loopmacro.c        |  16 +--
 .../CoverageMapping/macro-expansion-kind.c    |  22 ++++
 clang/test/CoverageMapping/macro-expansion.c  |   2 +-
 .../CoverageMapping/macro-expressions.cpp     |  34 +++---
 clang/test/CoverageMapping/macroception.c     |  24 ++--
 clang/test/CoverageMapping/macroparams.c      |   4 +-
 clang/test/CoverageMapping/macroparams2.c     |   2 +-
 clang/test/CoverageMapping/macros.c           |  22 ++--
 clang/test/CoverageMapping/macroscopes.cpp    |  30 ++---
 .../test/CoverageMapping/mcdc-scratch-space.c |  12 +-
 .../CoverageMapping/mcdc-system-headers.cpp   |   8 +-
 clang/test/CoverageMapping/moremacros.c       |   8 +-
 clang/test/CoverageMapping/switchmacro.c      |   6 +-
 clang/test/CoverageMapping/system_macro.cpp   |   4 +-
 clang/test/CoverageMapping/trymacro.cpp       |   6 +-
 .../test/CoverageMapping/unreachable-macro.c  |   2 +-
 compiler-rt/include/profile/InstrProfData.inc |   2 +-
 .../ProfileData/Coverage/CoverageMapping.h    |  37 +++++-
 .../Coverage/CoverageMappingReader.h          |  14 ++-
 .../llvm/ProfileData/InstrProfData.inc        |   2 +-
 .../ProfileData/Coverage/CoverageMapping.cpp  |   8 +-
 .../Coverage/CoverageMappingReader.cpp        |  37 ++++--
 .../Coverage/CoverageMappingWriter.cpp        |  20 +--
 .../tools/llvm-cov/Inputs/macro-filter-test.c |  24 ++++
 .../tools/llvm-cov/Inputs/macro-filter-test.o | Bin 0 -> 3664 bytes
 .../Inputs/macro-filter-test.proftext         |  19 +++
 .../tools/llvm-cov/Inputs/macro-vs-include.c  |  34 ++++++
 .../tools/llvm-cov/Inputs/macro-vs-include.o  | Bin 0 -> 4760 bytes
 .../llvm-cov/Inputs/macro-vs-include.proftext |  28 +++++
 .../llvm-cov/macro-expansion-filter.test      |  49 ++++++++
 .../test/tools/llvm-cov/macro-vs-include.test |  38 ++++++
 llvm/tools/llvm-cov/CodeCoverage.cpp          |  40 +++++-
 llvm/tools/llvm-cov/CoverageExporterJson.cpp  |  30 +++--
 llvm/tools/llvm-cov/CoverageExporterLcov.cpp  |  57 +++++----
 llvm/tools/llvm-cov/CoverageReport.cpp        |   6 +-
 llvm/tools/llvm-cov/CoverageSummaryInfo.cpp   |  15 ++-
 llvm/tools/llvm-cov/CoverageSummaryInfo.h     |   3 +-
 llvm/tools/llvm-cov/CoverageViewOptions.h     |   2 +
 .../ProfileData/CoverageMappingTest.cpp       | 114 ++++++++++++++++++
 44 files changed, 629 insertions(+), 178 deletions(-)
 create mode 100644 clang/test/CoverageMapping/macro-expansion-kind.c
 create mode 100644 llvm/test/tools/llvm-cov/Inputs/macro-filter-test.c
 create mode 100644 llvm/test/tools/llvm-cov/Inputs/macro-filter-test.o
 create mode 100644 llvm/test/tools/llvm-cov/Inputs/macro-filter-test.proftext
 create mode 100644 llvm/test/tools/llvm-cov/Inputs/macro-vs-include.c
 create mode 100644 llvm/test/tools/llvm-cov/Inputs/macro-vs-include.o
 create mode 100644 llvm/test/tools/llvm-cov/Inputs/macro-vs-include.proftext
 create mode 100644 llvm/test/tools/llvm-cov/macro-expansion-filter.test
 create mode 100644 llvm/test/tools/llvm-cov/macro-vs-include.test

diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp 
b/clang/lib/CodeGen/CoverageMappingGen.cpp
index c90afacbde293..739350d048ac9 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -604,7 +604,8 @@ class CoverageMappingBuilder {
       assert(SR.isInSourceOrder() && "region start and end out of order");
       MappingRegions.push_back(CounterMappingRegion::makeExpansion(
           *ParentFileID, *ExpandedFileID, SR.LineStart, SR.ColumnStart,
-          SR.LineEnd, SR.ColumnEnd));
+          SR.LineEnd, SR.ColumnEnd,
+          /*IsMacro=*/ExpandedLoc.isMacroID()));
     }
     return Filter;
   }
@@ -2446,6 +2447,9 @@ static void dump(llvm::raw_ostream &OS, StringRef 
FunctionName,
     case CounterMappingRegion::ExpansionRegion:
       OS << "Expansion,";
       break;
+    case CounterMappingRegion::MacroExpansionRegion:
+      OS << "MacroExpansion,";
+      break;
     case CounterMappingRegion::SkippedRegion:
       OS << "Skipped,";
       break;
@@ -2484,7 +2488,7 @@ static void dump(llvm::raw_ostream &OS, StringRef 
FunctionName,
       OS << "," << BranchParams->Conds[false] + 1 << "] ";
     }
 
-    if (R.Kind == CounterMappingRegion::ExpansionRegion)
+    if (R.isExpansion())
       OS << " (Expanded file = " << R.ExpandedFileID << ")";
     OS << "\n";
   }
diff --git a/clang/test/CoverageMapping/comment-in-macro.c 
b/clang/test/CoverageMapping/comment-in-macro.c
index 1afde46f1e4a5..9a05edfcfe402 100644
--- a/clang/test/CoverageMapping/comment-in-macro.c
+++ b/clang/test/CoverageMapping/comment-in-macro.c
@@ -4,8 +4,8 @@
 #define x2 return 0
 // CHECK: main
 int main(void) { // CHECK-NEXT: File 0, [[@LINE]]:16 -> [[@LINE+3]]:2 = #0
-  x1;            // CHECK-NEXT: Expansion,File 0, [[@LINE]]:3 -> [[@LINE]]:5 = 
#0
-  x2;            // CHECK-NEXT: Expansion,File 0, [[@LINE]]:3 -> [[@LINE]]:5 = 
#0
+  x1;            // CHECK-NEXT: MacroExpansion,File 0, [[@LINE]]:3 -> 
[[@LINE]]:5 = #0
+  x2;            // CHECK-NEXT: MacroExpansion,File 0, [[@LINE]]:3 -> 
[[@LINE]]:5 = #0
 }
 // CHECK-NEXT: File 1, 3:12 -> 3:14 = #0
 // CHECK-NEXT: File 2, 4:12 -> 4:20 = #0
diff --git a/clang/test/CoverageMapping/control-flow-macro.c 
b/clang/test/CoverageMapping/control-flow-macro.c
index b73ac989057db..f78dad28348d4 100644
--- a/clang/test/CoverageMapping/control-flow-macro.c
+++ b/clang/test/CoverageMapping/control-flow-macro.c
@@ -5,9 +5,9 @@
 // CHECK: main
 // CHECK-NEXT: File 0, {{[0-9]+}}:40 -> [[END:[0-9]+]]:2 = #0
 int main(int argc, const char *argv[]) {
-  // CHECK: Expansion,File 0, [[@LINE+1]]:3 -> [[@LINE+1]]:6 = #0
+  // CHECK: MacroExpansion,File 0, [[@LINE+1]]:3 -> [[@LINE+1]]:6 = #0
   ifc(1) return 0;
-  // Expansion,File 0, [[@LINE+2]]:3 -> [[@LINE+2]]:6 = (#0 - #1)
+  // MacroExpansion,File 0, [[@LINE+2]]:3 -> [[@LINE+2]]:6 = (#0 - #1)
   // File 0, [[@LINE+1]]:6 -> [[END]]:2 = (#0 - #1)
   ifc(1) return 0;
   return 0;
diff --git a/clang/test/CoverageMapping/if.cpp 
b/clang/test/CoverageMapping/if.cpp
index b6fd525e930f9..73d5e8176f19e 100644
--- a/clang/test/CoverageMapping/if.cpp
+++ b/clang/test/CoverageMapping/if.cpp
@@ -121,8 +121,8 @@ int check_constexpr_init_with_if_def(int i) {   // 
CHECK-NEXT: [[@LINE]]:{{[0-9]
 
 // CHECK-LABEL: _Z32check_macro_constexpr_if_skippedi:
 int check_macro_constexpr_if_skipped(int i) {   // CHECK-NEXT: 
[[@LINE]]:{{[0-9]+}} -> {{[0-9]+}}:2 = #0
-#define IF_CONSTEXPR if constexpr               // CHECK-NEXT: Expansion,File 
0, [[@LINE+1]]:3 -> [[@LINE+1]]:15 = #0 (Expanded file = 1)
-  IF_CONSTEXPR(false) {                         // CHECK-NEXT: Skipped,File 0, 
[[@LINE]]:3 -> [[@LINE+2]]:4 = 0
+#define IF_CONSTEXPR if constexpr               // CHECK-NEXT: Skipped,File 0, 
[[@LINE+1]]:3 -> [[@LINE+3]]:4 = 0
+  IF_CONSTEXPR(false) {                         // CHECK-NEXT: 
MacroExpansion,File 0, [[@LINE]]:3 -> [[@LINE]]:15 = #0 (Expanded file = 1)
     i *= 2;                                     // CHECK-NEXT: File 1, 
[[@LINE-2]]:22 -> [[@LINE-2]]:34 = #0
   }
   return i;
@@ -227,8 +227,8 @@ constexpr int check_notconsteval_branch_kept(int i) { // 
CHECK-NEXT: [[@LINE]]:{
 
 // CHECK-LABEL: _Z32check_macro_consteval_if_skippedi:
 constexpr int check_macro_consteval_if_skipped(int i) {   // CHECK-NEXT: 
[[@LINE]]:{{[0-9]+}} -> {{[0-9]+}}:2 = #0
-#define IF_RUNTIME if !consteval               // CHECK-NEXT: Expansion,File 
0, [[@LINE+1]]:3 -> [[@LINE+1]]:13 = #0 (Expanded file = 1)
-  IF_RUNTIME {                                 // CHECK-NEXT: Skipped,File 0, 
[[@LINE]]:3 -> [[@LINE]]:14 = 0
+#define IF_RUNTIME if !consteval               // CHECK-NEXT: Skipped,File 0, 
[[@LINE+1]]:3 -> [[@LINE+1]]:14 = 0
+  IF_RUNTIME {                                 // CHECK-NEXT: 
MacroExpansion,File 0, [[@LINE]]:3 -> [[@LINE]]:13 = #0 (Expanded file = 1)
     i *= 2;                                    // CHECK-NEXT: File 0, 
[[@LINE-1]]:14 -> [[@LINE+1]]:4 = #0
   }                                            // CHECK-NEXT: File 1, 
[[@LINE-3]]:20 -> [[@LINE-3]]:33 = #0
   return i;
diff --git a/clang/test/CoverageMapping/label.cpp 
b/clang/test/CoverageMapping/label.cpp
index cf7cbe5d00f43..7bbe27253c509 100644
--- a/clang/test/CoverageMapping/label.cpp
+++ b/clang/test/CoverageMapping/label.cpp
@@ -54,7 +54,7 @@ void test2(int x) {          // CHECK-NEXT: File 0, 
[[@LINE]]:19 -> {{[0-9]+}}:2
 void test3() {
   if (0)
     goto b; // CHECK: Gap,File 0, [[@LINE]]:12 -> [[@LINE+1]]:1 = (#0 - #1)
-a: // CHECK-NEXT: Expansion,File 0, [[@LINE]]:1 -> [[@LINE]]:2 = 
[[retnCount:#[0-9]+]] (Expanded file = 1)
+a: // CHECK-NEXT: MacroExpansion,File 0, [[@LINE]]:1 -> [[@LINE]]:2 = 
[[retnCount:#[0-9]+]] (Expanded file = 1)
   return; // CHECK-NEXT: File 0, [[@LINE-1]]:2 -> [[@LINE]]:9 = [[retnCount]]
 }
 #undef a
diff --git a/clang/test/CoverageMapping/loopmacro.c 
b/clang/test/CoverageMapping/loopmacro.c
index 1fbb1139abf04..fc03bf8e3bb1a 100644
--- a/clang/test/CoverageMapping/loopmacro.c
+++ b/clang/test/CoverageMapping/loopmacro.c
@@ -3,27 +3,27 @@
 // CHECK: main
 // CHECK-NEXT: File 0, {{[0-9]+}}:16 -> {{[0-9]+}}:2 = #0
 // CHECK-NEXT: File 0, {{[0-9]+}}:6 -> {{[0-9]+}}:4 = (#0 + #1)
-// CHECK-NEXT: Expansion,File 0, {{[0-9]+}}:7 -> {{[0-9]+}}:20 = (#0 + #1)
+// CHECK-NEXT: MacroExpansion,File 0, {{[0-9]+}}:7 -> {{[0-9]+}}:20 = (#0 + #1)
 // CHECK-NEXT: File 0, {{[0-9]+}}:12 -> {{[0-9]+}}:30 = (#0 + #1)
 
 // CHECK-NEXT: Branch,File 0, {{[0-9]+}}:12 -> {{[0-9]+}}:30 = #1, #0
 // CHECK-NEXT: File 1, [[@LINE+4]]:4 -> [[@LINE+6]]:23 = (#0 + #1)
-// CHECK-NEXT: Expansion,File 1, [[@LINE+3]]:5 -> [[@LINE+3]]:16 = (#0 + #1)
-// CHECK-NEXT: Expansion,File 1, [[@LINE+3]]:16 -> [[@LINE+3]]:21 = (#0 + #1)
+// CHECK-NEXT: MacroExpansion,File 1, [[@LINE+3]]:5 -> [[@LINE+3]]:16 = (#0 + 
#1)
+// CHECK-NEXT: MacroExpansion,File 1, [[@LINE+3]]:16 -> [[@LINE+3]]:21 = (#0 + 
#1)
 #define INSERT_STRING(s, match_head) \
    (UPDATE_HASH(ins_h, window[(s) + MIN_MATCH-1]), \
     prev[(s) & WMASK] = match_head = head[ins_h], \
     head[ins_h] = (s))
 // CHECK-NEXT: File 2, [[@LINE+3]]:26 -> [[@LINE+3]]:66 = (#0 + #1)
-// CHECK-NEXT: Expansion,File 2, [[@LINE+2]]:38 -> [[@LINE+2]]:45 = (#0 + #1)
-// CHECK-NEXT: Expansion,File 2, [[@LINE+1]]:56 -> [[@LINE+1]]:65 = (#0 + #1)
+// CHECK-NEXT: MacroExpansion,File 2, [[@LINE+2]]:38 -> [[@LINE+2]]:45 = (#0 + 
#1)
+// CHECK-NEXT: MacroExpansion,File 2, [[@LINE+1]]:56 -> [[@LINE+1]]:65 = (#0 + 
#1)
 #define UPDATE_HASH(h,c) (h = (((h)<<H_SHIFT) ^ (c)) & HASH_MASK)
 // CHECK-NEXT: File 3, [[@LINE+1]]:15 -> [[@LINE+1]]:21 = (#0 + #1)
 #define WMASK 0xFFFF
 // CHECK-NEXT: File 4, [[@LINE+4]]:18 -> [[@LINE+4]]:53 = (#0 + #1)
-// CHECK-NEXT: Expansion,File 4, [[@LINE+3]]:20 -> [[@LINE+3]]:29 = (#0 + #1)
-// CHECK-NEXT: Expansion,File 4, [[@LINE+2]]:30 -> [[@LINE+2]]:39 = (#0 + #1)
-// CHECK-NEXT: Expansion,File 4, [[@LINE+1]]:43 -> [[@LINE+1]]:52 = (#0 + #1)
+// CHECK-NEXT: MacroExpansion,File 4, [[@LINE+3]]:20 -> [[@LINE+3]]:29 = (#0 + 
#1)
+// CHECK-NEXT: MacroExpansion,File 4, [[@LINE+2]]:30 -> [[@LINE+2]]:39 = (#0 + 
#1)
+// CHECK-NEXT: MacroExpansion,File 4, [[@LINE+1]]:43 -> [[@LINE+1]]:52 = (#0 + 
#1)
 #define H_SHIFT  ((HASH_BITS+MIN_MATCH-1)/MIN_MATCH)
 // CHECK-NEXT: File 5, [[@LINE+1]]:19 -> [[@LINE+1]]:25 = (#0 + #1)
 #define HASH_MASK 0xFFFF
diff --git a/clang/test/CoverageMapping/macro-expansion-kind.c 
b/clang/test/CoverageMapping/macro-expansion-kind.c
new file mode 100644
index 0000000000000..ee229df353e11
--- /dev/null
+++ b/clang/test/CoverageMapping/macro-expansion-kind.c
@@ -0,0 +1,22 @@
+// RUN: %clang_cc1 -mllvm -emptyline-comment-coverage=false 
-fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping 
-emit-llvm-only -main-file-name macro-expansion-kind.c %s | FileCheck %s
+
+// Test that macro expansions are marked as MacroExpansion in the coverage
+// mapping dump, distinguishing them from regular Expansion regions (#include).
+
+#define SIMPLE_MACRO(x) ((x) > 0 ? (x) : 0)
+
+// CHECK-LABEL: test_func:
+// CHECK: File 0, [[@LINE+1]]:22 -> [[@LINE+13]]:2 = #0
+void test_func(void) {
+  // CHECK: MacroExpansion,File 0, [[@LINE+1]]:16 -> [[@LINE+1]]:28
+  int result = SIMPLE_MACRO(42);
+
+  // CHECK: MacroExpansion,File 0, [[@LINE+1]]:13 -> [[@LINE+1]]:25
+  int val = SIMPLE_MACRO(1);
+
+  // CHECK: File 1,
+  int x = 0;
+  (void)result;
+  (void)val;
+  (void)x;
+}
diff --git a/clang/test/CoverageMapping/macro-expansion.c 
b/clang/test/CoverageMapping/macro-expansion.c
index 4cd2c93437193..88022045ceadb 100644
--- a/clang/test/CoverageMapping/macro-expansion.c
+++ b/clang/test/CoverageMapping/macro-expansion.c
@@ -24,7 +24,7 @@
 #define M2(x) do { if (x) {} } while (0)
 // CHECK-NEXT: File 4, [[@LINE+5]]:15 -> [[@LINE+5]]:38 = #0
 // CHECK-NEXT: File 4, [[@LINE+4]]:18 -> [[@LINE+4]]:28 = (#0 + #8)
-// CHECK-NEXT: Expansion,File 4, [[@LINE+3]]:20 -> [[@LINE+3]]:22 = (#0 + #8)
+// CHECK-NEXT: MacroExpansion,File 4, [[@LINE+3]]:20 -> [[@LINE+3]]:22 = (#0 + 
#8)
 // CHECK-NEXT: File 4, [[@LINE+2]]:36 -> [[@LINE+2]]:37 = (#0 + #8)
 // CHECK-NEXT: Branch,File 4, [[@LINE+1]]:36 -> [[@LINE+1]]:37 = 0, #0
 #define M3(x) do { M2(x); } while (0)
diff --git a/clang/test/CoverageMapping/macro-expressions.cpp 
b/clang/test/CoverageMapping/macro-expressions.cpp
index 2b6a1b64c2594..3d31c237dfe42 100644
--- a/clang/test/CoverageMapping/macro-expressions.cpp
+++ b/clang/test/CoverageMapping/macro-expressions.cpp
@@ -58,33 +58,33 @@ void foo(int i) {
   // CHECK-NEXT: File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:12 = #1
   if (0) {}
 
-  // CHECK-NEXT: Expansion,File 0, [[@LINE+3]]:7 -> [[@LINE+3]]:11 = #0
+  // CHECK-NEXT: MacroExpansion,File 0, [[@LINE+3]]:7 -> [[@LINE+3]]:11 = #0
   // CHECK-NEXT: Gap,File 0, [[@LINE+2]]:15 -> [[@LINE+2]]:16 = #2
   // CHECK-NEXT: File 0, [[@LINE+1]]:16 -> [[@LINE+1]]:18 = #2
   if (EXPR(i)) {}
-  // CHECK-NEXT: Expansion,File 0, [[@LINE+3]]:9 -> [[@LINE+3]]:14 = (#0 + #3)
+  // CHECK-NEXT: MacroExpansion,File 0, [[@LINE+3]]:9 -> [[@LINE+3]]:14 = (#0 
+ #3)
   // CHECK-NEXT: Gap,File 0, [[@LINE+2]]:19 -> [[@LINE+2]]:20 = #3
   // CHECK-NEXT: File 0, [[@LINE+1]]:20 -> [[@LINE+1]]:22 = #3
   for (;NEXPR(i);) {}
-  // CHECK-NEXT: Expansion,File 0, [[@LINE+5]]:8 -> [[@LINE+5]]:14 = #0
-  // CHECK-NEXT: Expansion,File 0, [[@LINE+4]]:33 -> [[@LINE+4]]:35 = (#0 + #4)
-  // CHECK-NEXT: Expansion,File 0, [[@LINE+3]]:43 -> [[@LINE+3]]:46 = #4
+  // CHECK-NEXT: MacroExpansion,File 0, [[@LINE+5]]:8 -> [[@LINE+5]]:14 = #0
+  // CHECK-NEXT: MacroExpansion,File 0, [[@LINE+4]]:33 -> [[@LINE+4]]:35 = (#0 
+ #4)
+  // CHECK-NEXT: MacroExpansion,File 0, [[@LINE+3]]:43 -> [[@LINE+3]]:46 = #4
   // CHECK-NEXT: Gap,File 0, [[@LINE+2]]:50 -> [[@LINE+2]]:51 = #4
   // CHECK: File 0, [[@LINE+1]]:51 -> [[@LINE+1]]:53 = #4
   for (ASSIGN(DECL(int, j), 0); LT(j, i); INC(j)) {}
-  // CHECK-NEXT: Expansion,File 0, [[@LINE+1]]:3 -> [[@LINE+1]]:9 = #0
+  // CHECK-NEXT: MacroExpansion,File 0, [[@LINE+1]]:3 -> [[@LINE+1]]:9 = #0
   ASSIGN(DECL(int, k), 0);
-  // CHECK-NEXT: Expansion,File 0, [[@LINE+4]]:10 -> [[@LINE+4]]:12 = (#0 + #5)
+  // CHECK-NEXT: MacroExpansion,File 0, [[@LINE+4]]:10 -> [[@LINE+4]]:12 = (#0 
+ #5)
   // CHECK-NEXT: Gap,File 0, [[@LINE+3]]:19 -> [[@LINE+3]]:20 = #5
   // CHECK-NEXT: File 0, [[@LINE+2]]:20 -> [[@LINE+2]]:31 = #5
-  // CHECK-NEXT: Expansion,File 0, [[@LINE+1]]:22 -> [[@LINE+1]]:25 = #5
+  // CHECK-NEXT: MacroExpansion,File 0, [[@LINE+1]]:22 -> [[@LINE+1]]:25 = #5
   while (LT(k, i)) { INC(k); }
   // CHECK-NEXT: File 0, [[@LINE+2]]:6 -> [[@LINE+2]]:8 = (#0 + #6)
-  // CHECK-NEXT: Expansion,File 0, [[@LINE+1]]:16 -> [[@LINE+1]]:21 = (#0 + #6)
+  // CHECK-NEXT: MacroExpansion,File 0, [[@LINE+1]]:16 -> [[@LINE+1]]:21 = (#0 
+ #6)
   do {} while (NEXPR(i));
-  // CHECK-NEXT: Expansion,File 0, [[@LINE+5]]:8 -> [[@LINE+5]]:12 = #0
+  // CHECK-NEXT: MacroExpansion,File 0, [[@LINE+5]]:8 -> [[@LINE+5]]:12 = #0
   // CHECK-NEXT: Branch,File 0, [[@LINE+4]]:21 -> [[@LINE+4]]:22 = #7, #0
-  // CHECK-NEXT: Expansion,File 0, [[@LINE+3]]:23 -> [[@LINE+3]]:26 = #0
+  // CHECK-NEXT: MacroExpansion,File 0, [[@LINE+3]]:23 -> [[@LINE+3]]:26 = #0
   // CHECK-NEXT: Gap,File 0, [[@LINE+2]]:41 -> [[@LINE+2]]:42 = #7
   // CHECK: File 0, [[@LINE+1]]:42 -> [[@LINE+1]]:44 = #7
   for (DECL(int, j) : ARR(int, 1, 2, 3)) {}
@@ -92,21 +92,21 @@ void foo(int i) {
   // CHECK-NEXT: File 0, [[@LINE+5]]:10 -> [[@LINE+5]]:11 = #0
   // CHECK-NEXT: Branch,File 0, [[@LINE+4]]:10 -> [[@LINE+4]]:11 = #8, (#0 - 
#8)
   // CHECK-NEXT: Gap,File 0, [[@LINE+3]]:13 -> [[@LINE+3]]:14 = #8
-  // CHECK-NEXT: Expansion,File 0, [[@LINE+2]]:14 -> [[@LINE+2]]:20 = #0
-  // CHECK-NEXT: Expansion,File 0, [[@LINE+1]]:23 -> [[@LINE+1]]:29 = #0
+  // CHECK-NEXT: MacroExpansion,File 0, [[@LINE+2]]:14 -> [[@LINE+2]]:20 = #0
+  // CHECK-NEXT: MacroExpansion,File 0, [[@LINE+1]]:23 -> [[@LINE+1]]:29 = #0
   (void)(i ? PRIo64 : PRIu64);
 
   // CHECK-NEXT: File 0, [[@LINE+6]]:10 -> [[@LINE+6]]:11 = #0
   // CHECK: File 0, [[@LINE+5]]:14 -> [[@LINE+5]]:15 = #9
   // CHECK-NEXT: File 0, [[@LINE+4]]:18 -> [[@LINE+4]]:33 = (#0 - #9)
-  // CHECK-NEXT: Expansion,File 0, [[@LINE+3]]:18 -> [[@LINE+3]]:22 = (#0 - #9)
+  // CHECK-NEXT: MacroExpansion,File 0, [[@LINE+3]]:18 -> [[@LINE+3]]:22 = (#0 
- #9)
   // CHECK: File 0, [[@LINE+2]]:28 -> [[@LINE+2]]:29 = #10
   // CHECK-NEXT: File 0, [[@LINE+1]]:32 -> [[@LINE+1]]:33 = ((#0 - #9) - #10)
   (void)(i ? i : EXPR(i) ? i : 0);
   // CHECK-NEXT: File 0, [[@LINE+5]]:10 -> [[@LINE+5]]:11 = #0
   // CHECK-NEXT: Branch,File 0, [[@LINE+4]]:10 -> [[@LINE+4]]:11 = #11, (#0 - 
#11)
   // CHECK-NEXT: File 0, [[@LINE+3]]:15 -> [[@LINE+3]]:27 = (#0 - #11)
-  // CHECK-NEXT: Expansion,File 0, [[@LINE+2]]:15 -> [[@LINE+2]]:19 = (#0 - 
#11)
+  // CHECK-NEXT: MacroExpansion,File 0, [[@LINE+2]]:15 -> [[@LINE+2]]:19 = (#0 
- #11)
   // CHECK-NEXT: File 0, [[@LINE+1]]:26 -> [[@LINE+1]]:27 = ((#0 - #11) - #12)
   (void)(i ?: EXPR(i) ?: 0);
 }
@@ -128,10 +128,10 @@ void foo(int i) {
 // CHECK-NEXT: File {{[0-9]+}}, 5:20 -> 5:23 = #0
 // CHECK-NEXT: File {{[0-9]+}}, 9:25 -> 9:40 = #0
 // CHECK-NEXT: File {{[0-9]+}}, 12:16 -> 12:42 = #0
-// CHECK-NEXT: Expansion,File {{[0-9]+}}, 12:16 -> 12:38 = #8
+// CHECK-NEXT: MacroExpansion,File {{[0-9]+}}, 12:16 -> 12:38 = #8
 // CHECK-NEXT: File {{[0-9]+}}, 12:38 -> 12:42 = #8
 // CHECK-NEXT: File {{[0-9]+}}, 13:16 -> 13:42 = #0
-// CHECK-NEXT: Expansion,File {{[0-9]+}}, 13:16 -> 13:38 = (#0 - #8)
+// CHECK-NEXT: MacroExpansion,File {{[0-9]+}}, 13:16 -> 13:38 = (#0 - #8)
 // CHECK-NEXT: File {{[0-9]+}}, 13:38 -> 13:42 = (#0 - #8)
 // CHECK-NEXT: File {{[0-9]+}}, 3:17 -> 3:20 = (#0 - #9)
 // CHECK-NEXT: Branch,File {{[0-9]+}}, 3:17 -> 3:20 = #10, ((#0 - #9) - #10)
diff --git a/clang/test/CoverageMapping/macroception.c 
b/clang/test/CoverageMapping/macroception.c
index 6d4b3ed427f7f..4ad23bed7f182 100644
--- a/clang/test/CoverageMapping/macroception.c
+++ b/clang/test/CoverageMapping/macroception.c
@@ -6,41 +6,41 @@
 #define M11 M22
 
 // CHECK-LABEL: main:
-// CHECK-NEXT: Expansion,File 0, [[@LINE+2]]:16 -> [[@LINE+2]]:18 = #0
+// CHECK-NEXT: MacroExpansion,File 0, [[@LINE+2]]:16 -> [[@LINE+2]]:18 = #0
 // CHECK-NEXT: File 0, [[@LINE+1]]:18 -> [[@LINE+3]]:2 = #0
 int main(void) M1
   return 0;
 }
-// CHECK-NEXT: Expansion,File 1, 4:12 -> 4:14 = #0
+// CHECK-NEXT: MacroExpansion,File 1, 4:12 -> 4:14 = #0
 // CHECK-NEXT: File 2, 3:12 -> 3:13 = #0
 
 // CHECK-LABEL: func2:
 // CHECK-NEXT: File 0, [[@LINE+2]]:18 -> [[@LINE+4]]:4 = #0
-// CHECK-NEXT: Expansion,File 0, [[@LINE+3]]:1 -> [[@LINE+3]]:4 = #0
+// CHECK-NEXT: MacroExpansion,File 0, [[@LINE+3]]:1 -> [[@LINE+3]]:4 = #0
 void func2(void) {
   int x = 0;
 M11
-// CHECK-NEXT: Expansion,File 1, 6:13 -> 6:16 = #0
+// CHECK-NEXT: MacroExpansion,File 1, 6:13 -> 6:16 = #0
 // CHECK-NEXT: File 2, 5:13 -> 5:14 = #0
 
 // CHECK-LABEL: func3:
-// CHECK-NEXT: Expansion,File 0, [[@LINE+3]]:18 -> [[@LINE+3]]:20 = #0
+// CHECK-NEXT: MacroExpansion,File 0, [[@LINE+3]]:18 -> [[@LINE+3]]:20 = #0
 // CHECK-NEXT: File 0, [[@LINE+2]]:20 -> [[@LINE+4]]:4 = #0
-// CHECK-NEXT: Expansion,File 0, [[@LINE+3]]:1 -> [[@LINE+3]]:4 = #0
+// CHECK-NEXT: MacroExpansion,File 0, [[@LINE+3]]:1 -> [[@LINE+3]]:4 = #0
 void func3(void) M1
   int x = 0;
 M11
-// CHECK-NEXT: Expansion,File 1, 4:12 -> 4:14 = #0
-// CHECK-NEXT: Expansion,File 2, 6:13 -> 6:16 = #0
+// CHECK-NEXT: MacroExpansion,File 1, 4:12 -> 4:14 = #0
+// CHECK-NEXT: MacroExpansion,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
 
 // CHECK-LABEL: func4:
-// CHECK-NEXT: Expansion,File 0, [[@LINE+3]]:18 -> [[@LINE+3]]:20 = #0
+// CHECK-NEXT: MacroExpansion,File 0, [[@LINE+3]]:18 -> [[@LINE+3]]:20 = #0
 // CHECK-NEXT: File 0, [[@LINE+2]]:20 -> [[@LINE+2]]:24 = #0
-// CHECK-NEXT: Expansion,File 0, [[@LINE+1]]:21 -> [[@LINE+1]]:24 = #0
+// CHECK-NEXT: MacroExpansion,File 0, [[@LINE+1]]:21 -> [[@LINE+1]]:24 = #0
 void func4(void) M1 M11
-// CHECK-NEXT: Expansion,File 1, 4:12 -> 4:14 = #0
-// CHECK-NEXT: Expansion,File 2, 6:13 -> 6:16 = #0
+// CHECK-NEXT: MacroExpansion,File 1, 4:12 -> 4:14 = #0
+// CHECK-NEXT: MacroExpansion,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/macroparams.c 
b/clang/test/CoverageMapping/macroparams.c
index 2f60cffbfdb77..282ece3644123 100644
--- a/clang/test/CoverageMapping/macroparams.c
+++ b/clang/test/CoverageMapping/macroparams.c
@@ -2,10 +2,10 @@
 
 // CHECK: main
 // CHECK-NEXT: File 0, {{[0-9]+}}:16 -> {{[0-9]+}}:2 = #0
-// CHECK-NEXT: Expansion,File 0, {{[0-9]+}}:3 -> {{[0-9]+}}:8 = #0
+// CHECK-NEXT: MacroExpansion,File 0, {{[0-9]+}}:3 -> {{[0-9]+}}:8 = #0
 
 // CHECK-NEXT: File 1, [[@LINE+2]]:18 -> [[@LINE+2]]:27 = #0
-// CHECK-NEXT: Expansion,File 1, [[@LINE+1]]:18 -> [[@LINE+1]]:24 = #0
+// CHECK-NEXT: MacroExpansion,File 1, [[@LINE+1]]:18 -> [[@LINE+1]]:24 = #0
 #define MACRO(X) MACRO2(x)
 // CHECK-NEXT: File 2, [[@LINE+1]]:20 -> [[@LINE+1]]:28 = #0
 #define MACRO2(X2) (X2 + 2)
diff --git a/clang/test/CoverageMapping/macroparams2.c 
b/clang/test/CoverageMapping/macroparams2.c
index 7873b6ac12a9a..516516b4c4aa9 100644
--- a/clang/test/CoverageMapping/macroparams2.c
+++ b/clang/test/CoverageMapping/macroparams2.c
@@ -10,7 +10,7 @@ struct S {
 int main(void) {
   struct S arr[32] = { 0 };
   int n = 0;
-  // CHECK-NEXT: Expansion,File 0, [[@LINE+3]]:7 -> [[@LINE+3]]:12 = #0
+  // CHECK-NEXT: MacroExpansion,File 0, [[@LINE+3]]:7 -> [[@LINE+3]]:12 = #0
   // CHECK-NEXT: Gap,File 0, [[@LINE+2]]:33 -> [[@LINE+2]]:34 = #1
   // CHECK-NEXT: File 0, [[@LINE+1]]:34 -> [[@LINE+3]]:4 = #1
   if (MACRO(arr[n].j, arr[n].i)) {
diff --git a/clang/test/CoverageMapping/macros.c 
b/clang/test/CoverageMapping/macros.c
index 00139f33229d5..f070de7a0ea25 100644
--- a/clang/test/CoverageMapping/macros.c
+++ b/clang/test/CoverageMapping/macros.c
@@ -11,7 +11,7 @@ void bar(void) {}
 // CHECK: func
 void func(void) {  // CHECK-NEXT: File 0, [[@LINE]]:17 -> [[@LINE+5]]:2 = #0
   int i = 0;
-  // CHECK-NEXT: Expansion,File 0, [[@LINE+1]]:3 -> [[@LINE+1]]:8 = #0
+  // CHECK-NEXT: MacroExpansion,File 0, [[@LINE+1]]:3 -> [[@LINE+1]]:8 = #0
   MACRO;       // CHECK-NEXT: File 0, [[@LINE]]:8 -> [[@LINE+2]]:2 = 0
   i = 2;
 }
@@ -21,18 +21,18 @@ void func(void) {  // CHECK-NEXT: File 0, [[@LINE]]:17 -> 
[[@LINE+5]]:2 = #0
 // CHECK-NEXT: func2
 void func2(void) { // CHECK-NEXT: File 0, [[@LINE]]:18 -> [[@LINE+5]]:2 = #0
   int i = 0;
-  // CHECK-NEXT: Expansion,File 0, [[@LINE+1]]:3 -> [[@LINE+1]]:10 = #0
+  // CHECK-NEXT: MacroExpansion,File 0, [[@LINE+1]]:3 -> [[@LINE+1]]:10 = #0
   MACRO_1;     // CHECK-NEXT: File 0, [[@LINE]]:10 -> [[@LINE+2]]:2 = 0
   i = 2;
 }
 // CHECK-NEXT: File 1, 5:17 -> 5:32 = #0
-// CHECK-NEXT: Expansion,File 1, 5:25 -> 5:32 = 0
+// CHECK-NEXT: MacroExpansion,File 1, 5:25 -> 5:32 = 0
 // CHECK-NEXT: File 2, 4:17 -> 4:22 = 0
 
 // CHECK-NEXT: func3
 void func3(void) { // CHECK-NEXT: File 0, [[@LINE]]:18 -> [[@LINE+3]]:2 = #0
-  MACRO_2; // CHECK-NEXT: Expansion,File 0, [[@LINE]]:3 -> [[@LINE]]:10 = #0
-  MACRO_2; // CHECK-NEXT: Expansion,File 0, [[@LINE]]:3 -> [[@LINE]]:10 = #0
+  MACRO_2; // CHECK-NEXT: MacroExpansion,File 0, [[@LINE]]:3 -> [[@LINE]]:10 = 
#0
+  MACRO_2; // CHECK-NEXT: MacroExpansion,File 0, [[@LINE]]:3 -> [[@LINE]]:10 = 
#0
 }
 // CHECK-NEXT: File 1, 4:17 -> 4:22 = #0
 // CHECK-NEXT: File 2, 4:17 -> 4:22 = #0
@@ -45,7 +45,7 @@ void func4(void) { // CHECK-NEXT: File 0, [[@LINE]]:18 -> 
[[@LINE+8]]:2 = #0
                // CHECK-NEXT: File 0, [[@LINE-1]]:9 -> [[@LINE-1]]:14 = #1
                // CHECK-NEXT: Branch,File 0, [[@LINE-2]]:9 -> [[@LINE-2]]:14 = 
#2, (#1 - #2)
                // CHECK-NEXT: Gap,File 0, [[@LINE-3]]:15 -> [[@LINE+1]]:7 = #2
-      MACRO_2; // CHECK-NEXT: Expansion,File 0, [[@LINE]]:7 -> [[@LINE]]:14 = 
#2
+      MACRO_2; // CHECK-NEXT: MacroExpansion,File 0, [[@LINE]]:7 -> 
[[@LINE]]:14 = #2
 }
 // CHECK-NEXT: File 1, 4:17 -> 4:22 = #2
 // CHECK-NOT: File 1
@@ -56,9 +56,9 @@ void func5(void) { // CHECK-NEXT: File 0, [[@LINE]]:18 -> 
[[@LINE+6]]:2 = #0
   if (i > 5) // CHECK-NEXT: File 0, [[@LINE]]:7 -> [[@LINE]]:12 = #0
              // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:7 -> [[@LINE-1]]:12 = 
#1, (#0 - #1)
              // CHECK-NEXT: Gap,File 0, [[@LINE-2]]:13 -> [[@LINE+1]]:5 = #1
-    MACRO_3; // CHECK-NEXT: Expansion,File 0, [[@LINE]]:5 -> [[@LINE]]:12 = #1
+    MACRO_3; // CHECK-NEXT: MacroExpansion,File 0, [[@LINE]]:5 -> [[@LINE]]:12 
= #1
 }
-// CHECK-NEXT: Expansion,File 1, 6:17 -> 6:24 = #1
+// CHECK-NEXT: MacroExpansion,File 1, 6:17 -> 6:24 = #1
 // CHECK-NEXT: File 2, 4:17 -> 4:22 = #1
 
 // CHECK-NEXT: func6
@@ -69,7 +69,7 @@ void func6(unsigned count) { // CHECK-NEXT: File 0, 
[[@LINE]]:28 -> [[@LINE+6]]:
                              // CHECK-NEXT: Gap,File 0, [[@LINE-2]]:17 -> 
[[@LINE+1]]:9 = #2
         GOTO begin;          // CHECK-NEXT: File 0, [[@LINE]]:9 -> 
[[@LINE]]:19 = #2
 }
-// CHECK-NEXT: Expansion,File 0, [[@LINE-2]]:9 -> [[@LINE-2]]:13 = #2
+// CHECK-NEXT: MacroExpansion,File 0, [[@LINE-2]]:9 -> [[@LINE-2]]:13 = #2
 // CHECK-NEXT: File 1, 7:14 -> 7:18 = #2
 
 // Regression test for gap region between macros.
@@ -80,10 +80,10 @@ void func7(void) { // CHECK-NEXT: File 0, [[@LINE]]:18 -> 
[[@LINE+6]]:2 = #0
   int kk,ll;       // CHECK-NEXT: File 0, [[@LINE+1]]:7 -> [[@LINE+1]]:8 = #0
   if (k)           // CHECK-NEXT: Branch,File 0, [[@LINE]]:7 -> [[@LINE]]:8 = 
#1
     m(k);          // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:9 -> [[@LINE]]:5 = #1
-  else             // CHECK-NEXT: Expansion,File 0, [[@LINE-1]]:5 -> 
[[@LINE-1]]:6 = #0
+  else             // CHECK-NEXT: MacroExpansion,File 0, [[@LINE-1]]:5 -> 
[[@LINE-1]]:6 = #0
     l = m(l);      // CHECK-NEXT: Gap,File 0, [[@LINE-2]]:7 -> [[@LINE]]:5 = 
(#0 - #1)
 }                  // CHECK-NEXT: File 0, [[@LINE-1]]:5 -> [[@LINE-1]]:10 = 
(#0 - #1)
-                   // CHECK-NEXT: Expansion,File 0, [[@LINE-2]]:9 -> 
[[@LINE-2]]:10 = (#0 - #1)
+                   // CHECK-NEXT: MacroExpansion,File 0, [[@LINE-2]]:9 -> 
[[@LINE-2]]:10 = (#0 - #1)
                    // CHECK-NEXT: File 1, [[@LINE-9]]:14 -> [[@LINE-9]]:18 = #0
                    // CHECK-NEXT: File 1, [[@LINE-10]]:14 -> [[@LINE-10]]:17 = 
#1
                    // CHECK-NEXT: File 2, [[@LINE-11]]:14 -> [[@LINE-11]]:17 = 
(#0 - #1)
diff --git a/clang/test/CoverageMapping/macroscopes.cpp 
b/clang/test/CoverageMapping/macroscopes.cpp
index 88a72116fa7dc..c7544157710cb 100644
--- a/clang/test/CoverageMapping/macroscopes.cpp
+++ b/clang/test/CoverageMapping/macroscopes.cpp
@@ -37,49 +37,49 @@
 // CHECK-NEXT: File 0, [[@LINE+1]]:12 -> {{[0-9]+}}:2 = #0
 int main() {
   int x = 0;
-  // CHECK-NEXT: Expansion,File 0, [[@LINE+2]]:3 -> [[@LINE+2]]:17 = #0
+  // CHECK-NEXT: MacroExpansion,File 0, [[@LINE+2]]:3 -> [[@LINE+2]]:17 = #0
   // CHECK-NEXT: File 0, [[@LINE+1]]:17 -> [[@LINE+7]]:15 = #1
   starts_a_scope
     x = x;
-    // CHECK-NEXT: Expansion,File 0, [[@LINE+1]]:5 -> [[@LINE+1]]:14 = #1
+    // CHECK-NEXT: MacroExpansion,File 0, [[@LINE+1]]:5 -> [[@LINE+1]]:14 = #1
     some_code
     x = x;
-  // CHECK-NEXT: Expansion,File 0, [[@LINE+1]]:3 -> [[@LINE+1]]:15 = #1
+  // CHECK-NEXT: MacroExpansion,File 0, [[@LINE+1]]:3 -> [[@LINE+1]]:15 = #1
   ends_a_scope
 
-  // CHECK-NEXT: Expansion,File 0, [[@LINE+4]]:3 -> [[@LINE+4]]:17 = #0
+  // CHECK-NEXT: MacroExpansion,File 0, [[@LINE+4]]:3 -> [[@LINE+4]]:17 = #0
   // CHECK-NEXT: File 0, [[@LINE+3]]:17 -> [[@LINE+5]]:15 = #4
-  // CHECK-NEXT: Expansion,File 0, [[@LINE+3]]:5 -> [[@LINE+3]]:14 = #4
-  // CHECK-NEXT: Expansion,File 0, [[@LINE+3]]:3 -> [[@LINE+3]]:15 = #4
+  // CHECK-NEXT: MacroExpansion,File 0, [[@LINE+3]]:5 -> [[@LINE+3]]:14 = #4
+  // CHECK-NEXT: MacroExpansion,File 0, [[@LINE+3]]:3 -> [[@LINE+3]]:15 = #4
   starts_a_scope
     some_code
   ends_a_scope
 
-  // CHECK-NEXT: Expansion,File 0, [[@LINE+3]]:3 -> [[@LINE+3]]:17 = #0
+  // CHECK-NEXT: MacroExpansion,File 0, [[@LINE+3]]:3 -> [[@LINE+3]]:17 = #0
   // CHECK-NEXT: File 0, [[@LINE+2]]:17 -> [[@LINE+3]]:15 = #7
-  // CHECK-NEXT: Expansion,File 0, [[@LINE+2]]:3 -> [[@LINE+2]]:15 = #7
+  // CHECK-NEXT: MacroExpansion,File 0, [[@LINE+2]]:3 -> [[@LINE+2]]:15 = #7
   starts_a_scope
   ends_a_scope
 
-  // CHECK-NEXT: Expansion,File 0, [[@LINE+3]]:3 -> [[@LINE+3]]:17 = #0
+  // CHECK-NEXT: MacroExpansion,File 0, [[@LINE+3]]:3 -> [[@LINE+3]]:17 = #0
   // CHECK-NEXT: Gap,File 0, [[@LINE+2]]:17 -> [[@LINE+3]]:5 = #8
-  // CHECK-NEXT: Expansion,File 0, [[@LINE+2]]:5 -> [[@LINE+2]]:16 = #8
+  // CHECK-NEXT: MacroExpansion,File 0, [[@LINE+2]]:5 -> [[@LINE+2]]:16 = #8
   starts_a_while
     simple_stmt;
 
   x = 0;
-  // CHECK-NEXT: Expansion,File 0, [[@LINE+5]]:3 -> [[@LINE+5]]:17 = #0
+  // CHECK-NEXT: MacroExpansion,File 0, [[@LINE+5]]:3 -> [[@LINE+5]]:17 = #0
   // CHECK-NEXT: Gap,File 0, [[@LINE+4]]:17 -> [[@LINE+4]]:18 = #9
   // CHECK-NEXT: File 0, [[@LINE+3]]:18 -> [[@LINE+5]]:15 = #9
-  // CHECK-NEXT: Expansion,File 0, [[@LINE+3]]:5 -> [[@LINE+3]]:16 = #9
-  // CHECK-NEXT: Expansion,File 0, [[@LINE+3]]:3 -> [[@LINE+3]]:15 = #9
+  // CHECK-NEXT: MacroExpansion,File 0, [[@LINE+3]]:5 -> [[@LINE+3]]:16 = #9
+  // CHECK-NEXT: MacroExpansion,File 0, [[@LINE+3]]:3 -> [[@LINE+3]]:15 = #9
   starts_a_while {
     simple_stmt;
   ends_a_scope
 
-  // CHECK-NEXT: Expansion,File 0, [[@LINE+1]]:3 -> [[@LINE+1]]:17 = #0
+  // CHECK-NEXT: MacroExpansion,File 0, [[@LINE+1]]:3 -> [[@LINE+1]]:17 = #0
   macro_with_for
-  // CHECK-NEXT: Expansion,File 0, [[@LINE+1]]:3 -> [[@LINE+1]]:19 = #0
+  // CHECK-NEXT: MacroExpansion,File 0, [[@LINE+1]]:3 -> [[@LINE+1]]:19 = #0
   macro_with_while
 
   return 0;
diff --git a/clang/test/CoverageMapping/mcdc-scratch-space.c 
b/clang/test/CoverageMapping/mcdc-scratch-space.c
index 60e456948a518..0229f79a49c3e 100644
--- a/clang/test/CoverageMapping/mcdc-scratch-space.c
+++ b/clang/test/CoverageMapping/mcdc-scratch-space.c
@@ -19,7 +19,7 @@ int builtin_macro1(int a) {
 // CHECK: pre0:
 int pre0(int pre_a, int b_post) {
   // CHECK: Decision,File 0, [[@LINE+2]]:11 -> [[@LINE+3]]:20 = M:3, C:2
-  // CHECK: Expansion,File 0, [[@LINE+1]]:11 -> [[@LINE+1]]:14 = #0 (Expanded 
file = 1)
+  // CHECK: MacroExpansion,File 0, [[@LINE+1]]:11 -> [[@LINE+1]]:14 = #0 
(Expanded file = 1)
   return (PRE(a)
           && b_post);
   // CHECK: Branch,File 0, [[@LINE-1]]:14 -> [[@LINE-1]]:20 = #2, (#1 - #2) 
[2,0,0]
@@ -31,11 +31,11 @@ int pre0(int pre_a, int b_post) {
 // CHECK: pre1:
 int pre1(int pre_a, int b_post) {
   // CHECK: Decision,File 0, [[@LINE+3]]:11 -> [[@LINE+4]]:20 = M:3, C:2
-  // CHECK: Expansion,File 0, [[@LINE+2]]:11 -> [[@LINE+2]]:14 = #0 (Expanded 
file = 1)
+  // CHECK: MacroExpansion,File 0, [[@LINE+2]]:11 -> [[@LINE+2]]:14 = #0 
(Expanded file = 1)
   // CHECK: Branch,File 0, [[@LINE+2]]:14 -> [[@LINE+2]]:20 = #2, (#1 - #2) 
[2,0,0]
   return (PRE(foo)
           && b_post);
-  // CHECK: Expansion,File 1, 17:16 -> 17:20 = #0 (Expanded file = 2)
+  // CHECK: MacroExpansion,File 1, 17:16 -> 17:20 = #0 (Expanded file = 2)
   // CHECK: Branch,File 2, 29:17 -> 29:22 = #1, (#0 - #1) [1,2,0]
 }
 
@@ -47,7 +47,7 @@ int post0(int pre_a, int b_post) {
   // CHECK: Branch,File 0, [[@LINE+1]]:11 -> [[@LINE+1]]:16 = (#0 - #1), #1 
[1,0,2]
   return (pre_a
           || POST(b));
-  // CHECK: Expansion,File 0, [[@LINE-1]]:14 -> [[@LINE-1]]:18 = #1 (Expanded 
file = 1)
+  // CHECK: MacroExpansion,File 0, [[@LINE-1]]:14 -> [[@LINE-1]]:18 = #1 
(Expanded file = 1)
   // CHECK: Branch,File 1, [[@LINE-9]]:17 -> [[@LINE-9]]:20 = (#1 - #2), #2 
[2,0,0]
 }
 
@@ -57,9 +57,9 @@ int post0(int pre_a, int b_post) {
 int post1(int pre_a, int b_post) {
   // CHECK: Decision,File 0, [[@LINE+3]]:11 -> [[@LINE+4]]:18 = M:3, C:2
   // CHECK: Branch,File 0, [[@LINE+2]]:11 -> [[@LINE+2]]:16 = (#0 - #1), #1 
[1,0,2]
-  // CHECK: Expansion,File 0, [[@LINE+2]]:14 -> [[@LINE+2]]:18 = 0 (Expanded 
file = 1)
+  // CHECK: MacroExpansion,File 0, [[@LINE+2]]:14 -> [[@LINE+2]]:18 = 0 
(Expanded file = 1)
   return (pre_a
           || POST(bar));
-  // CHECK: Expansion,File 1, 42:17 -> 42:18 = #1 (Expanded file = 2)
+  // CHECK: MacroExpansion,File 1, 42:17 -> 42:18 = #1 (Expanded file = 2)
   // CHECK: Branch,File 2, 54:18 -> 54:24 = (#1 - #2), #2 [2,0,0]
 }
diff --git a/clang/test/CoverageMapping/mcdc-system-headers.cpp 
b/clang/test/CoverageMapping/mcdc-system-headers.cpp
index cb1c8743c36e8..379550387f5db 100644
--- a/clang/test/CoverageMapping/mcdc-system-headers.cpp
+++ b/clang/test/CoverageMapping/mcdc-system-headers.cpp
@@ -16,7 +16,7 @@
 // CHECK: _Z5func0i:
 int func0(int a) {
   // CHECK: Decision,File 0, [[@LINE+3]]:11 -> [[@LINE+3]]:21 = M:3, C:2
-  // W_SYS: Expansion,File 0, [[@LINE+2]]:11 -> [[@LINE+2]]:16 = #0 (Expanded 
file = 1)
+  // W_SYS: MacroExpansion,File 0, [[@LINE+2]]:11 -> [[@LINE+2]]:16 = #0 
(Expanded file = 1)
   // X_SYS: Branch,File 0, [[@LINE+1]]:11 -> [[@LINE+1]]:11 = #1, 0 [1,2,0]
   return (CONST && a);
   // CHECK: Branch,File 0, [[@LINE-1]]:20 -> [[@LINE-1]]:21 = #2, (#1 - #2) 
[2,0,0]
@@ -28,7 +28,7 @@ int func1(int a, int b) {
   // CHECK: Decision,File 0, [[@LINE+2]]:11 -> [[@LINE+2]]:21 = M:3, C:2
   // CHECK: Branch,File 0, [[@LINE+1]]:11 -> [[@LINE+1]]:12 = (#0 - #1), #1 
[1,0,2]
   return (a || EXPR1(b));
-  // W_SYS: Expansion,File 0, [[@LINE-1]]:16 -> [[@LINE-1]]:21 = #1 (Expanded 
file = 1)
+  // W_SYS: MacroExpansion,File 0, [[@LINE-1]]:16 -> [[@LINE-1]]:21 = #1 
(Expanded file = 1)
   // W_SYS: Branch,File 1, [[@LINE-24]]:18 -> [[@LINE-24]]:21 = (#1 - #2), #2 
[2,0,0]
   // X_SYS: Branch,File 0, [[@LINE-3]]:16 -> [[@LINE-3]]:16 = (#1 - #2), #2 
[2,0,0]
 }
@@ -37,8 +37,8 @@ int func1(int a, int b) {
 int func2(int a, int b) {
   // W_SYS: Decision,File 0, [[@LINE+5]]:11 -> [[@LINE+5]]:28 = M:4, C:3
   // X_SYS: Decision,File 0, [[@LINE+4]]:11 -> [[@LINE+4]]:28 = M:3, C:2
-  // W_SYS: Expansion,File 0, [[@LINE+3]]:11 -> [[@LINE+3]]:16 = #0 (Expanded 
file = 1)
-  // W_SYS: Expansion,File 0, [[@LINE+2]]:23 -> [[@LINE+2]]:28 = #1 (Expanded 
file = 2)
+  // W_SYS: MacroExpansion,File 0, [[@LINE+3]]:11 -> [[@LINE+3]]:16 = #0 
(Expanded file = 1)
+  // W_SYS: MacroExpansion,File 0, [[@LINE+2]]:23 -> [[@LINE+2]]:28 = #1 
(Expanded file = 2)
   // X_SYS: Branch,File 0, [[@LINE+1]]:11 -> [[@LINE+1]]:11 = #1, (#0 - #1) 
[1,2,0]
   return (EXPR2(a) && EXPR1(a));
   // W_SYS: Branch,File 1, [[@LINE-35]]:19 -> [[@LINE-35]]:22 = #3, (#0 - #3) 
[1,3,0]
diff --git a/clang/test/CoverageMapping/moremacros.c 
b/clang/test/CoverageMapping/moremacros.c
index 64e5c62bfac37..8ceadc99b5153 100644
--- a/clang/test/CoverageMapping/moremacros.c
+++ b/clang/test/CoverageMapping/moremacros.c
@@ -12,18 +12,18 @@ int main(int argc, const char *argv[]) {
   // CHECK-NEXT: File 0, [[@LINE+5]]:7 -> [[@LINE+5]]:12 = #0
   // CHECK-NEXT: Branch,File 0, [[@LINE+4]]:7 -> [[@LINE+4]]:12 = #2, (#0 - #2)
   // CHECK-NEXT: Gap,File 0, [[@LINE+3]]:13 -> [[@LINE+3]]:14 = #2
-  // CHECK-NEXT: Expansion,File 0, [[@LINE+2]]:14 -> [[@LINE+2]]:19 = #2
+  // CHECK-NEXT: MacroExpansion,File 0, [[@LINE+2]]:14 -> [[@LINE+2]]:19 = #2
   // CHECK-NEXT: File 0, [[@LINE+1]]:19 -> [[@LINE+4]]:8 = #2
   if (!argc) LBRAC
     return 0;
-  // CHECK-NEXT: Expansion,File 0, [[@LINE+1]]:3 -> [[@LINE+1]]:8 = #2
+  // CHECK-NEXT: MacroExpansion,File 0, [[@LINE+1]]:3 -> [[@LINE+1]]:8 = #2
   RBRAC // CHECK-NEXT: [[@LINE]]:8 -> [[@LINE+8]]:3 = (#0 - #2)
 
   // CHECK-NEXT: File 0, [[@LINE+6]]:3 -> [[@LINE+17]]:2 = (#0 - #2)
   // CHECK-NEXT: File 0, [[@LINE+5]]:7 -> [[@LINE+5]]:12 = (#0 - #2)
   // CHECK-NEXT: Branch,File 0, [[@LINE+4]]:7 -> [[@LINE+4]]:12 = #3, ((#0 - 
#2) - #3)
   // CHECK-NEXT: Gap,File 0, [[@LINE+3]]:13 -> [[@LINE+3]]:14 = #3
-  // CHECK-NEXT: Expansion,File 0, [[@LINE+2]]:14 -> [[@LINE+2]]:19 = #3
+  // CHECK-NEXT: MacroExpansion,File 0, [[@LINE+2]]:14 -> [[@LINE+2]]:19 = #3
   // CHECK-NEXT: File 0, [[@LINE+1]]:19 -> [[@LINE+3]]:4 = #3
   if (!argc) LBRAC
     return 0;
@@ -34,7 +34,7 @@ int main(int argc, const char *argv[]) {
   // CHECK: File 0, [[@LINE+1]]:14 -> [[@LINE+4]]:8 = #4
   if (!argc) {
     return 0;
-  // CHECK-NEXT: Expansion,File 0, [[@LINE+1]]:3 -> [[@LINE+1]]:8 = #4
+  // CHECK-NEXT: MacroExpansion,File 0, [[@LINE+1]]:3 -> [[@LINE+1]]:8 = #4
   RBRAC
 }
 
diff --git a/clang/test/CoverageMapping/switchmacro.c 
b/clang/test/CoverageMapping/switchmacro.c
index 4c98cc7d9403a..7e524ba2c8d13 100644
--- a/clang/test/CoverageMapping/switchmacro.c
+++ b/clang/test/CoverageMapping/switchmacro.c
@@ -11,14 +11,14 @@ int foo(int i) { // CHECK-NEXT: File 0, [[@LINE]]:16 -> 
{{[0-9]+}}:2 = #0
                  // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:9 -> [[@LINE-1]]:15 
= #3, (#2 - #3)
       return 0;  // CHECK: File 0, [[@LINE]]:7 -> [[@LINE]]:15 = #3
                  // CHECK-NEXT: File 0, [[@LINE-1]]:16 -> [[@LINE+3]]:5 = (#2 
- #3)
-    // CHECK-NEXT: Expansion,File 0, [[@LINE+2]]:5 -> [[@LINE+2]]:8 = (#2 - 
#3) (Expanded file = 1)
+    // CHECK-NEXT: MacroExpansion,File 0, [[@LINE+2]]:5 -> [[@LINE+2]]:8 = (#2 
- #3) (Expanded file = 1)
     // CHECK-NEXT: File 0, [[@LINE+1]]:8 -> {{[0-9]+}}:11 = (#2 - #3)
     FOO(1);
   case 0:        // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+2]]:13 = ((#2 + 
#4) - #3)
                  // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 
= #4, (#0 - #4)
     return 2;    // CHECK-NEXT: Gap,File 0, [[@LINE]]:14 -> [[@LINE+4]]:3 = 0
 
-  // CHECK-NEXT: Expansion,File 0, [[@LINE+2]]:3 -> [[@LINE+2]]:6 = 0
+  // CHECK-NEXT: MacroExpansion,File 0, [[@LINE+2]]:3 -> [[@LINE+2]]:6 = 0
   // CHECK-NEXT: File 0, [[@LINE+1]]:6 -> {{[0-9]+}}:11 = 0
   FOO(1);
   // CHECK-NEXT: File 0, [[@LINE+1]]:3 -> {{[0-9]+}}:11 = #5
@@ -41,7 +41,7 @@ default: ;
 #define START2 switch (0) default:
 void baz(void) {
   for (;;)
-    START2 return; // CHECK: Expansion,File 0, [[@LINE]]:5 -> [[@LINE]]:11 = 
#1 (Expanded file = 1)
+    START2 return; // CHECK: MacroExpansion,File 0, [[@LINE]]:5 -> 
[[@LINE]]:11 = #1 (Expanded file = 1)
 }
 
 int main(int argc, const char *argv[]) {
diff --git a/clang/test/CoverageMapping/system_macro.cpp 
b/clang/test/CoverageMapping/system_macro.cpp
index 38bbb2efb7075..3c778b3f1e86d 100644
--- a/clang/test/CoverageMapping/system_macro.cpp
+++ b/clang/test/CoverageMapping/system_macro.cpp
@@ -30,12 +30,12 @@ template <bool f> bool SysTmpl() { return f; }
 // CHECK-LABEL: doSomething
 void doSomething(int x) { // CHECK: File 0, [[@LINE]]:25 -> {{[0-9:]+}} = #0
   // WOSYS-NOT: Expansion,
-  // W_SYS: Expansion,File 0, [[@LINE+1]]:3 -> [[@LINE+1]]:7
+  // W_SYS: MacroExpansion,File 0, [[@LINE+1]]:3 -> [[@LINE+1]]:7
   Func(x);
   // CHECK: Gap,File 0, [[@LINE+1]]:10
   return;
   // WOSYS-NOT: Expansion,
-  // W_SYS: Expansion,File 0, [[@LINE+1]]:3 -> [[@LINE+1]]:11
+  // W_SYS: MacroExpansion,File 0, [[@LINE+1]]:3 -> [[@LINE+1]]:11
   SomeType *f; // CHECK: File 0, [[@LINE]]:11 -> {{[0-9:]+}} = 0
 }
 
diff --git a/clang/test/CoverageMapping/trymacro.cpp 
b/clang/test/CoverageMapping/trymacro.cpp
index 22de2ccb07769..0c69299ef59b4 100644
--- a/clang/test/CoverageMapping/trymacro.cpp
+++ b/clang/test/CoverageMapping/trymacro.cpp
@@ -19,7 +19,7 @@ CATCH(...) {}              // CHECK: [[@LINE]]:12 -> 
[[@LINE]]:14 = #2
 
 // CHECK: Z3fn4v:
 #define TRY2 try { // CHECK-DAG: File 1, [[@LINE]]:18 -> [[@LINE]]:19 = #1
-void fn4() TRY2 // CHECK-DAG: Expansion,File 0, [[@LINE]]:12 -> [[@LINE]]:16 = 
#1 (Expanded file = 1)
+void fn4() TRY2 // CHECK-DAG: MacroExpansion,File 0, [[@LINE]]:12 -> 
[[@LINE]]:16 = #1 (Expanded file = 1)
   for (;;)
     return;
 }
@@ -27,10 +27,10 @@ catch (...) {}
 
 // CHECK: Z3fn5v:
 #define TRY3 try { return; } catch (...) // CHECK-DAG: File 2, [[@LINE]]:18 -> 
[[@LINE]]:29 = #1
-#define TRY4 try { TRY3 { return; } } catch (...) // CHECK-DAG: Expansion,File 
1, [[@LINE]]:20 -> [[@LINE]]:24 = #1 (Expanded file = 2)
+#define TRY4 try { TRY3 { return; } } catch (...) // CHECK-DAG: 
MacroExpansion,File 1, [[@LINE]]:20 -> [[@LINE]]:24 = #1 (Expanded file = 2)
 void fn5() {
   for (;;) {
-    TRY4 { return; } // CHECK-DAG: Expansion,File 0, [[@LINE]]:5 -> 
[[@LINE]]:9 = #1 (Expanded file = 1)
+    TRY4 { return; } // CHECK-DAG: MacroExpansion,File 0, [[@LINE]]:5 -> 
[[@LINE]]:9 = #1 (Expanded file = 1)
   }                  // CHECK-DAG: File 0, [[@LINE-1]]:10 -> [[@LINE-1]]:21 = 
#5
 }
 
diff --git a/clang/test/CoverageMapping/unreachable-macro.c 
b/clang/test/CoverageMapping/unreachable-macro.c
index 7956c973f6ce8..04a70c7458392 100644
--- a/clang/test/CoverageMapping/unreachable-macro.c
+++ b/clang/test/CoverageMapping/unreachable-macro.c
@@ -7,7 +7,7 @@ void counters_in_macro_following_unreachable(void) {
   // CHECK-NEXT: File 0, [[@LINE-1]]:52 -> {{[0-9]+}}:2 = #0
   return;
   // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:10 -> [[@LINE+3]]:3 = 0
-  // CHECK-NEXT: Expansion,File 0, [[@LINE+2]]:3 -> [[@LINE+2]]:8 = 0
+  // CHECK-NEXT: MacroExpansion,File 0, [[@LINE+2]]:3 -> [[@LINE+2]]:8 = 0
   // CHECK-NEXT: File 0, [[@LINE+1]]:8 -> [[@LINE+2]]:2 = 0
   WHILE
 }
diff --git a/compiler-rt/include/profile/InstrProfData.inc 
b/compiler-rt/include/profile/InstrProfData.inc
index 8c092b5e0868b..be01da0b99994 100644
--- a/compiler-rt/include/profile/InstrProfData.inc
+++ b/compiler-rt/include/profile/InstrProfData.inc
@@ -756,7 +756,7 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure,
 /* Indexed profile format version (start from 1). */
 #define INSTR_PROF_INDEX_VERSION 13
 /* Coverage mapping format version (start from 0). */
-#define INSTR_PROF_COVMAP_VERSION 6
+#define INSTR_PROF_COVMAP_VERSION 7
 
 /* Profile version is always of type uint64_t. Reserve the upper 32 bits in the
  * version for other variants of profile. We set the 8th most significant bit
diff --git a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h 
b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
index a664b6b5fa560..bb2630da8a2a1 100644
--- a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
+++ b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
@@ -113,6 +113,15 @@ struct Counter {
   static const unsigned EncodingTagMask = 0x3;
   static const unsigned EncodingCounterTagAndExpansionRegionTagBits =
       EncodingTagBits + 1;
+  // Bit 2 is used to mark ExpansionRegion (both ExpansionRegion and
+  // MacroExpansionRegion). Bit 3 is used to distinguish MacroExpansionRegion
+  // from ExpansionRegion (Version8+). ExpandedFileID starts at bit 4 for both
+  // types.
+  static const unsigned EncodingExpansionRegionBit = 1 << EncodingTagBits;
+  static const unsigned EncodingMacroExpansionRegionBit =
+      1 << EncodingCounterTagAndExpansionRegionTagBits;
+  static const unsigned EncodingTagBitsMacroExpansion =
+      EncodingCounterTagAndExpansionRegionTagBits + 1;
 
 private:
   CounterKind Kind = Zero;
@@ -257,7 +266,13 @@ struct CounterMappingRegion {
     MCDCDecisionRegion,
 
     /// A Branch Region can be extended to include IDs to facilitate MC/DC.
-    MCDCBranchRegion
+    MCDCBranchRegion,
+
+    /// A MacroExpansionRegion is like an ExpansionRegion but specifically
+    /// represents a macro expansion (as opposed to an #include).
+    /// Added in Version8 to distinguish macro expansions from includes.
+    /// Must be at the end to preserve binary compatibility with old files.
+    MacroExpansionRegion
   };
 
   /// Primary Counter that is also used for Branch Regions (TrueCount).
@@ -287,6 +302,12 @@ struct CounterMappingRegion {
     return (Kind == BranchRegion || Kind == MCDCBranchRegion);
   }
 
+  bool isExpansion() const {
+    return Kind == ExpansionRegion || Kind == MacroExpansionRegion;
+  }
+
+  bool isMacroExpansion() const { return Kind == MacroExpansionRegion; }
+
   CounterMappingRegion(Counter Count, unsigned FileID, unsigned ExpandedFileID,
                        unsigned LineStart, unsigned ColumnStart,
                        unsigned LineEnd, unsigned ColumnEnd, RegionKind Kind)
@@ -321,10 +342,11 @@ struct CounterMappingRegion {
 
   static CounterMappingRegion
   makeExpansion(unsigned FileID, unsigned ExpandedFileID, unsigned LineStart,
-                unsigned ColumnStart, unsigned LineEnd, unsigned ColumnEnd) {
-    return CounterMappingRegion(Counter(), FileID, ExpandedFileID, LineStart,
-                                ColumnStart, LineEnd, ColumnEnd,
-                                ExpansionRegion);
+                unsigned ColumnStart, unsigned LineEnd, unsigned ColumnEnd,
+                bool IsMacro = false) {
+    return CounterMappingRegion(
+        Counter(), FileID, ExpandedFileID, LineStart, ColumnStart, LineEnd,
+        ColumnEnd, IsMacro ? MacroExpansionRegion : ExpansionRegion);
   }
 
   static CounterMappingRegion
@@ -1484,7 +1506,10 @@ enum CovMapVersion {
   Version6 = 5,
   // Branch regions extended and Decision Regions added for MC/DC.
   Version7 = 6,
-  // The current version is Version7.
+  // MacroExpansionRegion kind added to distinguish macro expansions
+  // from #include expansions.
+  Version8 = 7,
+  // The current version is Version8.
   CurrentVersion = INSTR_PROF_COVMAP_VERSION
 };
 
diff --git a/llvm/include/llvm/ProfileData/Coverage/CoverageMappingReader.h 
b/llvm/include/llvm/ProfileData/Coverage/CoverageMappingReader.h
index e91ba9147a745..2f08131a70247 100644
--- a/llvm/include/llvm/ProfileData/Coverage/CoverageMappingReader.h
+++ b/llvm/include/llvm/ProfileData/Coverage/CoverageMappingReader.h
@@ -135,17 +135,19 @@ class RawCoverageMappingReader : public RawCoverageReader 
{
   std::vector<StringRef> &Filenames;
   std::vector<CounterExpression> &Expressions;
   std::vector<CounterMappingRegion> &MappingRegions;
+  CovMapVersion Version;
 
 public:
-  RawCoverageMappingReader(StringRef MappingData,
-                           ArrayRef<std::string> &TranslationUnitFilenames,
-                           std::vector<StringRef> &Filenames,
-                           std::vector<CounterExpression> &Expressions,
-                           std::vector<CounterMappingRegion> &MappingRegions)
+  RawCoverageMappingReader(
+      StringRef MappingData, ArrayRef<std::string> &TranslationUnitFilenames,
+      std::vector<StringRef> &Filenames,
+      std::vector<CounterExpression> &Expressions,
+      std::vector<CounterMappingRegion> &MappingRegions,
+      CovMapVersion Version = CovMapVersion::CurrentVersion)
       : RawCoverageReader(MappingData),
         TranslationUnitFilenames(TranslationUnitFilenames),
         Filenames(Filenames), Expressions(Expressions),
-        MappingRegions(MappingRegions) {}
+        MappingRegions(MappingRegions), Version(Version) {}
   RawCoverageMappingReader(const RawCoverageMappingReader &) = delete;
   RawCoverageMappingReader &
   operator=(const RawCoverageMappingReader &) = delete;
diff --git a/llvm/include/llvm/ProfileData/InstrProfData.inc 
b/llvm/include/llvm/ProfileData/InstrProfData.inc
index 8c092b5e0868b..be01da0b99994 100644
--- a/llvm/include/llvm/ProfileData/InstrProfData.inc
+++ b/llvm/include/llvm/ProfileData/InstrProfData.inc
@@ -756,7 +756,7 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure,
 /* Indexed profile format version (start from 1). */
 #define INSTR_PROF_INDEX_VERSION 13
 /* Coverage mapping format version (start from 0). */
-#define INSTR_PROF_COVMAP_VERSION 6
+#define INSTR_PROF_COVMAP_VERSION 7
 
 /* Profile version is always of type uint64_t. Reserve the upper 32 bits in the
  * version for other variants of profile. We set the 8th most significant bit
diff --git a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp 
b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
index 0d9a5a6758f06..f2d82015b072c 100644
--- a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
+++ b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
@@ -766,7 +766,7 @@ struct CountedRegionEmitter {
         Files.resize(Region.FileID + 1);
       }
       Files[Region.FileID].LastIndex = I + 1;
-      if (Region.Kind == CounterMappingRegion::ExpansionRegion) {
+      if (Region.isExpansion()) {
         if (Region.ExpandedFileID >= Files.size()) {
           // Extend (only possible in CoverageMappingTests)
           Files.resize(Region.ExpandedFileID + 1);
@@ -799,7 +799,7 @@ struct CountedRegionEmitter {
       if (Region.FileID != Idx)
         break;
 
-      if (Region.Kind == CounterMappingRegion::ExpansionRegion)
+      if (Region.isExpansion())
         if (auto E = walk(Region.ExpandedFileID))
           return E;
 
@@ -1454,7 +1454,7 @@ findMainViewFileID(const FunctionRecord &Function) {
     return std::nullopt;
   SmallBitVector IsNotExpandedFile(Function.Filenames.size(), true);
   for (const auto &CR : Function.CountedRegions)
-    if (CR.Kind == CounterMappingRegion::ExpansionRegion)
+    if (CR.isExpansion())
       IsNotExpandedFile[CR.ExpandedFileID] = false;
   int I = IsNotExpandedFile.find_first();
   if (I == -1)
@@ -1474,7 +1474,7 @@ findMainViewFileID(StringRef SourceFile, const 
FunctionRecord &Function) {
 }
 
 static bool isExpansion(const CountedRegion &R, unsigned FileID) {
-  return R.Kind == CounterMappingRegion::ExpansionRegion && R.FileID == FileID;
+  return R.isExpansion() && R.FileID == FileID;
 }
 
 CoverageData CoverageMapping::getCoverageForFile(StringRef Filename) const {
diff --git a/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp 
b/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp
index e89efe09d49e8..8b5b157225d65 100644
--- a/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp
+++ b/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp
@@ -275,9 +275,24 @@ Error RawCoverageMappingReader::readMappingRegionsSubArray(
     } else {
       // Is it an expansion region?
       if (EncodedCounterAndRegion & EncodingExpansionRegionBit) {
-        Kind = CounterMappingRegion::ExpansionRegion;
-        ExpandedFileID = EncodedCounterAndRegion >>
-                         Counter::EncodingCounterTagAndExpansionRegionTagBits;
+        // Version8+: bit 2 marks expansion, bit 3 distinguishes macro, FileID
+        // at bit 4+ Version < 8: bit 2 marks expansion, FileID at bit 3+
+        if (Version >= CovMapVersion::Version8) {
+          // Check for macro expansion: bit 3 is set for MacroExpansionRegion
+          if (EncodedCounterAndRegion &
+              Counter::EncodingMacroExpansionRegionBit) {
+            Kind = CounterMappingRegion::MacroExpansionRegion;
+          } else {
+            Kind = CounterMappingRegion::ExpansionRegion;
+          }
+          ExpandedFileID =
+              EncodedCounterAndRegion >> 
Counter::EncodingTagBitsMacroExpansion;
+        } else {
+          // Pre-Version8: all expansions are ExpansionRegion, FileID at bit 3+
+          Kind = CounterMappingRegion::ExpansionRegion;
+          ExpandedFileID = EncodedCounterAndRegion >>
+                           
Counter::EncodingCounterTagAndExpansionRegionTagBits;
+        }
         if (ExpandedFileID >= NumFileIDs)
           return make_error<CoverageMapError>(coveragemap_error::malformed,
                                               "ExpandedFileID is invalid");
@@ -375,8 +390,12 @@ Error RawCoverageMappingReader::readMappingRegionsSubArray(
       dbgs() << "Counter in file " << InferredFileID << " " << LineStart << ":"
              << ColumnStart << " -> " << (LineStart + NumLines) << ":"
              << ColumnEnd << ", ";
-      if (Kind == CounterMappingRegion::ExpansionRegion)
-        dbgs() << "Expands to file " << ExpandedFileID;
+      if (Kind == CounterMappingRegion::ExpansionRegion ||
+          Kind == CounterMappingRegion::MacroExpansionRegion)
+        dbgs() << "Expands to file " << ExpandedFileID
+               << (Kind == CounterMappingRegion::MacroExpansionRegion
+                       ? " (macro)"
+                       : "");
       else
         CounterMappingContext(Expressions).dump(C, dbgs());
       dbgs() << "\n";
@@ -446,7 +465,7 @@ Error RawCoverageMappingReader::read() {
   FileIDExpansionRegionMapping.resize(VirtualFileMapping.size(), nullptr);
   for (;;) {
     for (auto &R : MappingRegions) {
-      if (R.Kind != CounterMappingRegion::ExpansionRegion)
+      if (!R.isExpansion())
         continue;
       assert(!FileIDExpansionRegionMapping[R.ExpandedFileID]);
       FileIDExpansionRegionMapping[R.ExpandedFileID] = &R;
@@ -837,6 +856,7 @@ Expected<std::unique_ptr<CovMapFuncRecordReader>> 
CovMapFuncRecordReader::get(
   case CovMapVersion::Version5:
   case CovMapVersion::Version6:
   case CovMapVersion::Version7:
+  case CovMapVersion::Version8:
     // Decompress the name data.
     if (Error E = P.create(P.getNameData()))
       return std::move(E);
@@ -858,6 +878,9 @@ Expected<std::unique_ptr<CovMapFuncRecordReader>> 
CovMapFuncRecordReader::get(
     else if (Version == CovMapVersion::Version7)
       return std::make_unique<VersionedCovMapFuncRecordReader<
           CovMapVersion::Version7, IntPtrT, Endian>>(P, R, D, F);
+    else if (Version == CovMapVersion::Version8)
+      return std::make_unique<VersionedCovMapFuncRecordReader<
+          CovMapVersion::Version8, IntPtrT, Endian>>(P, R, D, F);
   }
   llvm_unreachable("Unsupported version");
 }
@@ -1375,7 +1398,7 @@ Error 
BinaryCoverageReader::readNextRecord(CoverageMappingRecord &Record) {
   auto &R = MappingRecords[CurrentRecord];
   auto F = ArrayRef(Filenames).slice(R.FilenamesBegin, R.FilenamesSize);
   RawCoverageMappingReader Reader(R.CoverageMapping, F, FunctionsFilenames,
-                                  Expressions, MappingRegions);
+                                  Expressions, MappingRegions, R.Version);
   if (auto Err = Reader.read())
     return Err;
 
diff --git a/llvm/lib/ProfileData/Coverage/CoverageMappingWriter.cpp 
b/llvm/lib/ProfileData/Coverage/CoverageMappingWriter.cpp
index dc97870985145..ca5d7a3627e58 100644
--- a/llvm/lib/ProfileData/Coverage/CoverageMappingWriter.cpp
+++ b/llvm/lib/ProfileData/Coverage/CoverageMappingWriter.cpp
@@ -225,17 +225,19 @@ void CoverageMappingWriter::write(raw_ostream &OS) {
     case CounterMappingRegion::GapRegion:
       writeCounter(MinExpressions, Count, OS);
       break;
-    case CounterMappingRegion::ExpansionRegion: {
+    case CounterMappingRegion::ExpansionRegion:
+    case CounterMappingRegion::MacroExpansionRegion: {
       assert(Count.isZero());
-      assert(I->ExpandedFileID <=
-             (std::numeric_limits<unsigned>::max() >>
-              Counter::EncodingCounterTagAndExpansionRegionTagBits));
-      // Mark an expansion region with a set bit that follows the counter tag,
-      // and pack the expanded file id into the remaining bits.
+      // Both ExpansionRegion and MacroExpansionRegion use the same encoding:
+      // - bit 2: ExpansionRegionBit (set for both types)
+      // - bit 3: MacroExpansionRegionBit (set only for MacroExpansionRegion)
+      // - bit 4+: ExpandedFileID
+      bool IsMacro = I->Kind == CounterMappingRegion::MacroExpansionRegion;
       unsigned EncodedTagExpandedFileID =
-          (1 << Counter::EncodingTagBits) |
-          (I->ExpandedFileID
-           << Counter::EncodingCounterTagAndExpansionRegionTagBits);
+          Counter::EncodingExpansionRegionBit |
+          (I->ExpandedFileID << Counter::EncodingTagBitsMacroExpansion);
+      if (IsMacro)
+        EncodedTagExpandedFileID |= Counter::EncodingMacroExpansionRegionBit;
       encodeULEB128(EncodedTagExpandedFileID, OS);
       break;
     }
diff --git a/llvm/test/tools/llvm-cov/Inputs/macro-filter-test.c 
b/llvm/test/tools/llvm-cov/Inputs/macro-filter-test.c
new file mode 100644
index 0000000000000..bafc6af355d5f
--- /dev/null
+++ b/llvm/test/tools/llvm-cov/Inputs/macro-filter-test.c
@@ -0,0 +1,24 @@
+// Simple test for --ignore-branch-in-macro
+// This file is compiled to generate test input data
+
+#define MY_ABS(x) ((x) >= 0 ? (x) : -(x))
+#define MY_MAX(a, b) ((a) > (b) ? (a) : (b))
+
+int test_function(int val) {
+    // Macro branches - should be filtered with --ignore-branch-in-macro
+    int abs_val = MY_ABS(val);
+    int max_val = MY_MAX(val, 5);
+
+    // Source-level branches - always counted
+    if (val > 0) {
+        return abs_val + max_val;
+    }
+    return 0;
+}
+
+int main() {
+    test_function(1);
+    test_function(-1);
+    test_function(10);
+    return 0;
+}
diff --git a/llvm/test/tools/llvm-cov/Inputs/macro-filter-test.o 
b/llvm/test/tools/llvm-cov/Inputs/macro-filter-test.o
new file mode 100644
index 
0000000000000000000000000000000000000000..2fc016fe8251e602b3479bcdb13508e5ef8102b2
GIT binary patch
literal 3664
zcmbtWeQZ-z6u<YCuI)ylY#<2JJuoOZ`fRs#w20aP9Ys+Ikpxj}-ukgk`Z2mUGKpZ#
zfTS!CLj1sl#27`5Q3F8}{xJ;D5X}%Z5)C8<6N!r>5e-o!OXfMR_jGS>um9*t?mOrF
z&OP^>bMLvgeJQfOUE<uv1abB-<D?k)2Iqtl*2OTJ2QxQCi`R;~Zbb*}2u25nc(kaC
z1G{dq7w1pK2P3zNk?W&Q|4^eY4MwgPBR65TeRrkVBcs))aLr<5WRwj?Mv9Rexcct9
ztX98ii`*zi#zr0IBV(A-U}S9Txs)=qVGnA0zR`i}9$}rj!fC921gD-J2P#R`g!zY}
z1D|`go?|Ee=~}Vm^^G%&VA;H9-O;mw=WP3jzkcJB#^O#J=iJWSFznpLT{YZMUoCk!
zXY1;D9lLWGen904mt4#vyCnw9&1SK~g+jsUX0=k4BvtXfs7c(;+;%>#j@{4MY*sJZ
ztC87R16x$h7PF-g<PPTLY%Y^!S1mFZyNBId%a*cbklXD`2Yzi$yn4k2@;n$wlqY1w
zdEIooRD#*Ff;)gqsi*rdKlIfZcfsdmLko|-y?A@gn+L<5PrK*XKRB5C?cDFz+K(K*
zc6avMw4?U?d*5x@{z%;``OM3|bbPUQ^@5Lw8wO5>PDM|gK6AX`(nnVgJ$3fz{*(Lu
zTJ+hK@%zfXCc;@V+F#mR%Si@snn5;-R6o^jv{}jK-mjhCf4Om;S1CT(c;PYS%i)Xh
z;m3!EZLD2$EMxJsn(dT#B=f!9xvbpOtoRgPXSXIVflnAlS6_z`&t+Dm(>pQ`;K$pO
z&pn@vYYNWtb)@_)iH<<BC6NsJ)j%NO?@)ujrY4`?uf_w-q2>Niu(>6%6!V-dlI1%$
zGT!gu3#L1qhalN{z;PhGi=Va`o_*44ca`)O%qZDbA`Y|`KV|zW-H!F*-9nD%j)dJ_
z17kWWKr>*>gyBJ@0{sN|H1@~1mD$Fq!zNp8%<!lP(?OkMw@xLSo|zSn*-oZ+bk#i>
z6q-%1XsXGkS80XMngYHCNUfnReeVJLP~gXfhrZ_^;~6cK^p{b$920ij_k|MeJcAou
zB0K{m+&T0b!^a3{4uU{td{GH5<8&Xq74QuvoX+~03V6YUQ$G$?z|R_RJY~xNLIwN>
zfn(lynl%6C3ixORoO%@RJMJ6l#1Y4QNS8rI!u`ZS6cz&E$Aw<wo?)|BIbGE(7K`V0
z<dgB(npL4dYfE!$WO;DSnm~J7--M|>&=gwU6l`v54Yr3?`TLlXPo`BxOZICFUxrLF
ztHEr18e%>9R4ks=dX0Kk%_Mu7(wWco^$-qGGpbQb^<}{ZFH0&O(~`Yf41l->FH#xJ
zsNGqnWOG_lS^LB$Z?C4tw=qSJswNWfdUcA#l3lS>9%8bL8qepvsqVCv%zJTBCC-#y
zEw8B^z+cGd9BVNopHMZGw(mdlKf%-L2O=b{$XvWI1~RGaL9iiKWtf9vSm=KXPK^41
z^i~kC2g3viegvBdC@2EX1sQvTUNHK7*#_9u*8)IsA!$DP<LgBClz0I!J%l8KG(i;i
z*aW0Yv>w5g;yW$k<GW6Ai5CE~ihotqy_f<CZjPTPe<n|w>BP+fN|#vqYxb{{zeglU
z=Y{)+5amt$QNS=&n}`RZPW?icg-*;I-vQ26{zrs=m>dN+`%B=g=VFTgjc7>f6U@H`
z2Kf_SseV}$XsjQv1l3KvQvE-Qd?=nszZ{?RO7&m;pY@Me)Q|ruC?BeS3t+ha5|iOO
zL9%!h=)VqGaITTsKtarB1VLUY{JTv!`4c|@c9M-#k6ArR7IVKZVLhhfXYULD&BjGR
zruqrK2m+pEm;mD9{iC|DfABY${AvHr0A^c1o&#2ZQ6``8r+-%Hk7Ta(Helx5ah^{!
MSeI}>X4Sv{0)OeM*#H0l

literal 0
HcmV?d00001

diff --git a/llvm/test/tools/llvm-cov/Inputs/macro-filter-test.proftext 
b/llvm/test/tools/llvm-cov/Inputs/macro-filter-test.proftext
new file mode 100644
index 0000000000000..bb9d561b47fb9
--- /dev/null
+++ b/llvm/test/tools/llvm-cov/Inputs/macro-filter-test.proftext
@@ -0,0 +1,19 @@
+test_function
+# Func Hash:
+242690539886576728
+# Num Counters:
+4
+# Counter Values:
+3
+2
+1
+2
+
+main
+# Func Hash:
+24
+# Num Counters:
+1
+# Counter Values:
+1
+
diff --git a/llvm/test/tools/llvm-cov/Inputs/macro-vs-include.c 
b/llvm/test/tools/llvm-cov/Inputs/macro-vs-include.c
new file mode 100644
index 0000000000000..0af3c0ca14fd3
--- /dev/null
+++ b/llvm/test/tools/llvm-cov/Inputs/macro-vs-include.c
@@ -0,0 +1,34 @@
+// Test that --ignore-branch-in-macro distinguishes macros from #include
+
+// Header with branch
+static inline int header_func(int x) {
+    if (x > 10) {
+        return x * 2;
+    }
+    return x;
+}
+
+// Macro with branch
+#define CLAMP(x, lo, hi) ((x) < (lo) ? (lo) : (x) > (hi) ? (hi) : (x))
+
+int test_func(int val) {
+    // Macro branches - should be filtered
+    int clamped = CLAMP(val, 1, 100);
+
+    // #include branch - should be preserved
+    int h = header_func(val);
+
+    // Source branch - always counted
+    if (val > 0) {
+        return clamped + h;
+    }
+    return 0;
+}
+
+int main() {
+    test_func(1);
+    test_func(-1);
+    test_func(50);
+    test_func(150);
+    return 0;
+}
diff --git a/llvm/test/tools/llvm-cov/Inputs/macro-vs-include.o 
b/llvm/test/tools/llvm-cov/Inputs/macro-vs-include.o
new file mode 100644
index 
0000000000000000000000000000000000000000..958f5dcddaff34d2192c0262c2f145a7fe18a0d2
GIT binary patch
literal 4760
zcmbtWeQZ-z6u<9v-59J}H&o`>MloSRW=q?xTSpKJ+uJ%fKEx1-Fw0x}_JLcwbloyF
zgXutRss>0j#PEmFnGhoh8l(K9Off(v7%_qgk_g0)nN6L9n8hr?b6)T1-ro9vgwx!f
zdw%Dfdp_=c_r1MRbG;}CCdNr%>zF`-h8HfH6@2Q{$4bF+n?L@me|XXsADs3l%&71W
zj|%>{IvpOI76yyw<0mjeT$-G4fJJCeI*X8MF+P!*kf!6(ctRQn`-C(Zmu@Bor^h8#
zJq7M;Ps#iM3F)Runu<#^6Io}Z8L(vuX~sYNwXNk;n@WznW&03T^Eb+UVY<v9p9@!U
z<z!|vurMq-XFceLm4}_5+DWW^97CVH1(ck*Q`lQHbB#j2)|OLf3A8LS{_r!$uUvl>
z=G*r*9{I|%!*s*C`?Yn}sV3OJ1%gE|<F7P3ITi`Ig*l>C5LkJ!u$UFXOt4!`f>0)i
z+01IQhzyv8<+DRWLqiKJtU$~Z#Y|y8N}^z9mTV!Xh&2doDO+JPmm)K>mF$sHwwl%B
zUyUuh2w65;%X~$wmepgP|6P3j_o~pFKV`$b5CI^{6Os{x;+#wou+wLEgl@d(Sy=&d
ztOv1KJ3%mK2^nQ(s4Sc1+02-1o|#$MK}^rg^7YArH)Ad8KVw<IMdj&%%a4wIX&JKR
zu+fq$rngV*-`vpg_<MEl_!q7D;=(IGe{;<GZfV8N?{km&C;#5`!kK8jzcbX}K5^~z
zUnQ3gKb9HvI1i5O9e)3Z@ET>LEPOPve{0_4AHpX~%HllE?HKJB?bYpUQI~NC1L_y`
z>JH`%`<aete`s&g*=RBSU0`25aJjtE?uc(LKi|}LZez1!>_>a~rSs>SzFoDk@nX}b
zWB!fJjrNxs+kX>S{F-%w1-s;MyRBb|_I5_XHg|=?>2S7p#%wF$&j+KUuhkKZbg${^
z>hE5SfA*eeWVaHGInc`4+UBYZwR)7wkm7a89#6>CDtn!7x6|d4gPw|-YFCZ7qB69K
zCw(91!t-01Fklsy=435607Vo7jsxi<{9B)EeOauvWQrexMN+pGaUk^|r}XPn`khHN
zdjfe%->mAfPk84c$Mc6Ap8=#C7#0}0C;(Yu<ijXH0SI%xAI1YH7*Gi;n8E(Jl}>F+
zv)lP#FT!t>JE%4Bxrr^Dx6CgpqPgTX7ACa<4Zx=+wW_)Jzp9uw7fjh><@3p;c4IF7
zfhsPZ3v$V%c5J@Nq;@eKzGNOa2}psaZ|a!<>|>5waRY(Wy#|ira#4M&A<Rb9|Kzz@
zF5-?SX$9xiz?Z{KOSG9!=nUZVnF(VCUjjf6a=jie)8TYaxD0T=4#%^H^kkB$6=Ph&
zU(w<8{2VgC$22%rNBLhgz_06Y%KuLT{2|_V>;vXV>)Q?RYL4T&c<RW0y#d~2fNwLv
z>BQoFiG3rPIO5m`l8GaZ`IBseITF@|gUH7xgpYE0mky`%m}kl_Se%iWmAx>>lFI^t
zV5C2)1Ot-0u6BddBe|<3Z&kgkzHe4lx1q*URasFbReS5|JoW1}Dz~@7<8{@$t13Mk
zYQ42peasP6x@1R88Hh2wl)II13|7KhInWbr3k1WlUacIKyOmz%XpctvdI*P%x@E1@
z))xjHT<UGXK)2i(W{z+qrZ^flZL{~r<lwW+p{_57Lhy=c=P4*1fwm~Dp7M+-y|Dl+
z6-*)BaxfYR^!Elj!@;h;km3jiIutpiM3ZK!+TP!5PpO%sHx`Y_t-zn_RykIyDK8|)
zWZw6CWllIxsgG*SVxRLXfzBJL`0*o=Jq0tw@XTq+#|2sEK<A8Xx55OU2_FHR_wcLg
zIQK6B9M2xS0#%~#0=yUS9i=BfzXHh~{n3t|YvM-$Q$vV0n9b5r9(QCGQfIUt!A9}7
zq=}F3QHo34DE=1y@X<X@@$NSM_B8SFEk$vO8^s^s@#%eF6#orSBwJ-86P2Ik{ylTh
z+5IEfsDHb7{&Ze&{}7_QiMIiU@l8A)OjYvoLv7<SF@66ea8BpHo%{R9k#oJj51iFp
zbn$Kc`Jr=)`Qx`0`4etbe@~kF(U<BbZdCtao<H@Er=N;XvQhm<@3DSwn)>niyW9GQ
z($tS%eN;Dbqx#2r{uGbu)yqcpPu*kvThi2z-_8`D_P-x6Jbxmy!T&5dd4cr(L>jc!
zQVR%(Ikh0nW$xdp!^xlcXP~FK)^v;-tOe89UQS{?y5rBj<NgCWf2yBg{2oJ79|4?q
z@c#L^jL%OI4DzS`odL|$d@BNM2u6yIbANp1kkB7VU#k}YeeP&?fS<ps+yNPWx9Q{m
E4_<vM7XSbN

literal 0
HcmV?d00001

diff --git a/llvm/test/tools/llvm-cov/Inputs/macro-vs-include.proftext 
b/llvm/test/tools/llvm-cov/Inputs/macro-vs-include.proftext
new file mode 100644
index 0000000000000..9837ff4e8ddce
--- /dev/null
+++ b/llvm/test/tools/llvm-cov/Inputs/macro-vs-include.proftext
@@ -0,0 +1,28 @@
+test_func
+# Func Hash:
+241846114956444760
+# Num Counters:
+4
+# Counter Values:
+4
+1
+1
+3
+
+macro-vs-include.c:header_func
+# Func Hash:
+11211998296
+# Num Counters:
+2
+# Counter Values:
+4
+2
+
+main
+# Func Hash:
+24
+# Num Counters:
+1
+# Counter Values:
+1
+
diff --git a/llvm/test/tools/llvm-cov/macro-expansion-filter.test 
b/llvm/test/tools/llvm-cov/macro-expansion-filter.test
new file mode 100644
index 0000000000000..0f7c1003cb47b
--- /dev/null
+++ b/llvm/test/tools/llvm-cov/macro-expansion-filter.test
@@ -0,0 +1,49 @@
+// Test --ignore-branch-in-macro flag filters macro branches correctly
+//
+// The test binary was compiled with a clang that emits MacroExpansionRegion
+// (Version8 coverage mapping). It contains:
+// - 2 macro calls (MY_ABS, MY_MAX), each producing 2 branches = 4 macro 
branches
+// - 1 source-level if statement producing 2 branches = 2 source branches
+// - Total: 6 branches without filter, 2 branches with filter
+
+// Test 1: Verify flag is accepted and changes branch count in report
+// RUN: llvm-profdata merge %S/Inputs/macro-filter-test.proftext -o %t.profdata
+// RUN: llvm-cov report %S/Inputs/macro-filter-test.o -instr-profile 
%t.profdata --show-branch-summary -path-equivalence=/tmp,%S/Inputs | FileCheck 
%s -check-prefix=WITHOUT-FILTER
+// WITHOUT-FILTER: Branches
+// WITHOUT-FILTER: 6
+
+// RUN: llvm-cov report %S/Inputs/macro-filter-test.o -instr-profile 
%t.profdata --show-branch-summary --ignore-branch-in-macro 
-path-equivalence=/tmp,%S/Inputs | FileCheck %s -check-prefix=WITH-FILTER
+// WITH-FILTER: Branches
+// WITH-FILTER: 2
+
+// Test 2: Verify LCOV export filters macro branches
+// RUN: llvm-cov export --format=lcov %S/Inputs/macro-filter-test.o 
-instr-profile %t.profdata -path-equivalence=/tmp,%S/Inputs | FileCheck %s 
-check-prefix=LCOV-WITHOUT
+// LCOV-WITHOUT: BRDA:
+// LCOV-WITHOUT: BRDA:
+// LCOV-WITHOUT: BRDA:
+// LCOV-WITHOUT: BRDA:
+// LCOV-WITHOUT: BRDA:
+// LCOV-WITHOUT: BRDA:
+
+// RUN: llvm-cov export --format=lcov --ignore-branch-in-macro 
%S/Inputs/macro-filter-test.o -instr-profile %t.profdata 
-path-equivalence=/tmp,%S/Inputs | FileCheck %s -check-prefix=LCOV-WITH
+// LCOV-WITH: BRDA:
+// LCOV-WITH: BRDA:
+// LCOV-WITH-NOT: BRDA:
+
+// Test 3: Verify JSON export filters macro branches
+// RUN: llvm-cov export --format=text %S/Inputs/macro-filter-test.o 
-instr-profile %t.profdata -path-equivalence=/tmp,%S/Inputs | FileCheck %s 
-check-prefix=JSON-WITHOUT
+// JSON-WITHOUT: "branches"
+// JSON-WITHOUT: "branches"
+
+// RUN: llvm-cov export --format=text --ignore-branch-in-macro 
%S/Inputs/macro-filter-test.o -instr-profile %t.profdata 
-path-equivalence=/tmp,%S/Inputs | FileCheck %s -check-prefix=JSON-WITH
+// JSON-WITH: "branches"
+
+// Test 4: Verify backward compatibility with old binaries (Version7)
+// The branch-macros.o32l was compiled with an older clang (Version7)
+// RUN: llvm-profdata merge %S/Inputs/branch-macros.proftext -o %t.profdata
+// RUN: llvm-cov report --show-branch-summary --ignore-branch-in-macro 
%S/Inputs/branch-macros.o32l -instr-profile %t.profdata -show-functions 
-path-equivalence=/tmp,%S/Inputs %S/Inputs/branch-macros.cpp | FileCheck %s 
-check-prefix=BACKWARD-COMPAT
+// BACKWARD-COMPAT: Name
+// BACKWARD-COMPAT: _Z4funcii
+// BACKWARD-COMPAT: _Z5func2ii
+// BACKWARD-COMPAT: main
+// BACKWARD-COMPAT: TOTAL
diff --git a/llvm/test/tools/llvm-cov/macro-vs-include.test 
b/llvm/test/tools/llvm-cov/macro-vs-include.test
new file mode 100644
index 0000000000000..68440db758468
--- /dev/null
+++ b/llvm/test/tools/llvm-cov/macro-vs-include.test
@@ -0,0 +1,38 @@
+// Test that --ignore-branch-in-macro distinguishes macros from #include
+//
+// The test binary contains:
+// - 1 macro call (CLAMP) producing 2 branches
+// - 1 #include (header_func) producing 2 branches
+// - 1 source-level if producing 2 branches
+// - Total: 8 branches without filter, 4 branches with filter
+//
+// This verifies that macro branches are filtered while #include branches
+// are preserved.
+
+// Test: Verify branch count changes from 8 to 4
+// RUN: llvm-profdata merge %S/Inputs/macro-vs-include.proftext -o %t.profdata
+// RUN: llvm-cov report %S/Inputs/macro-vs-include.o -instr-profile 
%t.profdata --show-branch-summary -path-equivalence=/tmp,%S/Inputs | FileCheck 
%s -check-prefix=WITHOUT-FILTER
+// WITHOUT-FILTER: Branches
+// WITHOUT-FILTER: 8
+
+// RUN: llvm-cov report %S/Inputs/macro-vs-include.o -instr-profile 
%t.profdata --show-branch-summary --ignore-branch-in-macro 
-path-equivalence=/tmp,%S/Inputs | FileCheck %s -check-prefix=WITH-FILTER
+// WITH-FILTER: Branches
+// WITH-FILTER: 4
+
+// Test: Verify LCOV export preserves #include branches but filters macro 
branches
+// RUN: llvm-cov export --format=lcov %S/Inputs/macro-vs-include.o 
-instr-profile %t.profdata -path-equivalence=/tmp,%S/Inputs | FileCheck %s 
-check-prefix=LCOV-WITHOUT
+// LCOV-WITHOUT: BRDA:
+// LCOV-WITHOUT: BRDA:
+// LCOV-WITHOUT: BRDA:
+// LCOV-WITHOUT: BRDA:
+// LCOV-WITHOUT: BRDA:
+// LCOV-WITHOUT: BRDA:
+// LCOV-WITHOUT: BRDA:
+// LCOV-WITHOUT: BRDA:
+
+// RUN: llvm-cov export --format=lcov --ignore-branch-in-macro 
%S/Inputs/macro-vs-include.o -instr-profile %t.profdata 
-path-equivalence=/tmp,%S/Inputs | FileCheck %s -check-prefix=LCOV-WITH
+// LCOV-WITH: BRDA:
+// LCOV-WITH: BRDA:
+// LCOV-WITH: BRDA:
+// LCOV-WITH: BRDA:
+// LCOV-WITH-NOT: BRDA:
diff --git a/llvm/tools/llvm-cov/CodeCoverage.cpp 
b/llvm/tools/llvm-cov/CodeCoverage.cpp
index e19101ac76045..8a73394b8462f 100644
--- a/llvm/tools/llvm-cov/CodeCoverage.cpp
+++ b/llvm/tools/llvm-cov/CodeCoverage.cpp
@@ -308,6 +308,10 @@ void CodeCoverageTool::attachExpansionSubViews(
   if (!ViewOpts.ShowExpandedRegions)
     return;
   for (const auto &Expansion : Expansions) {
+    // Skip macro expansions if requested.
+    if (ViewOpts.IgnoreBranchesInMacros && Expansion.Region.isMacroExpansion())
+      continue;
+
     auto ExpansionCoverage = Coverage.getCoverageForExpansion(Expansion);
     if (ExpansionCoverage.empty())
       continue;
@@ -376,7 +380,15 @@ CodeCoverageTool::createFunctionView(const FunctionRecord 
&Function,
   if (!SourceBuffer)
     return nullptr;
 
-  auto Branches = FunctionCoverage.getBranches();
+  auto AllBranches = FunctionCoverage.getBranches();
+  // Filter out branches from macro expansions if requested.
+  // These branches have a FileID that differs from the main file's FileID.
+  unsigned MainFileID = AllBranches.empty() ? 0 : AllBranches[0].FileID;
+  SmallVector<CountedRegion, 0> Branches;
+  for (const auto &B : AllBranches)
+    if (!ViewOpts.IgnoreBranchesInMacros || B.FileID == MainFileID)
+      Branches.push_back(B);
+
   auto Expansions = FunctionCoverage.getExpansions();
   auto MCDCRecords = FunctionCoverage.getMCDCRecords();
   auto View = SourceCoverageView::create(DC.demangle(Function.Name),
@@ -399,7 +411,15 @@ CodeCoverageTool::createSourceFileView(StringRef 
SourceFile,
   if (FileCoverage.empty())
     return nullptr;
 
-  auto Branches = FileCoverage.getBranches();
+  auto AllBranches = FileCoverage.getBranches();
+  // Filter out branches from macro expansions if requested.
+  // These branches have a FileID that differs from the main file's FileID.
+  unsigned MainFileID = AllBranches.empty() ? 0 : AllBranches[0].FileID;
+  SmallVector<CountedRegion, 0> Branches;
+  for (const auto &B : AllBranches)
+    if (!ViewOpts.IgnoreBranchesInMacros || B.FileID == MainFileID)
+      Branches.push_back(B);
+
   auto Expansions = FileCoverage.getExpansions();
   auto MCDCRecords = FileCoverage.getMCDCRecords();
   auto View = SourceCoverageView::create(SourceFile, SourceBuffer.get(),
@@ -423,8 +443,17 @@ CodeCoverageTool::createSourceFileView(StringRef 
SourceFile,
       if (Function->ExecutionCount > 0) {
         auto SubViewCoverage = Coverage.getCoverageForFunction(*Function);
         auto SubViewExpansions = SubViewCoverage.getExpansions();
-        auto SubViewBranches = SubViewCoverage.getBranches();
+        auto AllSubViewBranches = SubViewCoverage.getBranches();
         auto SubViewMCDCRecords = SubViewCoverage.getMCDCRecords();
+
+        // Filter out branches from macro expansions if requested.
+        unsigned SubMainFileID =
+            AllSubViewBranches.empty() ? 0 : AllSubViewBranches[0].FileID;
+        SmallVector<CountedRegion, 0> SubViewBranches;
+        for (const auto &B : AllSubViewBranches)
+          if (!ViewOpts.IgnoreBranchesInMacros || B.FileID == SubMainFileID)
+            SubViewBranches.push_back(B);
+
         SubView = SourceCoverageView::create(
             Funcname, SourceBuffer.get(), ViewOpts, 
std::move(SubViewCoverage));
         attachExpansionSubViews(*SubView, SubViewExpansions, Coverage);
@@ -797,6 +826,10 @@ int CodeCoverageTool::run(Command Cmd, int argc, const 
char **argv) {
       "summary-only", cl::Optional,
       cl::desc("Export only summary information for each source file"));
 
+  cl::opt<bool> IgnoreBranchesInMacros(
+      "ignore-branch-in-macro", cl::Optional,
+      cl::desc("Ignore branches inside macro expansions in branch coverage"));
+
   cl::opt<unsigned> NumThreads(
       "num-threads", cl::init(0),
       cl::desc("Number of merge threads to use (default: autodetect)"));
@@ -978,6 +1011,7 @@ int CodeCoverageTool::run(Command Cmd, int argc, const 
char **argv) {
     ViewOpts.ShowFunctionSummary = FunctionSummary;
     ViewOpts.ShowInstantiationSummary = InstantiationSummary;
     ViewOpts.ExportSummaryOnly = SummaryOnly;
+    ViewOpts.IgnoreBranchesInMacros = IgnoreBranchesInMacros;
     ViewOpts.NumThreads = NumThreads;
     ViewOpts.CompilationDirectory = CompilationDirectory;
 
diff --git a/llvm/tools/llvm-cov/CoverageExporterJson.cpp 
b/llvm/tools/llvm-cov/CoverageExporterJson.cpp
index 4dbd6ea64da94..0eaa5130f8744 100644
--- a/llvm/tools/llvm-cov/CoverageExporterJson.cpp
+++ b/llvm/tools/llvm-cov/CoverageExporterJson.cpp
@@ -231,14 +231,20 @@ void renderMCDCRecords(json::OStream &JOS,
 
 std::vector<llvm::coverage::CountedRegion>
 collectNestedBranches(const coverage::CoverageMapping &Coverage,
-                      ArrayRef<llvm::coverage::ExpansionRecord> Expansions) {
+                      ArrayRef<llvm::coverage::ExpansionRecord> Expansions,
+                      bool IgnoreBranchesInMacros = false) {
   std::vector<llvm::coverage::CountedRegion> Branches;
   for (const auto &Expansion : Expansions) {
+    // Skip macro expansions if requested.
+    if (IgnoreBranchesInMacros && Expansion.Region.isMacroExpansion())
+      continue;
+
     auto ExpansionCoverage = Coverage.getCoverageForExpansion(Expansion);
 
     // Recursively collect branches from nested expansions.
     auto NestedExpansions = ExpansionCoverage.getExpansions();
-    auto NestedExBranches = collectNestedBranches(Coverage, NestedExpansions);
+    auto NestedExBranches = collectNestedBranches(Coverage, NestedExpansions,
+                                                  IgnoreBranchesInMacros);
     append_range(Branches, NestedExBranches);
 
     // Add branches from this level of expansion.
@@ -253,7 +259,8 @@ collectNestedBranches(const coverage::CoverageMapping 
&Coverage,
 
 void renderExpansion(json::OStream &JOS,
                      const coverage::CoverageMapping &Coverage,
-                     const coverage::ExpansionRecord &Expansion) {
+                     const coverage::ExpansionRecord &Expansion,
+                     bool IgnoreBranchesInMacros = false) {
   std::vector<llvm::coverage::ExpansionRecord> Expansions = {Expansion};
   JOS.object([&] {
     JOS.attributeArray("filenames", [&] {
@@ -262,7 +269,8 @@ void renderExpansion(json::OStream &JOS,
     });
     // Enumerate the branch coverage information for the expansion.
     JOS.attributeBegin("branches");
-    renderBranchRegions(JOS, collectNestedBranches(Coverage, Expansions));
+    renderBranchRegions(JOS, collectNestedBranches(Coverage, Expansions,
+                                                   IgnoreBranchesInMacros));
     JOS.attributeEnd();
     // Mark the beginning and end of this expansion in the source file.
     JOS.attributeBegin("source_region");
@@ -332,14 +340,22 @@ void renderFile(json::OStream &JOS, const 
coverage::CoverageMapping &Coverage,
     if (!Options.ExportSummaryOnly) {
       // Calculate and render detailed coverage information for given file.
       auto FileCoverage = Coverage.getCoverageForFile(Filename);
+      // Filter out branches from macro expansions if requested.
+      // These branches have a FileID that differs from the main file's FileID.
+      auto FileBranches = FileCoverage.getBranches();
+      unsigned MainFileID = FileBranches.empty() ? 0 : FileBranches[0].FileID;
       JOS.attributeArray("branches", [&] {
-        for (const auto &Branch : FileCoverage.getBranches())
-          renderBranch(JOS, Branch);
+        for (const auto &Branch : FileBranches)
+          if (!Options.IgnoreBranchesInMacros || Branch.FileID == MainFileID)
+            renderBranch(JOS, Branch);
       });
       if (!Options.SkipExpansions) {
         JOS.attributeArray("expansions", [&] {
           for (const auto &Expansion : FileCoverage.getExpansions())
-            renderExpansion(JOS, Coverage, Expansion);
+            if (!Options.IgnoreBranchesInMacros ||
+                !Expansion.Region.isMacroExpansion())
+              renderExpansion(JOS, Coverage, Expansion,
+                              Options.IgnoreBranchesInMacros);
         });
       }
       JOS.attributeArray("mcdc_records", [&] {
diff --git a/llvm/tools/llvm-cov/CoverageExporterLcov.cpp 
b/llvm/tools/llvm-cov/CoverageExporterLcov.cpp
index 96be9693a7047..90135d2b6a1d7 100644
--- a/llvm/tools/llvm-cov/CoverageExporterLcov.cpp
+++ b/llvm/tools/llvm-cov/CoverageExporterLcov.cpp
@@ -99,9 +99,13 @@ std::vector<NestedCountedRegion>
 collectNestedBranches(const coverage::CoverageMapping &Coverage,
                       ArrayRef<llvm::coverage::ExpansionRecord> Expansions,
                       std::vector<LineColPair> &NestedPath,
-                      unsigned &PositionCounter) {
+                      unsigned &PositionCounter,
+                      bool IgnoreBranchesInMacros = false) {
   std::vector<NestedCountedRegion> Branches;
   for (const auto &Expansion : Expansions) {
+    // Skip macro expansions if requested.
+    if (IgnoreBranchesInMacros && Expansion.Region.isMacroExpansion())
+      continue;
     auto ExpansionCoverage = Coverage.getCoverageForExpansion(Expansion);
 
     // Track the path to the nested expansions.
@@ -109,8 +113,9 @@ collectNestedBranches(const coverage::CoverageMapping 
&Coverage,
 
     // Recursively collect branches from nested expansions.
     auto NestedExpansions = ExpansionCoverage.getExpansions();
-    auto NestedExBranches = collectNestedBranches(Coverage, NestedExpansions,
-                                                  NestedPath, PositionCounter);
+    auto NestedExBranches =
+        collectNestedBranches(Coverage, NestedExpansions, NestedPath,
+                              PositionCounter, IgnoreBranchesInMacros);
     append_range(Branches, NestedExBranches);
 
     // Add branches from this level of expansion.
@@ -127,20 +132,6 @@ collectNestedBranches(const coverage::CoverageMapping 
&Coverage,
   return Branches;
 }
 
-void appendNestedCountedRegions(const std::vector<CountedRegion> &Src,
-                                std::vector<NestedCountedRegion> &Dst) {
-  auto Unfolded = make_filter_range(Src, [](auto &Region) {
-    return !Region.TrueFolded || !Region.FalseFolded;
-  });
-  Dst.reserve(Dst.size() + Src.size());
-  unsigned PositionCounter = Dst.size();
-  std::transform(Unfolded.begin(), Unfolded.end(), std::back_inserter(Dst),
-                 [=, &PositionCounter](auto &Region) {
-                   return NestedCountedRegion(Region, {Region.startLoc()},
-                                              PositionCounter++);
-                 });
-}
-
 void appendNestedCountedRegions(const std::vector<NestedCountedRegion> &Src,
                                 std::vector<NestedCountedRegion> &Dst) {
   auto Unfolded = make_filter_range(Src, [](auto &NestedRegion) {
@@ -181,17 +172,27 @@ void 
combineInstanceCounts(std::vector<NestedCountedRegion> &Branches) {
 void renderBranchExecutionCounts(raw_ostream &OS,
                                  const coverage::CoverageMapping &Coverage,
                                  const coverage::CoverageData &FileCoverage,
-                                 bool UnifyInstances) {
+                                 bool UnifyInstances,
+                                 bool IgnoreBranchesInMacros = false) {
 
   std::vector<NestedCountedRegion> Branches;
 
-  appendNestedCountedRegions(FileCoverage.getBranches(), Branches);
+  // Filter out branches from macro expansions if requested.
+  // These branches have a FileID that differs from the main file's FileID.
+  auto FileBranches = FileCoverage.getBranches();
+  unsigned MainFileID = FileBranches.empty() ? 0 : FileBranches[0].FileID;
+  for (const auto &B : FileBranches) {
+    if (IgnoreBranchesInMacros && B.FileID != MainFileID)
+      continue;
+    Branches.push_back(NestedCountedRegion(B, {B.startLoc()}, 
Branches.size()));
+  }
 
   // Recursively collect branches for all file expansions.
   std::vector<LineColPair> NestedPath;
   unsigned PositionCounter = 0;
-  std::vector<NestedCountedRegion> ExBranches = collectNestedBranches(
-      Coverage, FileCoverage.getExpansions(), NestedPath, PositionCounter);
+  std::vector<NestedCountedRegion> ExBranches =
+      collectNestedBranches(Coverage, FileCoverage.getExpansions(), NestedPath,
+                            PositionCounter, IgnoreBranchesInMacros);
 
   // Append Expansion Branches to Source Branches.
   appendNestedCountedRegions(ExBranches, Branches);
@@ -250,7 +251,8 @@ void renderBranchSummary(raw_ostream &OS, const 
FileCoverageSummary &Summary) {
 void renderFile(raw_ostream &OS, const coverage::CoverageMapping &Coverage,
                 const std::string &Filename,
                 const FileCoverageSummary &FileReport, bool ExportSummaryOnly,
-                bool SkipFunctions, bool SkipBranches, bool UnifyInstances) {
+                bool SkipFunctions, bool SkipBranches, bool UnifyInstances,
+                bool IgnoreBranchesInMacros = false) {
   OS << "SF:" << Filename << '\n';
 
   if (!ExportSummaryOnly && !SkipFunctions) {
@@ -263,7 +265,8 @@ void renderFile(raw_ostream &OS, const 
coverage::CoverageMapping &Coverage,
     auto FileCoverage = Coverage.getCoverageForFile(Filename);
     renderLineExecutionCounts(OS, FileCoverage);
     if (!SkipBranches)
-      renderBranchExecutionCounts(OS, Coverage, FileCoverage, UnifyInstances);
+      renderBranchExecutionCounts(OS, Coverage, FileCoverage, UnifyInstances,
+                                  IgnoreBranchesInMacros);
   }
   if (!SkipBranches)
     renderBranchSummary(OS, FileReport);
@@ -276,10 +279,11 @@ void renderFiles(raw_ostream &OS, const 
coverage::CoverageMapping &Coverage,
                  ArrayRef<std::string> SourceFiles,
                  ArrayRef<FileCoverageSummary> FileReports,
                  bool ExportSummaryOnly, bool SkipFunctions, bool SkipBranches,
-                 bool UnifyInstances) {
+                 bool UnifyInstances, bool IgnoreBranchesInMacros = false) {
   for (unsigned I = 0, E = SourceFiles.size(); I < E; ++I)
     renderFile(OS, Coverage, SourceFiles[I], FileReports[I], ExportSummaryOnly,
-               SkipFunctions, SkipBranches, UnifyInstances);
+               SkipFunctions, SkipBranches, UnifyInstances,
+               IgnoreBranchesInMacros);
 }
 
 } // end anonymous namespace
@@ -299,5 +303,6 @@ void CoverageExporterLcov::renderRoot(ArrayRef<std::string> 
SourceFiles) {
                                                         SourceFiles, Options);
   renderFiles(OS, Coverage, SourceFiles, FileReports, 
Options.ExportSummaryOnly,
               Options.SkipFunctions, Options.SkipBranches,
-              Options.UnifyFunctionInstantiations);
+              Options.UnifyFunctionInstantiations,
+              Options.IgnoreBranchesInMacros);
 }
diff --git a/llvm/tools/llvm-cov/CoverageReport.cpp 
b/llvm/tools/llvm-cov/CoverageReport.cpp
index 9b754d613370c..c43b3f5be9ee2 100644
--- a/llvm/tools/llvm-cov/CoverageReport.cpp
+++ b/llvm/tools/llvm-cov/CoverageReport.cpp
@@ -428,7 +428,8 @@ void 
CoverageReport::renderFunctionReports(ArrayRef<std::string> Files,
     OS << "\n";
     FunctionCoverageSummary Totals("TOTAL");
     for (const auto &F : Functions) {
-      auto Function = FunctionCoverageSummary::get(Coverage, F);
+      auto Function = FunctionCoverageSummary::get(
+          Coverage, F, Options.IgnoreBranchesInMacros);
       ++Totals.ExecutionCount;
       Totals.RegionCoverage += Function.RegionCoverage;
       Totals.LineCoverage += Function.LineCoverage;
@@ -453,7 +454,8 @@ void CoverageReport::prepareSingleFileReport(const 
StringRef Filename,
     for (const coverage::FunctionRecord *F : Group.getInstantiations()) {
       if (!Filters->matches(*Coverage, *F))
         continue;
-      auto InstantiationSummary = FunctionCoverageSummary::get(*Coverage, *F);
+      auto InstantiationSummary = FunctionCoverageSummary::get(
+          *Coverage, *F, Options.IgnoreBranchesInMacros);
       FileReport->addInstantiation(InstantiationSummary);
       InstantiationSummaries.push_back(InstantiationSummary);
     }
diff --git a/llvm/tools/llvm-cov/CoverageSummaryInfo.cpp 
b/llvm/tools/llvm-cov/CoverageSummaryInfo.cpp
index be9aef8416e8d..f4b922d4b4f40 100644
--- a/llvm/tools/llvm-cov/CoverageSummaryInfo.cpp
+++ b/llvm/tools/llvm-cov/CoverageSummaryInfo.cpp
@@ -38,12 +38,17 @@ static auto sumBranches(const ArrayRef<CountedRegion> 
&Branches) {
 
 static BranchCoverageInfo
 sumBranchExpansions(const CoverageMapping &CM,
-                    ArrayRef<ExpansionRecord> Expansions) {
+                    ArrayRef<ExpansionRecord> Expansions,
+                    bool IgnoreBranchesInMacros) {
   BranchCoverageInfo BranchCoverage;
   for (const auto &Expansion : Expansions) {
+    // Skip macro expansions if requested.
+    if (IgnoreBranchesInMacros && Expansion.Region.isMacroExpansion())
+      continue;
     auto CE = CM.getCoverageForExpansion(Expansion);
     BranchCoverage += sumBranches(CE.getBranches());
-    BranchCoverage += sumBranchExpansions(CM, CE.getExpansions());
+    BranchCoverage +=
+        sumBranchExpansions(CM, CE.getExpansions(), IgnoreBranchesInMacros);
   }
   return BranchCoverage;
 }
@@ -98,7 +103,8 @@ CoverageDataSummary::CoverageDataSummary(const CoverageData 
&CD,
 
 FunctionCoverageSummary
 FunctionCoverageSummary::get(const CoverageMapping &CM,
-                             const coverage::FunctionRecord &Function) {
+                             const coverage::FunctionRecord &Function,
+                             bool IgnoreBranchesInMacros) {
   CoverageData CD = CM.getCoverageForFunction(Function);
 
   auto Summary =
@@ -107,7 +113,8 @@ FunctionCoverageSummary::get(const CoverageMapping &CM,
   Summary += CoverageDataSummary(CD, Function.CountedRegions);
 
   // Compute the branch coverage, including branches from expansions.
-  Summary.BranchCoverage += sumBranchExpansions(CM, CD.getExpansions());
+  Summary.BranchCoverage +=
+      sumBranchExpansions(CM, CD.getExpansions(), IgnoreBranchesInMacros);
 
   return Summary;
 }
diff --git a/llvm/tools/llvm-cov/CoverageSummaryInfo.h 
b/llvm/tools/llvm-cov/CoverageSummaryInfo.h
index d9210676c41bf..82da6ad7a3943 100644
--- a/llvm/tools/llvm-cov/CoverageSummaryInfo.h
+++ b/llvm/tools/llvm-cov/CoverageSummaryInfo.h
@@ -253,7 +253,8 @@ struct FunctionCoverageSummary : CoverageDataSummary {
   /// Compute the code coverage summary for the given function coverage
   /// mapping record.
   static FunctionCoverageSummary get(const coverage::CoverageMapping &CM,
-                                     const coverage::FunctionRecord &Function);
+                                     const coverage::FunctionRecord &Function,
+                                     bool IgnoreBranchesInMacros = false);
 
   /// Compute the code coverage summary for an instantiation group \p Group,
   /// given a list of summaries for each instantiation in \p Summaries.
diff --git a/llvm/tools/llvm-cov/CoverageViewOptions.h 
b/llvm/tools/llvm-cov/CoverageViewOptions.h
index 4826d4adb53bf..80184f1e31c3d 100644
--- a/llvm/tools/llvm-cov/CoverageViewOptions.h
+++ b/llvm/tools/llvm-cov/CoverageViewOptions.h
@@ -49,6 +49,8 @@ struct CoverageViewOptions {
   bool SkipFunctions;
   bool SkipBranches;
   bool BinaryCounters;
+  /// Ignore branches inside macro expansions when computing branch coverage.
+  bool IgnoreBranchesInMacros = false;
   OutputFormat Format;
   BranchOutputType ShowBranches;
   std::string ShowOutputDirectory;
diff --git a/llvm/unittests/ProfileData/CoverageMappingTest.cpp 
b/llvm/unittests/ProfileData/CoverageMappingTest.cpp
index b268aa7cdd057..45d838ccb2452 100644
--- a/llvm/unittests/ProfileData/CoverageMappingTest.cpp
+++ b/llvm/unittests/ProfileData/CoverageMappingTest.cpp
@@ -219,6 +219,13 @@ struct CoverageMappingTest : 
::testing::TestWithParam<std::tuple<bool, bool>> {
         LS, CS, LE, CE));
   }
 
+  void addMacroExpansionCMR(StringRef File, StringRef ExpandedFile, unsigned 
LS,
+                            unsigned CS, unsigned LE, unsigned CE) {
+    
InputFunctions.back().Regions.push_back(CounterMappingRegion::makeExpansion(
+        getFileIndexForFunction(File), getFileIndexForFunction(ExpandedFile),
+        LS, CS, LE, CE, /*IsMacro=*/true));
+  }
+
   void addExpression(CounterExpression CE) {
     InputFunctions.back().Expressions.push_back(CE);
   }
@@ -1029,6 +1036,113 @@ TEST_P(CoverageMappingTest, 
load_coverage_for_expanded_file) {
   EXPECT_EQ(CoverageSegment(1, 10, false), Segments[1]);
 }
 
+TEST_P(CoverageMappingTest, macro_expansion_roundtrip) {
+  startFunction("func", 0x1234);
+  // Add code regions that the expansions reference
+  addCMR(Counter::getCounter(0), "main", 1, 1, 20, 1);
+  addCMR(Counter::getCounter(0), "include_file", 1, 1, 5, 10);
+  addCMR(Counter::getCounter(0), "macro_file", 1, 1, 5, 10);
+  // Add a regular expansion (e.g., #include)
+  addExpansionCMR("main", "include_file", 5, 1, 5, 10);
+  // Add a macro expansion
+  addMacroExpansionCMR("main", "macro_file", 10, 1, 10, 15);
+
+  writeAndReadCoverageRegions();
+  ASSERT_EQ(1u, OutputFunctions.size());
+  const OutputFunctionCoverageData &Output = OutputFunctions[0];
+
+  // Find the expansion regions (there should be 5 regions total: 3 code + 2
+  // expansion)
+  ASSERT_EQ(5u, Output.Regions.size());
+
+  // Check each region
+  size_t ExpansionCount = 0;
+  size_t MacroExpansionCount = 0;
+  for (const auto &Region : Output.Regions) {
+    if (Region.Kind == CounterMappingRegion::ExpansionRegion) {
+      ExpansionCount++;
+      EXPECT_TRUE(Region.isExpansion());
+      EXPECT_FALSE(Region.isMacroExpansion());
+    } else if (Region.Kind == CounterMappingRegion::MacroExpansionRegion) {
+      MacroExpansionCount++;
+      EXPECT_TRUE(Region.isExpansion());
+      EXPECT_TRUE(Region.isMacroExpansion());
+    } else {
+      EXPECT_EQ(CounterMappingRegion::CodeRegion, Region.Kind);
+      EXPECT_FALSE(Region.isExpansion());
+      EXPECT_FALSE(Region.isMacroExpansion());
+    }
+  }
+
+  EXPECT_EQ(1u, ExpansionCount);
+  EXPECT_EQ(1u, MacroExpansionCount);
+}
+
+TEST_P(CoverageMappingTest, macro_expansion_coverage_data) {
+  ProfileWriter.addRecord({"func", 0x1234, {5}}, Err);
+
+  startFunction("func", 0x1234);
+  addCMR(Counter::getCounter(0), "main", 1, 1, 10, 1);
+  addMacroExpansionCMR("main", "macro_def", 5, 1, 5, 20);
+  addCMR(Counter::getCounter(0), "macro_def", 1, 1, 1, 10);
+
+  EXPECT_THAT_ERROR(loadCoverageMapping(), Succeeded());
+
+  // Verify main file coverage
+  CoverageData MainData = LoadedCoverage->getCoverageForFile("main");
+  std::vector<CoverageSegment> MainSegments(MainData.begin(), MainData.end());
+  ASSERT_GE(MainSegments.size(), 2u);
+
+  // Verify macro definition file coverage
+  CoverageData MacroData = LoadedCoverage->getCoverageForFile("macro_def");
+  std::vector<CoverageSegment> MacroSegments(MacroData.begin(),
+                                             MacroData.end());
+  ASSERT_GE(MacroSegments.size(), 1u);
+  EXPECT_EQ(CoverageSegment(1, 1, 5, true), MacroSegments[0]);
+}
+
+TEST_P(CoverageMappingTest, mixed_expansion_types) {
+  startFunction("func", 0x1234);
+  // Add code regions
+  addCMR(Counter::getCounter(0), "main", 1, 1, 15, 1);
+  addCMR(Counter::getCounter(0), "header1", 1, 1, 3, 1);
+  addCMR(Counter::getCounter(0), "macro1", 1, 1, 5, 1);
+  addCMR(Counter::getCounter(0), "header2", 1, 1, 3, 1);
+  addCMR(Counter::getCounter(0), "macro2", 1, 1, 5, 1);
+  // Mix regular expansions and macro expansions
+  addExpansionCMR("main", "header1", 3, 1, 3, 10);
+  addMacroExpansionCMR("main", "macro1", 5, 1, 5, 15);
+  addExpansionCMR("main", "header2", 7, 1, 7, 10);
+  addMacroExpansionCMR("main", "macro2", 9, 1, 9, 15);
+
+  writeAndReadCoverageRegions();
+  ASSERT_EQ(1u, OutputFunctions.size());
+  const OutputFunctionCoverageData &Output = OutputFunctions[0];
+
+  ASSERT_EQ(9u, Output.Regions.size());
+
+  // Count expansion types
+  size_t ExpansionCount = 0;
+  size_t MacroExpansionCount = 0;
+  for (const auto &Region : Output.Regions) {
+    if (Region.Kind == CounterMappingRegion::ExpansionRegion) {
+      ExpansionCount++;
+      EXPECT_FALSE(Region.isMacroExpansion());
+    } else if (Region.Kind == CounterMappingRegion::MacroExpansionRegion) {
+      MacroExpansionCount++;
+      EXPECT_TRUE(Region.isMacroExpansion());
+    }
+    // All expansions should return true for isExpansion()
+    if (Region.isExpansion()) {
+      EXPECT_TRUE(Region.Kind == CounterMappingRegion::ExpansionRegion ||
+                  Region.Kind == CounterMappingRegion::MacroExpansionRegion);
+    }
+  }
+
+  EXPECT_EQ(2u, ExpansionCount);
+  EXPECT_EQ(2u, MacroExpansionCount);
+}
+
 TEST_P(CoverageMappingTest, skip_duplicate_function_record) {
   ProfileWriter.addRecord({"func", 0x1234, {1}}, Err);
 

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to