https://github.com/Nuullll updated 
https://github.com/llvm/llvm-project/pull/181319

>From 09974c15c4002541afb17b565421bbe8266fcc6d Mon Sep 17 00:00:00 2001
From: Nuullll <[email protected]>
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>
+}

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

Reply via email to