[C++] P0624R2 - Default constructible and assignable stateless lambdas

Message ID 20180614130006.GS7166@tucnak
State New
Headers show
Series
  • [C++] P0624R2 - Default constructible and assignable stateless lambdas
Related show

Commit Message

Jakub Jelinek June 14, 2018, 1 p.m.
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.


	Jakub

Comments

Jason Merrill June 14, 2018, 1:25 p.m. | #1
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

Patch

--- 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 }
 }