Index: lib/CodeGen/AsmPrinter/DwarfCompileUnit.h =================================================================== --- lib/CodeGen/AsmPrinter/DwarfCompileUnit.h +++ lib/CodeGen/AsmPrinter/DwarfCompileUnit.h @@ -127,6 +127,8 @@ unsigned getOrCreateSourceID(StringRef FileName, StringRef DirName) override; void addLocalDeclNode(const DINode *DI, DILocalScope *Scope) { + if (auto *File = dyn_cast(Scope)) + Scope = File->getScope(); LocalDeclNodes[Scope].push_back(DI); } Index: lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp =================================================================== --- lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +++ lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp @@ -884,7 +884,9 @@ void DwarfCompileUnit::addLocalScopeDieToLexicalScope(LexicalScope *LS, DIE *D) { - auto &LSInfo = getLSDieInfoMap()[LS->getScopeNode()]; + const DILocalScope *Scope = LS->getScopeNode(); + assert(!isa(Scope) && "Don't expect Lexical Block File!"); + auto &LSInfo = getLSDieInfoMap()[Scope]; if (LS->isAbstractScope()) { assert(!LSInfo.AbstractLSDie && "Adding abstract LS DIE twice."); LSInfo.AbstractLSDie = D; @@ -901,7 +903,9 @@ } void DwarfCompileUnit::addLocalDclDieToLexicalScope(LexicalScope *LS, DIE *D) { - auto &LSInfo = getLSDieInfoMap()[LS->getScopeNode()]; + const DILocalScope *Scope = LS->getScopeNode(); + assert(!isa(Scope) && "Don't expect Lexical Block File!"); + auto &LSInfo = getLSDieInfoMap()[Scope]; LSInfo.LocalDclDies.insert(D); return; } Index: test/DebugInfo/X86/lexical-block-file.ll =================================================================== --- test/DebugInfo/X86/lexical-block-file.ll +++ test/DebugInfo/X86/lexical-block-file.ll @@ -0,0 +1,90 @@ +; RUN: llc -mtriple=x86_64-unknown-linux-gnu -filetype=obj -O0 < %s | llvm-dwarfdump -debug-dump=info - | FileCheck %s + +;; This test checks that Inlined DILexicalBlockFile with local decl entry: +;; 1. Does not crash compilation. +;; 2. Is Skipped and only one DW_TAG_lexical_block is generated. +;; +;; This test was generated by running following command: +;; clang -cc1 -O0 -debug-info-kind=limited -emit-llvm test.cpp +;; Where test.cpp +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;;static __attribute__((always_inline)) int bar() { +;; { +;;#line 2 "test.h" +;; static int x = 0; +;; return x; +;; } +;;} +;;int foo() { +;; { +;; return bar(); +;; } +;;} +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; Abstract "bar" function +; CHECK: [[Offset_bar:0x[0-9abcdef]+]]: DW_TAG_subprogram +; CHECK-NOT: {{DW_TAG|NULL}} +; CHECK: DW_AT_name {{.*}} "bar" +; CHECK: DW_AT_inline + +; CHECK-NOT: {{DW_TAG|NULL}} +; CHECK: [[Offset_LB:0x[0-9abcdef]+]]: DW_TAG_lexical_block + +; CHECK-NOT: {{DW_TAG|NULL}} +; CHECK: [[Offset_x:0x[0-9abcdef]+]]: DW_TAG_variable +; CHECK-NOT: {{DW_TAG|NULL}} +; CHECK: DW_AT_name {{.*}} "x" + + +; CHECK: DW_TAG_subprogram +; CHECK-NOT: {{DW_TAG|NULL}} +; CHECK: DW_AT_name {{.*}} "foo" +; CHECK-NOT: {{NULL}} + +;; Inlined "bar" function +; CHECK: DW_TAG_inlined_subroutine +; CHECK-NEXT: DW_AT_abstract_origin {{.*}} {[[Offset_bar]]} + +; CHECK-NOT: {{DW_TAG|NULL}} +; CHECK: DW_TAG_lexical_block +; CHECK-NOT: {{DW_TAG|NULL}} +; CHECK: DW_AT_abstract_origin {{.*}} {[[Offset_LB]]} + + +@bar.x = internal global i32 0, align 4 + +; Function Attrs: nounwind +define i32 @foo() #0 !dbg !4 { +entry: + %0 = load i32, i32* @bar.x, align 4, !dbg !16 + ret i32 %0, !dbg !19 +} + +attributes #0 = { nounwind "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-features"="+mmx,+sse,+sse2" "unsafe-fp-math"="false" "use-soft-float"="false" } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!14} +!llvm.ident = !{!15} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 3.9.0 (trunk 263423)", isOptimized: false, runtimeVersion: 0, emissionKind: 1, enums: !2, subprograms: !3, globals: !10) +!1 = !DIFile(filename: "test.c", directory: "/") +!2 = !{} +!3 = !{!4, !9} +!4 = distinct !DISubprogram(name: "foo", scope: !5, file: !5, line: 6, type: !6, isLocal: false, isDefinition: true, scopeLine: 6, isOptimized: false, variables: !2) +!5 = !DIFile(filename: "test.h", directory: "/") +!6 = !DISubroutineType(types: !7) +!7 = !{!8} +!8 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed) +!9 = distinct !DISubprogram(name: "bar", scope: !1, file: !1, line: 2, type: !6, isLocal: true, isDefinition: true, scopeLine: 2, isOptimized: false, variables: !2) +!10 = !{!11} +!11 = !DIGlobalVariable(name: "x", scope: !12, file: !5, line: 2, type: !8, isLocal: true, isDefinition: true, variable: i32* @bar.x) +!12 = !DILexicalBlockFile(scope: !13, file: !5, discriminator: 0) +!13 = distinct !DILexicalBlock(scope: !9, file: !1, line: 3) +!14 = !{i32 2, !"Debug Info Version", i32 3} +!15 = !{!"clang version 3.9.0 (trunk 263423)"} +!16 = !DILocation(line: 3, scope: !12, inlinedAt: !17) +!17 = distinct !DILocation(line: 8, scope: !18) +!18 = distinct !DILexicalBlock(scope: !4, file: !5, line: 7) +!19 = !DILocation(line: 8, scope: !18)