gdb 8.x - g++ 7.x compatibility

classic Classic list List threaded Threaded
50 messages Options
123
Reply | Threaded
Open this post in threaded view
|

gdb 8.x - g++ 7.x compatibility

Roman Popov
Hello,
I'm trying to switch from g++ 5.4 to g++ 7.2.
GDB 8.0.1 however does not understand RTTI generated by g++7.2, so my
Python scripts for GDB are not working.

Here is a code example:

struct base {  virtual ~base(){}  };

template< int IVAL, unsigned UVAL, unsigned long long ULLVAL>
struct derived : base {
    int x = IVAL + + UVAL + ULLVAL;
};

int main()
{
    base * o = new derived<1,2,3>{};
    return 0;
}

When compiled with g++5.4 I can read value of x in debugger.
When compiled with g++7.2   gdb reports:
warning: RTTI symbol not found for class 'derived<1, 2u, 3ull>'

Problem here is that type name saved in debug information is
*derived<1, 2, 3>*, not *derived<1, 2u, 3ull>*

Do you plan to fix this anytime soon?

Thanks,
Roman
Reply | Threaded
Open this post in threaded view
|

Re: gdb 8.x - g++ 7.x compatibility

carl hansen
On Fri, Feb 2, 2018 at 7:17 PM, Roman Popov <[hidden email]> wrote:

> Hello,
> I'm trying to switch from g++ 5.4 to g++ 7.2.
> GDB 8.0.1 however does not understand RTTI generated by g++7.2, so my
> Python scripts for GDB are not working.
>
> Here is a code example:
>
> struct base {  virtual ~base(){}  };
>
> template< int IVAL, unsigned UVAL, unsigned long long ULLVAL>
> struct derived : base {
>     int x = IVAL + + UVAL + ULLVAL;
> };
>
> int main()
> {
>     base * o = new derived<1,2,3>{};
>     return 0;
> }
>
> When compiled with g++5.4 I can read value of x in debugger.
> When compiled with g++7.2   gdb reports:
> warning: RTTI symbol not found for class 'derived<1, 2u, 3ull>'
>
> Problem here is that type name saved in debug information is
> *derived<1, 2, 3>*, not *derived<1, 2u, 3ull>*
>
> Do you plan to fix this anytime soon?
>
> Thanks,
> Roman
>
​try  gdb 8.1 and gcc 7.3 and iterate.
see if fixed, repost.​
Reply | Threaded
Open this post in threaded view
|

Re: gdb 8.x - g++ 7.x compatibility

Simon Marchi
In reply to this post by Roman Popov
On 2018-02-02 22:17, Roman Popov wrote:

> Hello,
> I'm trying to switch from g++ 5.4 to g++ 7.2.
> GDB 8.0.1 however does not understand RTTI generated by g++7.2, so my
> Python scripts for GDB are not working.
>
> Here is a code example:
>
> struct base {  virtual ~base(){}  };
>
> template< int IVAL, unsigned UVAL, unsigned long long ULLVAL>
> struct derived : base {
>     int x = IVAL + + UVAL + ULLVAL;
> };
>
> int main()
> {
>     base * o = new derived<1,2,3>{};
>     return 0;
> }
>
> When compiled with g++5.4 I can read value of x in debugger.
> When compiled with g++7.2   gdb reports:
> warning: RTTI symbol not found for class 'derived<1, 2u, 3ull>'
>
> Problem here is that type name saved in debug information is
> *derived<1, 2, 3>*, not *derived<1, 2u, 3ull>*
>
> Do you plan to fix this anytime soon?
>
> Thanks,
> Roman

Hi Roman,

Your problem is probably linked to these issues, if you want to follow
them:

gcc: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81932
gdb: https://sourceware.org/bugzilla/show_bug.cgi?id=22013

As Carl said, it's a good idea to try with the latest version of both
tools, but I think the issue will still be present.

GCC changed how it outputs unsigned template parameters in the debug
info (from 2u to just 2), and it doesn't look like it's going to change
it back.  So I suppose we'll have to find a way to make GDB deal with
it.

Simon
Reply | Threaded
Open this post in threaded view
|

Re: gdb 8.x - g++ 7.x compatibility

Roman Popov
Yes, problem is still there in g++7.3 / gdb 8.1.  I wonder why they decided
to emit different strings to RTTI and debug info? What is the technical
reason behind this?

-Roman

2018-02-02 20:54 GMT-08:00 Simon Marchi <[hidden email]>:

> On 2018-02-02 22:17, Roman Popov wrote:
>
>> Hello,
>> I'm trying to switch from g++ 5.4 to g++ 7.2.
>> GDB 8.0.1 however does not understand RTTI generated by g++7.2, so my
>> Python scripts for GDB are not working.
>>
>> Here is a code example:
>>
>> struct base {  virtual ~base(){}  };
>>
>> template< int IVAL, unsigned UVAL, unsigned long long ULLVAL>
>> struct derived : base {
>>     int x = IVAL + + UVAL + ULLVAL;
>> };
>>
>> int main()
>> {
>>     base * o = new derived<1,2,3>{};
>>     return 0;
>> }
>>
>> When compiled with g++5.4 I can read value of x in debugger.
>> When compiled with g++7.2   gdb reports:
>> warning: RTTI symbol not found for class 'derived<1, 2u, 3ull>'
>>
>> Problem here is that type name saved in debug information is
>> *derived<1, 2, 3>*, not *derived<1, 2u, 3ull>*
>>
>> Do you plan to fix this anytime soon?
>>
>> Thanks,
>> Roman
>>
>
> Hi Roman,
>
> Your problem is probably linked to these issues, if you want to follow
> them:
>
> gcc: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81932
> gdb: https://sourceware.org/bugzilla/show_bug.cgi?id=22013
>
> As Carl said, it's a good idea to try with the latest version of both
> tools, but I think the issue will still be present.
>
> GCC changed how it outputs unsigned template parameters in the debug info
> (from 2u to just 2), and it doesn't look like it's going to change it
> back.  So I suppose we'll have to find a way to make GDB deal with it.
>
> Simon
>
Reply | Threaded
Open this post in threaded view
|

Re: gdb 8.x - g++ 7.x compatibility

Roman Popov
In reply to this post by Simon Marchi
2018-02-02 20:54 GMT-08:00 Simon Marchi <[hidden email]>:

>
> GCC changed how it outputs unsigned template parameters in the debug info
> (from 2u to just 2), and it doesn't look like it's going to change it
> back.  So I suppose we'll have to find a way to make GDB deal with it.
> Simon
>

I'm not so sure about it. In my opinion it is a gcc bug. 2u and 2 are
literals of different types. But I'm not a C++ expert.

It looks like g++ and clang treat C++ language differently in this case.
I've asked on stackoverflow:
https://stackoverflow.com/questions/48594693/auto-template-parameters-g-7-3-vs-clang-6-0-which-compiler-is-correct

If Clang is correct here, than foo<1u> and foo<1> are two different types.
And so gcc should emit correct postfixes to debuginfo.


-Roman
Reply | Threaded
Open this post in threaded view
|

Re: gdb 8.x - g++ 7.x compatibility

Paul Smith-20
In reply to this post by Simon Marchi
On Fri, 2018-02-02 at 23:54 -0500, Simon Marchi wrote:

> Your problem is probably linked to these issues, if you want to follow
> them:
>
> gcc: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81932
> gdb: https://sourceware.org/bugzilla/show_bug.cgi?id=22013
>
> As Carl said, it's a good idea to try with the latest version of both
> tools, but I think the issue will still be present.
>
> GCC changed how it outputs unsigned template parameters in the debug
> info (from 2u to just 2), and it doesn't look like it's going to change
> it back.  So I suppose we'll have to find a way to make GDB deal with
> it.

I also tried a couple of times [1][2][3] to get a discussion started on
the mailing lists for how to resolve this but didn't get any replies,
and I got busy with other things.

We really need to find someone who is knowlegeable on type lookup in
GDB.  That person needs to engage with the experts on the GCC side and
hash out the right answer to this problem.  In my experience, Jonathan
Wakely on the GCC side is extremely responsive, I'm just too much of a
tyro to be able to discuss it with him at the level needed to find a
solution.

I think it's an extremely serious issue, if GDB can't resolve some very
common (IME) types, but so far it hasn't risen to the level of getting
attention from those who have sufficient expertise to solve it.


[1] https://gcc.gnu.org/ml/gcc-help/2017-08/msg00120.html
[2] https://sourceware.org/ml/gdb/2017-08/msg00069.html
[3] https://sourceware.org/ml/gdb/2017-09/msg00042.html
Reply | Threaded
Open this post in threaded view
|

Re: gdb 8.x - g++ 7.x compatibility

Roman Popov
I've just checked g++8.0.1 from trunk, and the problem is still there. And
same with Clang compiler.

This is indeed is a serious issue for me, since my Python scripts for gdb
expect reliable dynamic type identification. However gdb is
completely powerless here. So I'm forced to stay on older compiler.
Consider this case (Results with g++ 8.0.1)

#include <iostream>
struct base {
    virtual void print() = 0;
};

template< auto IVAL>
struct foo : base {
    decltype(IVAL) x = -IVAL;
    void print() override { std::cout << x << std::endl; };
};

int main()
{
    base * fu = new foo<10u>();
    base * fi = new foo<10>();
    fu->print();
    fi->print();
    return 0;     // set breakpoint here
}:

Now check dynamic types in GDB:

(gdb) p *fu
warning: RTTI symbol not found for class 'foo<10u>'
$1 = warning: RTTI symbol not found for class 'foo<10u>'
warning: RTTI symbol not found for class 'foo<10u>'
{_vptr.base = 0x400bd0 <vtable for foo<10u>+16>}

(gdb) p *fi

(gdb) p *fi
$2 = (foo<10>) {<base> = {_vptr.base = 0x400bb8 <vtable for foo<10>+16>}, *x
= 4294967286*}

Here GDB picks wrong type!

In RTTI type names are different. And this is correct.

But in debuginfo both types have same name:

foo<10> {
  unsigned x;
}
foo<10> {
  int x;
}

So GDB picks the first one, which is wrong.

-Roman








2018-02-03 6:20 GMT-08:00 Paul Smith <[hidden email]>:

> On Fri, 2018-02-02 at 23:54 -0500, Simon Marchi wrote:
> > Your problem is probably linked to these issues, if you want to follow
> > them:
> >
> > gcc: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81932
> > gdb: https://sourceware.org/bugzilla/show_bug.cgi?id=22013
> >
> > As Carl said, it's a good idea to try with the latest version of both
> > tools, but I think the issue will still be present.
> >
> > GCC changed how it outputs unsigned template parameters in the debug
> > info (from 2u to just 2), and it doesn't look like it's going to change
> > it back.  So I suppose we'll have to find a way to make GDB deal with
> > it.
>
> I also tried a couple of times [1][2][3] to get a discussion started on
> the mailing lists for how to resolve this but didn't get any replies,
> and I got busy with other things.
>
> We really need to find someone who is knowlegeable on type lookup in
> GDB.  That person needs to engage with the experts on the GCC side and
> hash out the right answer to this problem.  In my experience, Jonathan
> Wakely on the GCC side is extremely responsive, I'm just too much of a
> tyro to be able to discuss it with him at the level needed to find a
> solution.
>
> I think it's an extremely serious issue, if GDB can't resolve some very
> common (IME) types, but so far it hasn't risen to the level of getting
> attention from those who have sufficient expertise to solve it.
>
>
> [1] https://gcc.gnu.org/ml/gcc-help/2017-08/msg00120.html
> [2] https://sourceware.org/ml/gdb/2017-08/msg00069.html
> [3] https://sourceware.org/ml/gdb/2017-09/msg00042.html
>
Reply | Threaded
Open this post in threaded view
|

