From bc04d1ff62db94aea033829249c8b09f4b7abff1 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Thu, 14 Jun 2018 21:05:13 +0200 Subject: [PATCH] P0624R2 - Default constructible and assignable stateless lambdas 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. From-SVN: r261605 --- gcc/cp/ChangeLog | 7 +++ gcc/cp/method.c | 11 +++- gcc/testsuite/ChangeLog | 7 +++ .../g++.dg/cpp0x/lambda/lambda-ice2.C | 10 ++-- gcc/testsuite/g++.dg/cpp2a/lambda1.C | 58 +++++++++++++++++++ 5 files changed, 85 insertions(+), 8 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp2a/lambda1.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index d1fdc42aa4b..dd9b7dba102 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2018-06-14 Jakub Jelinek + + 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. + 2018-06-14 Paolo Carlini * decl.c (duplicate_decls): Use DECL_SOURCE_LOCATION in diff --git a/gcc/cp/method.c b/gcc/cp/method.c index 8e7590c5dbb..858655b4a79 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -1539,10 +1539,15 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p, { /* "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; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index ecf65546ec7..92bc519e558 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2018-06-14 Jakub Jelinek + + P0624R2 - Default constructible and assignable stateless lambdas + * g++.dg/cpp2a/lambda1.C: New test. + * g++.dg/cpp0x/lambda/lambda-ice2.C: Adjust expected diagnostics + for -std=c++2a. + 2018-06-14 Paolo Carlini * g++.dg/other/static3.C: New. diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice2.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice2.C index 702f18f6ac8..a78688a4b1e 100644 --- a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice2.C +++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice2.C @@ -2,15 +2,15 @@ // { dg-do compile { target c++11 } } template -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 } } diff --git a/gcc/testsuite/g++.dg/cpp2a/lambda1.C b/gcc/testsuite/g++.dg/cpp2a/lambda1.C new file mode 100644 index 00000000000..245b10c6cf8 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/lambda1.C @@ -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 -- 2.30.2