P0624R2 - Default constructible and assignable stateless lambdas
authorJakub Jelinek <jakub@redhat.com>
Thu, 14 Jun 2018 19:05:13 +0000 (21:05 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Thu, 14 Jun 2018 19:05:13 +0000 (21:05 +0200)
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
gcc/cp/method.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice2.C
gcc/testsuite/g++.dg/cpp2a/lambda1.C [new file with mode: 0644]

index d1fdc42aa4b93d8572cec126f049834e5a9a3b14..dd9b7dba10217f323ef09f7693d3421ec85ba15d 100644 (file)
@@ -1,3 +1,10 @@
+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.
+
 2018-06-14  Paolo Carlini  <paolo.carlini@oracle.com>
 
        * decl.c (duplicate_decls): Use DECL_SOURCE_LOCATION in
index 8e7590c5dbb8c88eaeb60d3eca04320cddff737a..858655b4a79141d279f1aff6e03400aec8cdc59b 100644 (file)
@@ -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;
index ecf65546ec72b5c5431912b8e42927764d51edb8..92bc519e5583b5c426e7a0cadca2e4544a794da8 100644 (file)
@@ -1,3 +1,10 @@
+2018-06-14  Jakub Jelinek  <jakub@redhat.com>
+
+       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  <paolo.carlini@oracle.com>
 
        * g++.dg/other/static3.C: New.
index 702f18f6ac8098722f26f57a566ed98ec69b4e3f..a78688a4b1e1d2cc6ff824eba525e64abab244c8 100644 (file)
@@ -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 }
 }
diff --git a/gcc/testsuite/g++.dg/cpp2a/lambda1.C b/gcc/testsuite/g++.dg/cpp2a/lambda1.C
new file mode 100644 (file)
index 0000000..245b10c
--- /dev/null
@@ -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