Presently, the code to handle OpenMP attribute-syntax pragmas in the C front end assumes nothing else is messing with redirecting parser->tokens, and makes no provision for restoring it from anything other than parser->tokens_buf when the buffer allocated for the pragma is exhausted. Adding support for metadirectives will change that, since it also needs to buffer tokens for the metadirective alternatives, and an attribute-syntax directive can appear inside a metadirective.
This patch adds a more general save/restore mechanism attached to the parser via a pointer to a new struct omp_attribute_pragma_state. gcc/c/ChangeLog * c-parser.cc (struct c_parser): Change in_omp_attribute_pragma field to be of type struct omp_attribute_pragma_state. (struct omp_attribute_pragma_state): New. (c_parser_skip_until_found): Use the new way to restore state on EOF. (c_parser_skip_to_pragma_eol): Likewise. (c_parser_handle_statement_omp_attributes): Create an omp_attribute_pragma_state to hold the restore state. (omp_maybe_parse_omp_decl): Likewise. --- gcc/c/c-parser.cc | 45 +++++++++++++++++++++++++++++++++------------ 1 file changed, 33 insertions(+), 12 deletions(-) diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc index 04f24f1f30d..7c318f5d17f 100644 --- a/gcc/c/c-parser.cc +++ b/gcc/c/c-parser.cc @@ -262,13 +262,24 @@ struct GTY(()) c_parser { struct omp_for_parse_data * GTY((skip)) omp_for_parse_state; /* If we're in the context of OpenMP directives written as C23 - attributes turned into pragma, vector of tokens created from that, - otherwise NULL. */ - vec<c_token, va_gc> *in_omp_attribute_pragma; + attributes turned into pragma, the tokens field is temporarily + redirected. This holds data needed to restore state afterwards. + It's NULL otherwise. */ + struct omp_attribute_pragma_state *in_omp_attribute_pragma; /* Set for omp::decl attribute parsing to the decl to which it appertains. */ tree in_omp_decl_attribute; + +}; + +/* Holds data needed to restore the token stream to its previous state + after parsing an OpenMP attribute-syntax pragma. */ +struct GTY(()) omp_attribute_pragma_state +{ + vec<c_token, va_gc> *token_vec; + c_token * GTY((skip)) save_tokens; + unsigned int save_tokens_avail; }; /* Return a pointer to the Nth token in PARSERs tokens_buf. */ @@ -1312,8 +1323,9 @@ c_parser_skip_until_found (c_parser *parser, c_token *token = c_parser_peek_token (parser); if (token->type == CPP_EOF) { - parser->tokens = &parser->tokens_buf[0]; - parser->tokens_avail = token->flags; + parser->tokens = parser->in_omp_attribute_pragma->save_tokens; + parser->tokens_avail + = parser->in_omp_attribute_pragma->save_tokens_avail; parser->in_omp_attribute_pragma = NULL; } } @@ -1335,8 +1347,9 @@ c_parser_skip_until_found (c_parser *parser, c_token *token = c_parser_peek_token (parser); if (token->type == CPP_EOF) { - parser->tokens = &parser->tokens_buf[0]; - parser->tokens_avail = token->flags; + parser->tokens = parser->in_omp_attribute_pragma->save_tokens; + parser->tokens_avail + = parser->in_omp_attribute_pragma->save_tokens_avail; parser->in_omp_attribute_pragma = NULL; } } @@ -1429,8 +1442,9 @@ c_parser_skip_to_pragma_eol (c_parser *parser, bool error_if_not_eol = true) c_token *token = c_parser_peek_token (parser); if (token->type == CPP_EOF) { - parser->tokens = &parser->tokens_buf[0]; - parser->tokens_avail = token->flags; + parser->tokens = parser->in_omp_attribute_pragma->save_tokens; + parser->tokens_avail + = parser->in_omp_attribute_pragma->save_tokens_avail; parser->in_omp_attribute_pragma = NULL; } } @@ -7152,7 +7166,6 @@ c_parser_handle_statement_omp_attributes (c_parser *parser, tree &attrs, return false; unsigned int tokens_avail = parser->tokens_avail; - gcc_assert (parser->tokens == &parser->tokens_buf[0]); tokens++; vec<c_token, va_gc> *toks = NULL; @@ -7187,9 +7200,13 @@ c_parser_handle_statement_omp_attributes (c_parser *parser, tree &attrs, tok.flags = tokens_avail; toks->quick_push (tok); + gcc_assert (!parser->in_omp_attribute_pragma); + parser->in_omp_attribute_pragma = ggc_alloc<omp_attribute_pragma_state> (); + parser->in_omp_attribute_pragma->token_vec = toks; + parser->in_omp_attribute_pragma->save_tokens = parser->tokens; + parser->in_omp_attribute_pragma->save_tokens_avail = tokens_avail; parser->tokens = toks->address (); parser->tokens_avail = tokens; - parser->in_omp_attribute_pragma = toks; return true; } @@ -27166,9 +27183,13 @@ c_maybe_parse_omp_decl (tree decl, tree d) tok.flags = tokens_avail; toks->quick_push (tok); parser->in_omp_decl_attribute = decl; + gcc_assert (!parser->in_omp_attribute_pragma); + parser->in_omp_attribute_pragma = ggc_alloc<omp_attribute_pragma_state> (); + parser->in_omp_attribute_pragma->token_vec = toks; + parser->in_omp_attribute_pragma->save_tokens = parser->tokens; + parser->in_omp_attribute_pragma->save_tokens_avail = tokens_avail; parser->tokens = toks->address (); parser->tokens_avail = toks->length (); - parser->in_omp_attribute_pragma = toks; c_parser_pragma (parser, pragma_external, NULL, NULL_TREE); parser->in_omp_decl_attribute = NULL_TREE; return true; -- 2.25.1