Re: gdb 8.x - g++ 7.x compatibility

Maurizio Manfredini
n4659 17.4 (Type equivalence) p1.3:

Two template-ids refer to the same class, function, or variable if
...
their corresponding non-type template arguments of integral or
enumeration type have identical values
...

It looks that for non-type template arguments the template type
equivalence is based on argument /value/ not /type/ (and value), so IMHO
gcc is correct where it considers foo<10u> and foo<10> to be the same
type, i.e. "refer to the same class"

FWIW, type_info reports the same class name for both templates, which
appears to be correct as per the above.

I would think someone from gcc might be more specific on why both
templates print 4294967286, and what debug info is actually stored by -g
in this case.


On 2/3/2018 6:18 PM, Roman Popov wrote:

> I've just checked g++8.0.1 from trunk, and the problem is still there. And
> same with Clang compiler.
>
> This is indeed is a serious issue for me, since my Python scripts for gdb
> expect reliable dynamic type identification. However gdb is
> completely powerless here. So I'm forced to stay on older compiler.
> Consider this case (Results with g++ 8.0.1)
>
> #include <iostream>
> struct base {
>      virtual void print() = 0;
> };
>
> template< auto IVAL>
> struct foo : base {
>      decltype(IVAL) x = -IVAL;
>      void print() override { std::cout << x << std::endl; };
> };
>
> int main()
> {
>      base * fu = new foo<10u>();
>      base * fi = new foo<10>();
>      fu->print();
>      fi->print();
>      return 0;     // set breakpoint here
> }:
>
> Now check dynamic types in GDB:
>
> (gdb) p *fu
> warning: RTTI symbol not found for class 'foo<10u>'
> $1 = warning: RTTI symbol not found for class 'foo<10u>'
> warning: RTTI symbol not found for class 'foo<10u>'
> {_vptr.base = 0x400bd0 <vtable for foo<10u>+16>}
>
> (gdb) p *fi
>
> (gdb) p *fi
> $2 = (foo<10>) {<base> = {_vptr.base = 0x400bb8 <vtable for foo<10>+16>}, *x
> = 4294967286*}
>
> Here GDB picks wrong type!
>
> In RTTI type names are different. And this is correct.
>
> But in debuginfo both types have same name:
>
> foo<10> {
>    unsigned x;
> }
> foo<10> {
>    int x;
> }
>
> So GDB picks the first one, which is wrong.
>
> -Roman
>
>
>
>
>
>
>
>
> 2018-02-03 6:20 GMT-08:00 Paul Smith <[hidden email]>:
>
>> On Fri, 2018-02-02 at 23:54 -0500, Simon Marchi wrote:
>>> Your problem is probably linked to these issues, if you want to follow
>>> them:
>>>
>>> gcc: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81932
>>> gdb: https://sourceware.org/bugzilla/show_bug.cgi?id=22013
>>>
>>> As Carl said, it's a good idea to try with the latest version of both
>>> tools, but I think the issue will still be present.
>>>
>>> GCC changed how it outputs unsigned template parameters in the debug
>>> info (from 2u to just 2), and it doesn't look like it's going to change
>>> it back.  So I suppose we'll have to find a way to make GDB deal with
>>> it.
>>
>> I also tried a couple of times [1][2][3] to get a discussion started on
>> the mailing lists for how to resolve this but didn't get any replies,
>> and I got busy with other things.
>>
>> We really need to find someone who is knowlegeable on type lookup in
>> GDB.  That person needs to engage with the experts on the GCC side and
>> hash out the right answer to this problem.  In my experience, Jonathan
>> Wakely on the GCC side is extremely responsive, I'm just too much of a
>> tyro to be able to discuss it with him at the level needed to find a
>> solution.
>>
>> I think it's an extremely serious issue, if GDB can't resolve some very
>> common (IME) types, but so far it hasn't risen to the level of getting
>> attention from those who have sufficient expertise to solve it.
>>
>>
>> [1] https://gcc.gnu.org/ml/gcc-help/2017-08/msg00120.html
>> [2] https://sourceware.org/ml/gdb/2017-08/msg00069.html
>> [3] https://sourceware.org/ml/gdb/2017-09/msg00042.html
>>
Reply | Threaded
Open this post in threaded view
|

Re: gdb 8.x - g++ 7.x compatibility

Simon Marchi
On 2018-02-03 13:35, Manfred wrote:

> n4659 17.4 (Type equivalence) p1.3:
>
> Two template-ids refer to the same class, function, or variable if
> ...
> their corresponding non-type template arguments of integral or
> enumeration type have identical values
> ...
>
> It looks that for non-type template arguments the template type
> equivalence is based on argument /value/ not /type/ (and value), so
> IMHO gcc is correct where it considers foo<10u> and foo<10> to be the
> same type, i.e. "refer to the same class"
>
> FWIW, type_info reports the same class name for both templates, which
> appears to be correct as per the above.
>
> I would think someone from gcc might be more specific on why both
> templates print 4294967286, and what debug info is actually stored by
> -g in this case.

I think that Roman's example clearly shows that they are not equivalent in
all cases.

Building Roman's example with g++ 7.3 results in a single instantiated type.  You
can see that both "new foo<10>()" and "new foo<10u>()" end up calling the same
constructor.  It seems like which type is instantiated depends on which template
parameter (the signed or unsigned one) you use first.  So with this:

     base * fi = new foo<10>();
     base * fu = new foo<10u>();

the output is -10 for both, and with

     base * fu = new foo<10u>();
     base * fi = new foo<10>();

the output is 4294967286 for both.  But it's probably a bogus behavior.  I tested
with clangd, it instantiates two different types, so you get 4294967286 for the
<10u> case and -10 for the <10> case.  I also just built gcc from master, and it
also instantiates two types, so it seems like that was fixed recently.

