Message ID | Yizy4DxkpTk22v7i@tucnak |
---|---|
State | New |
Headers | show |
Series | c++: Fix up cp_parser_skip_to_pragma_eol [PR104623] | expand |
On 3/12/22 14:22, Jakub Jelinek wrote: > Hi! > > We ICE on the following testcase, because we tentatively parse it multiple > times and the erroneous attribute syntax results in > cp_parser_skip_to_end_of_statement, which when seeing CPP_PRAGMA (can be > any deferred one, OpenMP/OpenACC/ivdep etc.) it calls > cp_parser_skip_to_pragma_eol, which calls cp_lexer_purge_tokens_after. > That call purges all the tokens from CPP_PRAGMA until CPP_PRAGMA_EOL, > excluding the initial CPP_PRAGMA though (but including the final > CPP_PRAGMA_EOL). This means the second time we parse this, we see > CPP_PRAGMA with no tokens after it from the pragma, most importantly > not the CPP_PRAGMA_EOL, so either if it is the last pragma in the TU, > we ICE, or if there are other pragmas we treat everything in between > as a pragma. > > I've tried various things, including making the CPP_PRAGMA token > itself also purged, or changing the cp_parser_skip_to_end_of_statement > (and cp_parser_skip_to_end_of_block_or_statement) to call it with > NULL instead of token, so that this purging isn't done there, > but each patch resulted in lots of regressions. > But removing the purging altogether surprisingly doesn't regress anything, > and I think it is the right thing, if we e.g. parse tentatively, why can't > we parse the pragma multiple times or at least skip over it? > > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? OK. The purging seems to date back to rth's r109336 that introduced CPP_PRAGMA. > 2022-03-12 Jakub Jelinek <jakub@redhat.com> > > PR c++/104623 > * parser.cc (cp_parser_skip_to_pragma_eol): Don't purge any tokens. > > * g++.dg/gomp/pr104623.C: New test. > > --- gcc/cp/parser.cc.jj 2022-03-11 13:11:53.622094878 +0100 > +++ gcc/cp/parser.cc 2022-03-11 14:45:36.877647173 +0100 > @@ -4111,8 +4111,6 @@ cp_parser_skip_to_pragma_eol (cp_parser* > > if (pragma_tok) > { > - /* Ensure that the pragma is not parsed again. */ > - cp_lexer_purge_tokens_after (parser->lexer, pragma_tok); > parser->lexer->in_pragma = false; > if (parser->lexer->in_omp_attribute_pragma > && cp_lexer_next_token_is (parser->lexer, CPP_EOF)) > --- gcc/testsuite/g++.dg/gomp/pr104623.C.jj 2022-03-11 14:22:15.724288282 +0100 > +++ gcc/testsuite/g++.dg/gomp/pr104623.C 2022-03-11 14:22:06.746413835 +0100 > @@ -0,0 +1,9 @@ > +// PR c++/104623 > +// { dg-do compile } > + > +void > +foo () > +{ > + struct __attribute__() a // { dg-error "expected primary-expression before" } > + #pragma omp task > +} > > Jakub >
--- gcc/cp/parser.cc.jj 2022-03-11 13:11:53.622094878 +0100 +++ gcc/cp/parser.cc 2022-03-11 14:45:36.877647173 +0100 @@ -4111,8 +4111,6 @@ cp_parser_skip_to_pragma_eol (cp_parser* if (pragma_tok) { - /* Ensure that the pragma is not parsed again. */ - cp_lexer_purge_tokens_after (parser->lexer, pragma_tok); parser->lexer->in_pragma = false; if (parser->lexer->in_omp_attribute_pragma && cp_lexer_next_token_is (parser->lexer, CPP_EOF)) --- gcc/testsuite/g++.dg/gomp/pr104623.C.jj 2022-03-11 14:22:15.724288282 +0100 +++ gcc/testsuite/g++.dg/gomp/pr104623.C 2022-03-11 14:22:06.746413835 +0100 @@ -0,0 +1,9 @@ +// PR c++/104623 +// { dg-do compile } + +void +foo () +{ + struct __attribute__() a // { dg-error "expected primary-expression before" } + #pragma omp task +}