On 2/7/2018 4:15 PM, Jonathan Wakely wrote:
On 7 February 2018 at 15:07, Manfred <mx2...@gmail.com> wrote:
On 02/07/2018 02:44 PM, Simon Marchi wrote:
[...]
This addresses the issue of how to do good software design in GDB to
support different producers cleanly, but I think we have some issues even
before that, like how to support g++ 7.3 and up. I'll try to summarize the
issue quickly. It's now possible to end up with two templated classes with
the same name that differ only by the signedness of their non-type template
parameter. One is Foo<int N> and the other is Foo<unsigned int N> (the 10
is unsigned). Until 7.3, g++ would generate names like Foo<10> for the
former and names like Foo<10u> for the later (in the DW_AT_name attribute of
the classes' DIEs). Since 7.3, it produces Foo<10> for both.
When GDB wants to know the run time type of an object, it fetches the
pointer to its vtable, does a symbol lookup to get the linkage name and
demangles it, which gives a string like "vtable for Foo<10>" or "vtable for
Foo<10u>". It strips the "vtable for " and uses the remainder to do a type
lookup. Since g++ 7.3, you can see that doing a type lookup for Foo<10> may
find the wrong type, and doing a lookup for Foo<10u> won't find anything.
So the problem here is how to uniquely identify those two classes when we
are doing this run-time type finding operation (and probably in other cases
too).
Simon
Hi all,
In the perspective of "type identity", the way I see it the issue has a few
parts:
1) How GCC compiles such templates
2) How GCC emits debugging information via -g
3) How such information is interpreted (and merged with the compiled code)
by GDB
Regarding 1) and 2), IMHO I think that there should be a one-to-one
relationship between the compiled code output and debug info:
This means that if GCC compiles such templates into two different
classes[1], it should generate two different type identifiers.
What do you mean by "such templates"? There have been several
different examples in the thread, which should be handled differently.
From Roman 2/3/2018
#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; };
};
From Simon 2/4/2018
base * fi = new foo<10>();
base * fu = new foo<10u>();
You are right that the original thread was started by Roman with:
struct base { virtual ~base(){} };
template< int IVAL, unsigned UVAL, unsigned long long ULLVAL>
struct derived : base {
int x = IVAL + + UVAL + ULLVAL;
};
Conversely, if it compiles the templates into the same class, then a single
identifier should be emitted for the single class compiled.
(This goes besides the point of what the standard dictates[2])
If I understand it right, currently the issue is that gcc emits two types
with the same debug identifier.
Regarding 3), I think that after 1) and 2) are set up, GDB should be able to
find the correct type definition (using the most appropriate design choice).
Hope this helps,
Not really :-)
Sorry for that :-)
You're basically just saying "GCC and GDB should do the right thing"
which is a statement of the obvious.
Besides the obvious, the main point was:
"IMHO I think that there should be a one-to-one relationship between the
compiled code output and debug info"
and:
"If I understand it right, currently the issue is that gcc emits two
types with the same debug identifier."
Which was an attempt to help by making obvious what I understood was
going wrong.
[1] According to the findings of Simon, this appears to be the case with
clang, older GCC, and current GCC master. Do I understand this right?
As I said above, it's not clear what you're referring to.
I had in mind foo<10> and foo<10u>
After your remark, I realize I should have left out "older GCC" because
'auto' does not apply to it - older GCC dealt with the initial example:
template< int IVAL, unsigned UVAL, unsigned long long ULLVAL>
[2] About handling both templates instantiation as a single class, I think
that if GCC wants to emit a single class, then its argument type
instantiation should be well-definined,i.e. independent of the order of
declaration - see the findings from Simon earlier in this thread where you
could get the program output either -10 or 4294967286 depending on which
declaration would come first.
That's just a GCC 7 bug in the handling of auto template parameters,
see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79092
It's not really relevant here, and is already fixed on trunk.
Thanks for pointing this out.
If I understand it correctly, the solution of the bug is that foo<10>
and foo<10u> result in two different classes
(according to your comment #1 in the bug, which by the way I am not sure
how it plays with the wording of the standard, but that's beyond gdb
compatibility)
Has -g type identification been differentiated too?
Getting back to auto/non-auto template arguments, I understand they are
different subjects, still, though, type identification in debug info
applies to both.
I am just a C++ gcc and gdb user, so I am missing their internals.
I think I'll keep quiet if this leads to unintentional noise.