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

Mangling the name of an externally visible lambda in a static data member of a class #157

Open
dwblaikie opened this issue Dec 1, 2022 · 1 comment

Comments

@dwblaikie
Copy link

Clang fails and emits these with local linkage and non-standard mangling (if they are actually internal, that'd be fine)
GCC emits these names without using the member name in the mangling and a numbering that's not local to the member, or even local to the type (similar names in subsequent classes get numberings that differ depending on the previous class - despite the class name in the mangling)
https://godbolt.org/z/7514cTh5o

struct A {
    static constexpr auto x = [] {
        return 1;
    };
};
template <typename>
struct B {
    static constexpr auto x = [] {
        return 1;
    };
};
template <typename T>
struct C {
    static int x;
};
void side_effect();
template <typename T>
int C<T>::x = (side_effect(), [] { return 1; }());
template int C<int>::x;
void f() {
    A::x();
    B<int>::x();
}

GCC produces these manglings:

A::{lambda()#1}::operator()() const
_ZNK1AUlvE_clEv

B<int>::{lambda()#3}::operator()() const
_ZNK1BIiEUlvE1_clEv

C<int>::x::{lambda()#1}::operator()() const
_ZNK1CIiE1xMUlvE_clEv

Clang produces these manglings:

A::$_0::operator()() const
_ZNK1A3$_0clEv

B<int>::x::{lambda()#1}::operator()() const
_ZNK1BIiE1xMUlvE_clEv

C<int>::x::{lambda()#1}::operator()() const
_ZNK1CIiE1xMUlvE_clEv

I think both GCC and Clang gets C right, Clang gets B right (& GCC gets it wrong) and both Clang and GCC get A wrong for different reasons. (and it should be like Clang's B behavior).

This is discussed in Clang (llvm/llvm-project#58819) and GCC (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107741)

@zygoloid
Copy link
Contributor

The ABI already mostly covers this: we require a lambda to be numbered within the scope of the enclosing variable if the variable is inline or a variable template, but we missed the case where it's a non-inline static data member, eg:

template<typename T> int print_hello = (std::cout << "hello\n", 0);
struct X {
  // Should only print hello once, regardless of how many TUs this appears in.
  static const intptr_t n = (print_hello<decltype([]{})>, 0);
};

I've updated #85 to cover that case too.

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

2 participants