c++: Fix parsing of invalid enum specifiers [PR90995]
authorJakub Jelinek <jakub@redhat.com>
Tue, 17 Mar 2020 20:21:16 +0000 (21:21 +0100)
committerJakub Jelinek <jakub@redhat.com>
Tue, 17 Mar 2020 20:21:16 +0000 (21:21 +0100)
commitcd0b71242738a1901405f421b352e4f6c30ff7c5
tree186fb6ceaa448d9aebb7d74359ce993dd9da5c77
parent58a703f0726b3bb6c5ac8b600369106985906590
c++: Fix parsing of invalid enum specifiers [PR90995]

The testcase shows some accepts-invalid (the ones without alignas) and
ice-on-invalid-code (the ones with alignas) cases.
If the enum doesn't have an underlying type and is not a definition,
the caller retries to parse it as elaborated type specifier.
E.g. for enum struct S s it will then pedwarn that elaborated type specifier
shouldn't have the struct/class keywords.
The problem is if the enum specifier is not followed by { when it has
underlying type.  In that case we have already called
cp_parser_parse_definitely to end the tentative parsing started at the
beginning of cp_parser_enum_specifier.  But the
cp_parser_error (parser, "expected %<;%> or %<{%>");
doesn't emit any error because the whole function is called from yet another
tentative parse and the caller starts parsing the elaborated type
specifier where the cp_parser_enum_specifier stopped (i.e. after the
underlying type token(s)).  The ultimate caller than commits the tentative
parsing (and even if it wouldn't, it wouldn't know what kind of error
to report).  I think after seeing enum {,struct,class} : type not being
followed by { or ;, there is no reason not to report it right away, as it
can't be valid C++, which is what the patch does.  Not sure if we shouldn't
also return error_mark_node instead of NULL_TREE, so that the caller doesn't
try to parse it as elaborated type specifier (the patch doesn't do that
right now).

Furthermore, while reading the code, I've noticed that
parser->colon_corrects_to_scope_p is saved and set to false at the start
of the function, but not restored back in some cases.  Don't have a testcase
where this would be a problem, but it just seems wrong.  Either we can in
the two spots replace return NULL_TREE; with { type = NULL_TREE; goto out; }
or we could perhaps abuse warning_sentinel or create a special class with
dtor to clean the flag up.

And lastly, I've fixed some formatting issues in the function while reading
it.

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/ChangeLog
gcc/cp/parser.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/enum40.C [new file with mode: 0644]