@@ -1,3 +1,17 @@
+2016-12-29 Zhouyi Zhou <yizhouzhou@ict.ac.cn>
+
+ Simplifying tentative firewalls
+ * parser.c (cp_parser_start_tentative_firewall): Simplifying
+ tentative firewall so that it only do the necessary jobs to
+ guard current context.
+ * parser.c (cp_parser_end_tentative_firewall): Simplifying the
+ end of tentative firewall.
+ * parser.c (tentative_firewall::tentative_firewall): Simplifying
+ tentative firewall so that it only do the necessary jobs to
+ guard current context.
+ * parser.c (tentative_firewall::~tentative_firewall): Simplifying
+ the end of tentative firewall.
+
2016-12-24 Jakub Jelinek <jakub@redhat.com>
PR middle-end/78901
@@ -4424,8 +4424,8 @@ cp_parser_start_tentative_firewall (cp_parser *parser)
if (!cp_parser_uncommitted_to_tentative_parse_p (parser))
return 0;
- cp_parser_parse_tentatively (parser);
- cp_parser_commit_to_topmost_tentative_parse (parser);
+ parser->context = cp_parser_context_new (parser->context);
+ parser->context->status = CP_PARSER_STATUS_KIND_COMMITTED;
return cp_lexer_token_position (parser->lexer, false);
}
@@ -4436,11 +4436,16 @@ static void
cp_parser_end_tentative_firewall (cp_parser *parser, cp_token_position start,
tree expr)
{
+ cp_parser_context *context;
+
if (!start)
return;
/* Finish the firewall level. */
- cp_parser_parse_definitely (parser);
+ context = parser->context;
+ parser->context = context->next;
+ context->next = cp_parser_context_free_list;
+ cp_parser_context_free_list = context;
/* And remember the result of the parse for when we try again. */
cp_token *token = cp_lexer_token_at (parser->lexer, start);
token->type = CPP_PREPARSED_EXPR;
@@ -4465,8 +4470,8 @@ struct tentative_firewall
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);
+ parser->context = cp_parser_context_new (parser->context);
+ parser->context->status = CP_PARSER_STATUS_KIND_COMMITTED;
cp_parser_parse_tentatively (parser);
}
}
@@ -4477,9 +4482,14 @@ struct tentative_firewall
{
/* Finish the inner tentative parse and the firewall, propagating any
uncommitted error state to the outer tentative parse. */
+ cp_parser_context *context;
bool err = cp_parser_error_occurred (parser);
cp_parser_parse_definitely (parser);
- cp_parser_parse_definitely (parser);
+ /* Finish the firewall level. */
+ context = parser->context;
+ parser->context = context->next;
+ context->next = cp_parser_context_free_list;
+ cp_parser_context_free_list = context;
if (err)
cp_parser_simulate_error (parser);
}
I carefully examined the code of setting up tentative firewalls to guard current context in cp/parser.c recent days, and think the code could be simplified. For example, in function cp_parser_start_tentative_firewall, 4427 cp_parser_parse_tentatively (parser); 4428 cp_parser_commit_to_topmost_tentative_parse (parser); A) cp_parser_parse_tentatively does following jobs: 1) create a new context 2) save current token 3) push deferring access B) cp_parser_commit_to_topmost_tentative_parse does following jobs: 1) mark the new context as committed 2) pop current token Clearly saving and popping current token is unneccessary. Push deferring access is also unneccessary after a carefull analysis: In function cp_parser_parse_definitely, error_occurred = cp_parser_error_occurred (parser) will always return false for committed context, so pop_to_parent_deferring_access_checks is always got called, while pushed deferring access in step (A) won't affect the result wether or not the access check should delayed to parent access level. Performance evaluation: orig) perf stat -e instructions:u ../gcc/cc1plus.orig g++.dg/template/friend28.C 59,171,628 instructions:u after) perf stat -e instructions:u ../gcc/cc1plus g++.dg/template/friend28.C 59,171,598 instructions:u bootstrapped and checked on x86-64 Signed-off-by: Zhouyi Zhou <yizhouzhou@ict.ac.cn> --- gcc/cp/ChangeLog | 14 ++++++++++++++ gcc/cp/parser.c | 22 ++++++++++++++++------ 2 files changed, 30 insertions(+), 6 deletions(-)