diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/lib/Parse/ParseExprCXX.cpp @@ -690,7 +690,7 @@ /// 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 @@ /*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 @@ // 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 @@ 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 --- a/clang/test/Parser/cxx-concepts-requires-clause.cpp +++ b/clang/test/Parser/cxx-concepts-requires-clause.cpp @@ -154,7 +154,9 @@ auto lambda2 = [] (auto x) constexpr -> int requires (sizeof(decltype(x)) == 1) { return 0; }; -auto lambda3 = [] requires (sizeof(char) == 1) { }; +auto lambda3 = [] 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 --- a/clang/test/Parser/cxx2a-template-lambdas.cpp +++ b/clang/test/Parser/cxx2a-template-lambdas.cpp @@ -7,3 +7,28 @@ auto L2 = [](T1 arg1, T2 arg2) -> T1 { }; auto L3 = [](auto arg) { T t; }; auto L4 = []() { }; + +// http://llvm.org/PR49736 +auto L5 = [](){}; +auto L6 = []{}; +auto L7 = []() noexcept {}; +auto L8 = [] noexcept {}; +#if __cplusplus <= 202002L +// expected-warning@-2 {{is a C++2b extension}} +#endif +auto L9 = [] requires true {}; +auto L10 = [] requires true(){}; +auto L11 = [] requires true() noexcept {}; +auto L12 = [] requires true noexcept {}; +#if __cplusplus <= 202002L +// expected-warning@-2 {{is a C++2b extension}} +#endif +auto L13 = []() noexcept requires true {}; +auto L14 = [] requires true() noexcept requires true {}; + +auto XL0 = [] noexcept requires true {}; // expected-error {{expected body of lambda expression}} +auto XL1 = [] requires true noexcept requires true {}; // expected-error {{expected body}} +#if __cplusplus <= 202002L +// expected-warning@-3 {{lambda without a parameter clause 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 --- a/clang/test/Parser/cxx2b-lambdas.cpp +++ b/clang/test/Parser/cxx2b-lambdas.cpp @@ -18,13 +18,14 @@ auto L10 = [] noexcept { return true; }; auto L11 = [] -> bool { return true; }; auto L12 = [] consteval {}; -auto L13 = [] requires requires() { true; } -{}; -auto L15 = [] [[maybe_unused]]{}; +auto L13 = []() requires true {}; +auto L14 = [] requires true() requires true {}; +auto L15 = [] 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 @@ // 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 = [] requires true requires true {}; // expected-error{{expected body}} +auto XL6 = [] requires true noexcept requires true {}; // expected-error{{expected body}}