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.

Reply via email to