[clang] [clang] Set linkage name for atexit destructor debug info (PR #189794)
Haohai Wen via cfe-commits
cfe-commits at lists.llvm.org
Tue Mar 31 22:06:20 PDT 2026
https://github.com/HaohaiWen created https://github.com/llvm/llvm-project/pull/189794
Compiler-generated atexit destructors for global variables were missing
DW_AT_linkage_name in their DWARF debug info. Different template
instantiations of the same variable all shared the same unmangled name,
making them indistinguishable in the debug info.
Set LinkageName to Fn->getName() (the mangled IR function name) for the
VarDecl/DynamicInitKind case, matching what other compiler-generated
functions already do.
>From e2151dd480216fabcf562cc4f44dec648422b5d2 Mon Sep 17 00:00:00 2001
From: "Wen, Haohai" <haohai.wen at intel.com>
Date: Wed, 1 Apr 2026 10:19:16 +0800
Subject: [PATCH] [clang] Set linkage name for atexit destructor debug info
Compiler-generated atexit destructors for global variables were missing
DW_AT_linkage_name in their DWARF debug info. Different template
instantiations of the same variable all shared the same unmangled name,
making them indistinguishable in the debug info.
Set LinkageName to Fn->getName() (the mangled IR function name) for the
VarDecl/DynamicInitKind case, matching what other compiler-generated
functions already do.
---
clang/lib/CodeGen/CGDebugInfo.cpp | 1 +
.../debug-info-atexit-linkage-name.cpp | 27 +++++++++++++++++++
2 files changed, 28 insertions(+)
create mode 100644 clang/test/CodeGenCXX/debug-info-atexit-linkage-name.cpp
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index 0fd17b98570fc..05e7d4b0a025b 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -4907,6 +4907,7 @@ void CGDebugInfo::emitFunctionStart(GlobalDecl GD, SourceLocation Loc,
// This is a global initializer or atexit destructor for a global variable.
Name = getDynamicInitializerName(cast<VarDecl>(D), GD.getDynamicInitKind(),
Fn);
+ LinkageName = Fn->getName();
} else {
Name = Fn->getName();
diff --git a/clang/test/CodeGenCXX/debug-info-atexit-linkage-name.cpp b/clang/test/CodeGenCXX/debug-info-atexit-linkage-name.cpp
new file mode 100644
index 0000000000000..5c89dc4300a26
--- /dev/null
+++ b/clang/test/CodeGenCXX/debug-info-atexit-linkage-name.cpp
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 -triple x86_64-windows-msvc -debug-info-kind=limited -emit-llvm %s -o - | \
+// RUN: FileCheck %s
+
+// Verify that compiler-generated atexit destructors for global variables have
+// a non-empty linkageName in their DISubprogram. Without this, different
+// template instantiations would be indistinguishable in the debug info.
+
+struct Foo {
+ ~Foo();
+};
+
+template <typename T>
+struct Bar {
+ static Foo &get() {
+ static Foo instance;
+ return instance;
+ }
+};
+
+void use() {
+ Bar<int>::get();
+ Bar<float>::get();
+}
+
+// Both atexit destructors should have distinct linkageNames.
+// CHECK-DAG: distinct !DISubprogram({{.*}}linkageName: "??__Finstance@?2??get@?$Bar at H@@SAAEAUFoo@@XZ at YAXXZ"
+// CHECK-DAG: distinct !DISubprogram({{.*}}linkageName: "??__Finstance@?2??get@?$Bar at M@@SAAEAUFoo@@XZ at YAXXZ"
More information about the cfe-commits
mailing list