[llvm] r188082 - DebugInfo: provide the ability to add members to a class after it has been constructed

David Blaikie dblaikie at gmail.com
Mon Aug 12 11:56:05 PDT 2013


On Mon, Aug 12, 2013 at 11:19 AM, Robinson, Paul
<Paul_Robinson at playstation.sony.com> wrote:
>>
>>
>> From: David Blaikie [mailto:dblaikie at gmail.com]
>> Sent: Saturday, August 10, 2013 12:52 PM
>> To: Robinson, Paul
>> Cc: llvm-commits at cs.uiuc.edu
>> Subject: Re: [llvm] r188082 - DebugInfo: provide the ability to add members to a class after it has been constructed
>>
>>
>>
>> On Fri, Aug 9, 2013 at 11:23 AM, Robinson, Paul
>>  <Paul_Robinson at playstation.sony.com> wrote:
>> > > -----Original Message-----
>> > > From: llvm-commits-bounces at cs.uiuc.edu [mailto:llvm-commits-
>> > > bounces at cs.uiuc.edu] On Behalf Of David Blaikie
>> > > Sent: Friday, August 09, 2013 10:17 AM
>> > > To: llvm-commits at cs.uiuc.edu
>> > > Subject: [llvm] r188082 - DebugInfo: provide the ability to add members
>> > > to a class after it has been constructed
>> > >
>> > > Author: dblaikie
>> > > Date: Fri Aug  9 12:17:12 2013
>> > > New Revision: 188082
>> > >
>> > > URL: http://llvm.org/viewvc/llvm-project?rev=188082&view=rev
>> > > Log:
>> > > DebugInfo: provide the ability to add members to a class after it has
>> > > been constructed
>> > >
>> > > This is necessary to allow Clang to only emit implicit members when
>> > > there is code generated for them, rather than whenever they are ODR
>> > > used.
>> > Um, so classes could have different member lists in different TUs,
>> > meaning if you're using type units, the type units won't match?
>>
>> This has always been true of C++ due to
>>
>> 1) nested types:
>>
>> struct foo {
>>  struct bar;
>> };
>>
>> One TU has struct foo::bar { }; and another TU doesn't (this is common
>> in the pimpl idiom) - the DIE for 'foo' can't be the same between those
>> TUs since one will contain a declaration of 'bar' and another a definition
>> (& in fact both Clang and GCC don't even emit the declaration of 'bar'
>> if it's unreferenced in the current TU - so you'll get 3 versions: no
>> mention of 'bar', a declaration of 'bar', and a definition of 'bar'). We
>> could possibly use out-of-line definitions the same way we do for function
>> definitions, but I doubt GDB/debuggers could handle that just yet.
>
> With pimpl I'd expect only one TU with a definition so not matching the
> declaration is okay.

Not sure what definition (I can think of a few) of "okay" you are using.

For what it's worth - GCC & Clang produce this in many more cases than
just the classic pimpl - since both compiler's don even emit a
declaration of the nested type in TUs that don't reference it. So
you'll easily get a bunch of TUs without the nested type, some with a
declaration, some with the definition. These could be considered bugs
& we could say these debuggers should emit the full definition (or
declaration if that's all that's available) in any TU that provides it
whenever emitting the outer type. I'm not sure that'd be the best way
forward.

> That is, yes, you get two copies in different TUs.

Given the above description of the way things are today it'll
potentially be 3 for every nested member type & all the combinations
if you have more than one (so if you've got two nested members it
wouldn't be hard to imagine a total of 9 different versions of the
outer type, etc...).

>> 2) implicit special members, as mentioned in the Clang side of this change:
>>
>> struct foo { };
>>
>> in a TU with only that code, 'foo' does not contain a declaration for any
>> of the 5 special members (default ctor, copy ctor, move ctor, copy assign,
>> move assign, dtor). Only in a TU that references those special members
>> would they be declared and then possibly defined (if they are ODR-used (eg:
>> used from an evaluated context, not just "sizeof", etc))). The compiler
>> isn't allowed to speculate about the existence/viability of creating
>> declarations of those special members in a TU that doesn't reference them
>> in any way.
>>
>> This was already true of Clang prior to this change - a TU that never used
>> the special members would not have declarations of them, some other TU that
>> did reference them would have them.
>
> Makes me think these artificial members should not contribute to the type
> signature. They are of little to no value in the debugger anyhow.

They're necessary for correct backtraces, so how would we ensure we
can describe this code?

(something I don't know: how do we ensure the address references
(hi/lo_pc) make sense when using type units? If we pick a random copy
of the type it might refer to instances of the functions that aren't
emitted in this TU (I suppose then it'll have a different type hash?)
Do type units break down when there's a reasonable proliferation of
inline functions because each TU will have a different type
signature?)

> Maybe ALL artificial members should not contribute to the type signature...
>
>>
>> 3) member function template specializations
>>
>> struct foo { template<typename T> void func(); };
>>
>> In this case it's completely unbounded - 'func' could be instantiated with
>> any number of types. There's no way we could even speculate about which
>> members 'foo'f might have in total.
>>
>> GCC and Clang both simply emit declarations (and, optionally, definitions)
>> of any specializations that 'func' has in this TU. GCC already only did
>> this for specializations that actually generated code (because they were
>> used by code that was being emitted) but Clang emitted it for every
>> specialization.
>>
>> eg:
>>
>> inline void f() {
>>  foo().func<int>();
>> }
>>
>> int main() {
>>  foo().func<float>();
>> }
>>
>> produced two specializations (foo<int> only as a declaration with no
>> definition, foo<float> with both declaration and definition) from Clang,
>> but only one from GCC. Clang now produces only one in the above program.
>> But as you can see, there could be any number of other instances of this
>> member function template (foo<bool>, foo<string>, foo<bar>, etc) in other
>> translation units.
>
> I knew about member templates, I think such classes shouldn't be considered
> candidates for type units.  They aren't common.

Perhaps.



More information about the llvm-commits mailing list