On Thu, Nov 18, 2021 at 09:55:52PM +0000, Joseph Myers wrote:
> On Thu, 18 Nov 2021, Jakub Jelinek via Gcc-patches wrote:
> 
> > Are we handling the pragma at a wrong phase of preprocessing?
> 
> I think that converting it to a single preprocessing token (rather than 
> four separate preprocessing tokens), at a stage when stringizing might 
> still occur, does indicate it's being processed too soon, and it would be 
> better to do that only when it's known that the _Pragma preprocessing 
> token will actually occur in the results of preprocessing the source file.

So like this?  I.e. don't process _Pragma during expand_args where we can't
know what the macro will do with it?

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2021-11-22  Jakub Jelinek  <ja...@redhat.com>
            Tobias Burnus  <tob...@codesourcery.com>

        PR preprocessor/103165
libcpp/
        * internal.h (struct lexer_state): Add ignore__Pragma field.
        * macro.c (builtin_macro): Don't interpret _Pragma if
        pfile->state.ignore__Pragma.
        (expand_arg): Temporarily set pfile->state.ignore__Pragma to 1.
gcc/testsuite/
        * c-c++-common/gomp/pragma-3.c: New test.
        * c-c++-common/gomp/pragma-4.c: New test.
        * c-c++-common/gomp/pragma-5.c: New test.

--- libcpp/internal.h.jj        2021-11-18 12:33:18.409679558 +0100
+++ libcpp/internal.h   2021-11-20 11:00:58.044399990 +0100
@@ -287,6 +287,9 @@ struct lexer_state
 
   /* Nonzero if the deferred pragma being handled allows macro expansion.  */
   unsigned char pragma_allow_expansion;
+
+  /* Nonzero if _Pragma should not be interpreted.  */
+  unsigned char ignore__Pragma;
 };
 
 /* Special nodes - identifiers with predefined significance.  */
