[Bug c++/88164] New: Copy initialization of function argument not performed inside lambda when the argument is a constexpr block scope variable.

okannen at gmail dot com gcc-bugzilla@gcc.gnu.org
Fri Nov 23 09:24:00 GMT 2018


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

            Bug ID: 88164
           Summary: Copy initialization of function argument not performed
                    inside lambda when the argument is a constexpr block
                    scope variable.
           Product: gcc
           Version: unknown
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: okannen at gmail dot com
  Target Milestone: ---

In the code bellow the copy constructor of "a" should be called:

  struct A {
    int x=12;
    constexpr A(){}
    A(const A& x);
    };

  int f(A);

  // This function should not compile
  // And the generated code does not call the copy constructor of A
  int test() {
    constexpr A a{};
    auto lambda = []{
        return f(a); // Unexpected: does not call the copy constructor, 
                     // should not compile: a should be explicitly captured
        };
    return lambda();
    }

The the call to the copy constructor does not appear in the generated assembly:
      test():
        subq    $24, %rsp
        leaq    12(%rsp), %rdi
        movl    $12, 12(%rsp)
        call    f(A)
        addq    $24, %rsp
        ret

While without the lambda:

  int test_expect_assembly(){
    constexpr A a{};
    return f(a);
    }

the copy constructor is called:

  test_expect_assembly():
        subq    $24, %rsp
        leaq    8(%rsp), %rsi
        leaq    12(%rsp), %rdi
        movl    $12, 8(%rsp)
        call    A::A(A const&)
        leaq    12(%rsp), %rdi
        call    f(A)
        addq    $24, %rsp
        ret

This unexpected copy constructor elision
only happens for function arguments construction.
The code below produces the expected assembly
and GCC requires the explicit capture of "a":

  int test_copy_initialization() {
    constexpr A a{};
    auto lambda = [&a]{ // a must be captured
        A b=a;
        return a.x;
        };
    return lambda();
    }


Moreover there is a related bug when the variable has global scope,
the copy constructor is called, nevertheless GCC should not implicitly captures
the variable because the variable is ODR used. 

The capture should be explicit, the code below should not compile:

  constexpr A n_a{};
  int test_ns() {
    auto lambda = []{
        return f(n_a);// call the copy constructor so odr use n_a
                      // Unexpected: n_a should be explictly captured
        };
    return lambda();
    }


More information about the Gcc-bugs mailing list