Author: Richard Smith Date: 2020-12-03T15:54:16-08:00 New Revision: eccc734a69c0c012ae3160887b65a535b35ead3e
URL: https://github.com/llvm/llvm-project/commit/eccc734a69c0c012ae3160887b65a535b35ead3e DIFF: https://github.com/llvm/llvm-project/commit/eccc734a69c0c012ae3160887b65a535b35ead3e.diff LOG: P0857R0: Parse a requires-clause after an explicit template-parameter-list in a lambda. This implements one of the missing parts of P0857R0. Mark it as not done on the cxx_status page given that it's still incomplete. Added: Modified: clang/include/clang/Sema/ScopeInfo.h clang/include/clang/Sema/Sema.h clang/lib/Parse/ParseExprCXX.cpp clang/lib/Sema/SemaLambda.cpp clang/test/SemaTemplate/concepts.cpp clang/www/cxx_status.html Removed: ################################################################################ diff --git a/clang/include/clang/Sema/ScopeInfo.h b/clang/include/clang/Sema/ScopeInfo.h index ff2a20923415..8ec74cafeeca 100644 --- a/clang/include/clang/Sema/ScopeInfo.h +++ b/clang/include/clang/Sema/ScopeInfo.h @@ -849,6 +849,11 @@ class LambdaScopeInfo final : /// Source range covering the explicit template parameter list (if it exists). SourceRange ExplicitTemplateParamsRange; + /// The requires-clause immediately following the explicit template parameter + /// list, if any. (Note that there may be another requires-clause included as + /// part of the lambda-declarator.) + ExprResult RequiresClause; + /// If this is a generic lambda, and the template parameter /// list has been created (from the TemplateParams) then store /// a reference to it (cache it to avoid reconstructing it). diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index fc19e04e6c5d..b3ede504542f 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -6551,7 +6551,8 @@ class Sema final { /// on a lambda (if it exists) in C++2a. void ActOnLambdaExplicitTemplateParameterList(SourceLocation LAngleLoc, ArrayRef<NamedDecl *> TParams, - SourceLocation RAngleLoc); + SourceLocation RAngleLoc, + ExprResult RequiresClause); /// Introduce the lambda parameters into scope. void addLambdaParameters( diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index 96df2c932bea..4b5703d79f28 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/lib/Parse/ParseExprCXX.cpp @@ -1268,7 +1268,6 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( << A.getAttrName()->getName(); }; - // FIXME: Consider allowing this as an extension for GCC compatibiblity. MultiParseScope TemplateParamScope(*this); if (Tok.is(tok::less)) { Diag(Tok, getLangOpts().CPlusPlus20 @@ -1288,8 +1287,17 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( Diag(RAngleLoc, diag::err_lambda_template_parameter_list_empty); } else { + ExprResult RequiresClause; + if (TryConsumeToken(tok::kw_requires)) { + RequiresClause = + Actions.ActOnRequiresClause(ParseConstraintLogicalOrExpression( + /*IsTrailingRequiresClause=*/false)); + if (RequiresClause.isInvalid()) + SkipUntil({tok::l_brace, tok::l_paren}, StopAtSemi | StopBeforeMatch); + } + Actions.ActOnLambdaExplicitTemplateParameterList( - LAngleLoc, TemplateParams, RAngleLoc); + LAngleLoc, TemplateParams, RAngleLoc, RequiresClause); ++CurTemplateDepthTracker; } } diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp index c2eb663147c2..ec1db50cfaaa 100644 --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/lib/Sema/SemaLambda.cpp @@ -233,7 +233,7 @@ getGenericLambdaTemplateParameterList(LambdaScopeInfo *LSI, Sema &SemaRef) { /*L angle loc*/ LSI->ExplicitTemplateParamsRange.getBegin(), LSI->TemplateParams, /*R angle loc*/LSI->ExplicitTemplateParamsRange.getEnd(), - nullptr); + LSI->RequiresClause.get()); } return LSI->GLTemplateParameterList; } @@ -520,7 +520,8 @@ void Sema::finishLambdaExplicitCaptures(LambdaScopeInfo *LSI) { void Sema::ActOnLambdaExplicitTemplateParameterList(SourceLocation LAngleLoc, ArrayRef<NamedDecl *> TParams, - SourceLocation RAngleLoc) { + SourceLocation RAngleLoc, + ExprResult RequiresClause) { LambdaScopeInfo *LSI = getCurLambda(); assert(LSI && "Expected a lambda scope"); assert(LSI->NumExplicitTemplateParams == 0 && @@ -533,6 +534,7 @@ void Sema::ActOnLambdaExplicitTemplateParameterList(SourceLocation LAngleLoc, LSI->TemplateParams.append(TParams.begin(), TParams.end()); LSI->NumExplicitTemplateParams = TParams.size(); LSI->ExplicitTemplateParamsRange = {LAngleLoc, RAngleLoc}; + LSI->RequiresClause = RequiresClause; } void Sema::addLambdaParameters( diff --git a/clang/test/SemaTemplate/concepts.cpp b/clang/test/SemaTemplate/concepts.cpp index d228ff07837d..2a46dec5afb7 100644 --- a/clang/test/SemaTemplate/concepts.cpp +++ b/clang/test/SemaTemplate/concepts.cpp @@ -34,11 +34,11 @@ namespace PR45699 { template<class ...Ts> requires C<Ts...> void f3b(); // expected-error {{pack expansion used as argument for non-pack parameter of concept}} template<class ...Ts> void f4() { ([] () requires C<Ts> {} ()); // expected-error {{expression contains unexpanded parameter pack 'Ts'}} - ([]<int = 0> requires C<Ts> () {} ()); // FIXME: expected-error {{lambda requires '()' before 'requires' clause}} expected-error 0+{{}} + ([]<int = 0> requires C<Ts> () {} ()); // expected-error {{expression contains unexpanded parameter pack 'Ts'}} } template<class ...Ts> void f5() { ([] () requires C<Ts> {} (), ...); - ([]<int = 0> requires C<Ts> () {} (), ...); // FIXME: expected-error {{lambda requires '()' before 'requires' clause}} expected-error 0+{{}} + ([]<int = 0> requires C<Ts> () {} (), ...); } void g() { f1a(); @@ -51,3 +51,17 @@ namespace PR45699 { f5(); } } + +namespace P0857R0 { + void f() { + auto x = []<bool B> requires B {}; // expected-note {{constraints not satisfied}} expected-note {{false}} + x.operator()<true>(); + x.operator()<false>(); // expected-error {{no matching member function}} + } + + // FIXME: This is valid under P0857R0. + template<typename T> concept C = true; + template<template<typename T> requires C<T> typename U> struct X {}; // expected-error {{requires 'class'}} expected-error 0+{{}} + template<typename T> requires C<T> struct Y {}; + X<Y> xy; // expected-error {{no template named 'X'}} +} diff --git a/clang/www/cxx_status.html b/clang/www/cxx_status.html index de6c5eff7609..4a66b7f9465e 100755 --- a/clang/www/cxx_status.html +++ b/clang/www/cxx_status.html @@ -875,13 +875,15 @@ <h2 id="cxx20">C++20 implementation status</h2> <tr id="p0734"> <td rowspan="12">Concepts</td> <td><a href="https://wg21.link/p0734r0">P0734R0</a></td> - <td rowspan="4" class="full" align="center">Clang 10</td> + <td class="full" align="center">Clang 10</td> </tr> <tr> <!-- from Albuquerque --> <td><a href="https://wg21.link/p0857r0">P0857R0</a></td> + <td class="partial" align="center">Partial</td> </tr> <tr> <!-- from San Diego --> <td><a href="https://wg21.link/p1084r2">P1084R2</a></td> + <td rowspan="2" class="full" align="center">Clang 10</td> </tr> <tr> <td><a href="https://wg21.link/p1141r2">P1141R2</a></td> @@ -899,14 +901,13 @@ <h2 id="cxx20">C++20 implementation status</h2> </tr> <tr> <!-- from Belfast --> <td><a href="https://wg21.link/p1972r0">P1972R0</a></td> - <td rowspan="2" class="none" align="center">No</td> + <td rowspan="5" class="none" align="center">No</td> </tr> <tr> <td><a href="https://wg21.link/p1980r0">P1980R0</a></td> </tr> <tr> <!-- from Prague --> <td><a href="https://wg21.link/p2103r0">P2103R0</a></td> - <td rowspan="3" class="none" align="center">No</td> </tr> <tr> <td><a href="https://wg21.link/p2092r0">P2092R0</a></td> _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits