On 11/16/18 9:16 PM, Alexandre Oliva wrote: > We used to preserve deferred access check along with resolved template > ids, but a tentative parsing firewall introduced additional layers of > deferred access checks, so that we don't preserve the checks we > want to any more. > > This patch collapses the access check levels introduced by the > firewall with those we wanted to preserve to begin with, saves them, > pushes them one more layer up so that the firewall doesn't drop them, > and then pushes new empty levels so balance out with the upcoming > popping. > > We may want to avoid the pop_to_parent and one push after the save, and > instead leave the firewall's scope before the final pop_to_parent. > However, this patch is what I regression-tested successfully with > check-g++ on x86_64-linux-gnu. Regstrapping on i686- and > x86_64-linux-gnu now. Ok to install? > > > for gcc/cp/ChangeLog > > PR c++/86823 > * parser.c (cp_parser_template_id): Merge access checks from > outside the tentative parsing firewall with those from inside, > and save them all with the template id token. > > for gcc/testsuite/ChangeLog > > PR c++/86823 > * g++.dg/pr86823.C: New. > --- > gcc/cp/parser.c | 12 ++++++++++++ > gcc/testsuite/g++.dg/pr86823.C | 15 +++++++++++++++ > 2 files changed, 27 insertions(+) > create mode 100644 gcc/testsuite/g++.dg/pr86823.C > > diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c > index db0f0338179e..6a08b09715a7 100644 > --- a/gcc/cp/parser.c > +++ b/gcc/cp/parser.c > @@ -16185,7 +16185,19 @@ cp_parser_template_id (cp_parser *parser, > so the memory will not be reclaimed during token replacing below. */ > token->u.tree_check_value = ggc_cleared_alloc (); > token->u.tree_check_value->value = template_id; > + /* Collapse the access check levels introduced by > + tentative_firewall with the one we introduced ourselves. */ > + pop_to_parent_deferring_access_checks (); > + pop_to_parent_deferring_access_checks (); > token->u.tree_check_value->checks = get_deferred_access_checks (); > + /* Push the checks up one more level, so that the firewall > + doesn't drop them on the floor when we return. Then, push > + empty levels back in place so that they are popped > + properly. */ > + pop_to_parent_deferring_access_checks (); > + push_deferring_access_checks (dk_deferred); > + push_deferring_access_checks (dk_deferred); > + push_deferring_access_checks (dk_deferred); Hmm, I'm uncomfortable with how this depends on the specific implementation of tentative_firewall. What do you think of this alternate approach (untested other than with the testcase)? Jason