aboutsummaryrefslogtreecommitdiff
path: root/libcpp/macro.c
diff options
context:
space:
mode:
Diffstat (limited to 'libcpp/macro.c')
-rw-r--r--libcpp/macro.c56
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;
}