Patchwork C++ PATCH to add capture initializers to -std=c++1y

login
register
mail settings
Submitter Jason Merrill
Date April 22, 2013, 7:19 p.m.
Message ID <51758D3A.1080305@redhat.com>
Download mbox | patch
Permalink /patch/238642/
State New
Headers show

Comments

Jason Merrill - April 22, 2013, 7:19 p.m.
At the Bristol C++ meeting we voted to accept generalized lambda capture 
initializers (e.g. [x = 42, y = std::move(y)]{ ... }), which were part 
of the initial implementation of lambdas in GCC, so initial support for 
C++1y is just a matter of checking cxx_dialect to avoid the pedwarn.

The only thing missing from our implementation is support for 
list-initialization as well as = initialization; I'll add that soon.

Tested x86_64-pc-linux-gnu, applying to trunk.

Patch

commit a920644105779dceffd5912822b10b331457a227
Author: Jason Merrill <jason@redhat.com>
Date:   Mon Apr 22 12:56:01 2013 -0400

    	N3648
    
    	* parser.c (cp_parser_lambda_introducer): Make lambda capture init
    	pedwarn unconditional except in C++1y mode.

diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 1893482..1fbc9bd 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -8518,9 +8518,10 @@  cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr)
 	{
 	  /* An explicit expression exists.  */
 	  cp_lexer_consume_token (parser->lexer);
-          pedwarn (input_location, OPT_Wpedantic,
-                   "ISO C++ does not allow initializers "
-                   "in lambda expression capture lists");
+	  if (cxx_dialect < cxx1y)
+	    pedwarn (input_location, 0,
+		     "lambda capture initializers "
+		     "only available with -std=c++1y or -std=gnu++1y");
 	  capture_init_expr = cp_parser_assignment_expression (parser,
 							       /*cast_p=*/true,
 							       &idk);
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-deduce-ext.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-deduce-ext.C
deleted file mode 100644
index 9b5ab79..0000000
--- a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-deduce-ext.C
+++ /dev/null
@@ -1,27 +0,0 @@ 
-// Testcase for an extension to allow return type deduction when the lambda
-// contains more than just a single return-statement.
-
-// { dg-options -std=c++0x }
-// { dg-do run }
-
-bool b;
-template <class T>
-T f (T t)
-{
-  return [=] {
-    auto i = t+1;
-    if (b)
-      return i+1;
-    else
-      return i+1;
-  }();
-}
-
-int main()
-{
-  // Pointless, but well-formed.
-  [] { return 1; return 2; }();
-
-  if (f(1) != 3)
-    return 1;
-}
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-init.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-init.C
deleted file mode 100644
index 03c94e9..0000000
--- a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-init.C
+++ /dev/null
@@ -1,8 +0,0 @@ 
-// Test for the explicit initializer extension
-// { dg-options "-std=c++0x" }
-
-int main()
-{
-  int j = [i = 2]{sizeof(i); return i;}();
-  return (j != 2);
-}
diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-deduce-mult.C b/gcc/testsuite/g++.dg/cpp1y/lambda-deduce-mult.C
new file mode 100644
index 0000000..1181a80
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/lambda-deduce-mult.C
@@ -0,0 +1,27 @@ 
+// Testcase for an extension to allow return type deduction when the lambda
+// contains more than just a single return-statement.
+
+// { dg-options -std=c++1y }
+// { dg-do run }
+
+bool b;
+template <class T>
+T f (T t)
+{
+  return [=] {
+    auto i = t+1;
+    if (b)
+      return i+1;
+    else
+      return i+1;
+  }();
+}
+
+int main()
+{
+  // Pointless, but well-formed.
+  [] { return 1; return 2; }();
+
+  if (f(1) != 3)
+    return 1;
+}
diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-init.C b/gcc/testsuite/g++.dg/cpp1y/lambda-init.C
new file mode 100644
index 0000000..a443642
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/lambda-init.C
@@ -0,0 +1,8 @@ 
+// Test for the explicit initializer extension of C++1y
+// { dg-options "-std=c++1y" }
+
+int main()
+{
+  int j = [i = 2]{sizeof(i); return i;}();
+  return (j != 2);
+}
diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-init1.C b/gcc/testsuite/g++.dg/cpp1y/lambda-init1.C
new file mode 100644
index 0000000..6411fca
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/lambda-init1.C
@@ -0,0 +1,13 @@ 
+// N3648: capture init
+// { dg-options "-std=c++1y -w" }
+// { dg-do run }
+
+int main()
+{
+  int x = 41;
+  auto r = [x = x+1]{ return x; }();
+  if (r != 42) __builtin_abort();
+
+  static auto *p = &r;
+  [&x=r]{ if (&x != p) __builtin_abort(); }();
+}
diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-init2.C b/gcc/testsuite/g++.dg/cpp1y/lambda-init2.C
new file mode 100644
index 0000000..068621d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/lambda-init2.C
@@ -0,0 +1,13 @@ 
+// N3648: redundancy and capture init
+// { dg-options "-std=c++1y -pedantic-errors" }
+
+int main()
+{
+  int x = 42;
+  [=,x]{};			// { dg-error "redundant" }
+  [=,&x]{};
+  [&,&x]{};			// { dg-error "redundant" }
+  [&,x]{};
+  [=,x=24]{};
+  [&,&r=x]{};
+}
diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-init3.C b/gcc/testsuite/g++.dg/cpp1y/lambda-init3.C
new file mode 100644
index 0000000..9044be6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/lambda-init3.C
@@ -0,0 +1,11 @@ 
+// N3648: capture init at non-block scope
+// { dg-options "-std=c++1y -w" }
+// { dg-do run }
+
+int i = 42;
+int j = [x=i]{ return x; }();
+
+int main()
+{
+  if (j != 42) __builtin_abort();
+}
diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-init4.C b/gcc/testsuite/g++.dg/cpp1y/lambda-init4.C
new file mode 100644
index 0000000..da4ea37
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/lambda-init4.C
@@ -0,0 +1,14 @@ 
+// N3648: capture init example from paper
+// { dg-options "-std=c++1y" }
+// { dg-do run }
+
+int x = 4;
+auto y = [&r = x, x = x+1]()->int {
+  r += 2;
+  return x+2;
+}();  // Updates ::x to 6, and initializes y to 7.
+
+int main()
+{
+  if (x != 6 || y != 7) __builtin_abort();
+}