2012-04-30 Dodji Seketeli <dodji@redhat.com>
+ 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
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;
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
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,
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;
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
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;
}