[cxx-abi-dev] Seeking clarification about mangling nested template specializations

John McCall rjmccall at apple.com
Sun Apr 26 08:07:57 UTC 2015


In the current ABI document, there’s this little bit:
  
  Names of objects nested in namespaces or classes are identified
  as a delimited sequence of names identifying the enclosing scopes.
  In addition, when naming a class member function, CV-qualifiers
  and ref-qualifiers may be prefixed to the compound name, encoding
  the this attributes. Note that if member function CV-qualifiers or a
  ref-qualifier are required, the delimited form must be used even if
  the remainder of the name is a single substitution.

That last sentence is really weird, because the "delimited form" is
<nested-name>, and the non-delimited form is either
<unscoped-name> or <unscoped-template-name> <template-args>,
and <unscoped-name> can never just be a single substitution.

The only way I can make any sense from this is to read it as saying
that, if you’re mangling a member function template specialization,
and you already have a substitution for the member function
template, but the member function template specialization has
CV- or ref-qualifiers, you still need to use <nested-name> in order
to mangle the CV- or ref-qualifiers.  As opposed to just using
<unscoped-template-name> <template-args>.

More concretely, suppose I have:
  struct A {
    template <class T> void foo() const;
  };
and I need to mangle a reference to A::foo<int>, and I’ve already
decided that the template A::foo is S2_.  The sentence *might* be
saying that I can’t just mangle this as “S2_IiE", I have to mangle it
as “NKS2_IiEE”.

But that implies that if the method weren’t const then I *could* mangle
this as “S2_IiE”, and that’s very strange, because I’ve always interpreted
the general rule for substitutions as only allowing substitution if the
unsubstituted entity would naturally end up in that production.  A member
entity can’t normally be mangled as an unscoped name, so you don’t
consider that production, so you don’t have the opportunity to apply
the substitution for the template-name there.

Abstractly, it’s not an unreasonable idea to use that mangling, since it
does produce strictly shorter names, so I’m not completely opposed.
But it does seem like a special-case rule that needs to be written explicitly.
Also, neither Clang nor GCC actually does it this way, and I’m curious
if anyone does.

(Even if we adopted this rule, there’s still no reason for the qualifiers
exception to it, since you can recover those qualifiers from the original
place that gave rise to the substitution.)

Here’s a concrete example using a member class template:

struct A {
  template <unsigned I> class B {};
};
template <class T> void bar(T t, A::B<0> x = {}, A::B<1> y = {}) {}
int main() { bar(0); }

A compiler which always mangles member templates as nested-names
will mangle this as:
  _Z3barIiEvT_N1A1BILj0EEENS2_ILj1EEE

A compiler which uses the unscoped mangling when a substitution
already exists will mangle this as:
  _Z3barIiEvT_N1A1BILj0EEES2_ILj1EE

Unless somebody finds a compiler that actually does the latter, I think
this is just a specification bug and we’ve always meant the former.
I’m in the middle of rewriting the prose in this section anyway; if nobody
objects in the next week or so, I’ll just fix this while I’m there.

John.


More information about the cxx-abi-dev mailing list