[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