aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2015-12-06 23:35:14 -0500
committerJason Merrill <jason@gcc.gnu.org>2015-12-06 23:35:14 -0500
commit1bf2ca0b75a3b6ce72ab4065dbc10b7f80413d4b (patch)
treeafce09c0b85c9dae374e599eab13a28b6d6b0510 /gcc
parentca8e4b87ad6da53a0e8c17227f7ef82e38df66fb (diff)
downloadgcc-1bf2ca0b75a3b6ce72ab4065dbc10b7f80413d4b.zip
gcc-1bf2ca0b75a3b6ce72ab4065dbc10b7f80413d4b.tar.gz
gcc-1bf2ca0b75a3b6ce72ab4065dbc10b7f80413d4b.tar.bz2
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. From-SVN: r231354
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog3
-rw-r--r--gcc/cp/parser.c47
-rw-r--r--gcc/testsuite/g++.dg/parse/no-type-defn1.C2
3 files changed, 52 insertions, 0 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index ca9b97c..c4daf75 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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.
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index ce5a21a..3e90f11 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 9e89957..a8d6ad8 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<typename> struct A { };
A< struct B { }* >::SomeNonSense // { dg-error "types may not be defined" }
int y;
+
+// { dg-prune-output "SomeNonSense" }