curdeius updated this revision to Diff 330901.
curdeius marked 4 inline comments as done.
curdeius added a comment.

- Add test.
- Remove unnecessary PrototypeScope.exit().


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D98433/new/

https://reviews.llvm.org/D98433

Files:
  clang/lib/Parse/ParseExprCXX.cpp
  clang/test/Parser/cxx2b-lambdas.cpp
  clang/www/cxx_status.html

Index: clang/www/cxx_status.html
===================================================================
--- clang/www/cxx_status.html
+++ clang/www/cxx_status.html
@@ -63,7 +63,7 @@
 <tr>
  <td><a href="#cxx23">C++2b (tentatively C++23)</a></td>
  <td><tt>-std=c++2b</tt></td>
- <td class="none" align="center">No</td>
+ <td class="partial" align="center">Partial</td>
 </tr>
 </table>
 
@@ -1276,7 +1276,7 @@
     <tr>
       <td>Make <tt>()</tt> in lambdas optional in all cases</td>
       <td><a href="https://wg21.link/p1102r2";>P1102R2</a></td>
-      <td class="none" align="center">No</td>
+      <td class="full" align="center">Clang 13</td>
     </tr>
 </table>
 </details>
Index: clang/test/Parser/cxx2b-lambdas.cpp
===================================================================
--- /dev/null
+++ clang/test/Parser/cxx2b-lambdas.cpp
@@ -0,0 +1,29 @@
+// RUN: %clang_cc1 -std=c++2b %s -verify
+
+auto L0 = [] constexpr {};
+auto L1 = [] mutable {};
+auto L2 = [] noexcept {};
+auto L3 = [] constexpr mutable {};
+auto L4 = [] mutable constexpr {};
+auto L5 = [] constexpr mutable noexcept {};
+auto L6 = [s = 1] mutable {};
+auto L7 = [s = 1] constexpr mutable noexcept {};
+auto L8 = [] -> bool { return true; };
+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 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 XL3 = []( constexpr mutable constexpr {}; // expected-error{{invalid storage class specifier}} \
+                                               // expected-error{{function parameter cannot be constexpr}} \
+                                               // expected-error{{C++ requires}} \
+                                               // expected-error{{expected ')'}} \
+                                               // expected-note{{to match this '('}} \
+                                               // expected-error{{expected body}} \
+                                               // expected-warning{{duplicate 'constexpr'}}
Index: clang/lib/Parse/ParseExprCXX.cpp
===================================================================
--- clang/lib/Parse/ParseExprCXX.cpp
+++ clang/lib/Parse/ParseExprCXX.cpp
@@ -688,9 +688,9 @@
 /// ParseLambdaExpression - Parse a C++11 lambda expression.
 ///
 ///       lambda-expression:
-///         lambda-introducer lambda-declarator[opt] compound-statement
+///         lambda-introducer lambda-declarator compound-statement
 ///         lambda-introducer '<' template-parameter-list '>'
-///             lambda-declarator[opt] compound-statement
+///             lambda-declarator compound-statement
 ///
 ///       lambda-introducer:
 ///         '[' lambda-capture[opt] ']'
@@ -722,9 +722,13 @@
 ///         '&' identifier initializer
 ///
 ///       lambda-declarator:
-///         '(' parameter-declaration-clause ')' attribute-specifier[opt]
-///           'mutable'[opt] exception-specification[opt]
-///           trailing-return-type[opt]
+///         lambda-specifiers     [C++2b]
+///         '(' parameter-declaration-clause ')' lambda-specifiers
+///             requires-clause[opt]
+///
+///       lambda-specifiers:
+///         decl-specifier-seq[opt] noexcept-specifier[opt]
+///             attribute-specifier-seq[opt] trailing-return-type[opt]
 ///
 ExprResult Parser::ParseLambdaExpression() {
   // Parse lambda-introducer.
@@ -1315,11 +1319,92 @@
 
   TypeResult TrailingReturnType;
   SourceLocation TrailingReturnTypeLoc;
+
+  auto ParseLambdaSpecifiers =
+      [&](SourceLocation LParenLoc, SourceLocation RParenLoc,
+          MutableArrayRef<DeclaratorChunk::ParamInfo> ParamInfo,
+          SourceLocation EllipsisLoc) {
+        SourceLocation DeclEndLoc = RParenLoc;
+
+        // GNU-style attributes must be parsed before the mutable specifier to
+        // be compatible with GCC. MSVC-style attributes must be parsed before
+        // the mutable specifier to be compatible with MSVC.
+        MaybeParseAttributes(PAKM_GNU | PAKM_Declspec, Attr);
+
+        // Parse mutable-opt and/or constexpr-opt or consteval-opt, and update
+        // the DeclEndLoc.
+        SourceLocation MutableLoc;
+        SourceLocation ConstexprLoc;
+        SourceLocation ConstevalLoc;
+        tryConsumeLambdaSpecifierToken(*this, MutableLoc, ConstexprLoc,
+                                       ConstevalLoc, DeclEndLoc);
+
+        addConstexprToLambdaDeclSpecifier(*this, ConstexprLoc, DS);
+        addConstevalToLambdaDeclSpecifier(*this, ConstevalLoc, DS);
+        // Parse exception-specification[opt].
+        ExceptionSpecificationType ESpecType = EST_None;
+        SourceRange ESpecRange;
+        SmallVector<ParsedType, 2> DynamicExceptions;
+        SmallVector<SourceRange, 2> DynamicExceptionRanges;
+        ExprResult NoexceptExpr;
+        CachedTokens *ExceptionSpecTokens;
+        ESpecType = tryParseExceptionSpecification(
+            /*Delayed=*/false, ESpecRange, DynamicExceptions,
+            DynamicExceptionRanges, NoexceptExpr, ExceptionSpecTokens);
+
+        if (ESpecType != EST_None)
+          DeclEndLoc = ESpecRange.getEnd();
+
+        // Parse attribute-specifier[opt].
+        MaybeParseCXX11Attributes(Attr, &DeclEndLoc);
+
+        // Parse OpenCL addr space attribute.
+        if (Tok.isOneOf(tok::kw___private, tok::kw___global, tok::kw___local,
+                        tok::kw___constant, tok::kw___generic)) {
+          ParseOpenCLQualifiers(DS.getAttributes());
+          ConsumeToken();
+        }
+
+        SourceLocation FunLocalRangeEnd = DeclEndLoc;
+
+        // Parse trailing-return-type[opt].
+        if (Tok.is(tok::arrow)) {
+          FunLocalRangeEnd = Tok.getLocation();
+          SourceRange Range;
+          TrailingReturnType = ParseTrailingReturnType(
+              Range, /*MayBeFollowedByDirectInit*/ false);
+          TrailingReturnTypeLoc = Range.getBegin();
+          if (Range.getEnd().isValid())
+            DeclEndLoc = Range.getEnd();
+        }
+
+        SourceLocation NoLoc;
+        D.AddTypeInfo(
+            DeclaratorChunk::getFunction(
+                /*HasProto=*/true,
+                /*IsAmbiguous=*/false, LParenLoc, ParamInfo.data(),
+                ParamInfo.size(), EllipsisLoc, RParenLoc,
+                /*RefQualifierIsLvalueRef=*/true,
+                /*RefQualifierLoc=*/NoLoc, MutableLoc, ESpecType, ESpecRange,
+                DynamicExceptions.data(), DynamicExceptionRanges.data(),
+                DynamicExceptions.size(),
+                NoexceptExpr.isUsable() ? NoexceptExpr.get() : nullptr,
+                /*ExceptionSpecTokens*/ nullptr,
+                /*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)) {
-    ParseScope PrototypeScope(this,
-                              Scope::FunctionPrototypeScope |
-                              Scope::FunctionDeclarationScope |
-                              Scope::DeclScope);
+    ParseScope PrototypeScope(this, Scope::FunctionPrototypeScope |
+                                        Scope::FunctionDeclarationScope |
+                                        Scope::DeclScope);
 
     BalancedDelimiterTracker T(*this, tok::l_paren);
     T.consumeOpen();
@@ -1345,86 +1430,20 @@
     }
 
     T.consumeClose();
-    SourceLocation RParenLoc = T.getCloseLocation();
-    SourceLocation DeclEndLoc = RParenLoc;
-
-    // GNU-style attributes must be parsed before the mutable specifier to be
-    // compatible with GCC. MSVC-style attributes must be parsed before the
-    // mutable specifier to be compatible with MSVC.
-    MaybeParseAttributes(PAKM_GNU | PAKM_Declspec, Attr);
-
-    // Parse mutable-opt and/or constexpr-opt or consteval-opt, and update the
-    // DeclEndLoc.
-    SourceLocation MutableLoc;
-    SourceLocation ConstexprLoc;
-    SourceLocation ConstevalLoc;
-    tryConsumeLambdaSpecifierToken(*this, MutableLoc, ConstexprLoc,
-                                   ConstevalLoc, DeclEndLoc);
-
-    addConstexprToLambdaDeclSpecifier(*this, ConstexprLoc, DS);
-    addConstevalToLambdaDeclSpecifier(*this, ConstevalLoc, DS);
-    // Parse exception-specification[opt].
-    ExceptionSpecificationType ESpecType = EST_None;
-    SourceRange ESpecRange;
-    SmallVector<ParsedType, 2> DynamicExceptions;
-    SmallVector<SourceRange, 2> DynamicExceptionRanges;
-    ExprResult NoexceptExpr;
-    CachedTokens *ExceptionSpecTokens;
-    ESpecType = tryParseExceptionSpecification(/*Delayed=*/false,
-                                               ESpecRange,
-                                               DynamicExceptions,
-                                               DynamicExceptionRanges,
-                                               NoexceptExpr,
-                                               ExceptionSpecTokens);
-
-    if (ESpecType != EST_None)
-      DeclEndLoc = ESpecRange.getEnd();
-
-    // Parse attribute-specifier[opt].
-    MaybeParseCXX11Attributes(Attr, &DeclEndLoc);
-
-    // Parse OpenCL addr space attribute.
-    if (Tok.isOneOf(tok::kw___private, tok::kw___global, tok::kw___local,
-                    tok::kw___constant, tok::kw___generic)) {
-      ParseOpenCLQualifiers(DS.getAttributes());
-      ConsumeToken();
-    }
 
-    SourceLocation FunLocalRangeEnd = DeclEndLoc;
-
-    // Parse trailing-return-type[opt].
-    if (Tok.is(tok::arrow)) {
-      FunLocalRangeEnd = Tok.getLocation();
-      SourceRange Range;
-      TrailingReturnType =
-          ParseTrailingReturnType(Range, /*MayBeFollowedByDirectInit*/ false);
-      TrailingReturnTypeLoc = Range.getBegin();
-      if (Range.getEnd().isValid())
-        DeclEndLoc = Range.getEnd();
-    }
+    // Parse lambda-specifiers.
+    ParseLambdaSpecifiers(LParenLoc, /*DeclEndLoc=*/T.getCloseLocation(),
+                          ParamInfo, EllipsisLoc);
+  } else if (getLangOpts().CPlusPlus2b) {
+    ParseScope PrototypeScope(this, Scope::FunctionPrototypeScope |
+                                        Scope::FunctionDeclarationScope |
+                                        Scope::DeclScope);
 
     SourceLocation NoLoc;
-    D.AddTypeInfo(DeclaratorChunk::getFunction(
-                      /*HasProto=*/true,
-                      /*IsAmbiguous=*/false, LParenLoc, ParamInfo.data(),
-                      ParamInfo.size(), EllipsisLoc, RParenLoc,
-                      /*RefQualifierIsLvalueRef=*/true,
-                      /*RefQualifierLoc=*/NoLoc, MutableLoc, ESpecType,
-                      ESpecRange, DynamicExceptions.data(),
-                      DynamicExceptionRanges.data(), DynamicExceptions.size(),
-                      NoexceptExpr.isUsable() ? NoexceptExpr.get() : nullptr,
-                      /*ExceptionSpecTokens*/ nullptr,
-                      /*DeclsInPrototype=*/None, LParenLoc, FunLocalRangeEnd, D,
-                      TrailingReturnType, TrailingReturnTypeLoc, &DS),
-                  std::move(Attr), DeclEndLoc);
-
-    // Parse requires-clause[opt].
-    if (Tok.is(tok::kw_requires))
-      ParseTrailingRequiresClause(D);
-
-    PrototypeScope.Exit();
-
-    WarnIfHasCUDATargetAttr();
+    // Parse lambda-specifiers.
+    std::vector<DeclaratorChunk::ParamInfo> EmptyParamInfo;
+    ParseLambdaSpecifiers(/*LParenLoc=*/NoLoc, /*RParenLoc=*/NoLoc,
+                          EmptyParamInfo, /*EllipsisLoc=*/NoLoc);
   } 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,
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to