[SelectionDAG] Fix null pointer dereference in resolveDanglingDebugInfo (#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 commit is contained in:
Haoren Wang 2026-02-23 23:30:13 +08:00 committed by GitHub
parent 426573f1e1
commit 329cd8985d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 38 additions and 1 deletions

View File

@ -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 "

View File

@ -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)