https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86943
Bug ID: 86943 Summary: [8 Regression] Wrong code when converting stateless generic lambda to function pointer Product: gcc Version: 9.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: oremanj at mit dot edu Target Milestone: --- When creating a function pointer from a stateless generic lambda that accepts the argument of generic type by value, gcc 8+ on x86_64 generates wrong code, invoking a move constructor on a pointer-to-pointer to the moved-from object rather than just a pointer to it. This occurs regardless of optimizations as far as I can tell. $ cat t.cc extern "C" int printf(const char *fmt, ...); struct nontrivial { nontrivial() { printf("default-construct %p\n", this); } nontrivial(const nontrivial& other) { printf("copy-construct %p from %p\n", this, &other); } nontrivial(nontrivial&& other) noexcept { printf("move-construct %p from %p\n", this, &other); } ~nontrivial() { printf("destroy %p\n", this); } }; using cb_t = void(*)(nontrivial); cb_t test() { return [](auto val) { printf("called %p\n", &val); }; } int main() { volatile cb_t cb = test(); cb({}); return 0; } $ g++-7 -o t.ok t.cc -std=c++14 $ ./t.ok default-construct 0x7ffc6cf08b0f move-construct 0x7ffc6cf08adf from 0x7ffc6cf08b0f called 0x7ffc6cf08adf destroy 0x7ffc6cf08adf destroy 0x7ffc6cf08b0f $ g++-8 -o t.fail t.cc -std=c++14 $ ./t.fail default-construct 0x7fffd8a636ff move-construct 0x7fffd8a636c7 from 0x7fffd8a636c8 called 0x7fffd8a636c7 destroy 0x7fffd8a636c7 destroy 0x7fffd8a636ff In the second example, the object is move-constructed from an address at which no object has been constructed. Examining in a debugger, 0x7fffd8a636c8 contains the address 0x7fffd8a636ff, i.e., there is one level of indirection too many. Tested with godbolt.org, bug is absent on 7.1.0, 7.2.0, 7.3.0, and present on 8.1.0, 8.2.0, and 9.0.0 20180812.