[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" } +}