[3/6] libcpp: Fix paste error with unknown pragma after macro expansion

Message ID 2222c8ff04699ae5671e1b654aafe5502259feaa.1667514153.git.lhyatt@gmail.com
State Accepted
Headers
Series diagnostics: libcpp: Overhaul locations for _Pragma tokens |

Checks

Context Check Description
snail/gcc-patch-check success Github commit url

Commit Message

Lewis Hyatt Nov. 4, 2022, 1:44 p.m. UTC
  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.
---
 gcc/testsuite/c-c++-common/gomp/pragma-omp-unknown.c | 10 ++++++++++
 libcpp/directives.cc                                 | 10 +++++-----
 2 files changed, 15 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/c-c++-common/gomp/pragma-omp-unknown.c
  

Comments

Jeff Law Nov. 21, 2022, 5:50 p.m. UTC | #1
On 11/4/22 07:44, Lewis Hyatt via Gcc-patches wrote:
> 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.

OK

jeff
  

Patch

diff --git a/gcc/testsuite/c-c++-common/gomp/pragma-omp-unknown.c b/gcc/testsuite/c-c++-common/gomp/pragma-omp-unknown.c
new file mode 100644
index 00000000000..04881f786ab
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/pragma-omp-unknown.c
@@ -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" } } */
diff --git a/libcpp/directives.cc b/libcpp/directives.cc
index 918752f6b1f..9dc4363c65a 100644
--- a/libcpp/directives.cc
+++ b/libcpp/directives.cc
@@ -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);
     }