Author: Marek Kurdej Date: 2021-03-30T13:53:55+02:00 New Revision: a99b8ae3909106d831d880c1647dabe92f470290
URL: https://github.com/llvm/llvm-project/commit/a99b8ae3909106d831d880c1647dabe92f470290 DIFF: https://github.com/llvm/llvm-project/commit/a99b8ae3909106d831d880c1647dabe92f470290.diff LOG: [clang] [PR49736] [C++2b] Correctly reject lambdas with requires clause and no parameter list This fixes http://llvm.org/PR49736 caused by implementing http://wg21.link/P1102 (https://reviews.llvm.org/rG0620e6f4b76a9725dbd82454d58c5a68a7e47074), by correctly allowing requires-clause only: 1) directly after template-parameter-list 2) after lambda-specifiers iff parameter-declaration-clause is present (2nd kind of lambda-declarator) Reviewed By: aaron.ballman Differential Revision: https://reviews.llvm.org/D99489 Added: Modified: clang/lib/Parse/ParseExprCXX.cpp clang/test/Parser/cxx-concepts-requires-clause.cpp clang/test/Parser/cxx2a-template-lambdas.cpp clang/test/Parser/cxx2b-lambdas.cpp Removed: ################################################################################ diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index c2e74b5a7bbd..644df55bf46e 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/lib/Parse/ParseExprCXX.cpp @@ -690,7 +690,7 @@ ExprResult Parser::ParseCXXIdExpression(bool isAddressOfOperand) { /// lambda-expression: /// lambda-introducer lambda-declarator compound-statement /// lambda-introducer '<' template-parameter-list '>' -/// lambda-declarator compound-statement +/// requires-clause[opt] lambda-declarator compound-statement /// /// lambda-introducer: /// '[' lambda-capture[opt] ']' @@ -1392,12 +1392,6 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( /*DeclsInPrototype=*/None, LParenLoc, FunLocalRangeEnd, D, TrailingReturnType, TrailingReturnTypeLoc, &DS), std::move(Attr), DeclEndLoc); - - // Parse requires-clause[opt]. - if (Tok.is(tok::kw_requires)) - ParseTrailingRequiresClause(D); - - WarnIfHasCUDATargetAttr(); }; if (Tok.is(tok::l_paren)) { @@ -1433,6 +1427,10 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( // Parse lambda-specifiers. ParseLambdaSpecifiers(LParenLoc, /*DeclEndLoc=*/T.getCloseLocation(), ParamInfo, EllipsisLoc); + + // Parse requires-clause[opt]. + if (Tok.is(tok::kw_requires)) + ParseTrailingRequiresClause(D); } else if (Tok.isOneOf(tok::kw_mutable, tok::arrow, tok::kw___attribute, tok::kw_constexpr, tok::kw_consteval, tok::kw___private, tok::kw___global, tok::kw___local, @@ -1453,6 +1451,8 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( EmptyParamInfo, /*EllipsisLoc=*/NoLoc); } + WarnIfHasCUDATargetAttr(); + // FIXME: Rename BlockScope -> ClosureScope if we decide to continue using // it. unsigned ScopeFlags = Scope::BlockScope | Scope::FnScope | Scope::DeclScope | diff --git a/clang/test/Parser/cxx-concepts-requires-clause.cpp b/clang/test/Parser/cxx-concepts-requires-clause.cpp index 4d6d166d6fef..68f1af8b12cc 100644 --- a/clang/test/Parser/cxx-concepts-requires-clause.cpp +++ b/clang/test/Parser/cxx-concepts-requires-clause.cpp @@ -154,7 +154,9 @@ auto lambda1 = [] (auto x) requires (sizeof(decltype(x)) == 1) { }; auto lambda2 = [] (auto x) constexpr -> int requires (sizeof(decltype(x)) == 1) { return 0; }; -auto lambda3 = [] requires (sizeof(char) == 1) { }; +auto lambda3 = []<auto> requires(sizeof(char) == 1){}; + +auto lambda4 = [] requires(sizeof(char) == 1){}; // expected-error {{expected body of lambda expression}} #if __cplusplus <= 202002L -// expected-warning@-2{{is a C++2b extension}} +// expected-warning@-2{{lambda without a parameter clause is a C++2b extension}} #endif diff --git a/clang/test/Parser/cxx2a-template-lambdas.cpp b/clang/test/Parser/cxx2a-template-lambdas.cpp index 2a2305b5530c..f85280f7ece5 100644 --- a/clang/test/Parser/cxx2a-template-lambdas.cpp +++ b/clang/test/Parser/cxx2a-template-lambdas.cpp @@ -7,3 +7,28 @@ auto L1 = []<typename T1, typename T2> { }; auto L2 = []<typename T1, typename T2>(T1 arg1, T2 arg2) -> T1 { }; auto L3 = []<typename T>(auto arg) { T t; }; auto L4 = []<int I>() { }; + +// http://llvm.org/PR49736 +auto L5 = []<auto>(){}; +auto L6 = []<auto>{}; +auto L7 = []<auto>() noexcept {}; +auto L8 = []<auto> noexcept {}; +#if __cplusplus <= 202002L +// expected-warning@-2 {{lambda without a parameter clause is a C++2b extension}} +#endif +auto L9 = []<auto> requires true {}; +auto L10 = []<auto> requires true(){}; +auto L11 = []<auto> requires true() noexcept {}; +auto L12 = []<auto> requires true noexcept {}; +#if __cplusplus <= 202002L +// expected-warning@-2 {{is a C++2b extension}} +#endif +auto L13 = []<auto>() noexcept requires true {}; +auto L14 = []<auto> requires true() noexcept requires true {}; + +auto XL0 = []<auto> noexcept requires true {}; // expected-error {{expected body of lambda expression}} +auto XL1 = []<auto> requires true noexcept requires true {}; // expected-error {{expected body}} +#if __cplusplus <= 202002L +// expected-warning@-3 {{is a C++2b extension}} +// expected-warning@-3 {{is a C++2b extension}} +#endif diff --git a/clang/test/Parser/cxx2b-lambdas.cpp b/clang/test/Parser/cxx2b-lambdas.cpp index e008dc8f2d36..57e81eed7b9e 100644 --- a/clang/test/Parser/cxx2b-lambdas.cpp +++ b/clang/test/Parser/cxx2b-lambdas.cpp @@ -18,13 +18,14 @@ auto L9 = []<typename T> { return true; }; auto L10 = []<typename T> noexcept { return true; }; auto L11 = []<typename T> -> bool { return true; }; auto L12 = [] consteval {}; -auto L13 = [] requires requires() { true; } -{}; -auto L15 = [] [[maybe_unused]]{}; +auto L13 = []() requires true {}; +auto L14 = []<auto> requires true() requires true {}; +auto L15 = []<auto> requires true noexcept {}; +auto L16 = [] [[maybe_unused]]{}; auto XL0 = [] mutable constexpr mutable {}; // expected-error{{cannot appear multiple times}} auto XL1 = [] constexpr mutable constexpr {}; // expected-error{{cannot appear multiple times}} -auto XL2 = []) constexpr mutable constexpr {}; // expected-error{{expected body}} +auto XL2 = []) constexpr mutable constexpr {}; // expected-error{{expected body of lambda expression}} auto XL3 = []( constexpr mutable constexpr {}; // expected-error{{invalid storage class specifier}} \ // expected-error{{function parameter cannot be constexpr}} \ // expected-error{{C++ requires}} \ @@ -32,3 +33,8 @@ auto XL3 = []( constexpr mutable constexpr {}; // expected-error{{invalid storag // expected-note{{to match this '('}} \ // expected-error{{expected body}} \ // expected-warning{{duplicate 'constexpr'}} + +// http://llvm.org/PR49736 +auto XL4 = [] requires true {}; // expected-error{{expected body}} +auto XL5 = []<auto> requires true requires true {}; // expected-error{{expected body}} +auto XL6 = []<auto> requires true noexcept requires true {}; // expected-error{{expected body}} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits