From: jason Date: Mon, 7 Dec 2015 04:35:14 +0000 (+0000) Subject: Fix parse/no-type-defn1.C with -std=c++1z. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a529dea86b45018dd2cc4e3f10d95a97e629c5af;p=thirdparty%2Fgcc.git Fix parse/no-type-defn1.C with -std=c++1z. * parser.c (struct tentative_firewall): New. (cp_parser_template_id, cp_parser_decltype_expr): Use it. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@231354 138bc75d-0d04-0410-961f-82ee72b054a4 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index ca9b97cba47a..c4daf75d3946 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,8 @@ 2015-12-06 Jason Merrill + * 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. diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index ce5a21a759a3..3e90f11dc037 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -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. */ diff --git a/gcc/testsuite/g++.dg/parse/no-type-defn1.C b/gcc/testsuite/g++.dg/parse/no-type-defn1.C index 9e899579ef64..a8d6ad88ae0a 100644 --- a/gcc/testsuite/g++.dg/parse/no-type-defn1.C +++ b/gcc/testsuite/g++.dg/parse/no-type-defn1.C @@ -3,3 +3,5 @@ template struct A { }; A< struct B { }* >::SomeNonSense // { dg-error "types may not be defined" } int y; + +// { dg-prune-output "SomeNonSense" }