Description
Building the following in --std=c++20
struct P { int a; int b; };
void repro() {
const auto [a, b] = P{1, 2};
(void)[&](const auto c) { return c - b; }(2);
}
Produces a failure with error message:
/home/pmoran/clang_testcase.cpp:13:41: error: reference to local binding 'b' declared in enclosing function 'main'
(void)[&](const auto c) { return c - b; }(2);
^
/home/pmoran/clang_testcase.cpp:13:45: note: in instantiation of function template specialization 'main()::(anonymous class)::operator()<int>' requested here
(void)[&](const auto c) { return c - b; }(2);
^
/home/pmoran/clang_testcase.cpp:12:18: note: 'b' declared here
const auto [a, b] = P{1, 2};
^
It is my understanding that the capturing structured bindings in lambdas may not have been standards conforming in earlier language versions, but that it is standards-conforming in C++20. Commit 127bf44 added support for capturing structured bindings in lambdas to fix #54300 and #52720. The error seems to persist here specifically because the lambda is a generic lambda. If you change the argument from const auto c
to instead be the const int c
that the lambda's call will resolve to, the error goes away.
I chased the source of the error as far as clang/lib/Sema/SemaExpr.cpp line 18831 where we see this comment:
// If we are instantiating a generic lambda call operator body,
// we do not want to capture new variables. What was captured
// during either a lambdas transformation or initial parsing
// should be used.
If you capture b
by reference explicitly by name rather than using a default capture like so:
(void)[&b](const auto c) { return c - b; }(2);
Then you instead get this warning:
/home/pmoran/clang_testcase.cpp:13:12: warning: lambda capture 'b' is not required to be captured for this use [-Wunused-lambda-capture]
(void)[&b](const auto c) { return c - b; }(2);
^
So I think the issue resides in the detection of which values need to be captured by a lambda's body (even though here neither b
's type nor its value depend on the type parameter of the generic operator()
).
Platform: I have only tested on linux x86_64,. but I don't think it's platform-specific
Versions Affected: I believe all versions up to and including the HEAD I pulled earlier today (2022-09-19).