Skip to content

Rejecting captures of structured bindings in generic lambdas in C++20 #57826

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
PatrickAMoran opened this issue Sep 19, 2022 · 2 comments
Closed
Labels
c++20 clang:frontend Language frontend issues, e.g. anything involving "Sema"

Comments

@PatrickAMoran
Copy link

PatrickAMoran commented Sep 19, 2022

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).

@EugeneZelenko EugeneZelenko added c++20 clang:frontend Language frontend issues, e.g. anything involving "Sema" and removed new issue labels Sep 19, 2022
@llvmbot
Copy link
Member

llvmbot commented Sep 19, 2022

@llvm/issue-subscribers-c-20

@llvmbot
Copy link
Member

llvmbot commented Sep 19, 2022

@llvm/issue-subscribers-clang-frontend

cor3ntin added a commit to cor3ntin/llvm-project that referenced this issue Dec 29, 2022
Structured bindings were not properly marked odr-used
and therefore captured in generic lambddas.

Fixes llvm#57826

It is unclear to me if further simplification can be gained
through the allowance described in
https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0588r1.html.

Either way, I think this makes support for P0588 completes,
but we probably want to add test for that in a separate PR.
(and I lack confidence I understand P0588 sufficiently to assert
the completeness of our cnformance).

Differential Revision: https://reviews.llvm.org/D137244
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c++20 clang:frontend Language frontend issues, e.g. anything involving "Sema"
Projects
None yet
Development

No branches or pull requests

3 participants