[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