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 <yizhouz...@ict.ac.cn> --- gcc/cp/ChangeLog | 14 ++++++++++++++ gcc/cp/parser.c | 22 ++++++++++++++++------ 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 7aca3ac..f095b1d 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,17 @@ +2016-12-29 Zhouyi Zhou <yizhouz...@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 <ja...@redhat.com> PR middle-end/78901 diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index e2a0a49..ebcc802 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -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); } -- 1.9.1