Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

need mangling for lambdas appearing in unevaluated operands within a class body #165

Open
zygoloid opened this issue Apr 5, 2023 · 3 comments

Comments

@zygoloid
Copy link
Contributor

zygoloid commented Apr 5, 2023

Testcase:

struct C {
  template<typename T, decltype(([](T, auto) { return 0; }, 0)) N = 0> void f() {}
  template<typename T, decltype(([](typename T::type, auto) { return 0; }, 0)) N = 0> void f() {}
};
void g() { C().f<int>(); }

This case is very awkward: we don't have anything good to key the lambda off when numbering. We can't use the function f because we can't refer to f without naming the lambda. Some options:

  1. Use the <unqualified-name> (1f) but not the signature as part of the context when numbering the lambdas -- that would mean reordering multiple declarations of f (if it's overloaded) could result in a different overload getting the same mangling, but I think that's unavoidable here, if we don't want to mangle the body of the lambda.

  2. Number such lambdas within the enclosing class. The risk of innocuous / unrelated changes altering a mangling of a different function would be higher with that approach, but it'd be simpler for implementations.

  3. Assign some placeholder mangling for such lambdas, say UL. Then, if you used that placeholder in an <encoding>, enumerate the declarations in the class that have the same name in lexical order of first appearance, and mangle all of them. Number the declarations that have the same mangling, and append that numbering to the overall mangling of that name. (So we'd mangle the function called above as "the first template<typename, decltype((some lambda, 0))> void f() in C", and the function we didn't call would be mangled as "the second template<typename, decltype((some lambda, 0))> void f() in C".)

  4. If an <encoding> would refer to a lambda that appears in a class body outside of the four contexts where we number lambdas, then mangle the function declaration as simply the name of the member function (with no function parameters) plus a discriminator, so the above are something like (for example) _ZN1C1fIiEE_ and _ZN1C1fIiEE0_.

I'm leaning towards (2) being the simplest thing, and probably good enough if people don't do this sort of thing very often. Note that all of these options are unstable under reordering of member functions within a class; they're just trading off which kinds of reordering result in mangled names changing / swapping.

@zygoloid
Copy link
Contributor Author

zygoloid commented Apr 5, 2023

Simpler example not relying on mangling of template parameter decls:

struct C {
  template<typename T> void f(decltype([](T, auto) {})) {}  
};
void g() { C().f<int>({}); }

@zygoloid
Copy link
Contributor Author

zygoloid commented Apr 5, 2023

struct C {
  template<typename T>
  void f(decltype([](T, auto) { return 0; }(1, 2))*) {}  

  template<typename T>
  void f(decltype([](T, auto) {}(1, 2))*) {}  
};
void g() { C().f<int>((int*)0); }
void h() { C().f<int>((void*)0); }

GCC mangles these as _ZN1C1fIiEEvPDTcltlNS_UlT_T_E_EELi1ELi2EEE and _ZN1C1fIiEEvPDTcltlNS_UlT_T_E0_EELi1ELi2EEE respectively, and generally appears to be following option (2). Note, however, that GCC mangles both the enclosing template parameter T and the lambda's implied template parameter for auto as T_, which seems wrong; I think these should actually be T_TL__.

@zygoloid
Copy link
Contributor Author

PR #85 addresses this following option 2.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant