[llvm] [SelectionDAG] Fix null pointer dereference in resolveDanglingDebugInfo (PR #180425)
Haoren Wang via llvm-commits
llvm-commits at lists.llvm.org
Sun Feb 8 09:33:29 PST 2026
https://github.com/MetalOxideSemi created https://github.com/llvm/llvm-project/pull/180425
Fix crash when Val.getNode() is null by moving ValSDNodeOrder declaration inside the null check.
The crash occurred when compiling code with debug info containing aggregate types with nested empty structs.
---
**This is a resubmission of #174341**, which was reverted in #180352 due to test failures on ASAN builders.
**Changes from the original PR:**
- Removed Darwin test (as suggested by @nikic in #174341)
- The x86_64-linux-gnu test is sufficient to verify the fix
**Note:** The Darwin crash appears to be a separate DWARF generation issue that should be tracked separately.
cc @arsenm @nikic @MacDue @qinkunbao @tstellar
>From a6895a8240e734f092f97a8210051b81644a8110 Mon Sep 17 00:00:00 2001
From: Haoren Wang <haorenwange2 at outlook.com>
Date: Mon, 9 Feb 2026 01:29:43 +0800
Subject: [PATCH] [SelectionDAG] Fix null pointer dereference in
resolveDanglingDebugInfo
Fix crash when Val.getNode() is null by moving ValSDNodeOrder
declaration inside the null check.
The crash occurred when compiling code with debug info containing
aggregate types with nested empty structs.
---
.../SelectionDAG/SelectionDAGBuilder.cpp | 2 +-
.../X86/selectiondag-dbgvalue-null-crash.ll | 37 +++++++++++++++++++
2 files changed, 38 insertions(+), 1 deletion(-)
create mode 100644 llvm/test/CodeGen/X86/selectiondag-dbgvalue-null-crash.ll
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index f45092db69cd3..1fd0dbee9e6a4 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -1505,7 +1505,6 @@ void SelectionDAGBuilder::resolveDanglingDebugInfo(const Value *V,
DanglingDebugInfoVector &DDIV = DanglingDbgInfoIt->second;
for (auto &DDI : DDIV) {
DebugLoc DL = DDI.getDebugLoc();
- unsigned ValSDNodeOrder = Val.getNode()->getIROrder();
unsigned DbgSDNodeOrder = DDI.getSDNodeOrder();
DILocalVariable *Variable = DDI.getVariable();
DIExpression *Expr = DDI.getExpression();
@@ -1519,6 +1518,7 @@ void SelectionDAGBuilder::resolveDanglingDebugInfo(const Value *V,
// in the first place we should not be more successful here). Unless we
// have some test case that prove this to be correct we should avoid
// calling EmitFuncArgumentDbgValue here.
+ unsigned ValSDNodeOrder = Val.getNode()->getIROrder();
if (!EmitFuncArgumentDbgValue(V, Variable, Expr, DL,
FuncArgumentDbgValueKind::Value, Val)) {
LLVM_DEBUG(dbgs() << "Resolve dangling debug info for "
diff --git a/llvm/test/CodeGen/X86/selectiondag-dbgvalue-null-crash.ll b/llvm/test/CodeGen/X86/selectiondag-dbgvalue-null-crash.ll
new file mode 100644
index 0000000000000..69b4b7adbc07c
--- /dev/null
+++ b/llvm/test/CodeGen/X86/selectiondag-dbgvalue-null-crash.ll
@@ -0,0 +1,37 @@
+; Test that the code generation works correctly on Linux
+; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu | FileCheck %s
+
+; Regression test for SelectionDAG::resolveDanglingDebugInfo crash when
+; handling aggregate types with nested empty structs.
+;
+; This test verifies the fix for null pointer dereference in
+; SelectionDAG::resolveDanglingDebugInfo. The original issue occurred when
+; insertvalue operations on aggregate types containing nested empty structs
+; produced SDValue nodes with null pointers.
+
+; CHECK-LABEL: test_empty_struct_debug:
+; CHECK: retq
+
+define void @test_empty_struct_debug() !dbg !4 {
+entry:
+ %tmp = alloca { { i1, {} }, ptr, { { {} }, { {} } }, i64 }, align 8
+ #dbg_value({ { {} }, { {} } } zeroinitializer, !5, !DIExpression(), !6)
+ #dbg_value(i64 2, !7, !DIExpression(), !6)
+ %0 = insertvalue { { i1, {} }, ptr, { { {} }, { {} } }, i64 } { { i1, {} } zeroinitializer, ptr null, { { {} }, { {} } } zeroinitializer, i64 2 }, ptr null, 1, !dbg !6
+ %1 = insertvalue { { i1, {} }, ptr, { { {} }, { {} } }, i64 } %0, { i1, {} } zeroinitializer, 0, !dbg !8
+ store { { i1, {} }, ptr, { { {} }, { {} } }, i64 } %1, ptr %tmp, align 8
+ ret void
+}
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!2, !3}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C11, file: !1, isOptimized: false, runtimeVersion: 0, emissionKind: LineTablesOnly)
+!1 = !DIFile(filename: "test_selectiondag.cpp", directory: "/home/AnonTokyo/documents/llvm-project/temp")
+!2 = !{i32 2, !"Debug Info Version", i32 3}
+!3 = !{i32 2, !"Dwarf Version", i32 4}
+!4 = distinct !DISubprogram(name: "test_empty_struct_debug", scope: !1, file: !1, line: 1, scopeLine: 1, spFlags: DISPFlagDefinition, unit: !0)
+!5 = !DILocalVariable(name: "v1", scope: !4, file: !1, line: 2)
+!6 = !DILocation(line: 2, column: 1, scope: !4)
+!7 = !DILocalVariable(name: "v2", scope: !4, file: !1, line: 3)
+!8 = !DILocation(line: 3, column: 1, scope: !4)
More information about the llvm-commits
mailing list