Skip to content

[DWARF][DebugInfo] Function-local types may have concrete out-of-line parent subprogram instead of abstract one #55680

@chbessonova

Description

@chbessonova

Consider the following example:

template<typename T>
struct A { 
  A(T &in) : a(in) {}
  T a;
};

__attribute__((always_inline))
void foo() {
  struct B { int i; };
  B objB;
  A<B> objA(objB);
}

int main() {
  foo();
}

Here the function foo() should have 3 subprogram instances emitted: abstract, inlined and out-of-line.
The definition of struct B is expected to be a child of abstract instance of foo().

But actually, it is emitted as a child of out-of-line instance of foo():

$ clang -g -c -o - test.cpp | llvm-dwarfdump - --name=foo --show-children 

0x0000002a: DW_TAG_subprogram
              DW_AT_low_pc	(0x0000000000000000)
              DW_AT_high_pc	(0x000000000000001b)
              DW_AT_frame_base	(DW_OP_reg6 RBP)
              DW_AT_abstract_origin	(0x000000dc "_Z3foov")
              ...

0x0000004d:   DW_TAG_structure_type
                DW_AT_calling_convention	(DW_CC_pass_by_value)
                DW_AT_name	("B")
                DW_AT_byte_size	(0x04)
                DW_AT_decl_file	("test.cpp")
                DW_AT_decl_line	(9)
                ...
0x00000062:     NULL

0x00000063:   NULL

0x000000dc: DW_TAG_subprogram
              DW_AT_linkage_name	("_Z3foov")
              DW_AT_name	("foo")
              DW_AT_decl_file	("test.cpp")
              DW_AT_decl_line	(8)
              DW_AT_external	(true)
              DW_AT_inline	(DW_INL_inlined)
              ...
0x000000fe:   NULL

0x00000118: DW_TAG_inlined_subroutine
              DW_AT_abstract_origin	(0x000000dc "_Z3foov")
              DW_AT_low_pc	(0x0000000000000048)
              DW_AT_high_pc	(0x0000000000000055)
              DW_AT_call_file	("test.cpp")
              DW_AT_call_line	(15)
              DW_AT_call_column	(0x03)
              ...
0x0000013c:   NULL

While looking for a context subprogram DIE for foo()::B we are considering to get or create only a concrete subprogram DIE, never accounting an abstract one.

This makes impossible to directly inspect the type in debugger:

Breakpoint 1, foo () at test.cpp:11
11	  A<B> objA(objB);
(gdb) ptype B
No symbol "B" in current context.
(gdb) ptype objB
type = struct B {
    int i;
}

while gcc-compiled example (where struct B gets placed correctly) allows this:

Breakpoint 1, foo () at test.cpp:11
11	  A<B> objA(objB);
(gdb) ptype B
type = struct B {
    int i;
}
(gdb) ptype objB
type = struct B {
    int i;
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions