On 3/15/20 7:35 PM, Jakub Jelinek wrote:
On Sun, Mar 15, 2020 at 05:21:59PM -0400, Jason Merrill wrote:
Let's use temp_override.

So like this?

Yes, thanks.

Bootstrapped/regtested on x86_64-linux and i686-linux.

2020-03-15  Jakub Jelinek  <ja...@redhat.com>

        PR c++/90995
        * parser.c (cp_parser_enum_specifier): Use temp_override for
        parser->colon_corrects_to_scope_p, replace goto out with return.
        If scoped enum or enum with underlying type is not followed by
        { or ;, call error_at rather than cp_parser_error.  Formatting fixes.

        * g++.dg/cpp0x/enum40.C: New test.

--- gcc/cp/parser.c.jj  2020-03-14 08:14:47.125740994 +0100
+++ gcc/cp/parser.c     2020-03-15 22:39:09.003266300 +0100
@@ -19001,9 +19001,7 @@ cp_parser_enum_specifier (cp_parser* par
    bool is_unnamed = false;
    tree underlying_type = NULL_TREE;
    cp_token *type_start_token = NULL;
-  bool saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p;
-
-  parser->colon_corrects_to_scope_p = false;
+  temp_override<bool> cleanup (parser->colon_corrects_to_scope_p, false);
/* Parse tentatively so that we can back up if we don't find a
       enum-specifier.  */
@@ -19043,24 +19041,24 @@ cp_parser_enum_specifier (cp_parser* par
push_deferring_access_checks (dk_no_check);
    nested_name_specifier
-      = cp_parser_nested_name_specifier_opt (parser,
-                                            /*typename_keyword_p=*/true,
-                                            /*check_dependency_p=*/false,
-                                            /*type_p=*/false,
-                                            /*is_declaration=*/false);
+    = cp_parser_nested_name_specifier_opt (parser,
+                                          /*typename_keyword_p=*/true,
+                                          /*check_dependency_p=*/false,
+                                          /*type_p=*/false,
+                                          /*is_declaration=*/false);
if (nested_name_specifier)
      {
        tree name;
identifier = cp_parser_identifier (parser);
-      name =  cp_parser_lookup_name (parser, identifier,
-                                    enum_type,
-                                    /*is_template=*/false,
-                                    /*is_namespace=*/false,
-                                    /*check_dependency=*/true,
-                                    /*ambiguous_decls=*/NULL,
-                                    input_location);
+      name = cp_parser_lookup_name (parser, identifier,
+                                   enum_type,
+                                   /*is_template=*/false,
+                                   /*is_namespace=*/false,
+                                   /*check_dependency=*/true,
+                                   /*ambiguous_decls=*/NULL,
+                                   input_location);
        if (name && name != error_mark_node)
        {
          type = TREE_TYPE (name);
@@ -19142,21 +19140,20 @@ cp_parser_enum_specifier (cp_parser* par
        {
          cp_parser_error (parser, "expected %<{%>");
          if (has_underlying_type)
-           {
-             type = NULL_TREE;
-             goto out;
-           }
+           return NULL_TREE;
        }
        /* An opaque-enum-specifier must have a ';' here.  */
        if ((scoped_enum_p || underlying_type)
          && cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
        {
-         cp_parser_error (parser, "expected %<;%> or %<{%>");
          if (has_underlying_type)
            {
-             type = NULL_TREE;
-             goto out;
+             error_at (cp_lexer_peek_token (parser->lexer)->location,
+                       "expected %<;%> or %<{%>");
+             return NULL_TREE;

Hmm, what happens if we commit_to_tentative_parse before the cp_parser_error if has_underlying_type? That would also get us a diagnostic in this case even in enclosing tentative context.

And yes, I think returning error_mark_node seems appropriate; this is an enum-specifier, just an ill-formed one.

            }
+         else
+           cp_parser_error (parser, "expected %<;%> or %<{%>");
        }
      }
@@ -19172,9 +19169,7 @@ cp_parser_enum_specifier (cp_parser* par
          push_scope (nested_name_specifier);
        }
        else if (TREE_CODE (nested_name_specifier) == NAMESPACE_DECL)
-       {
-         push_nested_namespace (nested_name_specifier);
-       }
+       push_nested_namespace (nested_name_specifier);
      }
/* Issue an error message if type-definitions are forbidden here. */
@@ -19334,12 +19329,8 @@ cp_parser_enum_specifier (cp_parser* par
          pop_scope (nested_name_specifier);
        }
        else if (TREE_CODE (nested_name_specifier) == NAMESPACE_DECL)
-       {
-         pop_nested_namespace (nested_name_specifier);
-       }
+       pop_nested_namespace (nested_name_specifier);
      }
- out:
-  parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p;
    return type;
  }
--- gcc/testsuite/g++.dg/cpp0x/enum40.C.jj 2020-03-15 22:35:43.413297557 +0100
+++ gcc/testsuite/g++.dg/cpp0x/enum40.C 2020-03-15 22:35:43.413297557 +0100
@@ -0,0 +1,26 @@
+// PR c++/90995
+// { dg-do compile { target c++11 } }
+
+void
+foo ()
+{
+  enum : int a alignas;                // { dg-error "expected" }
+}
+
+void
+bar ()
+{
+  enum : int a;                        // { dg-error "expected" }
+}
+
+void
+baz ()
+{
+  enum class a : int b alignas;        // { dg-error "expected" }
+}
+
+void
+qux ()
+{
+  enum class a : int b;                // { dg-error "expected" }
+}


        Jakub


Reply via email to