So let's see what debug info gcc master generates for these two instances of foo
(clang master generates the equivalent).

  <1><9257>: Abbrev Number: 66 (DW_TAG_structure_type)
     <9258>   DW_AT_name        : (indirect string, offset: 0x8455): foo<10>
     <925c>   DW_AT_byte_size   : 16
     <925d>   DW_AT_decl_file   : 1
     <925e>   DW_AT_decl_line   : 7
     <925f>   DW_AT_decl_column : 8
     <9260>   DW_AT_containing_type: <0x92fd>
     <9264>   DW_AT_sibling     : <0x92f8>
...
 <1><93be>: Abbrev Number: 66 (DW_TAG_structure_type)
    <93bf>   DW_AT_name        : (indirect string, offset: 0x8455): foo<10>
    <93c3>   DW_AT_byte_size   : 16
    <93c4>   DW_AT_decl_file   : 1
    <93c5>   DW_AT_decl_line   : 7
    <93c6>   DW_AT_decl_column : 8
    <93c7>   DW_AT_containing_type: <0x92fd>
    <93cb>   DW_AT_sibling     : <0x945f>

If there are two types with the same name, how is gdb expected to differentiate
them?

If we can't rely on the DW_AT_name anymore to differentiate templated types, then
the only alternative I see would be to make GDB ignore the template part of the
DW_AT_name value, and reconstruct it in the format it expects (with the u) from the
DW_TAG_template_value_param DIEs children of DW_TAG_structure_type (there's already
code to do that in dwarf2_compute_name).  Their types correctly point to the signed
int or unsigned int DIE, so we have the necessary information.  However, that would
mean reading many more full DIEs early on, when just building partial symbols, which
would slow done loading the symbols of pretty much any C++ program.

From what I understand from the original change that caused all this [1], removing
the suffixes was meant to make the error messages more readable for the user.
However, since foo<10>::print() and foo<10u>::print() are not the same function,
I think it would actually be more confusing if an error message talked about the
instantiation with the unsigned type, but mentioned "foo<10>::print()".  For example,
if you put a

  static_assert (std::is_signed<decltype(x)>::value);

in the print method, this is the error message from gcc:

  test.cpp: In instantiation of 'void foo<IVAL>::print() [with auto IVAL = 10]':
  test.cpp:24:1:   required from here
  test.cpp:12:22: error: static assertion failed
         static_assert (std::is_signed<decltype(x)>::value);
                        ^~~

Wouldn't the message make more sense with a u suffix?

Simon

