libcpp: Fix _Pragma stringification [PR103165]
As the testcase show, sometimes _Pragma is turned into CPP_PRAGMA .. CPP_PRAGMA_EOL tokens, even when it might still need to be stringized later on. We are then ICEing because we don't handle stringification of CPP_PRAGMA or CPP_PRAGMA_EOL, but trying to reconstruct the exact tokens with exact spacing after it has been lowered is very hard. So, instead this patch ensures we don't lower _Pragma during expand_arg calls, but only later when cpp_get_token_1 is called outside of expand_arg. 2021-11-22 Jakub Jelinek <jakub@redhat.com> Tobias Burnus <tobias@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. Co-Authored-By: Tobias Burnus <tobias@codesourcery.com>
This commit is contained in:
parent
a944b5dec3
commit
a6e0d59370
5 changed files with 72 additions and 2 deletions
20
gcc/testsuite/c-c++-common/gomp/pragma-3.c
Normal file
20
gcc/testsuite/c-c++-common/gomp/pragma-3.c
Normal file
|
@ -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" } } */
|
20
gcc/testsuite/c-c++-common/gomp/pragma-4.c
Normal file
20
gcc/testsuite/c-c++-common/gomp/pragma-4.c
Normal file
|
@ -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" } } */
|
20
gcc/testsuite/c-c++-common/gomp/pragma-5.c
Normal file
20
gcc/testsuite/c-c++-common/gomp/pragma-5.c
Normal file
|
@ -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" } } */
|
|
@ -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. */
|
||||
|
|
|
@ -750,8 +750,10 @@ builtin_macro (cpp_reader *pfile, cpp_hashnode *node,
|
|||
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 *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 *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 *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
|
||||
|
|
Loading…
Add table
Reference in a new issue