From: dodji Date: Mon, 30 Apr 2012 11:41:46 +0000 (+0000) Subject: Fix expansion point loc for macro-like tokens X-Git-Tag: upstream/4.9.2~12978 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=00abfdc0d5e2c9c3c55c6ca182c2522a6c17be0e;p=platform%2Fupstream%2Flinaro-gcc.git Fix expansion point loc for macro-like tokens Consider the test case gcc/testsuite/gcc.dg/debug/dwarf2/pr41445-5.c. Its interesting part is: #define A(x) vari x /* line 7. */ #define vari(x) #define B , varj int A(B) ; /* line 10. */ In its initial version, this test was being pre-processed as: # 1 "gcc/testsuite/gcc.dg/debug/dwarf2/pr41445-5.c" # 1 "build/gcc//" # 1 "" # 1 "gcc/testsuite/gcc.dg/debug/dwarf2/pr41445-5.c" # 10 "gcc/testsuite/gcc.dg/debug/dwarf2/pr41445-5.c" int # 7 "gcc/testsuite/gcc.dg/debug/dwarf2/pr41445-5.c" vari , varj ; Note how "int" and "vari" are on separate lines, whereas "int" and ", varj" are on the same line. This looks like a bug to me, even independantly from the macro location tracking work. With macro location tracking turned on, the preprocessed output becomes: # 1 "gcc/testsuite/gcc.dg/debug/dwarf2/pr41445-5.c" # 1 "" # 1 "gcc/testsuite/gcc.dg/debug/dwarf2/pr41445-5.c" # 10 "gcc/testsuite/gcc.dg/debug/dwarf2/pr41445-5.c" int vari , varj ; Which, IMO, is what we'd expect. This is due to an unexpected side effect of enter_macro_context when passed a token that might look like a function-like macro at first sight, but that it eventually considers to not be a macro after all. This is the case for the "vari" token which looks like a macro when it is first lexed, but is eventually considered to be a normal token by enter_macro_context because it's not used as a function-like macro invocation. In that case, besides returning NULL, enter_macro_context sets pfile->context->c.macro to NULL, making cpp_get_token_1 forget to set the location of the "vari" to the expansion point of A. enter_macro_context sets pfile->context->c.macro to NULL in that case because funlike_invocation_p reads one token pass "foo", sees that there is no '(' token, so we are not invoking the function-like parameter. It then puts the tokens (which it has read after "foo") back into the tokens stream by calling _cpp_push_token_context on it, which sets pfile->context->c.macro to NULL, saying in essence that the current macro expansion context is "stopped". The fix here is to teach _cpp_push_token and push_extended_tokens_context to continue the current macro context when passed a NULL macro. But then, now that there can be several continguous contexts associated with the same macro, we need to teach _cpp_pop_context to re-enable the expansion of the current macro only when we are really out of expanding the current macro. Otherwise we can run in cases where we have recursive expansions of the same macro. Tested on x86_64-unknown-linux-gnu against trunk. Now this test has the same output with and without tracking locations accross macro expansions. Note that the bootstrap with -ftrack-macro-expansion exhibits other separate issues that are addressed in subsequent patches. This patch just fixes one class of problems. The patch does pass bootstrap with -ftrack-macro-expansion turned off, though. 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@186968 138bc75d-0d04-0410-961f-82ee72b054a4 --- diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index c7f6419..ed2779e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,9 @@ 2012-04-30 Dodji Seketeli + Fix expansion point loc for macro-like tokens + * gcc.dg/debug/dwarf2/pr41445-5.c: Adjust. + * gcc.dg/debug/dwarf2/pr41445-6.c: Likewise. + Fix token pasting with -ftrack-macro-expansion * gcc.dg/cpp/paste17.c: New test case for -ftrack-macro-expansion=2 mode only. 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/ChangeLog b/libcpp/ChangeLog index 189f394..5e93396 100644 --- a/libcpp/ChangeLog +++ b/libcpp/ChangeLog @@ -1,5 +1,13 @@ 2012-04-30 Dodji Seketeli + Fix expansion point loc for macro-like tokens + * 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. + Fix token pasting with -ftrack-macro-expansion * macro.c (paste_all_tokens): Put the token resulting from pasting into an extended token context with -ftrack-macro-location is in 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; }