[clang] [clang][Coverage] Fix crash for nested macro in system headers (PR #181319)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Feb 12 22:55:27 PST 2026
https://github.com/Nuullll created https://github.com/llvm/llvm-project/pull/181319
When compiling with coverage enabled, clang crashes if a file includes a system header that contains nested macro expansions.
The existing logic in `CoverageMappingBuilder::gatherFileIDs` attempts to remap locations from system macros by checking `SM.isInSystemMacro(Loc)`. This check is insufficient as it misses cases where a location's *spelling location* is still in a system header, such as with nested macros. This leads to the `!SM.isInSystemHeader(SM.getSpellingLoc(Loc))` assertion firing later on.
This patch fixes the issue by checking the spelling location anyway. It replaces the assertion with a check that skips any region whose spelling location is in a system header (when system header coverage is disabled). This correctly handles all cases, including nested macros.
>From 2f9b62c784b9d12ab0b4fde48862752f2d3efb1a Mon Sep 17 00:00:00 2001
From: Nuullll <vfirst218 at gmail.com>
Date: Fri, 13 Feb 2026 14:01:53 +0800
Subject: [PATCH] [clang][Coverage] Fix crash for nested macro in system
headers
When compiling with coverage enabled, clang crashes if a file includes a
header via `-isystem` that contains macro expansions.
The existing logic in `CoverageMappingBuilder::gatherFileIDs` attempts to
remap locations from system macros by checking `SM.isInSystemMacro(Loc)`.
This check is insufficient as it misses cases where a location's *spelling
location* is still in a system header, such as with nested macros. This
leads to the `!SM.isInSystemHeader(SM.getSpellingLoc(Loc))` assertion
correctly firing later on.
This patch fixes the issue by checking the spelling location directly.
It replaces the problematic logic with a check that skips any region whose
spelling location is in a system header (when system header coverage is
disabled). This correctly handles all cases, including nested macros.
---
clang/lib/CodeGen/CoverageMappingGen.cpp | 10 ++++++++--
clang/test/CoverageMapping/Inputs/nested.h | 2 ++
clang/test/CoverageMapping/system_nested_macro.cpp | 8 ++++++++
3 files changed, 18 insertions(+), 2 deletions(-)
create mode 100644 clang/test/CoverageMapping/Inputs/nested.h
create mode 100644 clang/test/CoverageMapping/system_nested_macro.cpp
diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp
index 803037d1874b3..82426d2893484 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -401,8 +401,14 @@ class CoverageMappingBuilder {
if (!Visited.insert(File).second)
continue;
- assert(SystemHeadersCoverage ||
- !SM.isInSystemHeader(SM.getSpellingLoc(Loc)));
+ // Ignore regions from system headers unless collecting coverage from
+ // system headers is explicitly enabled.
+ if (!SystemHeadersCoverage &&
+ SM.isInSystemHeader(SM.getSpellingLoc(Loc))) {
+ assert(!Region.isMCDCBranch() && !Region.isMCDCDecision() &&
+ "Don't suppress the condition in system headers");
+ continue;
+ }
unsigned Depth = 0;
for (SourceLocation Parent = getIncludeOrExpansionLoc(Loc);
diff --git a/clang/test/CoverageMapping/Inputs/nested.h b/clang/test/CoverageMapping/Inputs/nested.h
new file mode 100644
index 0000000000000..46c46242e1f73
--- /dev/null
+++ b/clang/test/CoverageMapping/Inputs/nested.h
@@ -0,0 +1,2 @@
+#define Y X
+Y
diff --git a/clang/test/CoverageMapping/system_nested_macro.cpp b/clang/test/CoverageMapping/system_nested_macro.cpp
new file mode 100644
index 0000000000000..ec73d2a69de5f
--- /dev/null
+++ b/clang/test/CoverageMapping/system_nested_macro.cpp
@@ -0,0 +1,8 @@
+// clang previously crashes when including nested macro from a system header.
+// REQUIRES: asserts
+// RUN: %clang -isystem %S/Inputs -fprofile-instr-generate -fcoverage-mapping -c %s
+
+int main() {
+#define X ;
+#include <nested.h>
+}
More information about the cfe-commits
mailing list