[clang] [clang][Coverage] Fix crash for nested macro in system headers (PR #181319)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Feb 13 00:04:03 PST 2026
https://github.com/Nuullll updated https://github.com/llvm/llvm-project/pull/181319
>From 09974c15c4002541afb17b565421bbe8266fcc6d 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 coverage mapping is enabled, including a nested macro through `-isystem`
can produce source regions whose spelling locations are still in system
headers. `CoverageMappingBuilder::gatherFileIDs` asserted these regions away
instead of treating them as uncovered when system header coverage is disabled.
Replace the assert-only behavior with a real filter based on spelling
locations, and reuse the same system-header predicate in both
`gatherFileIDs` and `emitSourceRegions` to keep the policy consistent.
---
clang/lib/CodeGen/CoverageMappingGen.cpp | 25 ++++++++++++-------
clang/test/CoverageMapping/Inputs/nested.h | 2 ++
.../CoverageMapping/system_nested_macro.cpp | 15 +++++++++++
3 files changed, 33 insertions(+), 9 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..d861e6f6ee2cf 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -338,6 +338,19 @@ class CoverageMappingBuilder {
return SM.getBufferName(SM.getSpellingLoc(Loc)) == "<built-in>";
}
+ /// Return true if \p Region should be suppressed because its spelling
+ /// location is in a system header and system header coverage is disabled.
+ bool skipSystemHeaderRegion(const SourceMappingRegion &Region,
+ SourceLocation Loc) {
+ if (SystemHeadersCoverage)
+ return false;
+ if (!SM.isInSystemHeader(SM.getSpellingLoc(Loc)))
+ return false;
+ assert(!Region.isMCDCBranch() && !Region.isMCDCDecision() &&
+ "Don't suppress the condition in system headers");
+ return true;
+ }
+
/// Check whether \c Loc is included or expanded from \c Parent.
bool isNestedIn(SourceLocation Loc, FileID Parent) {
do {
@@ -401,8 +414,8 @@ class CoverageMappingBuilder {
if (!Visited.insert(File).second)
continue;
- assert(SystemHeadersCoverage ||
- !SM.isInSystemHeader(SM.getSpellingLoc(Loc)));
+ if (skipSystemHeaderRegion(Region, Loc))
+ continue;
unsigned Depth = 0;
for (SourceLocation Parent = getIncludeOrExpansionLoc(Loc);
@@ -515,14 +528,8 @@ class CoverageMappingBuilder {
SourceLocation LocStart = Region.getBeginLoc();
assert(SM.getFileID(LocStart).isValid() && "region in invalid file");
- // Ignore regions from system headers unless collecting coverage from
- // system headers is explicitly enabled.
- if (!SystemHeadersCoverage &&
- SM.isInSystemHeader(SM.getSpellingLoc(LocStart))) {
- assert(!Region.isMCDCBranch() && !Region.isMCDCDecision() &&
- "Don't suppress the condition in system headers");
+ if (skipSystemHeaderRegion(Region, LocStart))
continue;
- }
auto CovFileID = getCoverageFileID(LocStart);
// Ignore regions that don't have a file, such as builtin macros.
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..7e6bcce3fcbec
--- /dev/null
+++ b/clang/test/CoverageMapping/system_nested_macro.cpp
@@ -0,0 +1,15 @@
+// Check nested macro handling when including a system header.
+// RUN: %clang_cc1 -std=c++11 -isystem %S/Inputs -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -emit-llvm -main-file-name system_nested_macro.cpp -o - %s | FileCheck %s --check-prefixes=CHECK,X_SYS
+// RUN: %clang_cc1 -std=c++11 -isystem %S/Inputs -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -mllvm -system-headers-coverage=true -emit-llvm -main-file-name system_nested_macro.cpp -o - %s | FileCheck %s --check-prefixes=CHECK,W_SYS
+//
+// CHECK-LABEL: main:
+// CHECK: File 0, [[@LINE+6]]:12 -> [[@LINE+9]]:2 = #0
+// X_SYS: File 1, [[@LINE+6]]:11 -> [[@LINE+6]]:12 = #0
+// X_SYS-NOT: Expansion,
+// W_SYS: Expansion,File 0, [[@LINE+5]]:10 -> [[@LINE+5]]:11 = #0 (Expanded file = 1)
+// W_SYS: File 1, 1:1 -> 3:1 = #0
+
+int main() {
+#define X ;
+#include <nested.h>
+}
More information about the cfe-commits
mailing list