Message ID | 20180614130006.GS7166@tucnak |
---|---|
State | New |
Headers | show |
Series | [C++] P0624R2 - Default constructible and assignable stateless lambdas | expand |
OK. On Thu, Jun 14, 2018 at 9:00 AM, Jakub Jelinek <jakub@redhat.com> wrote: > Hi! > > The following patch implements P0624R2, where stateless lambdas don't have > deleted default ctor and copy assignment operator anymore. > > Tested on x86_64-linux with check-c++-all and libstdc++ testsuite, ok for > trunk? > > 2018-06-14 Jakub Jelinek <jakub@redhat.com> > > P0624R2 - Default constructible and assignable stateless lambdas > * method.c (synthesized_method_walk): For C++2a don't mark > sfk_constructor or sfk_copy_assignment as deleted if lambda has > no lambda-captures. > > * g++.dg/cpp2a/lambda1.C: New test. > * g++.dg/cpp0x/lambda/lambda-ice2.C: Adjust expected diagnostics > for -std=c++2a. > > --- gcc/cp/method.c.jj 2018-05-21 13:15:33.519575351 +0200 > +++ gcc/cp/method.c 2018-06-14 13:48:58.825585083 +0200 > @@ -1539,10 +1539,15 @@ synthesized_method_walk (tree ctype, spe > { > /* "The closure type associated with a lambda-expression has a deleted > default constructor and a deleted copy assignment operator." > - This is diagnosed in maybe_explain_implicit_delete. */ > + This is diagnosed in maybe_explain_implicit_delete. > + In C++2a, only lambda-expressions with lambda-captures have those > + deleted. */ > if (LAMBDA_TYPE_P (ctype) > - && (sfk == sfk_constructor > - || sfk == sfk_copy_assignment)) > + && (sfk == sfk_constructor || sfk == sfk_copy_assignment) > + && (cxx_dialect < cxx2a > + || LAMBDA_EXPR_CAPTURE_LIST (CLASSTYPE_LAMBDA_EXPR (ctype)) > + || LAMBDA_EXPR_DEFAULT_CAPTURE_MODE > + (CLASSTYPE_LAMBDA_EXPR (ctype)) != CPLD_NONE)) > { > *deleted_p = true; > return; > --- gcc/testsuite/g++.dg/cpp2a/lambda1.C.jj 2018-06-14 14:27:29.903602374 +0200 > +++ gcc/testsuite/g++.dg/cpp2a/lambda1.C 2018-06-14 14:26:51.462571226 +0200 > @@ -0,0 +1,58 @@ > +// P0624R2 > +// { dg-do compile { target c++11 } } > + > +#if __cplusplus >= 201402L > +#define A auto > +#else > +#define A int > +#endif > + > +void > +f1 () > +{ > + auto greater = [](A x, A y) { return x > y; }; // { dg-message "a lambda closure type has a deleted (default constructor|copy assignment operator)" "" { target c++17_down } } > + decltype (greater) gt; // { dg-error "use of deleted function" "" { target c++17_down } } > + gt = greater; // { dg-error "use of deleted function" "" { target c++17_down } } > +} > + > +void > +f2 () > +{ > + auto greater = [&](A x, A y) { return x > y; }; // { dg-message "a lambda closure type has a deleted (default constructor|copy assignment operator)" } > + decltype (greater) gt; // { dg-error "use of deleted function" } > + gt = greater; // { dg-error "use of deleted function" } > +} > + > +void > +f3 () > +{ > + auto greater = [=](A x, A y) { return x > y; }; // { dg-message "a lambda closure type has a deleted (default constructor|copy assignment operator)" } > + decltype (greater) gt; // { dg-error "use of deleted function" } > + gt = greater; // { dg-error "use of deleted function" } > +} > + > +void > +f4 (int i) > +{ > + auto greater = [i](A x, A y) { return x > y; }; // { dg-message "a lambda closure type has a deleted (default constructor|copy assignment operator)" } > + decltype (greater) gt; // { dg-error "use of deleted function" } > + gt = greater; // { dg-error "use of deleted function" } > +} > + > +#if __cplusplus > 201703L > +void > +f5 () > +{ > + auto greater = [](auto x, auto y) constexpr { return x > y; }; > + decltype (greater) gt; > + static_assert (!gt (1, 2)); > + static_assert (gt (4, 3)); > + static_assert (!gt (3.5, 3.75)); > + static_assert (gt (3.5, 3.25)); > + gt = greater; > + static_assert (!gt (1, 2)); > + static_assert (gt (4, 3)); > + static_assert (!gt (3.5, 3.75)); > + static_assert (gt (3.5, 3.25)); > +} > +#endif > --- gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice2.C.jj 2014-05-15 11:58:42.000000000 +0200 > +++ gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice2.C 2018-06-14 14:32:03.760824236 +0200 > @@ -2,15 +2,15 @@ > // { dg-do compile { target c++11 } } > > template<typename F> > -decltype(F()) run(F f) // { dg-message "note" } > +decltype(F()) run(F f) // { dg-message "note" "" { target c++17_down } } > { > - return f(); > + return f(); // { dg-error "could not convert" "" { target c++2a } } > } > > int main() > { > - auto l = []() { return 5; }; // { dg-message "lambda closure type" } > + auto l = []() { return 5; }; // { dg-message "lambda closure type" "" { target c++17_down } } > > - run(l); // { dg-error "no match" } > - // { dg-error "use of deleted function" "candidate explanation" { target *-*-* } 5 } > + run(l); // { dg-error "no match" "" { target c++17_down } } > + // { dg-error "use of deleted function" "candidate explanation" { target c++17_down } 5 } > } > > Jakub
--- gcc/cp/method.c.jj 2018-05-21 13:15:33.519575351 +0200 +++ gcc/cp/method.c 2018-06-14 13:48:58.825585083 +0200 @@ -1539,10 +1539,15 @@ synthesized_method_walk (tree ctype, spe { /* "The closure type associated with a lambda-expression has a deleted default constructor and a deleted copy assignment operator." - This is diagnosed in maybe_explain_implicit_delete. */ + This is diagnosed in maybe_explain_implicit_delete. + In C++2a, only lambda-expressions with lambda-captures have those + deleted. */ if (LAMBDA_TYPE_P (ctype) - && (sfk == sfk_constructor - || sfk == sfk_copy_assignment)) + && (sfk == sfk_constructor || sfk == sfk_copy_assignment) + && (cxx_dialect < cxx2a + || LAMBDA_EXPR_CAPTURE_LIST (CLASSTYPE_LAMBDA_EXPR (ctype)) + || LAMBDA_EXPR_DEFAULT_CAPTURE_MODE + (CLASSTYPE_LAMBDA_EXPR (ctype)) != CPLD_NONE)) { *deleted_p = true; return; --- gcc/testsuite/g++.dg/cpp2a/lambda1.C.jj 2018-06-14 14:27:29.903602374 +0200 +++ gcc/testsuite/g++.dg/cpp2a/lambda1.C 2018-06-14 14:26:51.462571226 +0200 @@ -0,0 +1,58 @@ +// P0624R2 +// { dg-do compile { target c++11 } } + +#if __cplusplus >= 201402L +#define A auto +#else +#define A int +#endif + +void +f1 () +{ + auto greater = [](A x, A y) { return x > y; }; // { dg-message "a lambda closure type has a deleted (default constructor|copy assignment operator)" "" { target c++17_down } } + decltype (greater) gt; // { dg-error "use of deleted function" "" { target c++17_down } } + gt = greater; // { dg-error "use of deleted function" "" { target c++17_down } } +} + +void +f2 () +{ + auto greater = [&](A x, A y) { return x > y; }; // { dg-message "a lambda closure type has a deleted (default constructor|copy assignment operator)" } + decltype (greater) gt; // { dg-error "use of deleted function" } + gt = greater; // { dg-error "use of deleted function" } +} + +void +f3 () +{ + auto greater = [=](A x, A y) { return x > y; }; // { dg-message "a lambda closure type has a deleted (default constructor|copy assignment operator)" } + decltype (greater) gt; // { dg-error "use of deleted function" } + gt = greater; // { dg-error "use of deleted function" } +} + +void +f4 (int i) +{ + auto greater = [i](A x, A y) { return x > y; }; // { dg-message "a lambda closure type has a deleted (default constructor|copy assignment operator)" } + decltype (greater) gt; // { dg-error "use of deleted function" } + gt = greater; // { dg-error "use of deleted function" } +} + +#if __cplusplus > 201703L +void +f5 () +{ + auto greater = [](auto x, auto y) constexpr { return x > y; }; + decltype (greater) gt; + static_assert (!gt (1, 2)); + static_assert (gt (4, 3)); + static_assert (!gt (3.5, 3.75)); + static_assert (gt (3.5, 3.25)); + gt = greater; + static_assert (!gt (1, 2)); + static_assert (gt (4, 3)); + static_assert (!gt (3.5, 3.75)); + static_assert (gt (3.5, 3.25)); +} +#endif --- gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice2.C.jj 2014-05-15 11:58:42.000000000 +0200 +++ gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice2.C 2018-06-14 14:32:03.760824236 +0200 @@ -2,15 +2,15 @@ // { dg-do compile { target c++11 } } template<typename F> -decltype(F()) run(F f) // { dg-message "note" } +decltype(F()) run(F f) // { dg-message "note" "" { target c++17_down } } { - return f(); + return f(); // { dg-error "could not convert" "" { target c++2a } } } int main() { - auto l = []() { return 5; }; // { dg-message "lambda closure type" } + auto l = []() { return 5; }; // { dg-message "lambda closure type" "" { target c++17_down } } - run(l); // { dg-error "no match" } - // { dg-error "use of deleted function" "candidate explanation" { target *-*-* } 5 } + run(l); // { dg-error "no match" "" { target c++17_down } } + // { dg-error "use of deleted function" "candidate explanation" { target c++17_down } 5 } }