[cxx-abi-dev] abi_tag mangling

Jason Merrill jason at redhat.com
Tue Jun 14 21:09:25 UTC 2016


On Mon, Jun 6, 2016 at 5:29 PM, Richard Smith <richardsmith at google.com> wrote:
> On 3 June 2016 at 15:25, Jason Merrill <jason at redhat.com> wrote:
>>
>> On Jun 2, 2016, at 3:01 PM, Richard Smith <richardsmith at google.com> wrote:
>>
>> > If a type is not part of the regular mangling, and it contains an ABI
>> > tag in
>> > its mangling but not as part of its type (for instance, a dependent
>> > expression in a template argument references an entity with an ABI tag),
>> > does that appear in the resulting mangling?
>>
>> > (That is, is an implementation required to effectively mangle the return
>> > type and throw it away, or is some walk over the top-level type required
>> > instead?)
>>
>> Hmm, good question.  The current G++ implementation scans dependent
>> expressions in a (member function of a class) template, and considers
>> those in both the signature and the return type of a non-template
>> member function (which is not part of its signature), leading to a
>> somewhat curious result for this example:
>>
>> struct [[gnu::abi_tag ("foo")]] A
>> {
>>   template <class T> static T f();
>> };
>>
>> template <class T> struct B
>> {
>>   static decltype(A::f<T>()) g(decltype(A::f<T>()));
>>   static decltype(A::f<T>()) h();
>> };
>>
>> int main()
>> {
>>   B<int>::g(0); // _ZN1BIiE1gEi -- the tag does not appear in the mangled
>> name
>>   B<int>::h();  // _ZN1BIiE1hB3fooEv
>> }
>>
>> Here G++ sees that A (and thus tag "foo") appears in the signature of
>> B<T>::g, so it doesn't tag B<T>::g, even though the dependent
>> expression isn't actually part of the eventual mangling of B<int>::g
>> because for non-template member functions we mangle the instantiated
>> type rather than the temploid type.  The tag doesn't appear in the
>> signature of B<T>::h, so h gets tagged.
>
> Is that how this is supposed to work, or is it a bug? It would seem more
> reasonable to say the tag set added after to the declaration's name is the
> tag set from scanning the original unsubstituted declaration, minus the tags
> produced by mangling (and I suspect that probably doesn't change the
> mangling for any cases in the wild).

It does seem like a bug.  For non-template member functions, since the
signature we mangle is the fully-instantiated signature, it probably
also makes sense to use that signature in determining tags, so that
neither of the above functions would mention a tag:

struct [[gnu::abi_tag ("foo")]] A
{
  template <class T> static T f();
  template <class T> static A g();
};

template <class T> struct B
{
  static decltype(A::f<T>()) fa(decltype(A::f<T>()));
  static decltype(A::f<T>()) fv();
  static decltype(A::g<T>()) ga(decltype(A::g<T>()));
  static decltype(A::g<T>()) gv();
};

int main()
{
  B<int>::fa(0);   // _ZN1BIiE2faEi
  B<int>::fv();    // _ZN1BIiE2fvEv
  B<int>::ga(A()); // _ZN1BIiE2gaE1AB3foo
  B<int>::gv();    // _ZN1BIiE2gvB3fooEv
}

Thoughts?

> Is the declaration that you scan the one from which a definition would
> ultimately be instantiated, or do you look back further than that? In
> particular, do you stop at member specializations:
>
>   template<> float B<float>::h() {} // how is this mangled?

My proposal just above would have us not look any farther back than
the fully-instantiated signature, but for member templates, you look
at the primary template.

>
> ?
>
>> On Thu, Jun 2, 2016 at 7:22 PM, John McCall <rjmccall at apple.com> wrote:
>>
>> > Do templates have ABI tags, or are the tags only properties of template
>> > specializations?  How does that play into mangling and/or
>> > substitutability?
>>
>> Templates have tags.
>>
>> > I assume ABI tags can apply to unions as well.  (The standard's
>> > definition
>> > of "compound type" distinguishes classes and unions.)
>>
>> Of course, unions are classes.  There are separate bullets for them in
>> that paragraph, but the union bullet says that unions are classes.
>>
>> > It's probably worth spelling out that tags do not apply to enumerators.
>>
>> OK.
>>
>> > Are ABI tags mangled in the <prefix>, or just on the entity <name>?
>>
>> They are mangled as part of the name of the entity, whenever that name
>> appears.
>>
>> > What
>> > happens if the same tag is applied to multiple places in the lexical
>> > hierarchy, e.g. to both a class and one of its member functions?
>>
>> Then it appears multiple times.
>>
>> > I guess an inline friend function definition doesn't implicitly use the
>> > tags
>> > of its defining class, but presumably has them anyway because of their
>> > presence in the function signature.
>>
>> Right.
>>
>> > Can you clarify which things in the Clang description are no longer
>> > correct?
>>
>> These lines:
>>
>> "If a function is used as a local scope for another name, and is part
>> of another function as local scope, it doesn’t have any required tags.
>> If a function is used as a local scope for a guard variable name, it
>> doesn’t have any required tags."
>>
>> > I assume that a type used in the name of a conversion function should be
>> > mangled with its ABI tag.
>>
>> Yes, any time the name of the type appears, the tags appear as well.
>
> Coupled with the behavior of attributes on the return type, this seems
> strange.
>
> Once a library has ABI tags added to it, you can't add the same ABI tag to
> more types in a later release: suppose v1 has an ABI tag on std::list and v2
> adds the same ABI tag to std::string. Then "std::string f(std::list<char>)"
> has the same mangling in v1 and v2. Since you can't ABI-tag more entities in
> a later version of the same library, it would seem sufficient to list the
> ABI tags only once, with the name of the complete entity, rather than
> alongside each ABI-tagged constituent of its mangled name.
>
> But I guess you've already shipped this, so it's too late to do much about
> it :(

That was my original concept, actually; I don't remember now why I
shifted away from it.

>> > Also, I don't see anything in your proposed
>> > wording that talks about not mangling ABI tags on an entity that appear
>> > in
>> > its type.
>>
>> "that are not otherwise represented in the mangling" was supposed to
>> cover that, but as we see with my example above it should really talk
>> about the type or signature rather than the mangling.
>>
>> Jason


More information about the cxx-abi-dev mailing list