Jason Merrill <ja...@redhat.com> writes: > On 04/25/2012 05:07 AM, Dodji Seketeli wrote: >> + /* If the first token we got was a padding token, let's put >> + it back into the stream so that cpp_get_token will get it >> + first; and if we are currently expanding a macro, don't >> + forget that information. */ >> + cpp_hashnode *macro = >> + (pfile->context->tokens_kind == TOKENS_KIND_EXTENDED) >> + ? pfile->context->c.mc->macro_node >> + : pfile->context->c.macro; >> + _cpp_push_token_context (pfile, macro, padding, 1); > > What about the other places that call _cpp_push_token_context with a > NULL macro argument? Don't we want to continue the current macro > context in that case, too? Perhaps we should move this new code > inside _cpp_push_token_context for the case when the macro parameter > is NULL.
Right. I did that. But then, now that there can be some contiguous contexts representing the same macro, I had to adjust how _cpp_pop_context was re-enabling the 'expandability' of a given macro M. For the background, When M is being expanded, it's flagged by enter_macro_context as being non-expandable, to prevent its possible recursive expansions. And it's flagged back to being expandable when we get out of its expansion context. Now, getting out of the expansion context means to test that have actually popped all the possibly contiguous contexts that are related to M. Otherwise, we get into situations of recursive expansion of M. Bootstrapped and tested on x86_64-unknown-linux-gnu against trunk. libcpp/ * macro.c (macro_of_context): New static function. (_cpp_push_token_context, push_extended_tokens_context): If the macro argument is NULL, it means we are continuing the expansion of the current macro, if any. Update comments. (_cpp_pop_context): Re-enable expansion of the macro only when we are really out of the context of the current expansion. gcc/testsuite/ * gcc.dg/debug/dwarf2/pr41445-5.c: Adjust. * gcc.dg/debug/dwarf2/pr41445-6.c: Likewise. --- gcc/testsuite/gcc.dg/debug/dwarf2/pr41445-5.c | 5 ++- gcc/testsuite/gcc.dg/debug/dwarf2/pr41445-6.c | 5 ++- libcpp/macro.c | 56 +++++++++++++++++++++---- 3 files changed, 56 insertions(+), 10 deletions(-) diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/pr41445-5.c b/gcc/testsuite/gcc.dg/debug/dwarf2/pr41445-5.c index 03af604..d21acd5 100644 --- a/gcc/testsuite/gcc.dg/debug/dwarf2/pr41445-5.c +++ b/gcc/testsuite/gcc.dg/debug/dwarf2/pr41445-5.c @@ -9,6 +9,9 @@ #define B , varj int A(B) ; -/* { dg-final { scan-assembler "DW_TAG_variable\[^\\r\\n\]*\[\\r\\n\]+\[^\\r\\n\]*\"vari\[^\\r\\n\]*DW_AT_name(\[^\\r\\n\]*\[\\r\\n\]+\[^\\r\\n\]*DW_AT_)*\[^\\r\\n\]*\[\\r\\n\]+\[^\\r\\n\]*\[^0-9a-fA-FxX](0x)?7\[^0-9a-fA-FxX]\[^\\r\\n\]*DW_AT_decl_line" } } */ +/* We want to check that both vari and varj have the same line + number. */ + +/* { dg-final { scan-assembler "DW_TAG_variable\[^\\r\\n\]*\[\\r\\n\]+\[^\\r\\n\]*\"vari\[^\\r\\n\]*DW_AT_name(\[^\\r\\n\]*\[\\r\\n\]+\[^\\r\\n\]*DW_AT_)*\[^\\r\\n\]*\[\\r\\n\]+\[^\\r\\n\]*\[^0-9a-fA-FxX](0xa|10)\[^0-9a-fA-FxX]\[^\\r\\n\]*DW_AT_decl_line" } } */ /* { dg-final { scan-assembler "DW_TAG_variable\[^\\r\\n\]*\[\\r\\n\]+\[^\\r\\n\]*\"varj\[^\\r\\n\]*DW_AT_name(\[^\\r\\n\]*\[\\r\\n\]+\[^\\r\\n\]*DW_AT_)*\[^\\r\\n\]*\[\\r\\n\]+\[^\\r\\n\]*\[^0-9a-fA-FxX](0xa|10)\[^0-9a-fA-FxX]\[^\\r\\n\]*DW_AT_decl_line" } } */ /* { dg-final { cleanup-saved-temps } } */ diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/pr41445-6.c b/gcc/testsuite/gcc.dg/debug/dwarf2/pr41445-6.c index 8aa37d1..d6d79cc 100644 --- a/gcc/testsuite/gcc.dg/debug/dwarf2/pr41445-6.c +++ b/gcc/testsuite/gcc.dg/debug/dwarf2/pr41445-6.c @@ -4,5 +4,8 @@ #include "pr41445-5.c" -/* { dg-final { scan-assembler "DW_TAG_variable\[^\\r\\n\]*\[\\r\\n\]+\[^\\r\\n\]*\"vari\[^\\r\\n\]*DW_AT_name(\[^\\r\\n\]*\[\\r\\n\]+\[^\\r\\n\]*DW_AT_)*\[^\\r\\n\]*\[\\r\\n\]+\[^\\r\\n\]*\[^0-9a-fA-FxX](0x)?7\[^0-9a-fA-FxX]\[^\\r\\n\]*DW_AT_decl_line" } } */ +/* We want to check that both vari and varj have the same line + number. */ + +/* { dg-final { scan-assembler "DW_TAG_variable\[^\\r\\n\]*\[\\r\\n\]+\[^\\r\\n\]*\"vari\[^\\r\\n\]*DW_AT_name(\[^\\r\\n\]*\[\\r\\n\]+\[^\\r\\n\]*DW_AT_)*\[^\\r\\n\]*\[\\r\\n\]+\[^\\r\\n\]*\[^0-9a-fA-FxX](0xa|10)?\[^0-9a-fA-FxX]\[^\\r\\n\]*DW_AT_decl_line" } } */ /* { dg-final { scan-assembler "DW_TAG_variable\[^\\r\\n\]*\[\\r\\n\]+\[^\\r\\n\]*\"varj\[^\\r\\n\]*DW_AT_name(\[^\\r\\n\]*\[\\r\\n\]+\[^\\r\\n\]*DW_AT_)*\[^\\r\\n\]*\[\\r\\n\]+\[^\\r\\n\]*\[^0-9a-fA-FxX](0xa|10)\[^0-9a-fA-FxX]\[^\\r\\n\]*DW_AT_decl_line" } } */ diff --git a/libcpp/macro.c b/libcpp/macro.c index f4638c4..ab3e8f6 100644 --- a/libcpp/macro.c +++ b/libcpp/macro.c @@ -165,6 +165,8 @@ static void consume_next_token_from_context (cpp_reader *pfile, source_location *); static const cpp_token* cpp_get_token_1 (cpp_reader *, source_location *); +static cpp_hashnode* macro_of_context (cpp_context *context); + /* Statistical counter tracking the number of macros that got expanded. */ unsigned num_expanded_macros_counter = 0; @@ -1808,18 +1810,27 @@ push_ptoken_context (cpp_reader *pfile, cpp_hashnode *macro, _cpp_buff *buff, LAST (context).ptoken = first + count; } -/* Push a list of tokens. */ +/* Push a list of tokens. + + A NULL macro means that we should continue the current macro + expansion, in essence. That means that if we are currently in a + macro expansion context, we'll make the new pfile->context refer to + the current macro. */ void _cpp_push_token_context (cpp_reader *pfile, cpp_hashnode *macro, const cpp_token *first, unsigned int count) { - cpp_context *context = next_context (pfile); - + cpp_context *context; + + if (macro == NULL) + macro = macro_of_context (pfile->context); + + context = next_context (pfile); context->tokens_kind = TOKENS_KIND_DIRECT; context->c.macro = macro; context->buff = NULL; - FIRST (context).token = first; - LAST (context).token = first + count; + FIRST (context).token = first; + LAST (context).token = first + count; } /* Build a context containing a list of tokens as well as their @@ -1827,7 +1838,12 @@ _cpp_push_token_context (cpp_reader *pfile, cpp_hashnode *macro, contains the tokens pointed to by FIRST. If TOKENS_BUFF is non-NULL, it means that the context owns it, meaning that _cpp_pop_context will free it as well as VIRT_LOCS_BUFF that - contains the virtual locations. */ + contains the virtual locations. + + A NULL macro means that we should continue the current macro + expansion, in essence. That means that if we are currently in a + macro expansion context, we'll make the new pfile->context refer to + the current macro. */ static void push_extended_tokens_context (cpp_reader *pfile, cpp_hashnode *macro, @@ -1836,9 +1852,13 @@ push_extended_tokens_context (cpp_reader *pfile, const cpp_token **first, unsigned int count) { - cpp_context *context = next_context (pfile); + cpp_context *context; macro_context *m; + if (macro == NULL) + macro = macro_of_context (pfile->context); + + context = next_context (pfile); context->tokens_kind = TOKENS_KIND_EXTENDED; context->buff = token_buff; @@ -2110,6 +2130,19 @@ expand_arg (cpp_reader *pfile, macro_arg *arg) CPP_WTRADITIONAL (pfile) = saved_warn_trad; } +/* Returns the macro associated to the current context if we are in + the context a macro expansion, NULL otherwise. */ +static cpp_hashnode* +macro_of_context (cpp_context *context) +{ + if (context == NULL) + return NULL; + + return (context->tokens_kind == TOKENS_KIND_EXTENDED) + ? context->c.mc->macro_node + : context->c.macro; +} + /* Pop the current context off the stack, re-enabling the macro if the context represented a macro's replacement list. Initially the context structure was not freed so that we can re-use it later, but @@ -2146,7 +2179,14 @@ _cpp_pop_context (cpp_reader *pfile) tokens is pushed just for the purpose of walking them using cpp_get_token_1. In that case, no 'macro' field is set into the dummy context. */ - if (macro != NULL) + if (macro != NULL + /* Several contiguous macro expansion contexts can be + associated to the same macro; that means it's the same + macro expansion that spans accross all these (sub) + contexts. So we should re-enable an expansion-disabled + macro only when we are sure we are really out of that + macro expansion. */ + && macro_of_context (context->prev) != macro) macro->flags &= ~NODE_DISABLED; } -- Dodji