[Dwarf-discuss] Extensions for nested template type parameters

Ben Woodard woodard@redhat.com
Mon Jun 8 16:02:10 GMT 2026


On 6/4/26 6:00 PM, Cary Coutant via Dwarf-discuss wrote:
>
>     template<typename T> struct t1 {
>       T n1;
>     };
>
>     template<typename T> struct t2 {
>       T m1;
>       t1<T> m2;
>     };
>
>     int main()
>     {
>       t2<int> v1;
>       return 0;
>     }
>
>     Based on the current specification, the type of m1 should reference
>     a template parameter entry.  This is a bug in gcc which has already
>     been described [1].  llvm/clang attempted to fix this in PR [2].
>
>     Also for m2 we can see that there is no information that its type was
>     originally described by a template type parameter of t2. However,
>     there is no specification addressing this specific case in the DWARF
>     Standard.
>
>
> Like Ben, I'm not sure I see why this isn't possible given the current 
> spec. The type attribute for v1 should point to a type DIE for 
> t2<int>, which will have a template type parameter and two data 
> members, m1 and m2. Briefly:
>
> L1: DW_TAG_structure_type (name: t2<int>)
> L2:  DW_TAG_template_type_parameter (name: T, type: ref to type int)
> L3:   DW_TAG_member (name: m1, type: ref to L2) [NOTE 1]
> L4:   DW_TAG_member (name: m2, type: ref to type t1<T>) [NOTE 2]
>
> NOTE 1: This is the bug you point out where gcc and clang don't do 
> what the spec says, and put a ref to type int instead of to the 
> template type parameter entry.
>
> NOTE 2: This is the part that may not be so obvious. We want a ref to 
> a DIE that represents the type t1<T> rather than t1<int>. I think we 
> can have that, but that new type entry will need to be a child of the 
> t2<int> type. Otherwise, it won't be able to reference the template 
> type parameter entry (technically, it *could*, but pointing from one 
> type DIE into the interior of another is ugly, and could conceivably 
> cause problems down the road).
>
> L1: DW_TAG_structure_type (name: t2<int>)
> L2:  DW_TAG_template_type_parameter (name: T, type: ref to type int)
> L3:   DW_TAG_member (name: m1, type: ref to L2)
> L4:   DW_TAG_member (name: m2, type: ref to L5)
> L5:   DW_TAG_structure_type (name: t1<T>)
> L6:  DW_TAG_template_type_parameter (name: T, type: ref to type int)
> L7:     DW_TAG_member (name: n1, type: ref to L6)

This is a more compact version of what I came up with. I kept on getting 
things jumbled up until I changed one of the names of the template 
parameters so that I could keep them straight.

There were two twists that I played with as well. These are probably 
obvious to other people:

Say there was also a variable with a t1<int> instance outside of the t2 
template. I puzzled for a few minutes about that and thought is that the 
same as the t1<T> inside of t2's instantiation. The other one was I made 
t3 which also had a t1<T> inside of it.

It took me a few minutes but I eventually realized that they were 
different types even though they resolved to the same thing t1<int>. 
However, m2 was like t2::t1<int> while my other m2 was really t3::t1<int>

 From an ABI (libabigail) perspective they were different but 
potentially compatible types.

So if there was a function that took t1<int> and somehow was changed to 
t2::t1<int> then I at least should warn about it. However, since the bit 
representation was the same it should still work.

I didn't check to see if any current compilers do this but I could 
imagine where a compiler could choose to use the same text region for both:

void foo( t1<int> v);
void foo( t2::t1<int> v);

and I considered how that may affect consumers.

>     Besides missing consumer support (e.g. GDB or LLDB), missing
>     support for
>     nested templates was one further reason why the llvm PR [2] was
>     rejected
>     by David Blaikie.  I discussed this topic with him since I am
>     working on
>     the enablement in GDB and submitted a patch series [3] to support
>     template
>     type resolution based on the current DWARF specification. David
>     Blaikie
>     asked me to submit a DWARF issue for this, since we could not come
>     up with
>     a useful specification for the nested case (type of m2 in the example
>     above).
>
>
> In the PR, David noted:
>
>     That's basically my point, sorry, that v1 must be represented as
>     "trait::type" (because it has to be canonical) and so if many
>     uses, like this one, of a type in a template can't reference the
>     DW_TAG_template_type_parameter, because it's non-canonical - I'm
>     not sure there's a lot of value in making it work for the subset
>     of cases where it is workable.
>
>
> I guess I don't understand the part about "it has to be canonical". 
> David, can you explain why the approach I used above wouldn't work for 
> the PR's example with trait::type?
>
> If we need something canonical (and if I understand what that means), 
> could we also have a canonical instantiation of the type for t1<int> 
> at the outermost scope, and add an attribute to the entry for t1<T> at 
> L5 that points to that canonical instantiation — maybe call it 
> DW_AT_canonical_type?
>
> There's also the concern that the compilers currently don't generate 
> what the DWARF spec says they should, and if they did, the debuggers 
> wouldn't be able to handle it.

I'd just say, we file bugs and if they have a compelling reason we 
assimilate that into our understanding and THEN if necessary make 
changes to DWARF based upon that information.

-ben

> And if David's point above is right that we can represent the simple 
> case, but not the more complex ones, is it worth doing it even for the 
> simple cases? If the spec is calling for something that can't be done 
> in the general case, should we remove it from the spec?
>
> -cary
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.dwarfstd.org/pipermail/dwarf-discuss/attachments/20260608/9128e5e5/attachment.htm>


More information about the Dwarf-discuss mailing list