cor3ntin created this revision. Herald added a project: All. cor3ntin requested review of this revision. Herald added a project: clang. Herald added a subscriber: cfe-commits.
Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D137172 Files: clang/docs/ReleaseNotes.rst clang/lib/Sema/SemaDeclCXX.cpp clang/test/CXX/drs/dr23xx.cpp clang/test/CXX/expr/expr.prim/expr.prim.lambda/p13.cpp clang/www/cxx_dr_status.html Index: clang/www/cxx_dr_status.html =================================================================== --- clang/www/cxx_dr_status.html +++ clang/www/cxx_dr_status.html @@ -13956,7 +13956,7 @@ <td><a href="https://wg21.link/cwg2358">2358</a></td> <td>CD5</td> <td>Explicit capture of value</td> - <td class="none" align="center">Unknown</td> + <td class="unreleased" align="center">Clang 16</td> </tr> <tr id="2359"> <td><a href="https://wg21.link/cwg2359">2359</a></td> Index: clang/test/CXX/expr/expr.prim/expr.prim.lambda/p13.cpp =================================================================== --- clang/test/CXX/expr/expr.prim/expr.prim.lambda/p13.cpp +++ clang/test/CXX/expr/expr.prim/expr.prim.lambda/p13.cpp @@ -1,5 +1,6 @@ // RUN: %clang_cc1 -std=c++11 %s -Wunused -Wno-unused-lambda-capture -verify +const int global = 0; void f2() { int i = 1; void g1(int = ([i]{ return i; })()); // expected-error{{lambda expression in default argument cannot capture any entity}} @@ -7,6 +8,8 @@ void g3(int = ([=]{ return i; })()); // expected-error{{lambda expression in default argument cannot capture any entity}} void g4(int = ([=]{ return 0; })()); void g5(int = ([]{ return sizeof i; })()); + void g6(int = ([x=1, y = global, &z = global]{ return x; })()); + void g7(int = ([x=i, &y=i]{ return x; })()); // expected-error 2{{default argument references local variable 'i' of enclosing function}} } namespace lambda_in_default_args { Index: clang/test/CXX/drs/dr23xx.cpp =================================================================== --- clang/test/CXX/drs/dr23xx.cpp +++ clang/test/CXX/drs/dr23xx.cpp @@ -89,6 +89,16 @@ #pragma clang __debug dump not_use_2 } +#if __cplusplus >= 201402L +namespace dr2358 { // dr2358: 16 + void f2() { + int i = 1; + void g1(int = ([x=1] { return x; }))(); // OK + void g2(int = ([x=i] { return x; }))(); // expected-error {{default argument references local variable 'i' of enclosing function}} + } +} +#endif + #if __cplusplus >= 201707L // Otherwise, if the qualified-id std::tuple_size<E> names a complete class // type **with a member value**, the expression std::tuple_size<E>::value shall Index: clang/lib/Sema/SemaDeclCXX.cpp =================================================================== --- clang/lib/Sema/SemaDeclCXX.cpp +++ clang/lib/Sema/SemaDeclCXX.cpp @@ -149,13 +149,19 @@ } bool CheckDefaultArgumentVisitor::VisitLambdaExpr(const LambdaExpr *Lambda) { - // C++11 [expr.lambda.prim]p13: - // A lambda-expression appearing in a default argument shall not - // implicitly or explicitly capture any entity. - if (Lambda->capture_begin() == Lambda->capture_end()) - return false; - - return S.Diag(Lambda->getBeginLoc(), diag::err_lambda_capture_default_arg); + // [expr.prim.lambda.capture]/p9 + // a lambda-expression appearing in a default argument cannot implicitly or explicitly capture any local entity. + // Such a lambda-expression can still have an init-capture if any full-expression in its initializer + // satisfies the constraints of an expression appearing in a default argument. + bool Invalid = false; + for(const LambdaCapture& LC : Lambda->captures()) { + if(!Lambda->isInitCapture(&LC)) + return S.Diag(LC.getLocation(), diag::err_lambda_capture_default_arg); + // Init captures are always VarDecl. + auto *D = cast<VarDecl>(LC.getCapturedVar()); + Invalid |= Visit(D->getInit()); + } + return Invalid; } } // namespace Index: clang/docs/ReleaseNotes.rst =================================================================== --- clang/docs/ReleaseNotes.rst +++ clang/docs/ReleaseNotes.rst @@ -507,6 +507,7 @@ This means Clang will by default accept code using features from C++17 and conforming GNU extensions. Projects incompatible with C++17 can add ``-std=gnu++14`` to their build settings to restore the previous behaviour. +- Implemented DR2358 allowing init captures in lambdas in default arguments. C++20 Feature Support ^^^^^^^^^^^^^^^^^^^^^
Index: clang/www/cxx_dr_status.html =================================================================== --- clang/www/cxx_dr_status.html +++ clang/www/cxx_dr_status.html @@ -13956,7 +13956,7 @@ <td><a href="https://wg21.link/cwg2358">2358</a></td> <td>CD5</td> <td>Explicit capture of value</td> - <td class="none" align="center">Unknown</td> + <td class="unreleased" align="center">Clang 16</td> </tr> <tr id="2359"> <td><a href="https://wg21.link/cwg2359">2359</a></td> Index: clang/test/CXX/expr/expr.prim/expr.prim.lambda/p13.cpp =================================================================== --- clang/test/CXX/expr/expr.prim/expr.prim.lambda/p13.cpp +++ clang/test/CXX/expr/expr.prim/expr.prim.lambda/p13.cpp @@ -1,5 +1,6 @@ // RUN: %clang_cc1 -std=c++11 %s -Wunused -Wno-unused-lambda-capture -verify +const int global = 0; void f2() { int i = 1; void g1(int = ([i]{ return i; })()); // expected-error{{lambda expression in default argument cannot capture any entity}} @@ -7,6 +8,8 @@ void g3(int = ([=]{ return i; })()); // expected-error{{lambda expression in default argument cannot capture any entity}} void g4(int = ([=]{ return 0; })()); void g5(int = ([]{ return sizeof i; })()); + void g6(int = ([x=1, y = global, &z = global]{ return x; })()); + void g7(int = ([x=i, &y=i]{ return x; })()); // expected-error 2{{default argument references local variable 'i' of enclosing function}} } namespace lambda_in_default_args { Index: clang/test/CXX/drs/dr23xx.cpp =================================================================== --- clang/test/CXX/drs/dr23xx.cpp +++ clang/test/CXX/drs/dr23xx.cpp @@ -89,6 +89,16 @@ #pragma clang __debug dump not_use_2 } +#if __cplusplus >= 201402L +namespace dr2358 { // dr2358: 16 + void f2() { + int i = 1; + void g1(int = ([x=1] { return x; }))(); // OK + void g2(int = ([x=i] { return x; }))(); // expected-error {{default argument references local variable 'i' of enclosing function}} + } +} +#endif + #if __cplusplus >= 201707L // Otherwise, if the qualified-id std::tuple_size<E> names a complete class // type **with a member value**, the expression std::tuple_size<E>::value shall Index: clang/lib/Sema/SemaDeclCXX.cpp =================================================================== --- clang/lib/Sema/SemaDeclCXX.cpp +++ clang/lib/Sema/SemaDeclCXX.cpp @@ -149,13 +149,19 @@ } bool CheckDefaultArgumentVisitor::VisitLambdaExpr(const LambdaExpr *Lambda) { - // C++11 [expr.lambda.prim]p13: - // A lambda-expression appearing in a default argument shall not - // implicitly or explicitly capture any entity. - if (Lambda->capture_begin() == Lambda->capture_end()) - return false; - - return S.Diag(Lambda->getBeginLoc(), diag::err_lambda_capture_default_arg); + // [expr.prim.lambda.capture]/p9 + // a lambda-expression appearing in a default argument cannot implicitly or explicitly capture any local entity. + // Such a lambda-expression can still have an init-capture if any full-expression in its initializer + // satisfies the constraints of an expression appearing in a default argument. + bool Invalid = false; + for(const LambdaCapture& LC : Lambda->captures()) { + if(!Lambda->isInitCapture(&LC)) + return S.Diag(LC.getLocation(), diag::err_lambda_capture_default_arg); + // Init captures are always VarDecl. + auto *D = cast<VarDecl>(LC.getCapturedVar()); + Invalid |= Visit(D->getInit()); + } + return Invalid; } } // namespace Index: clang/docs/ReleaseNotes.rst =================================================================== --- clang/docs/ReleaseNotes.rst +++ clang/docs/ReleaseNotes.rst @@ -507,6 +507,7 @@ This means Clang will by default accept code using features from C++17 and conforming GNU extensions. Projects incompatible with C++17 can add ``-std=gnu++14`` to their build settings to restore the previous behaviour. +- Implemented DR2358 allowing init captures in lambdas in default arguments. C++20 Feature Support ^^^^^^^^^^^^^^^^^^^^^
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits