https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115946

            Bug ID: 115946
           Summary: lambda in class body should have the same type among
                    different TUs
           Product: gcc
           Version: 15.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: namniav at gmail dot com
  Target Milestone: ---

[basic.def.odr#15.6](https://eel.is/c++draft/basic.def.odr#15.6)
> In each such definition, except within the default arguments and default
> template arguments of `D`, corresponding *lambda-expression*s shall have
> the same closure type

When the lambda expression is used inside class body(but not inside a
function), GCC generates different closure types in different TUs.
Clang with libc++ has a similar problem only when the lambda is used in
`decltype`(reported: https://github.com/llvm/llvm-project/issues/98963). Clang
with libstdc++ seems not have this problem.

Demo: https://godbolt.org/z/M4xjWesYn

* common.hpp
```c++
#include <typeinfo>
#include <array>

struct A {
    using F1 = decltype([]{});   // GCC generates different closure types for
different TUs
    inline static auto f2 = []{};
    using F2 = decltype(f2);  // GCC generates different closure types for
different TUs
};

[[gnu::always_inline]]
inline auto func() {
    using F3 = decltype([]{}); // OK
    auto f4 = []{};
    using F4 = decltype(f4); // OK
    return std::array{ &typeid(F3), &typeid(F4) };
}

auto FOOBAR() {
    auto t = func();
    return std::array{
        &typeid(A::F1),
        &typeid(A::F2),
        t[0],
        t[1]
    };
}
```
* foo.cpp
```c++
#define FOOBAR foo
#include "common.hpp"
```

* bar.cpp
```c++
#define FOOBAR bar
#include "common.hpp"
```

* main.cpp
```c++
#include <cstdio>
#include <typeinfo>
#include <array>

std::array<const std::type_info*, 4> foo();
std::array<const std::type_info*, 4> bar();

int main() {
    auto f = foo();
    auto b = bar();
    for (int i = 0; i < 4; ++i) {
        std::printf("F%d same type ? %d\n", i+1, *f[i] == *b[i]);
        //std::printf("name=%s hash_code=%-20llu addr=%p\n", f[i]->name(),
(unsigned long long)f[i]->hash_code(), f[i]);
        //std::printf("name=%s hash_code=%-20llu addr=%p\n", b[i]->name(),
(unsigned long long)b[i]->hash_code(), b[i]);
    }
}

```

**Outputs** :
* Clang, libc++
> ```
> F1 same type ? 0
> F2 same type ? 1
> F3 same type ? 1
> F4 same type ? 1
> ```

* Clang, libstdc++
> ```
> F1 same type ? 1
> F2 same type ? 1
> F3 same type ? 1
> F4 same type ? 1
> ```

* GCC, libstdc++
> ```
> F1 same type ? 0
> F2 same type ? 0
> F3 same type ? 1
> F4 same type ? 1
> ```

Reply via email to