[llvm-branch-commits] [clang] eccc734 - P0857R0: Parse a requires-clause after an explicit
Richard Smith via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Thu Dec 3 16:01:34 PST 2020
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>
More information about the llvm-branch-commits
mailing list