From 45f9f14027303630c96496f59f8ad25b1f0a693f Mon Sep 17 00:00:00 2001 From: jakub Date: Fri, 25 Jan 2008 09:01:27 +0000 Subject: [PATCH 1/1] PR preprocessor/34692 * macro.c (collect_args): Add pragma_buff argument. Push CPP_PRAGMA ... CPP_PRAGMA_EOL tokens to *pragma_buff, rather than into arguments. Reset prevent_expansion and parsing_args state at CPP_PRAGMA_EOL/CPP_EOF. (funlike_invocation_p): Add pragma_buff argument, pass it through to collect_args. (enter_macro_context): Add result argument. Adjust funlike_invocation_p caller. Emit all deferred pragma tokens gathered during collect_args before the expansion, add a padding token. Return 2 instead of 1 if any pragma tokens were prepended. (cpp_get_token): If enter_macro_context returns 2, don't return a padding token, instead cycle to grab CPP_PRAGMA token. * directives.c (_cpp_handle_directive): If was_parsing_args in deferred pragma, leave parsing_args and prevent_expansion as is. * gcc.dg/cpp/pr34692.c: New test. * gcc.dg/gomp/pr34692.c: New test. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@131819 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/testsuite/ChangeLog | 6 ++ gcc/testsuite/gcc.dg/cpp/pr34692.c | 35 ++++++++++++ gcc/testsuite/gcc.dg/gomp/pr34692.c | 26 +++++++++ libcpp/ChangeLog | 50 ++++++++++------ libcpp/directives.c | 2 +- libcpp/macro.c | 111 +++++++++++++++++++++++++++++++----- 6 files changed, 199 insertions(+), 31 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/cpp/pr34692.c create mode 100644 gcc/testsuite/gcc.dg/gomp/pr34692.c diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 8705d66744b..a722cb3b309 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2008-01-25 Jakub Jelinek + + PR preprocessor/34692 + * gcc.dg/cpp/pr34692.c: New test. + * gcc.dg/gomp/pr34692.c: New test. + 2008-01-25 Olga Golovanevsky * gcc.dg/struct/wo_prof_malloc_size_var.c: UnXFAIL. diff --git a/gcc/testsuite/gcc.dg/cpp/pr34692.c b/gcc/testsuite/gcc.dg/cpp/pr34692.c new file mode 100644 index 00000000000..bcb0ca33d24 --- /dev/null +++ b/gcc/testsuite/gcc.dg/cpp/pr34692.c @@ -0,0 +1,35 @@ +/* PR preprocessor/34692 */ +/* { dg-do compile } */ +/* { dg-options "" } */ +/* { dg-require-visibility "" } */ +/* { dg-final { scan-hidden "vara" } } */ +/* { dg-final { scan-hidden "varb" } } */ +/* { dg-final { scan-hidden "varc" } } */ +/* { dg-final { scan-hidden "vard" } } */ +/* { dg-final { scan-assembler "a b cde f g h" } } */ + +#define FOO(y, x) y #x +#define BAR(x) x +#define BAZ(x) x +FOO (const char *vara =, +a +#pragma GCC visibility push(hidden) +b +#pragma GCC visibility push(hidden) +cde f g h); +int varb = 6; +#pragma GCC visibility pop +#pragma GCC visibility pop +FOO ( +BAR ( +#pragma GCC visibility push(hidden) +const) char *varc =,); +#pragma GCC visibility pop +FOO ( +BAR ( +BAZ ( +#pragma GCC visibility push(hidden) +#pragma GCC visibility push(hidden) +const) char) *vard =,); +#pragma GCC visibility pop +#pragma GCC visibility pop diff --git a/gcc/testsuite/gcc.dg/gomp/pr34692.c b/gcc/testsuite/gcc.dg/gomp/pr34692.c new file mode 100644 index 00000000000..0e1a1eb827f --- /dev/null +++ b/gcc/testsuite/gcc.dg/gomp/pr34692.c @@ -0,0 +1,26 @@ +/* PR preprocessor/34692 */ +/* { dg-do compile } */ +/* { dg-options "-fopenmp -fdump-tree-gimple" } */ +/* { dg-final { scan-tree-dump-times "#pragma omp parallel" 1 "gimple" } } */ +/* { dg-final { scan-tree-dump-times "#pragma omp for private" 1 "gimple" } } */ + +void +foo (void) +{ + int i; +#define FOO(y, x) y #x +#define BAR(x) x +#define BAZ(x) x +FOO (for (i = 0; i < 10; i++) { const char *vara =, +a +#define P parallel +#pragma omp P +#undef P +#define P for +b +#pragma omp P +#undef P +#define parallel atomic +cde f g h); + } +} diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog index eb2a35cb088..a14c38ef9a9 100644 --- a/libcpp/ChangeLog +++ b/libcpp/ChangeLog @@ -1,12 +1,30 @@ +2008-01-25 Jakub Jelinek + + PR preprocessor/34692 + * macro.c (collect_args): Add pragma_buff argument. Push + CPP_PRAGMA ... CPP_PRAGMA_EOL tokens to *pragma_buff, rather + than into arguments. Reset prevent_expansion and parsing_args + state at CPP_PRAGMA_EOL/CPP_EOF. + (funlike_invocation_p): Add pragma_buff argument, pass it through + to collect_args. + (enter_macro_context): Add result argument. Adjust + funlike_invocation_p caller. Emit all deferred pragma tokens + gathered during collect_args before the expansion, add a padding + token. Return 2 instead of 1 if any pragma tokens were prepended. + (cpp_get_token): If enter_macro_context returns 2, don't return + a padding token, instead cycle to grab CPP_PRAGMA token. + * directives.c (_cpp_handle_directive): If was_parsing_args + in deferred pragma, leave parsing_args and prevent_expansion as is. + 2008-01-22 Tom Tromey - PR c++/34859: + PR c++/34859 * macro.c (_cpp_create_definition): Handle __STDC_LIMIT_MACROS and __STDC_CONSTANT_MACROS. 2008-01-07 Fred Fish - PR preprocessor/30363: + PR preprocessor/30363 * traditional.c (replace_args_and_push): Add local variable cxtquote, calculate the replacement text size assuming a worst case of every input character quoted with backslash, @@ -15,7 +33,7 @@ 2008-01-03 Tom Tromey - PR preprocessor/34602. + PR preprocessor/34602 * directives.c (do_line): Don't try to spell EOF token. (do_linemarker): Add comment. @@ -26,7 +44,7 @@ 2007-12-06 Tom Tromey - PR c/29172: + PR c/29172 * internal.h (struct cpp_reader) : Changed type. : Removed. @@ -43,13 +61,13 @@ 2007-12-03 Tom Tromey - PR preprocessor/34288: + PR preprocessor/34288 * configure.ac, config.in: Rebuilt. * configure.ac: Check for ssize_t. 2007-11-30 Tom Tromey - PR preprocessor/32868: + PR preprocessor/32868 * macro.c (_cpp_create_definition): Special case __STDC_FORMAT_MACROS. @@ -59,7 +77,7 @@ 2007-11-11 Tom Tromey - PR c++/17557: + PR c++/17557 * include/cpplib.h (cpp_included_before): Declare. * files.c (struct file_hash_entry) : New field. (_cpp_find_file): Initialize new field. @@ -68,13 +86,13 @@ 2007-11-01 Tom Tromey - PR preprocessor/30805: + PR preprocessor/30805 * macro.c (paste_tokens): Handle padding token. (paste_tokens): Don't abort unless padding has PASTE_LEFT flag. 2007-10-31 Tom Tromey - PR preprocessor/30786: + PR preprocessor/30786 * macro.c (builtin_macro): Return result of _cpp_do__Pragma. * directives.c (_cpp_do__Pragma): Return error status. * internal.h (_cpp_do__Pragma): Update. @@ -112,7 +130,7 @@ 2007-08-18 Tom Tromey - PR preprocessor/32974: + PR preprocessor/32974 * directives.c (parse_include): Don't check for EOL when processing #pragma dependency. @@ -227,7 +245,7 @@ 2007-05-02 Tom Tromey - PR preprocessor/28709: + PR preprocessor/28709 * macro.c (paste_tokens): Remove PASTE_LEFT from the old lhs. 2007-03-30 Michael Meissner @@ -247,13 +265,13 @@ 2007-01-30 Tom Tromey - PR preprocessor/30468: + PR preprocessor/30468 * mkdeps.c (apply_vpath): Strip successive '/'s if we stripped './'. 2007-01-30 Tom Tromey - PR preprocessor/29966: + PR preprocessor/29966 * macro.c (lex_expansion_token): Save and restore cpp_reader's cur_token. (_cpp_create_definition): Don't restore cur_token here. @@ -265,7 +283,7 @@ 2007-01-12 Tom Tromey - PR preprocessor/28227: + PR preprocessor/28227 * directives.c (lex_macro_node): Added 'is_def_or_undef' argument. (do_define): Update. @@ -283,7 +301,7 @@ 2007-01-04 Tom Tromey - PR preprocessor/28165: + PR preprocessor/28165 * internal.h (cpp_in_primary_file): New function. * directives.c (do_include_next): Use cpp_in_primary_file. (do_pragma_once): Likewise. @@ -302,7 +320,7 @@ 2006-12-28 Tom Tromey - PR preprocessor/30001: + PR preprocessor/30001 * charset.c (_cpp_convert_input): Check that to.len is greater than zero. diff --git a/libcpp/directives.c b/libcpp/directives.c index 6e2e55c5389..c77e84bfec1 100644 --- a/libcpp/directives.c +++ b/libcpp/directives.c @@ -475,7 +475,7 @@ _cpp_handle_directive (cpp_reader *pfile, int indented) _cpp_backup_tokens (pfile, 1); end_directive (pfile, skip); - if (was_parsing_args) + if (was_parsing_args && !pfile->state.in_deferred_pragma) { /* Restore state when within macro args. */ pfile->state.parsing_args = 2; diff --git a/libcpp/macro.c b/libcpp/macro.c index 3a3bf412724..fd624b10110 100644 --- a/libcpp/macro.c +++ b/libcpp/macro.c @@ -41,11 +41,13 @@ struct macro_arg /* Macro expansion. */ -static int enter_macro_context (cpp_reader *, cpp_hashnode *); +static int enter_macro_context (cpp_reader *, cpp_hashnode *, + const cpp_token *); static int builtin_macro (cpp_reader *, cpp_hashnode *); static void push_ptoken_context (cpp_reader *, cpp_hashnode *, _cpp_buff *, const cpp_token **, unsigned int); -static _cpp_buff *collect_args (cpp_reader *, const cpp_hashnode *); +static _cpp_buff *collect_args (cpp_reader *, const cpp_hashnode *, + _cpp_buff **); static cpp_context *next_context (cpp_reader *); static const cpp_token *padding_token (cpp_reader *, const cpp_token *); static void expand_arg (cpp_reader *, macro_arg *); @@ -55,7 +57,8 @@ static void paste_all_tokens (cpp_reader *, const cpp_token *); static bool paste_tokens (cpp_reader *, const cpp_token **, const cpp_token *); static void replace_args (cpp_reader *, cpp_hashnode *, cpp_macro *, macro_arg *); -static _cpp_buff *funlike_invocation_p (cpp_reader *, cpp_hashnode *); +static _cpp_buff *funlike_invocation_p (cpp_reader *, cpp_hashnode *, + _cpp_buff **); static bool create_iso_definition (cpp_reader *, cpp_macro *); /* #define directive parsing and handling. */ @@ -575,9 +578,12 @@ _cpp_arguments_ok (cpp_reader *pfile, cpp_macro *macro, const cpp_hashnode *node invocation. Assumes the opening parenthesis has been processed. If there is an error, emits an appropriate diagnostic and returns NULL. Each argument is terminated by a CPP_EOF token, for the - future benefit of expand_arg(). */ + future benefit of expand_arg(). If there are any deferred + #pragma directives among macro arguments, store pointers to the + CPP_PRAGMA ... CPP_PRAGMA_EOL tokens into *PRAGMA_BUFF buffer. */ static _cpp_buff * -collect_args (cpp_reader *pfile, const cpp_hashnode *node) +collect_args (cpp_reader *pfile, const cpp_hashnode *node, + _cpp_buff **pragma_buff) { _cpp_buff *buff, *base_buff; cpp_macro *macro; @@ -645,6 +651,51 @@ collect_args (cpp_reader *pfile, const cpp_hashnode *node) else if (token->type == CPP_EOF || (token->type == CPP_HASH && token->flags & BOL)) break; + else if (token->type == CPP_PRAGMA) + { + cpp_token *newtok = _cpp_temp_token (pfile); + + /* CPP_PRAGMA token lives in directive_result, which will + be overwritten on the next directive. */ + *newtok = *token; + token = newtok; + do + { + if (*pragma_buff == NULL + || BUFF_ROOM (*pragma_buff) < sizeof (cpp_token *)) + { + _cpp_buff *next; + if (*pragma_buff == NULL) + *pragma_buff + = _cpp_get_buff (pfile, 32 * sizeof (cpp_token *)); + else + { + next = *pragma_buff; + *pragma_buff + = _cpp_get_buff (pfile, + (BUFF_FRONT (*pragma_buff) + - (*pragma_buff)->base) * 2); + (*pragma_buff)->next = next; + } + } + *(const cpp_token **) BUFF_FRONT (*pragma_buff) = token; + BUFF_FRONT (*pragma_buff) += sizeof (cpp_token *); + if (token->type == CPP_PRAGMA_EOL) + break; + token = cpp_get_token (pfile); + } + while (token->type != CPP_EOF); + + /* In deferred pragmas parsing_args and prevent_expansion + had been changed, reset it. */ + pfile->state.parsing_args = 2; + pfile->state.prevent_expansion = 1; + + if (token->type == CPP_EOF) + break; + else + continue; + } arg->first[ntokens++] = token; } @@ -709,9 +760,11 @@ collect_args (cpp_reader *pfile, const cpp_hashnode *node) /* Search for an opening parenthesis to the macro of NODE, in such a way that, if none is found, we don't lose the information in any intervening padding tokens. If we find the parenthesis, collect - the arguments and return the buffer containing them. */ + the arguments and return the buffer containing them. PRAGMA_BUFF + argument is the same as in collect_args. */ static _cpp_buff * -funlike_invocation_p (cpp_reader *pfile, cpp_hashnode *node) +funlike_invocation_p (cpp_reader *pfile, cpp_hashnode *node, + _cpp_buff **pragma_buff) { const cpp_token *token, *padding = NULL; @@ -728,7 +781,7 @@ funlike_invocation_p (cpp_reader *pfile, cpp_hashnode *node) if (token->type == CPP_OPEN_PAREN) { pfile->state.parsing_args = 2; - return collect_args (pfile, node); + return collect_args (pfile, node, pragma_buff); } /* CPP_EOF can be the end of macro arguments, or the end of the @@ -749,9 +802,13 @@ funlike_invocation_p (cpp_reader *pfile, cpp_hashnode *node) /* Push the context of a macro with hash entry NODE onto the context stack. If we can successfully expand the macro, we push a context containing its yet-to-be-rescanned replacement list and return one. - Otherwise, we don't push a context and return zero. */ + If there were additionally any unexpanded deferred #pragma directives + among macro arguments, push another context containing the + pragma tokens before the yet-to-be-rescanned replacement list + and return two. Otherwise, we don't push a context and return zero. */ static int -enter_macro_context (cpp_reader *pfile, cpp_hashnode *node) +enter_macro_context (cpp_reader *pfile, cpp_hashnode *node, + const cpp_token *result) { /* The presence of a macro invalidates a file's controlling macro. */ pfile->mi_valid = false; @@ -762,6 +819,7 @@ enter_macro_context (cpp_reader *pfile, cpp_hashnode *node) if (! (node->flags & NODE_BUILTIN)) { cpp_macro *macro = node->value.macro; + _cpp_buff *pragma_buff = NULL; if (macro->fun_like) { @@ -770,7 +828,7 @@ enter_macro_context (cpp_reader *pfile, cpp_hashnode *node) pfile->state.prevent_expansion++; pfile->keep_tokens++; pfile->state.parsing_args = 1; - buff = funlike_invocation_p (pfile, node); + buff = funlike_invocation_p (pfile, node, &pragma_buff); pfile->state.parsing_args = 0; pfile->keep_tokens--; pfile->state.prevent_expansion--; @@ -782,6 +840,9 @@ enter_macro_context (cpp_reader *pfile, cpp_hashnode *node) "function-like macro \"%s\" must be used with arguments in traditional C", NODE_NAME (node)); + if (pragma_buff) + _cpp_release_buff (pfile, pragma_buff); + return 0; } @@ -798,6 +859,25 @@ enter_macro_context (cpp_reader *pfile, cpp_hashnode *node) if (macro->paramc == 0) _cpp_push_token_context (pfile, node, macro->exp.tokens, macro->count); + if (pragma_buff) + { + if (!pfile->state.in_directive) + _cpp_push_token_context (pfile, NULL, + padding_token (pfile, result), 1); + do + { + _cpp_buff *tail = pragma_buff->next; + pragma_buff->next = NULL; + push_ptoken_context (pfile, NULL, pragma_buff, + (const cpp_token **) pragma_buff->base, + ((const cpp_token **) BUFF_FRONT (pragma_buff) + - (const cpp_token **) pragma_buff->base)); + pragma_buff = tail; + } + while (pragma_buff != NULL); + return 2; + } + return 1; } @@ -1144,14 +1224,17 @@ cpp_get_token (cpp_reader *pfile) if (!(node->flags & NODE_DISABLED)) { + int ret; /* If not in a macro context, and we're going to start an expansion, record the location. */ if (can_set && !context->macro) pfile->invocation_location = result->src_loc; - if (!pfile->state.prevent_expansion - && enter_macro_context (pfile, node)) + if (pfile->state.prevent_expansion) + break; + ret = enter_macro_context (pfile, node, result); + if (ret) { - if (pfile->state.in_directive) + if (pfile->state.in_directive || ret == 2) continue; return padding_token (pfile, result); } -- 2.11.0