libcpp: Fix paste error with unknown pragma after macro expansion

In directives.cc, do_pragma() contains logic to handle a case such as the new
testcase pragma-omp-unknown.c, where an unknown pragma was the result of macro
expansion (for pragma namespaces that permit expansion). This no longer works
correctly as shown by the testcase, fixed by adding PREV_WHITE to the flags on
the second token to prevent an unwanted paste.  Also fixed the memory leak,
since the temporary tokens are pushed on their own context, nothing prevents
freeing of the buffer that holds them when the context is eventually popped.

libcpp/ChangeLog:

	* directives.cc (do_pragma): Fix memory leak in token buffer.  Fix
	unwanted paste between two tokens.

gcc/testsuite/ChangeLog:

	* c-c++-common/gomp/pragma-omp-unknown.c: New test.
This commit is contained in:
Lewis Hyatt 2022-11-02 16:04:36 -04:00
parent 5c0d171f67
commit 6f46d14d49
2 changed files with 15 additions and 5 deletions

View file

@ -0,0 +1,10 @@
/* { dg-do preprocess } */
/* { dg-options "-fopenmp" } */
#define X UNKNOWN1
#pragma omp X
/* { dg-final { scan-file pragma-omp-unknown.i "#pragma omp UNKNOWN1" } } */
#define Y UNKNOWN2
_Pragma("omp Y")
/* { dg-final { scan-file pragma-omp-unknown.i "#pragma omp UNKNOWN2" } } */

View file

@ -1565,15 +1565,15 @@ do_pragma (cpp_reader *pfile)
{
/* Invalid name comes from macro expansion, _cpp_backup_tokens
won't allow backing 2 tokens. */
/* ??? The token buffer is leaked. Perhaps if def_pragma hook
reads both tokens, we could perhaps free it, but if it doesn't,
we don't know the exact lifespan. */
cpp_token *toks = XNEWVEC (cpp_token, 2);
const auto tok_buff = _cpp_get_buff (pfile, 2 * sizeof (cpp_token));
const auto toks = (cpp_token *)tok_buff->base;
toks[0] = ns_token;
toks[0].flags |= NO_EXPAND;
toks[1] = *token;
toks[1].flags |= NO_EXPAND;
toks[1].flags |= NO_EXPAND | PREV_WHITE;
_cpp_push_token_context (pfile, NULL, toks, 2);
/* Arrange to free this buffer when no longer needed. */
pfile->context->buff = tok_buff;
}
pfile->cb.def_pragma (pfile, pfile->directive_line);
}