Fix parse/no-type-defn1.C with -std=c++1z.
authorJason Merrill <jason@redhat.com>
Mon, 7 Dec 2015 04:35:14 +0000 (23:35 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Mon, 7 Dec 2015 04:35:14 +0000 (23:35 -0500)
* parser.c (struct tentative_firewall): New.
(cp_parser_template_id, cp_parser_decltype_expr): Use it.

From-SVN: r231354

gcc/cp/ChangeLog
gcc/cp/parser.c
gcc/testsuite/g++.dg/parse/no-type-defn1.C

index ca9b97cba47a0fc0828fbedb5f5d0070ad75cad5..c4daf75d3946d3c9e69d86a62717ba8f146279ce 100644 (file)
@@ -1,5 +1,8 @@
 2015-12-06  Jason Merrill  <jason@redhat.com>
 
+       * parser.c (struct tentative_firewall): New.
+       (cp_parser_template_id, cp_parser_decltype_expr): Use it.
+
        * parser.h (struct cp_token): Tell GTY that CPP_DECLTYPE uses
        tree_check_value.
        * parser.c (cp_parser_decltype): Use tree_check_value.
index ce5a21a759a36fa82f1f40726d4a95042c5c9bb6..3e90f11dc0374a9ee1598db80823532b2d0ba1ac 100644 (file)
@@ -4326,6 +4326,43 @@ cp_parser_end_tentative_firewall (cp_parser *parser, cp_token_position start,
   cp_lexer_purge_tokens_after (parser->lexer, start);
 }
 
+/* Like the above functions, but let the user modify the tokens.  Used by
+   CPP_DECLTYPE and CPP_TEMPLATE_ID, where we are saving the side-effects for
+   later parses, so it makes sense to localize the effects of
+   cp_parser_commit_to_tentative_parse.  */
+
+struct tentative_firewall
+{
+  cp_parser *parser;
+  bool set;
+
+  tentative_firewall (cp_parser *p): parser(p)
+  {
+    /* If we're currently parsing tentatively, start a committed level as a
+       firewall and then an inner tentative parse.  */
+    if ((set = cp_parser_uncommitted_to_tentative_parse_p (parser)))
+      {
+       cp_parser_parse_tentatively (parser);
+       cp_parser_commit_to_topmost_tentative_parse (parser);
+       cp_parser_parse_tentatively (parser);
+      }
+  }
+
+  ~tentative_firewall()
+  {
+    if (set)
+      {
+       /* Finish the inner tentative parse and the firewall, propagating any
+          uncommitted error state to the outer tentative parse.  */
+       bool err = cp_parser_error_occurred (parser);
+       cp_parser_parse_definitely (parser);
+       cp_parser_parse_definitely (parser);
+       if (err)
+         cp_parser_simulate_error (parser);
+      }
+  }
+};
+
 /* Parse a GNU statement-expression, i.e. ({ stmts }), except for the
    enclosing parentheses.  */
 
@@ -12921,6 +12958,11 @@ cp_parser_decltype_expr (cp_parser *parser,
   cp_token *id_expr_start_token;
   tree expr;
 
+  /* Since we're going to preserve any side-effects from this parse, set up a
+     firewall to protect our callers from cp_parser_commit_to_tentative_parse
+     in the expression.  */
+  tentative_firewall firewall (parser);
+
   /* First, try parsing an id-expression.  */
   id_expr_start_token = cp_lexer_peek_token (parser->lexer);
   cp_parser_parse_tentatively (parser);
@@ -14687,6 +14729,11 @@ cp_parser_template_id (cp_parser *parser,
       return templ;
     }
 
+  /* Since we're going to preserve any side-effects from this parse, set up a
+     firewall to protect our callers from cp_parser_commit_to_tentative_parse
+     in the template arguments.  */
+  tentative_firewall firewall (parser);
+
   /* If we find the sequence `[:' after a template-name, it's probably
      a digraph-typo for `< ::'. Substitute the tokens and check if we can
      parse correctly the argument list.  */
index 9e899579ef64c195326d9c8f86bff4ecc033b78d..a8d6ad88ae0a20fc38784596476965c934c1e918 100644 (file)
@@ -3,3 +3,5 @@
 template<typename> struct A { };
 A< struct B { }* >::SomeNonSense // { dg-error "types may not be defined" }
 int y;
+
+// { dg-prune-output "SomeNonSense" }