Hi!

In lambdas, the only valid decl specifiers are mutable, constexpr or
consteval.  For various other simple specifiers it is fine to parse them
and reject afterwards if the parsing is simple consuming of a single token
and setting some flags, but as the testcase shows, especially allowing
type specifiers, including new type definitions in there can cause ICEs.
The following patch punts for the cases where the parsing isn't that simple,
which I think is concept, typedef (there we e.g. commit tentative parsing)
or the type specifiers.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok of trunk?

2019-11-19  Jakub Jelinek  <ja...@redhat.com>

        PR c++/90842
        * parser.c (cp_parser_decl_specifier_seq): For concept, typedef
        or type specifier with CP_PARSER_FLAGS_ONLY_MUTABLE_OR_CONSTEXPR
        don't try to parse them at all.

        * g++.dg/cpp1y/lambda-generic-90842.C: New test.
        * g++.dg/cpp0x/lambda/lambda-86550.C: Adjust expected diagnostics.

--- gcc/cp/parser.c.jj  2019-11-14 09:13:24.356104252 +0100
+++ gcc/cp/parser.c     2019-11-19 17:47:24.776014270 +0100
@@ -14094,6 +14094,12 @@ cp_parser_decl_specifier_seq (cp_parser*
          break;
 
         case RID_CONCEPT:
+          if (flags & CP_PARSER_FLAGS_ONLY_MUTABLE_OR_CONSTEXPR)
+            {
+             found_decl_spec = false;
+             break;
+            }
+
           ds = ds_concept;
           cp_lexer_consume_token (parser->lexer);
 
@@ -14136,6 +14142,12 @@ cp_parser_decl_specifier_seq (cp_parser*
          /* decl-specifier:
               typedef  */
        case RID_TYPEDEF:
+          if (flags & CP_PARSER_FLAGS_ONLY_MUTABLE_OR_CONSTEXPR)
+            {
+             found_decl_spec = false;
+             break;
+            }
+
          ds = ds_typedef;
          /* Consume the token.  */
          cp_lexer_consume_token (parser->lexer);
@@ -14229,7 +14241,9 @@ cp_parser_decl_specifier_seq (cp_parser*
 
       /* If we don't have a DECL_SPEC yet, then we must be looking at
         a type-specifier.  */
-      if (!found_decl_spec && !constructor_p)
+      if (!found_decl_spec
+         && !constructor_p
+         && (flags & CP_PARSER_FLAGS_ONLY_MUTABLE_OR_CONSTEXPR) == 0)
        {
          int decl_spec_declares_class_or_enum;
          bool is_cv_qualifier;
@@ -14288,9 +14302,6 @@ cp_parser_decl_specifier_seq (cp_parser*
              found_decl_spec = true;
              if (!is_cv_qualifier)
                decl_specs->any_type_specifiers_p = true;
-
-             if ((flags & CP_PARSER_FLAGS_ONLY_MUTABLE_OR_CONSTEXPR) != 0)
-               error_at (token->location, "type-specifier invalid in lambda");
            }
        }
 
--- gcc/testsuite/g++.dg/cpp1y/lambda-generic-90842.C.jj        2019-11-19 
17:53:37.682440002 +0100
+++ gcc/testsuite/g++.dg/cpp1y/lambda-generic-90842.C   2019-11-19 
17:53:01.815976144 +0100
@@ -0,0 +1,4 @@
+// PR c++/90842
+// { dg-do compile { target c++14 } }
+
+auto a = [](auto x) struct C { void foo (); } {};      // { dg-error 
"expected" }
--- gcc/testsuite/g++.dg/cpp0x/lambda/lambda-86550.C.jj 2018-07-18 
23:01:22.824082949 +0200
+++ gcc/testsuite/g++.dg/cpp0x/lambda/lambda-86550.C    2019-11-19 
17:54:26.978703112 +0100
@@ -4,6 +4,6 @@
 void
 foo ()
 {
-  auto a = []() bool {};                       // { dg-error "type-specifier 
invalid in lambda" }
-  auto b = []() bool bool bool bool int {};    // { dg-error "type-specifier 
invalid in lambda" }
+  auto a = []() bool {};                       // { dg-error "expected" }
+  auto b = []() bool bool bool bool int {};    // { dg-error "expected" }
 }

        Jakub

Reply via email to