--- libcpp/macro.c.jj   2021-11-18 12:33:18.462678802 +0100
+++ libcpp/macro.c      2021-11-20 11:02:03.249478159 +0100
@@ -750,8 +750,10 @@ builtin_macro (cpp_reader *pfile, cpp_ha
   if (node->value.builtin == BT_PRAGMA)
     {
       /* Don't interpret _Pragma within directives.  The standard is
-         not clear on this, but to me this makes most sense.  */
-      if (pfile->state.in_directive)
+         not clear on this, but to me this makes most sense.
+         Similarly, don't interpret _Pragma inside expand_args, we might
+         need to stringize it later on.  */
+      if (pfile->state.in_directive || pfile->state.ignore__Pragma)
        return 0;
 
       return _cpp_do__Pragma (pfile, loc);
@@ -2648,6 +2650,7 @@ expand_arg (cpp_reader *pfile, macro_arg
   size_t capacity;
   bool saved_warn_trad;
   bool track_macro_exp_p = CPP_OPTION (pfile, track_macro_expansion);
+  bool saved_ignore__Pragma;
 
   if (arg->count == 0
       || arg->expanded != NULL)
@@ -2670,6 +2673,9 @@ expand_arg (cpp_reader *pfile, macro_arg
     push_ptoken_context (pfile, NULL, NULL,
                         arg->first, arg->count + 1);
 
+  saved_ignore__Pragma = pfile->state.ignore__Pragma;
+  pfile->state.ignore__Pragma = 1;
+
   for (;;)
     {
       const cpp_token *token;
@@ -2692,6 +2698,7 @@ expand_arg (cpp_reader *pfile, macro_arg
   _cpp_pop_context (pfile);
 
   CPP_WTRADITIONAL (pfile) = saved_warn_trad;
+  pfile->state.ignore__Pragma = saved_ignore__Pragma;
 }
 
 /* Returns the macro associated to the current context if we are in
--- gcc/testsuite/c-c++-common/gomp/pragma-3.c.jj       2021-11-20 
11:04:27.636429378 +0100
+++ gcc/testsuite/c-c++-common/gomp/pragma-3.c  2021-11-20 11:27:46.892589048 
+0100
@@ -0,0 +1,20 @@
+/* { dg-additional-options "-fdump-tree-original" }  */
+/* PR preprocessor/103165  */
+
+#define inner(...) #__VA_ARGS__ ; _Pragma("omp error severity(warning) message 
(\"Test\") at(compilation)")
+#define outer(...) inner(__VA_ARGS__)
+
+void
+f (void)
+{
+  const char *str = outer(inner(1,2));  /* { dg-warning "'pragma omp error' 
encountered: Test" } */
+}
+
+#if 0
+After preprocessing, the expected result are the following three lines:
+     const char *str = "\"1,2\" ; _Pragma(\"omp error severity(warning) 
message (\\\"Test\\\") at(compilation)\")" ;
+#pragma omp error severity(warning) message ("Test") at(compilation)
+                                     ;
+#endif
+
+/* { dg-final { scan-tree-dump "const char \\* str = \\(const char \\*\\) 
\"\\\\\"1,2\\\\\" ; _Pragma\\(\\\\\"omp error severity\\(warning\\) message 
\\(\\\\\\\\\\\\\"Test\\\\\\\\\\\\\"\\) at\\(compilation\\)\\\\\"\\)\";" 
"original" } }  */
--- gcc/testsuite/c-c++-common/gomp/pragma-4.c.jj       2021-11-20 
11:04:35.355319742 +0100
+++ gcc/testsuite/c-c++-common/gomp/pragma-4.c  2021-11-20 11:28:22.995078169 
+0100
@@ -0,0 +1,20 @@
+/* { dg-additional-options "-fdump-tree-original -save-temps" }  */
+/* PR preprocessor/103165  */
+
+#define inner(...) #__VA_ARGS__ ; _Pragma("omp error severity(warning) message 
(\"Test\") at(compilation)")
+#define outer(...) inner(__VA_ARGS__)
+
+void
+f (void)
+{
+  const char *str = outer(inner(1,2));  /* { dg-warning "'pragma omp error' 
encountered: Test" } */
+}
+
+#if 0
+After preprocessing, the expected result are the following three lines:
+     const char *str = "\"1,2\" ; _Pragma(\"omp error severity(warning) 
message (\\\"Test\\\") at(compilation)\")" ;
+#pragma omp error severity(warning) message ("Test") at(compilation)
+                                     ;
+#endif
+
+/* { dg-final { scan-tree-dump "const char \\* str = \\(const char \\*\\) 
\"\\\\\"1,2\\\\\" ; _Pragma\\(\\\\\"omp error severity\\(warning\\) message 
\\(\\\\\\\\\\\\\"Test\\\\\\\\\\\\\"\\) at\\(compilation\\)\\\\\"\\)\";" 
"original" } }  */
--- gcc/testsuite/c-c++-common/gomp/pragma-5.c.jj       2021-11-20 
11:05:22.855645064 +0100
+++ gcc/testsuite/c-c++-common/gomp/pragma-5.c  2021-11-20 11:30:33.777227520 
+0100
@@ -0,0 +1,20 @@
+/* { dg-additional-options "-fdump-tree-original" }  */
+/* PR preprocessor/103165  */
+
+#define inner(...) #__VA_ARGS__ ; _Pragma   (  "   omp         error severity  
 (warning)      message (\"Test\") at(compilation)" )
+#define outer(...) inner(__VA_ARGS__)
+
+void
+f (void)
+{
+  const char *str = outer(inner(1,2));  /* { dg-warning "'pragma omp error' 
encountered: Test" } */
+}
+
+#if 0
+After preprocessing, the expected result are the following three lines:
+     const char *str = "\"1,2\" ; _Pragma ( \"   omp           error severity  
 (warning)      message (\\\"Test\\\") at(compilation)\" )" ;
+#pragma omp error severity(warning) message ("Test") at(compilation)
+                                     ;
+#endif
+
+/* { dg-final { scan-tree-dump "const char \\* str = \\(const char \\*\\) 
\"\\\\\"1,2\\\\\" ; _Pragma \\( \\\\\"   omp\\\\t\\\\terror severity   
\\(warning\\)\\\\tmessage \\(\\\\\\\\\\\\\"Test\\\\\\\\\\\\\"\\) 
at\\(compilation\\)\\\\\" \\)\";" "original" } }  */


        Jakub

Reply via email to