[expr.prim.lambda.capture] p8 says "If a lambda-expression explicitly captures
an entity that is not odr-usable or captures a structured binding (explicitly
or implicitly), the program is ill-formed."
but we weren't respecting that and the attached testcase compiled.  I think we
can reject such uses in add_capture.

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

2018-05-29  Marek Polacek  <pola...@redhat.com>

        PR c++/85889
        * lambda.c (add_capture): Give error when capturing a structured
        binding.

        * g++.dg/cpp1z/decomp16.C: New test.
        * g++.dg/cpp1z/decomp46.C: New test.

diff --git gcc/cp/lambda.c gcc/cp/lambda.c
index 9c1b49b4d8e..c3d0decba08 100644
--- gcc/cp/lambda.c
+++ gcc/cp/lambda.c
@@ -569,6 +569,12 @@ add_capture (tree lambda, tree id, tree orig_init, bool 
by_reference_p,
       if (type == error_mark_node)
        return error_mark_node;
 
+      if (DECL_DECOMPOSITION_P (initializer))
+       {
+         error ("cannot capture a structured binding %qE", initializer);
+         return error_mark_node;
+       }
+
       if (id == this_identifier && !by_reference_p)
        {
          gcc_assert (INDIRECT_TYPE_P (type));
diff --git gcc/testsuite/g++.dg/cpp1z/decomp16.C 
gcc/testsuite/g++.dg/cpp1z/decomp16.C
index dad69b89c08..89ed774d614 100644
--- gcc/testsuite/g++.dg/cpp1z/decomp16.C
+++ gcc/testsuite/g++.dg/cpp1z/decomp16.C
@@ -8,7 +8,7 @@ void
 foo ()
 {
   auto [ a, b ] = A ();
-  for (; auto [ a, b ] = A (); )                       // { dg-error 
"expected|no match" }
+  for (; auto [ a, b ] = A (); )                       // { dg-error 
"expected|no match|cannot" }
     ;
   for (; false; auto [ a, b ] = A ())                  // { dg-error 
"expected" }
     ;
diff --git gcc/testsuite/g++.dg/cpp1z/decomp46.C 
gcc/testsuite/g++.dg/cpp1z/decomp46.C
index e69de29bb2d..cf5c8be6368 100644
--- gcc/testsuite/g++.dg/cpp1z/decomp46.C
+++ gcc/testsuite/g++.dg/cpp1z/decomp46.C
@@ -0,0 +1,26 @@
+// PR c++/85889
+// { dg-do compile }
+// { dg-options "-std=c++17" }
+
+struct X { int i, j; };
+void
+f ()
+{
+  X x{};
+  auto [i, j] = x;
+
+  auto [m, n] = X ();
+
+  [i]() { }; // { dg-error "cannot capture a structured binding" }
+  [&i]() { }; // { dg-error "cannot capture a structured binding" }
+  [j]() { }; // { dg-error "cannot capture a structured binding" }
+  [&j]() { }; // { dg-error "cannot capture a structured binding" }
+  [=]() { return i; }; // { dg-error "cannot capture a structured binding" }
+  [&]() { return i; }; // { dg-error "cannot capture a structured binding" }
+  [=]() { return j; }; // { dg-error "cannot capture a structured binding" }
+  [&]() { return j; }; // { dg-error "cannot capture a structured binding" }
+  [&, i]() { return i; }; // { dg-error "cannot capture a structured binding" }
+  [=, &i]() { return i; }; // { dg-error "cannot capture a structured binding" 
}
+  [&, i]() { return j; }; // { dg-error "cannot capture a structured binding" }
+  [=, &i]() { return j; }; // { dg-error "cannot capture a structured binding" 
}
+}

Reply via email to