Skip to content

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

@zygoloid

Description

@zygoloid

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions