This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

C++ PATCH to implement C++20 P0806R2, Deprecate implicit capture of this via [=]


When we capture the current object (*this) implicitly, it is always captured by
reference, even if the capture default is =.  This is surprising and irregular
so this proposal <http://wg21.link/p0806r2> deprecates implicit capture of this
via [=] (not via [&]).  Users should now use [=, this] (same as [=], added by
P0409R2), or [=, *this].

This patch adds a -Wdeprecated warning to address it.

Bootstrapped/regtested on x86_64-linux, ok for trunk?

2018-08-11  Marek Polacek  <polacek@redhat.com>

	P0806R2 - Deprecate implicit capture of this via [=]
	* lambda.c (add_default_capture): Formatting fixes.  Warn about
	deprecated implicit capture of this via [=].

	* g++.dg/cpp2a/lambda-this1.C: New test.
	* g++.dg/cpp2a/lambda-this2.C: New test.
	* g++.dg/cpp2a/lambda-this3.C: New test.

--- gcc/cp/lambda.c
+++ gcc/cp/lambda.c
@@ -695,14 +695,10 @@ tree
 add_default_capture (tree lambda_stack, tree id, tree initializer)
 {
   bool this_capture_p = (id == this_identifier);
-
   tree var = NULL_TREE;
-
   tree saved_class_type = current_class_type;
 
-  tree node;
-
-  for (node = lambda_stack;
+  for (tree node = lambda_stack;
        node;
        node = TREE_CHAIN (node))
     {
@@ -711,15 +707,26 @@ add_default_capture (tree lambda_stack, tree id, tree initializer)
       current_class_type = LAMBDA_EXPR_CLOSURE (lambda);
       if (DECL_PACK_P (initializer))
 	initializer = make_pack_expansion (initializer);
-      var = add_capture (lambda,
-                            id,
-                            initializer,
-                            /*by_reference_p=*/
-			    (this_capture_p
-			     || (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda)
-				 == CPLD_REFERENCE)),
-			    /*explicit_init_p=*/false);
+      var = add_capture (lambda, id, initializer,
+			 /*by_reference_p=*/
+			 (this_capture_p
+			  || (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda)
+			      == CPLD_REFERENCE)),
+			 /*explicit_init_p=*/false);
       initializer = convert_from_reference (var);
+
+      /* Warn about deprecated implicit capture of this via [=].  */
+      if (cxx_dialect >= cxx2a
+	  && this_capture_p
+	  && LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda) == CPLD_COPY
+	  && !in_system_header_at (LAMBDA_EXPR_LOCATION (lambda)))
+	{
+	  if (warning_at (LAMBDA_EXPR_LOCATION (lambda), OPT_Wdeprecated,
+			  "implicit capture of %qE via %<[=]%> is deprecated "
+			  "in C++20", this_identifier))
+	    inform (LAMBDA_EXPR_LOCATION (lambda), "add explicit %<this%> or "
+		    "%<*this%> capture");
+	}
     }
 
   current_class_type = saved_class_type;
--- gcc/testsuite/g++.dg/cpp2a/lambda-this1.C
+++ gcc/testsuite/g++.dg/cpp2a/lambda-this1.C
@@ -0,0 +1,51 @@
+// P0806R2
+// { dg-do compile }
+// { dg-options "-std=c++2a" }
+
+struct X {
+  int x;
+  void foo (int n) {
+    auto a1 = [=] { x = n; }; // { dg-warning "implicit capture" }
+    auto a2 = [=, this] { x = n; };
+    auto a3 = [=, *this]() mutable { x = n; };
+    auto a4 = [&] { x = n; };
+    auto a5 = [&, this] { x = n; };
+    auto a6 = [&, *this]() mutable { x = n; };
+
+    auto a7 = [=] { // { dg-warning "implicit capture" }
+      auto a = [=] { // { dg-warning "implicit capture" }
+	 auto a2 = [=] { x = n; }; // { dg-warning "implicit capture" }
+      };
+    };
+
+    auto a8 = [=, this] {
+      auto a = [=, this] {
+	 auto a2 = [=, this] { x = n; };
+      };
+    };
+
+    auto a9 = [=, *this]() mutable {
+      auto a = [=, *this]() mutable {
+	 auto a2 = [=, *this]() mutable { x = n; };
+      };
+    };
+
+    auto a10 = [&] {
+      auto a = [&] {
+	 auto a2 = [&] { x = n; };
+      };
+    };
+
+    auto a11 = [&, this] {
+      auto a = [&, this] {
+	 auto a2 = [&, this] { x = n; };
+      };
+    };
+
+    auto a12 = [&, *this]() mutable {
+      auto a = [&, *this]() mutable {
+	 auto a2 = [&, *this]() mutable { x = n; };
+      };
+    };
+  }
+};
--- gcc/testsuite/g++.dg/cpp2a/lambda-this2.C
+++ gcc/testsuite/g++.dg/cpp2a/lambda-this2.C
@@ -0,0 +1,51 @@
+// P0806R2
+// { dg-do compile }
+// { dg-options "-std=c++2a -Wno-deprecated" }
+
+struct X {
+  int x;
+  void foo (int n) {
+    auto a1 = [=] { x = n; }; // { dg-bogus "implicit capture" }
+    auto a2 = [=, this] { x = n; };
+    auto a3 = [=, *this]() mutable { x = n; };
+    auto a4 = [&] { x = n; };
+    auto a5 = [&, this] { x = n; };
+    auto a6 = [&, *this]() mutable { x = n; };
+
+    auto a7 = [=] { // { dg-bogus "implicit capture" }
+      auto a = [=] { // { dg-bogus "implicit capture" }
+	 auto a2 = [=] { x = n; }; // { dg-bogus "implicit capture" }
+      };
+    };
+
+    auto a8 = [=, this] {
+      auto a = [=, this] {
+	 auto a2 = [=, this] { x = n; };
+      };
+    };
+
+    auto a9 = [=, *this]() mutable {
+      auto a = [=, *this]() mutable {
+	 auto a2 = [=, *this]() mutable { x = n; };
+      };
+    };
+
+    auto a10 = [&] {
+      auto a = [&] {
+	 auto a2 = [&] { x = n; };
+      };
+    };
+
+    auto a11 = [&, this] {
+      auto a = [&, this] {
+	 auto a2 = [&, this] { x = n; };
+      };
+    };
+
+    auto a12 = [&, *this]() mutable {
+      auto a = [&, *this]() mutable {
+	 auto a2 = [&, *this]() mutable { x = n; };
+      };
+    };
+  }
+};
--- gcc/testsuite/g++.dg/cpp2a/lambda-this3.C
+++ gcc/testsuite/g++.dg/cpp2a/lambda-this3.C
@@ -0,0 +1,55 @@
+// P0806R2
+// { dg-do compile }
+// { dg-options "-std=c++17" }
+
+struct X {
+  int x;
+  void foo (int n) {
+    auto a1 = [=] { x = n; }; // { dg-bogus "implicit capture" }
+    auto a2 = [=, this] { x = n; };
+    // { dg-warning "explicit by-copy capture" "" { target c++17_down } .-1 }
+    auto a3 = [=, *this]() mutable { x = n; };
+    auto a4 = [&] { x = n; };
+    auto a5 = [&, this] { x = n; };
+    auto a6 = [&, *this]() mutable { x = n; };
+
+    auto a7 = [=] { // { dg-bogus "implicit capture" }
+      auto a = [=] { // { dg-bogus "implicit capture" }
+	 auto a2 = [=] { x = n; }; // { dg-bogus "implicit capture" }
+      };
+    };
+
+    auto a8 = [=, this] {
+    // { dg-warning "explicit by-copy capture" "" { target c++17_down } .-1 }
+      auto a = [=, this] {
+    // { dg-warning "explicit by-copy capture" "" { target c++17_down } .-1 }
+	 auto a2 = [=, this] { x = n; };
+    // { dg-warning "explicit by-copy capture" "" { target c++17_down } .-1 }
+      };
+    };
+
+    auto a9 = [=, *this]() mutable {
+      auto a = [=, *this]() mutable {
+	 auto a2 = [=, *this]() mutable { x = n; };
+      };
+    };
+
+    auto a10 = [&] {
+      auto a = [&] {
+	 auto a2 = [&] { x = n; };
+      };
+    };
+
+    auto a11 = [&, this] {
+      auto a = [&, this] {
+	 auto a2 = [&, this] { x = n; };
+      };
+    };
+
+    auto a12 = [&, *this]() mutable {
+      auto a = [&, *this]() mutable {
+	 auto a2 = [&, *this]() mutable { x = n; };
+      };
+    };
+  }
+};


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]