Message ID | 20200317082819.GU2156@tucnak |
---|---|
State | New |
Headers | show |
Series | [v3] c++: Fix parsing of invalid enum specifiers [PR90995] | expand |
On 3/17/20 4:28 AM, Jakub Jelinek wrote: > On Mon, Mar 16, 2020 at 06:01:25PM -0400, Jason Merrill wrote: >>> - 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. > > Seems to work too. Bootstrapped/regtested on x86_64-linux and i686-linux, > ok for trunk? OK, thanks. > 2020-03-17 Jakub Jelinek <jakub@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 cp_parser_commit_to_tentative_parse before calling > cp_parser_error and make sure to return error_mark_node instead of > NULL_TREE. 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-17 07:57:19.195642249 +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); > @@ -19140,23 +19138,21 @@ cp_parser_enum_specifier (cp_parser* par > { > if (cxx_dialect < cxx11 || (!scoped_enum_p && !underlying_type)) > { > + if (has_underlying_type) > + cp_parser_commit_to_tentative_parse (parser); > cp_parser_error (parser, "expected %<{%>"); > if (has_underlying_type) > - { > - type = NULL_TREE; > - goto out; > - } > + return error_mark_node; > } > /* An opaque-enum-specifier must have a ';' here. */ > if ((scoped_enum_p || underlying_type) > && cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON)) > { > + if (has_underlying_type) > + cp_parser_commit_to_tentative_parse (parser); > cp_parser_error (parser, "expected %<;%> or %<{%>"); > if (has_underlying_type) > - { > - type = NULL_TREE; > - goto out; > - } > + return error_mark_node; > } > } > > @@ -19172,9 +19168,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 +19328,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 >
--- gcc/cp/parser.c.jj 2020-03-14 08:14:47.125740994 +0100 +++ gcc/cp/parser.c 2020-03-17 07:57:19.195642249 +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); @@ -19140,23 +19138,21 @@ cp_parser_enum_specifier (cp_parser* par { if (cxx_dialect < cxx11 || (!scoped_enum_p && !underlying_type)) { + if (has_underlying_type) + cp_parser_commit_to_tentative_parse (parser); cp_parser_error (parser, "expected %<{%>"); if (has_underlying_type) - { - type = NULL_TREE; - goto out; - } + return error_mark_node; } /* An opaque-enum-specifier must have a ';' here. */ if ((scoped_enum_p || underlying_type) && cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON)) { + if (has_underlying_type) + cp_parser_commit_to_tentative_parse (parser); cp_parser_error (parser, "expected %<;%> or %<{%>"); if (has_underlying_type) - { - type = NULL_TREE; - goto out; - } + return error_mark_node; } } @@ -19172,9 +19168,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 +19328,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" } +}