/* Part of CPP library. (Macro and #define handling.)
- Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004, 2005,
- 2006, 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
+ Copyright (C) 1986-2013 Free Software Foundation, Inc.
Written by Per Bothner, 1994.
Based on CCCP program by Paul Rubin, June 1986
Adapted to ANSI C, Richard Stallman, Jan 1987
/* A pointer to the current token pointed to by the iterator. */
const cpp_token **token_ptr;
/* A pointer to the "full" location of the current token. If
- -ftrack-macro-expansion is used this location tracks loci accross
+ -ftrack-macro-expansion is used this location tracks loci across
macro expansion. */
const source_location *location_ptr;
#ifdef ENABLE_CHECKING
static const cpp_token *new_string_token (cpp_reader *, uchar *, unsigned int);
static const cpp_token *stringify_arg (cpp_reader *, macro_arg *);
static void paste_all_tokens (cpp_reader *, const cpp_token *);
-static bool paste_tokens (cpp_reader *, const cpp_token **, const cpp_token *);
+static bool paste_tokens (cpp_reader *, source_location,
+ const cpp_token **, const cpp_token *);
static void alloc_expanded_arg_mem (cpp_reader *, macro_arg *, size_t);
static void ensure_expanded_arg_room (cpp_reader *, macro_arg *, size_t, size_t *);
static void delete_macro_args (_cpp_buff*, unsigned num_args);
source_location *);
static const cpp_token* cpp_get_token_1 (cpp_reader *, source_location *);
+static cpp_hashnode* macro_of_context (cpp_context *context);
+
+static bool in_macro_expansion_p (cpp_reader *pfile);
+
/* Statistical counter tracking the number of macros that got
expanded. */
unsigned num_expanded_macros_counter = 0;
const uchar *
_cpp_builtin_macro_text (cpp_reader *pfile, cpp_hashnode *node)
{
- const struct line_map *map;
const uchar *result = NULL;
linenum_type number = 1;
break;
case BT_SPECLINE:
- map = LINEMAPS_LAST_ORDINARY_MAP (pfile->line_table);
/* If __LINE__ is embedded in a macro, it must expand to the
line of the macro's invocation, not its definition.
Otherwise things like assert() will not work properly. */
/* Try to paste two tokens. On success, return nonzero. In any
case, PLHS is updated to point to the pasted token, which is
- guaranteed to not have the PASTE_LEFT flag set. */
+ guaranteed to not have the PASTE_LEFT flag set. LOCATION is
+ the virtual location used for error reporting. */
static bool
-paste_tokens (cpp_reader *pfile, const cpp_token **plhs, const cpp_token *rhs)
+paste_tokens (cpp_reader *pfile, source_location location,
+ const cpp_token **plhs, const cpp_token *rhs)
{
unsigned char *buf, *end, *lhsend;
cpp_token *lhs;
/* Mandatory error for all apart from assembler. */
if (CPP_OPTION (pfile, lang) != CLK_ASM)
- cpp_error (pfile, CPP_DL_ERROR,
+ cpp_error_with_line (pfile, CPP_DL_ERROR, location, 0,
"pasting \"%s\" and \"%s\" does not give a valid preprocessing token",
buf, cpp_token_as_text (pfile, rhs));
return false;
{
const cpp_token *rhs = NULL;
cpp_context *context = pfile->context;
+ source_location virt_loc = 0;
+
+ /* We are expanding a macro and we must have been called on a token
+ that appears at the left hand side of a ## operator. */
+ if (macro_of_context (pfile->context) == NULL
+ || (!(lhs->flags & PASTE_LEFT)))
+ abort ();
+
+ if (context->tokens_kind == TOKENS_KIND_EXTENDED)
+ /* The caller must have called consume_next_token_from_context
+ right before calling us. That has incremented the pointer to
+ the current virtual location. So it now points to the location
+ of the token that comes right after *LHS. We want the
+ resulting pasted token to have the location of the current
+ *LHS, though. */
+ virt_loc = context->c.mc->cur_virt_loc[-1];
+ else
+ /* We are not tracking macro expansion. So the best virtual
+ location we can get here is the expansion point of the macro we
+ are currently expanding. */
+ virt_loc = pfile->invocation_location;
do
{
if (rhs->flags & PASTE_LEFT)
abort ();
}
- if (!paste_tokens (pfile, &lhs, rhs))
+ if (!paste_tokens (pfile, virt_loc, &lhs, rhs))
break;
}
while (rhs->flags & PASTE_LEFT);
/* Put the resulting token in its own context. */
- _cpp_push_token_context (pfile, NULL, lhs, 1);
+ if (context->tokens_kind == TOKENS_KIND_EXTENDED)
+ {
+ source_location *virt_locs = NULL;
+ _cpp_buff *token_buf = tokens_buff_new (pfile, 1, &virt_locs);
+ tokens_buff_add_token (token_buf, virt_locs, lhs,
+ virt_loc, 0, NULL, 0);
+ push_extended_tokens_context (pfile, context->c.mc->macro_node,
+ token_buf, virt_locs,
+ (const cpp_token **)token_buf->base, 1);
+ }
+ else
+ _cpp_push_token_context (pfile, NULL, lhs, 1);
}
/* Returns TRUE if the number of arguments ARGC supplied in an
pfile->state.angled_headers = false;
+ /* From here to when we push the context for the macro later down
+ this function, we need to flag the fact that we are about to
+ expand a macro. This is useful when -ftrack-macro-expansion is
+ turned off. In that case, we need to record the location of the
+ expansion point of the top-most macro we are about to to expand,
+ into pfile->invocation_location. But we must not record any such
+ location once the process of expanding the macro starts; that is,
+ we must not do that recording between now and later down this
+ function where set this flag to FALSE. */
+ pfile->about_to_expand_macro_p = true;
+
if ((node->flags & NODE_BUILTIN) && !(node->flags & NODE_USED))
{
node->flags |= NODE_USED;
if (pragma_buff)
_cpp_release_buff (pfile, pragma_buff);
+ pfile->about_to_expand_macro_p = false;
return 0;
}
}
while (pragma_buff != NULL);
+ pfile->about_to_expand_macro_p = false;
return 2;
}
+ pfile->about_to_expand_macro_p = false;
return 1;
}
+ pfile->about_to_expand_macro_p = false;
/* Handle built-in macros and the _Pragma operator. */
return builtin_macro (pfile, node);
}
/* Set the INDEXth token of the macro argument ARG. TOKEN is the token
to set, LOCATION is its virtual location. "Virtual" location means
- the location that encodes loci accross macro expansion. Otherwise
+ the location that encodes loci across macro expansion. Otherwise
it has to be TOKEN->SRC_LOC. KIND is the kind of tokens the
argument ARG is supposed to contain. Note that ARG must be
tailored so that it has enough room to contain INDEX + 1 numbers of
/* Move the iterator one token forward. Note that if IT was
initialized on an argument that has a stringified token, moving it
- foward doesn't make sense as a stringified token is essentially one
+ forward doesn't make sense as a stringified token is essentially one
string. */
static void
macro_arg_token_iter_forward (macro_arg_token_iter *it)
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;
means -ftrack-macro-expansion is effect; it then points to where to
insert the virtual location of TOKEN. TOKEN is the token to
insert. VIRT_LOC is the virtual location of the token, i.e, the
- location possibly encoding its locus accross macro expansion. If
+ location possibly encoding its locus across macro expansion. If
TOKEN is an argument of a function-like macro (inside a macro
replacement list), PARM_DEF_LOC is the spelling location of the
macro parameter that TOKEN is replacing, in the replacement list of
reaches BUFFER's size; it aborts in that situation.
TOKEN is the token to append. VIRT_LOC is the virtual location of
- the token, i.e, the location possibly encoding its locus accross
+ the token, i.e, the location possibly encoding its locus across
macro expansion. If TOKEN is an argument of a function-like macro
(inside a macro replacement list), PARM_DEF_LOC is the location of
the macro parameter that TOKEN is replacing. If TOKEN doesn't come
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;
+}
+
+/* Return TRUE iff we are expanding a macro or are about to start
+ expanding one. If we are effectively expanding a macro, the
+ function macro_of_context returns a pointer to the macro being
+ expanded. */
+static bool
+in_macro_expansion_p (cpp_reader *pfile)
+{
+ if (pfile == NULL)
+ return false;
+
+ return (pfile->about_to_expand_macro_p
+ || macro_of_context (pfile->context));
+}
+
/* 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
{
cpp_context *context = pfile->context;
+ /* We should not be popping the base context. */
+ if (context == &pfile->base_context)
+ abort ();
+
if (context->c.macro)
{
cpp_hashnode *macro;
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 across 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;
}
/* Consume the next token contained in the current context of PFILE,
and return it in *TOKEN. It's "full location" is returned in
*LOCATION. If -ftrack-macro-location is in effeect, fFull location"
- means the location encoding the locus of the token accross macro
+ means the location encoding the locus of the token across macro
expansion; otherwise it's just is the "normal" location of the
token which (*TOKEN)->src_loc. */
static inline void
cpp_get_token_1 (cpp_reader *pfile, source_location *location)
{
const cpp_token *result;
- bool can_set = pfile->set_invocation_location;
/* This token is a virtual token that either encodes a location
related to macro expansion or a spelling location. */
source_location virt_loc = 0;
- pfile->set_invocation_location = false;
+ /* pfile->about_to_expand_macro_p can be overriden by indirect calls
+ to functions that push macro contexts. So let's save it so that
+ we can restore it when we are about to leave this routine. */
+ bool saved_about_to_expand_macro = pfile->about_to_expand_macro_p;
for (;;)
{
int ret = 0;
/* If not in a macro context, and we're going to start an
expansion, record the location. */
- if (can_set && !context->c.macro)
+ if (!in_macro_expansion_p (pfile))
pfile->invocation_location = result->src_loc;
if (pfile->state.prevent_expansion)
break;
*location = virt_loc;
if (!CPP_OPTION (pfile, track_macro_expansion)
- && can_set
- && pfile->context->c.macro != NULL)
+ && macro_of_context (pfile->context) != NULL)
/* We are in a macro expansion context, are not tracking
virtual location, but were asked to report the location
of the expansion point of the macro being expanded. */
*location = maybe_adjust_loc_for_trad_cpp (pfile, *location);
}
+
+ pfile->about_to_expand_macro_p = saved_about_to_expand_macro;
return result;
}
const cpp_token *
cpp_get_token_with_location (cpp_reader *pfile, source_location *loc)
{
- const cpp_token *result;
-
- pfile->set_invocation_location = true;
- result = cpp_get_token_1 (pfile, loc);
- return result;
+ return cpp_get_token_1 (pfile, loc);
}
/* Returns true if we're expanding an object-like macro that was
int
cpp_sys_macro_p (cpp_reader *pfile)
{
- cpp_hashnode *node = pfile->context->c.macro;
+ cpp_hashnode *node = NULL;
+
+ if (pfile->context->tokens_kind == TOKENS_KIND_EXTENDED)
+ node = pfile->context->c.mc->macro_node;
+ else
+ node = pfile->context->c.macro;
return node && node->value.macro && node->value.macro->syshdr;
}