[1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78165
Reply | Threaded
Open this post in threaded view
|

Re: gdb 8.x - g++ 7.x compatibility

Maurizio Manfredini


On 2/4/2018 6:01 AM, Simon Marchi wrote:

> On 2018-02-03 13:35, Manfred wrote:
>> n4659 17.4 (Type equivalence) p1.3:
>>
>> Two template-ids refer to the same class, function, or variable if
>> ...
>> their corresponding non-type template arguments of integral or
>> enumeration type have identical values
>> ...
>>
>> It looks that for non-type template arguments the template type
>> equivalence is based on argument /value/ not /type/ (and value), so
>> IMHO gcc is correct where it considers foo<10u> and foo<10> to be the
>> same type, i.e. "refer to the same class"
>>
>> FWIW, type_info reports the same class name for both templates, which
>> appears to be correct as per the above.
>>
>> I would think someone from gcc might be more specific on why both
>> templates print 4294967286, and what debug info is actually stored by
>> -g in this case.
>
> I think that Roman's example clearly shows that they are not equivalent in
> all cases.
I was merely reporting the wording of the standard, which would be the
authority to follow. I may agree that not specifying type identity may
lead to unexpected results. Personally I would prefer the standard to
say "identical value and type" here (and it appears from your findings
below that quality compilers already handle it this way), but this is
only an opinion.

>
> Building Roman's example with g++ 7.3 results in a single instantiated type.  You
> can see that both "new foo<10>()" and "new foo<10u>()" end up calling the same
> constructor.  It seems like which type is instantiated depends on which template
> parameter (the signed or unsigned one) you use first.  So with this:
>
>       base * fi = new foo<10>();
>       base * fu = new foo<10u>();
>
> the output is -10 for both, and with
>
>       base * fu = new foo<10u>();
>       base * fi = new foo<10>();
>
> the output is 4294967286 for both.  But it's probably a bogus behavior.
Indeed.

   I tested

> with clangd, it instantiates two different types, so you get 4294967286 for the
> <10u> case and -10 for the <10> case.  I also just built gcc from master, and it
> also instantiates two types, so it seems like that was fixed recently.
>
> So let's see what debug info gcc master generates for these two instances of foo
> (clang master generates the equivalent).
>
>    <1><9257>: Abbrev Number: 66 (DW_TAG_structure_type)
>       <9258>   DW_AT_name        : (indirect string, offset: 0x8455): foo<10>
>       <925c>   DW_AT_byte_size   : 16
>       <925d>   DW_AT_decl_file   : 1
>       <925e>   DW_AT_decl_line   : 7
>       <925f>   DW_AT_decl_column : 8
>       <9260>   DW_AT_containing_type: <0x92fd>
>       <9264>   DW_AT_sibling     : <0x92f8>
> ...
>   <1><93be>: Abbrev Number: 66 (DW_TAG_structure_type)
>      <93bf>   DW_AT_name        : (indirect string, offset: 0x8455): foo<10>
>      <93c3>   DW_AT_byte_size   : 16
>      <93c4>   DW_AT_decl_file   : 1
>      <93c5>   DW_AT_decl_line   : 7
>      <93c6>   DW_AT_decl_column : 8
>      <93c7>   DW_AT_containing_type: <0x92fd>
>      <93cb>   DW_AT_sibling     : <0x945f>
>
> If there are two types with the same name, how is gdb expected to differentiate
> them?
>
> If we can't rely on the DW_AT_name anymore to differentiate templated types, then
> the only alternative I see would be to make GDB ignore the template part of the
> DW_AT_name value, and reconstruct it in the format it expects (with the u) from the
> DW_TAG_template_value_param DIEs children of DW_TAG_structure_type (there's already
> code to do that in dwarf2_compute_name).  Their types correctly point to the signed
> int or unsigned int DIE, so we have the necessary information.  However, that would
> mean reading many more full DIEs early on, when just building partial symbols, which
> would slow done loading the symbols of pretty much any C++ program.
>
>  From what I understand from the original change that caused all this [1], removing
> the suffixes was meant to make the error messages more readable for the user.
> However, since foo<10>::print() and foo<10u>::print() are not the same function,
> I think it would actually be more confusing if an error message talked about the
> instantiation with the unsigned type, but mentioned "foo<10>::print()".  For example,
> if you put a
>
>    static_assert (std::is_signed<decltype(x)>::value);
>
> in the print method, this is the error message from gcc:
>
>    test.cpp: In instantiation of 'void foo<IVAL>::print() [with auto IVAL = 10]':
>    test.cpp:24:1:   required from here
>    test.cpp:12:22: error: static assertion failed
>           static_assert (std::is_signed<decltype(x)>::value);
>                          ^~~
>
> Wouldn't the message make more sense with a u suffix?
Probably so.

>
> Simon
>
> [1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78165
>
Reply | Threaded
Open this post in threaded view
|

Re: gdb 8.x - g++ 7.x compatibility

Martin Sebor-3
In reply to this post by Simon Marchi
On 02/03/2018 10:01 PM, Simon Marchi wrote:

> On 2018-02-03 13:35, Manfred wrote:
>> n4659 17.4 (Type equivalence) p1.3:
>>
>> Two template-ids refer to the same class, function, or variable if
>> ...
>> their corresponding non-type template arguments of integral or
>> enumeration type have identical values
>> ...
>>
>> It looks that for non-type template arguments the template type
>> equivalence is based on argument /value/ not /type/ (and value), so
>> IMHO gcc is correct where it considers foo<10u> and foo<10> to be the
>> same type, i.e. "refer to the same class"
>>
>> FWIW, type_info reports the same class name for both templates, which
>> appears to be correct as per the above.
>>
>> I would think someone from gcc might be more specific on why both
>> templates print 4294967286, and what debug info is actually stored by
>> -g in this case.
>
> I think that Roman's example clearly shows that they are not equivalent in
> all cases.
>
> Building Roman's example with g++ 7.3 results in a single instantiated type.  You
> can see that both "new foo<10>()" and "new foo<10u>()" end up calling the same
> constructor.  It seems like which type is instantiated depends on which template
> parameter (the signed or unsigned one) you use first.  So with this:
>
>      base * fi = new foo<10>();
>      base * fu = new foo<10u>();
>
> the output is -10 for both, and with
>
>      base * fu = new foo<10u>();
>      base * fi = new foo<10>();
>
> the output is 4294967286 for both.  But it's probably a bogus behavior.  I tested
> with clangd, it instantiates two different types, so you get 4294967286 for the
> <10u> case and -10 for the <10> case.  I also just built gcc from master, and it
> also instantiates two types, so it seems like that was fixed recently.
>
> So let's see what debug info gcc master generates for these two instances of foo
> (clang master generates the equivalent).
>
>   <1><9257>: Abbrev Number: 66 (DW_TAG_structure_type)
>      <9258>   DW_AT_name        : (indirect string, offset: 0x8455): foo<10>
>      <925c>   DW_AT_byte_size   : 16
>      <925d>   DW_AT_decl_file   : 1
>      <925e>   DW_AT_decl_line   : 7
>      <925f>   DW_AT_decl_column : 8
>      <9260>   DW_AT_containing_type: <0x92fd>
>      <9264>   DW_AT_sibling     : <0x92f8>
> ...
>  <1><93be>: Abbrev Number: 66 (DW_TAG_structure_type)
>     <93bf>   DW_AT_name        : (indirect string, offset: 0x8455): foo<10>
>     <93c3>   DW_AT_byte_size   : 16
>     <93c4>   DW_AT_decl_file   : 1
>     <93c5>   DW_AT_decl_line   : 7
>     <93c6>   DW_AT_decl_column : 8
>     <93c7>   DW_AT_containing_type: <0x92fd>
>     <93cb>   DW_AT_sibling     : <0x945f>
>
> If there are two types with the same name, how is gdb expected to differentiate
> them?
>
> If we can't rely on the DW_AT_name anymore to differentiate templated types, then
> the only alternative I see would be to make GDB ignore the template part of the
> DW_AT_name value, and reconstruct it in the format it expects (with the u) from the
> DW_TAG_template_value_param DIEs children of DW_TAG_structure_type (there's already
> code to do that in dwarf2_compute_name).  Their types correctly point to the signed
> int or unsigned int DIE, so we have the necessary information.  However, that would
> mean reading many more full DIEs early on, when just building partial symbols, which
> would slow done loading the symbols of pretty much any C++ program.
>
> From what I understand from the original change that caused all this [1], removing
> the suffixes was meant to make the error messages more readable for the user.

Readability was a factor but it wasn't the main motivation for
the change.

Printing the suffix is unhelpful because it leads to unnecessary
differences in diagnostics (even in non-template contexts).  For
templates with non-type template parameters there is no difference
between, say A<1>, A<1U>, A<(unsigned) 1>, or even A<Green> when
Green is an enumerator that evaluates to 1, so including the suffix
serves no useful purpose.  In the GCC test suite, it would tend to
cause failures due to differences between the underlying type of
common typedefs like size_t and ptrdiff_t.  Avoiding these
unnecessary differences was the main motivation for the change.
Not necessarily just in the GCC test suite but in all setups that
process GCC messages.

> However, since foo<10>::print() and foo<10u>::print() are not the same function,
> I think it would actually be more confusing if an error message talked about the
> instantiation with the unsigned type, but mentioned "foo<10>::print()".  For example,
> if you put a
>
>   static_assert (std::is_signed<decltype(x)>::value);
>
> in the print method, this is the error message from gcc:
>
>   test.cpp: In instantiation of 'void foo<IVAL>::print() [with auto IVAL = 10]':
>   test.cpp:24:1:   required from here
>   test.cpp:12:22: error: static assertion failed
>          static_assert (std::is_signed<decltype(x)>::value);
>                         ^~~
>
> Wouldn't the message make more sense with a u suffix?

I think this message would be the most meaningful if the "auto"
part were replaced with the deduced type.  With that, the suffix
of the constant isn't important, just as in other contexts.

I didn't consider the use of auto as a template parameter but
I don't think it changes anything.  There, just like in other
contexts, what's important is the deduced types and the values
of constants, not the minute details of how they are spelled.

That said, it wasn't my intention to make things difficult for
the debugger.  But changing GCC back to include the suffix,
even just in the debug info, isn't a solution.  There are other
compilers besides GCC that don't emit the suffixes, and there
even are some that prepend a cast to the number, so if GDB is
to be usable with all these kinds of producers it needs to be
able to handle all of these forms.

Martin
Reply | Threaded
Open this post in threaded view
|

Re: gdb 8.x - g++ 7.x compatibility

Simon Marchi
Hi Martin,

Thanks for the reply.

On 2018-02-04 02:17 PM, Martin Sebor wrote:
> Printing the suffix is unhelpful because it leads to unnecessary
> differences in diagnostics (even in non-template contexts).  For
> templates with non-type template parameters there is no difference
> between, say A<1>, A<1U>, A<(unsigned) 1>, or even A<Green> when
> Green is an enumerator that evaluates to 1, so including the suffix
> serves no useful purpose.

This is the part I don't understand.  In Roman's example, spelling
foo<10> and foo<10u> resulted in two different instantiations of the
template, with different code.  So that means it can make a difference,
can't it?

> In the GCC test suite, it would tend to
> cause failures due to differences between the underlying type of
> common typedefs like size_t and ptrdiff_t.  Avoiding these
> unnecessary differences was the main motivation for the change.
> Not necessarily just in the GCC test suite but in all setups that
> process GCC messages.

Ok, I understand.

> I didn't consider the use of auto as a template parameter but
> I don't think it changes anything.  There, just like in other
> contexts, what's important is the deduced types and the values
> of constants, not the minute details of how they are spelled.

Well, it seems like using decltype on a template constant value is
a way to make the type of constants important, in addition to their
value.  I know the standard seems to say otherwise (what Manfred
quoted), but the reality seems different.  I'm not a language expert
so I can't tell if this is a deficiency in the language or not.

> That said, it wasn't my intention to make things difficult for
> the debugger.

I hope so :).

> But changing GCC back to include the suffix,
> even just in the debug info, isn't a solution.  There are other
> compilers besides GCC that don't emit the suffixes, and there
> even are some that prepend a cast to the number, so if GDB is
> to be usable with all these kinds of producers it needs to be
> able to handle all of these forms.

As I said earlier, there are probably ways to make GDB cope with it.
The only solution I saw (I'd like to hear about other ones) was to make
GDB ignore the template part in DW_AT_name and re-build it from the
DW_TAG_template_* DIEs in the format it expects.  It can already do
that somewhat, because, as you said, some compilers don't emit
the template part in DW_AT_name.

Doing so would cause major slowdowns in symbol reading, I've tried it
for the sake of experimentation/discussion.  I have a patch available
on the "users/simark/template-suffix" branch in the binutils-gdb
repo [1].  It works for Roman's example, but running the GDB testsuite
shows that, of course, the devil is in the details.

Consider something like this:

  template <int *P>
  struct foo { virtual ~foo() {} };

  int n;

  int main ()
  {
    foo<&n> f;
  }


The demangled name that GDB will be looking up is "foo<&n>".  The
debug info about the template parameter only contains the resulting
address of n (the value of &n):

 <2><bf>: Abbrev Number: 11 (DW_TAG_template_value_param)
    <c0>   DW_AT_name        : P
    <c2>   DW_AT_type        : <0x1ac>
    <c6>   DW_AT_location    : 10 byte block: 3 34 10 60 0 0 0 0 0 9f   (DW_OP_addr: 601034; DW_OP_stack_value)

I don't see how GDB could reconstruct the "&n" in the template, so
that's where my idea falls short.

Simon

[1] https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=shortlog;h=refs/heads/users/simark/template-suffix
Reply | Threaded
Open this post in threaded view
|

Re: gdb 8.x - g++ 7.x compatibility

Jonathan Wakely-4
In reply to this post by Martin Sebor-3
On 4 February 2018 at 19:17, Martin Sebor wrote:

> I think this message would be the most meaningful if the "auto"
> part were replaced with the deduced type.  With that, the suffix
> of the constant isn't important, just as in other contexts.
>
> I didn't consider the use of auto as a template parameter but
> I don't think it changes anything.  There, just like in other
> contexts, what's important is the deduced types and the values
> of constants, not the minute details of how they are spelled.
>
> That said, it wasn't my intention to make things difficult for
> the debugger.  But changing GCC back to include the suffix,
> even just in the debug info, isn't a solution.  There are other
> compilers besides GCC that don't emit the suffixes, and there
> even are some that prepend a cast to the number, so if GDB is
> to be usable with all these kinds of producers it needs to be
> able to handle all of these forms.

The change is a little unfortunate, I pointed out the problems for
debuginfo and template<auto> recently in another context:
https://sourceware.org/bugzilla/show_bug.cgi?id=21492#c1

As I said there, simply comparing strings from the debuginfo is
insufficient for Clang anyway. Now it is for GCC too.
Reply | Threaded
Open this post in threaded view
|

Re: gdb 8.x - g++ 7.x compatibility

Martin Sebor-3
In reply to this post by Simon Marchi
On 02/04/2018 10:06 PM, Simon Marchi wrote:

> Hi Martin,
>
> Thanks for the reply.
>
> On 2018-02-04 02:17 PM, Martin Sebor wrote:
>> Printing the suffix is unhelpful because it leads to unnecessary
>> differences in diagnostics (even in non-template contexts).  For
>> templates with non-type template parameters there is no difference
>> between, say A<1>, A<1U>, A<(unsigned) 1>, or even A<Green> when
>> Green is an enumerator that evaluates to 1, so including the suffix
>> serves no useful purpose.
>
> This is the part I don't understand.  In Roman's example, spelling
> foo<10> and foo<10u> resulted in two different instantiations of the
> template, with different code.  So that means it can make a difference,
> can't it?

Yes, with auto, the type of the constant does determine the type
of the specialization of the template in the source code.

In non-type template arguments, and more to the point I was making,
in diagnostics, the suffix shouldn't or doesn't need to be what
distinguishes the type of the template, even with auto.  The part
"with auto IVAL = 10" in the message

   'void foo<IVAL>::print() [with auto IVAL = 10]':

would be far clearer if auto were replaced by the deduced type,
say along these lines:

   'void foo<IVAL>::print() [with int IVAL = 10]':

rather than relying on the suffix alone to distinguish between
different specializations of the template.  That seems far too
subtle to me.  But I think the diagnostic format is (or should
be) independent of the debug info.

>> In the GCC test suite, it would tend to
>> cause failures due to differences between the underlying type of
>> common typedefs like size_t and ptrdiff_t.  Avoiding these
>> unnecessary differences was the main motivation for the change.
>> Not necessarily just in the GCC test suite but in all setups that
>> process GCC messages.
>
> Ok, I understand.
>
>> I didn't consider the use of auto as a template parameter but
>> I don't think it changes anything.  There, just like in other
>> contexts, what's important is the deduced types and the values
>> of constants, not the minute details of how they are spelled.
>
> Well, it seems like using decltype on a template constant value is
> a way to make the type of constants important, in addition to their
> value.  I know the standard seems to say otherwise (what Manfred
> quoted), but the reality seems different.  I'm not a language expert
> so I can't tell if this is a deficiency in the language or not.
>
>> That said, it wasn't my intention to make things difficult for
>> the debugger.
>
> I hope so :).
>
>> But changing GCC back to include the suffix,
>> even just in the debug info, isn't a solution.  There are other
>> compilers besides GCC that don't emit the suffixes, and there
>> even are some that prepend a cast to the number, so if GDB is
>> to be usable with all these kinds of producers it needs to be
>> able to handle all of these forms.
>
> As I said earlier, there are probably ways to make GDB cope with it.
> The only solution I saw (I'd like to hear about other ones) was to make
> GDB ignore the template part in DW_AT_name and re-build it from the
> DW_TAG_template_* DIEs in the format it expects.  It can already do
> that somewhat, because, as you said, some compilers don't emit
> the template part in DW_AT_name.
>
> Doing so would cause major slowdowns in symbol reading, I've tried it
> for the sake of experimentation/discussion.  I have a patch available
> on the "users/simark/template-suffix" branch in the binutils-gdb
> repo [1].  It works for Roman's example, but running the GDB testsuite
> shows that, of course, the devil is in the details.
>
> Consider something like this:
>
>   template <int *P>
>   struct foo { virtual ~foo() {} };
>
>   int n;
>
>   int main ()
>   {
>     foo<&n> f;
>   }
>
>
> The demangled name that GDB will be looking up is "foo<&n>".  The
> debug info about the template parameter only contains the resulting
> address of n (the value of &n):
>
>  <2><bf>: Abbrev Number: 11 (DW_TAG_template_value_param)
>     <c0>   DW_AT_name        : P
>     <c2>   DW_AT_type        : <0x1ac>
>     <c6>   DW_AT_location    : 10 byte block: 3 34 10 60 0 0 0 0 0 9f   (DW_OP_addr: 601034; DW_OP_stack_value)
>
> I don't see how GDB could reconstruct the "&n" in the template, so
> that's where my idea falls short.

I'm afraid I know too little about the internals of GDB to
fully appreciate the importance of this problem or have
an idea how it could be handled.

With respect to the suffix, I keep coming back to the reality
that even if GCC were to change to emit a format that GDB can
interpret easily and efficiently, there still are other
compilers that emit a different format.  So the conclusion
that a general solution that handles more than just one format
(at least for non-type template arguments without auto) seems
unescapable.

For auto, since it's new, a viable alternative might be to
standardize the debug info format so that eventually all
producers will converge on it. But even that approach won't
help users of existing compilers.

Martin

>
> Simon
>
> [1] https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=shortlog;h=refs/heads/users/simark/template-suffix
>

Reply | Threaded
Open this post in threaded view
|

Re: gdb 8.x - g++ 7.x compatibility

Simon Marchi
On 2018-02-05 11:45, Martin Sebor wrote:

> Yes, with auto, the type of the constant does determine the type
> of the specialization of the template in the source code.
>
> In non-type template arguments, and more to the point I was making,
> in diagnostics, the suffix shouldn't or doesn't need to be what
> distinguishes the type of the template, even with auto.  The part
> "with auto IVAL = 10" in the message
>
>   'void foo<IVAL>::print() [with auto IVAL = 10]':
>
> would be far clearer if auto were replaced by the deduced type,
> say along these lines:
>
>   'void foo<IVAL>::print() [with int IVAL = 10]':
>
> rather than relying on the suffix alone to distinguish between
> different specializations of the template.  That seems far too
> subtle to me.  But I think the diagnostic format is (or should
> be) independent of the debug info.

That makes sense.

> With respect to the suffix, I keep coming back to the reality
> that even if GCC were to change to emit a format that GDB can
> interpret easily and efficiently, there still are other
> compilers that emit a different format.  So the conclusion
> that a general solution that handles more than just one format
> (at least for non-type template arguments without auto) seems
> unescapable.

If there are other compilers we wanted to support for which we can't
trust the template format, we could always ignore the template part of
DW_AT_name specifically for them.  But since g++ and gdb are part of the
same project and are expected to work well and efficiently together, I
would have hoped that we could agree on a format so that gdb would not
have to do the extra work when parsing a g++-generated file
(consequently the same format that libiberty's demangler produces).

Given the problem I illustrated in my previous mail, I don't have a
general solution to the problem to propose.

Simon
Reply | Threaded
Open this post in threaded view
|

Re: gdb 8.x - g++ 7.x compatibility

Roman Popov
Interestingly RTTI name also gives no guarantees:
http://en.cppreference.com/w/cpp/types/type_info/name

<< Returns an implementation defined null-terminated character string
containing the name of the type. No guarantees are given; in particular,
the returned string can be identical for several types and change between
invocations of the same program. >>

It probably makes sense to look how g++ implements
std::type_info::operator== . Probably there are some hints that GDB
algorithm can utilize.
Operator std::type_info::operator== must return true for equivalent types.


2018-02-05 8:59 GMT-08:00 Simon Marchi <[hidden email]>:

> On 2018-02-05 11:45, Martin Sebor wrote:
>
>> Yes, with auto, the type of the constant does determine the type
>> of the specialization of the template in the source code.
>>
>> In non-type template arguments, and more to the point I was making,
>> in diagnostics, the suffix shouldn't or doesn't need to be what
>> distinguishes the type of the template, even with auto.  The part
>> "with auto IVAL = 10" in the message
>>
>>   'void foo<IVAL>::print() [with auto IVAL = 10]':
>>
>> would be far clearer if auto were replaced by the deduced type,
>> say along these lines:
>>
>>   'void foo<IVAL>::print() [with int IVAL = 10]':
>>
>> rather than relying on the suffix alone to distinguish between
>> different specializations of the template.  That seems far too
>> subtle to me.  But I think the diagnostic format is (or should
>> be) independent of the debug info.
>>
>
> That makes sense.
>
> With respect to the suffix, I keep coming back to the reality
>> that even if GCC were to change to emit a format that GDB can
>> interpret easily and efficiently, there still are other
>> compilers that emit a different format.  So the conclusion
>> that a general solution that handles more than just one format
>> (at least for non-type template arguments without auto) seems
>> unescapable.
>>
>
> If there are other compilers we wanted to support for which we can't trust
> the template format, we could always ignore the template part of DW_AT_name
> specifically for them.  But since g++ and gdb are part of the same project
> and are expected to work well and efficiently together, I would have hoped
> that we could agree on a format so that gdb would not have to do the extra
> work when parsing a g++-generated file (consequently the same format that
> libiberty's demangler produces).
>
> Given the problem I illustrated in my previous mail, I don't have a
> general solution to the problem to propose.
>
> Simon
>
Reply | Threaded
Open this post in threaded view
|

Re: gdb 8.x - g++ 7.x compatibility

Jonathan Wakely-4
On 5 February 2018 at 17:44, Roman Popov wrote:

> Interestingly RTTI name also gives no guarantees:
> http://en.cppreference.com/w/cpp/types/type_info/name
>
> << Returns an implementation defined null-terminated character string
> containing the name of the type. No guarantees are given; in particular,
> the returned string can be identical for several types and change between
> invocations of the same program. >>
>
> It probably makes sense to look how g++ implements
> std::type_info::operator== . Probably there are some hints that GDB
> algorithm can utilize.
> Operator std::type_info::operator== must return true for equivalent types.

It's the mangled name.
Reply | Threaded
Open this post in threaded view
|

Re: gdb 8.x - g++ 7.x compatibility

Roman Popov
Do you mean that g++ guarantees uniqueness of mangled names for types? And
uses name compare for operator==  ?

2018-02-05 12:08 GMT-08:00 Jonathan Wakely <[hidden email]>:

> On 5 February 2018 at 17:44, Roman Popov wrote:
> > Interestingly RTTI name also gives no guarantees:
> > http://en.cppreference.com/w/cpp/types/type_info/name
> >
> > << Returns an implementation defined null-terminated character string
> > containing the name of the type. No guarantees are given; in particular,
> > the returned string can be identical for several types and change between
> > invocations of the same program. >>
> >
> > It probably makes sense to look how g++ implements
> > std::type_info::operator== . Probably there are some hints that GDB
> > algorithm can utilize.
> > Operator std::type_info::operator== must return true for equivalent
> types.
>
> It's the mangled name.
>
Reply | Threaded
Open this post in threaded view
|

Re: gdb 8.x - g++ 7.x compatibility

Jonathan Wakely-4
On 5 February 2018 at 20:10, Roman Popov wrote:
> Do you mean that g++ guarantees uniqueness of mangled names for types? And

Of course. The mangled name is determined by the ABI and must be
stable, predictable and unique, so that linking works.

> uses name compare for operator==  ?

Yes.
Reply | Threaded
Open this post in threaded view
|

Re: gdb 8.x - g++ 7.x compatibility

Roman Popov
Well, if ABI has specification for type naming, why not to put this name to
debug_info so debugger can use it?

In this case argument that "each producer has its own naming conventions"
no longer works.  Any producer for given ABI must use ABI-specified names.



2018-02-05 12:12 GMT-08:00 Jonathan Wakely <[hidden email]>:

> On 5 February 2018 at 20:10, Roman Popov wrote:
> > Do you mean that g++ guarantees uniqueness of mangled names for types?
> And
>
> Of course. The mangled name is determined by the ABI and must be
> stable, predictable and unique, so that linking works.
>
> > uses name compare for operator==  ?
>
> Yes.
>
123