diff options
Diffstat (limited to 'libcpp/macro.c')
-rw-r--r-- | libcpp/macro.c | 56 |
1 files changed, 48 insertions, 8 deletions
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; } |