c++: Fix tentative parsing of enum-specifier [PR96077]
authorMarek Polacek <polacek@redhat.com>
Fri, 10 Jul 2020 00:44:05 +0000 (20:44 -0400)
committerMarek Polacek <polacek@redhat.com>
Mon, 13 Jul 2020 15:16:26 +0000 (11:16 -0400)
Here's an interesting issue: in this code a ) is missing:

  enum { E = (2 } e;

but we compile the code anyway, and E is set to 0 in build_enumerator,
which is sneaky.

The problem is that cp_parser_enum_specifier parses tentatively, because
when we see the enum keyword, we don't know yet if we'll find an
enum-specifier, opaque-enum-declaration, or elaborated-enum-specifier.

In this test when we call cp_parser_enumerator_list we're still parsing
tentatively, and as a consequence, parens.require_close (parser) in
cp_parser_primary_expression doesn't report any errors.  But we only go
on to parse the enumerator-list after we've seen a {, at which point we
might as well commit -- we know we're dealing with an enum-specifier.

gcc/cp/ChangeLog:

PR c++/96077
* parser.c (cp_parser_enum_specifier): Commit to tentative parse
after we've seen an opening brace.

gcc/testsuite/ChangeLog:

PR c++/96077
* g++.dg/parse/enum14.C: New test.

gcc/cp/parser.c
gcc/testsuite/g++.dg/parse/enum14.C [new file with mode: 0644]

index 528b41b717096b07590174003b8a9eeb760f500c..9e32a3c7772f9491c195a39da8600d6232eda537 100644 (file)
@@ -19412,7 +19412,12 @@ cp_parser_enum_specifier (cp_parser* parser)
                     "ISO C++ forbids empty unnamed enum");
        }
       else
-       cp_parser_enumerator_list (parser, type);
+       {
+         /* We've seen a '{' so we know we're in an enum-specifier.
+            Commit to any tentative parse to get syntax errors.  */
+         cp_parser_commit_to_tentative_parse (parser);
+         cp_parser_enumerator_list (parser, type);
+       }
 
       /* Consume the final '}'.  */
       braces.require_close (parser);
diff --git a/gcc/testsuite/g++.dg/parse/enum14.C b/gcc/testsuite/g++.dg/parse/enum14.C
new file mode 100644 (file)
index 0000000..be09cca
--- /dev/null
@@ -0,0 +1,7 @@
+// PR c++/96077
+
+int main ()
+{
+  enum { E = (2 } e; // { dg-error "expected" }
+  enum { F = true ? 2 : (3 /* missing ")" here */ } f; // { dg-error "expected" }
+}