[cxx-abi-dev] abi_tag mangling
Richard Smith
richardsmith at google.com
Mon Jun 27 20:35:34 UTC 2016
On 14 June 2016 at 14:09, Jason Merrill <jason at redhat.com> wrote:
> 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?
Seems reasonable to me. This runs the risk of the ABI variance existing
only in the SFINAE condition, rather than in the signature, but that's
probably not an issue in practice. Would the upshot then be that the tags
are always determined as if by mangling the declared return type (after
substitution) and checking which tags would appear?
> 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
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://sourcerytools.com/pipermail/cxx-abi-dev/attachments/20160627/7229058d/attachment.html>
More information about the cxx-abi-dev
mailing list