https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95437
Bug ID: 95437 Summary: DW_TAG_typedef for template alias missing template type parameters Product: gcc Version: unknown Status: UNCONFIRMED Severity: normal Priority: P3 Component: debug Assignee: unassigned at gcc dot gnu.org Reporter: palves at redhat dot com Target Milestone: --- Currently GCC represents instantiations of alias templates using DW_TAG_typedef instead of DW_TAG_template_alias. And, while Clang does the same (at least 5.0.2 does), Clang includes the template parameters in the typedef name, while GCC leaves the template parameters out. This causes problems in GDB. In more detail, with the following program: ~~~ template<typename T, typename U> struct Templ2 { static void method () {} }; template<typename T> using AliasTempl = Templ2<char, T>; typedef unsigned int UInt; AliasTempl<int> aliastmpl1; AliasTempl<long> aliastmpl2; AliasTempl<UInt> aliastmpl3; int main () { return 0; } ~~~ If compiled with Clang (I have 5.0.2 handy), we get: <1><2a>: Abbrev Number: 2 (DW_TAG_variable) <2b> DW_AT_name : (indirect string, offset: 0xba): aliastmpl1 <2f> DW_AT_type : <0x3f> <1><3f>: Abbrev Number: 3 (DW_TAG_typedef) <40> DW_AT_type : <0x4a> <44> DW_AT_name : (indirect string, offset: 0xe0): AliasTempl<int> <1><4a>: Abbrev Number: 4 (DW_TAG_structure_type) <4b> DW_AT_name : (indirect string, offset: 0xce): Templ2<char, int> <1><73>: Abbrev Number: 2 (DW_TAG_variable) <74> DW_AT_name : (indirect string, offset: 0xf0): aliastmpl2 <78> DW_AT_type : <0x88> ... <1><88>: Abbrev Number: 3 (DW_TAG_typedef) <89> DW_AT_type : <0x93> <8d> DW_AT_name : (indirect string, offset: 0x117): AliasTempl<long> <1><93>: Abbrev Number: 4 (DW_TAG_structure_type) <94> DW_AT_name : (indirect string, offset: 0x104): Templ2<char, long> <1><b5>: Abbrev Number: 2 (DW_TAG_variable) <b6> DW_AT_name : (indirect string, offset: 0x128): aliastmpl3 <ba> DW_AT_type : <0xca> (DW_OP_addr: 60101f) <1><ca>: Abbrev Number: 3 (DW_TAG_typedef) <cb> DW_AT_type : <0xd5> <cf> DW_AT_name : (indirect string, offset: 0x15b): AliasTempl<UInt> <1><d5>: Abbrev Number: 4 (DW_TAG_structure_type) <d6> DW_AT_name : (indirect string, offset: 0x140): Templ2<char, unsigned int> So when debugging the Clang-built binary, we get: (gdb) whatis aliastmpl1 type = AliasTempl<int> (gdb) whatis aliastmpl2 type = AliasTempl<long> (gdb) whatis aliastmpl3 type = AliasTempl<UInt> (gdb) ptype aliastmpl1 type = struct Templ2<char, int> [with T = char, U = int] { <no data fields> } (gdb) ptype aliastmpl2 type = struct Templ2<char, long> [with T = char, U = long] { <no data fields> } (gdb) ptype aliastmpl3 type = struct Templ2<char, unsigned int> [with T = char, U = unsigned int] { <no data fields> } (gdb) However, with GCC-built binaries we get three different typedefs with the same name: <1><34>: Abbrev Number: 3 (DW_TAG_structure_type) <35> DW_AT_name : (indirect string, offset: 0x10a): Templ2<char, int> <1><50>: Abbrev Number: 5 (DW_TAG_typedef) <51> DW_AT_name : (indirect string, offset: 0x23): AliasTempl <58> DW_AT_type : <0x34> <1><5c>: Abbrev Number: 6 (DW_TAG_variable) <5d> DW_AT_name : (indirect string, offset: 0x17b): aliastmpl1 <64> DW_AT_type : <0x50> <1><72>: Abbrev Number: 3 (DW_TAG_structure_type) <73> DW_AT_name : (indirect string, offset: 0x11c): Templ2<char, long int> <1><8e>: Abbrev Number: 5 (DW_TAG_typedef) <8f> DW_AT_name : (indirect string, offset: 0x23): AliasTempl <96> DW_AT_type : <0x72> <1><9a>: Abbrev Number: 6 (DW_TAG_variable) <9b> DW_AT_name : (indirect string, offset: 0x0): aliastmpl2 <a2> DW_AT_type : <0x8e> <1><b0>: Abbrev Number: 3 (DW_TAG_structure_type) <b1> DW_AT_name : (indirect string, offset: 0xef): Templ2<char, unsigned int> <1><cc>: Abbrev Number: 5 (DW_TAG_typedef) <cd> DW_AT_name : (indirect string, offset: 0x23): AliasTempl <d4> DW_AT_type : <0xb0> <1><d8>: Abbrev Number: 6 (DW_TAG_variable) <d9> DW_AT_name : (indirect string, offset: 0x18): aliastmpl3 <e0> DW_AT_type : <0xcc> I.e., all three typedefs are named "AliasTempl". This results in this with GDB: (gdb) whatis aliastmpl1 type = AliasTempl (gdb) whatis aliastmpl2 type = AliasTempl (gdb) whatis aliastmpl3 type = AliasTempl (gdb) ptype aliastmpl1 type = struct Templ2<char, int> [with T = char, U = int] { <no data fields> } (gdb) ptype aliastmpl2 type = struct Templ2<char, long> [with T = char, U = long] { <no data fields> } (gdb) ptype aliastmpl3 type = struct Templ2<char, unsigned int> [with T = char, U = unsigned int] { <no data fields> } I.e., the "whatis" command shows the same name three times, even though these are different types. And of course, the user is able to query info about the bogus "AliasTempl" typedef: (gdb) whatis AliasTempl type = Templ2<char, int> This "missing template parameters info" issue also prevents setting breakpoints using the alias template with GCC-built binaries. I.e., while this works (in current GDB master) with Clang-built binaries: (gdb) b AliasTempl<int>::method() Breakpoint 2 at 0x4004c4: file alias-template.cc, line 20. (gdb) info breakpoints Num Type Disp Enb Address What 2 breakpoint keep y 0x00000000004004c4 in Templ2<char, int>::method() at alias-template.cc:20 It does not work with GCC-built binaries: (gdb) b AliasTempl<int>::method() Function "AliasTempl<int>::method()" not defined. Make breakpoint pending on future shared library load? (y or [n]) n The above was tested with gcc 7.3.1, gcc 10 and clang 5.0.2.