summaryrefslogtreecommitdiff
path: root/libcpp/macro.c
diff options
context:
space:
mode:
authorJoseph Myers <joseph@codesourcery.com>2009-04-19 18:10:56 +0100
committerJoseph Myers <jsm28@gcc.gnu.org>2009-04-19 18:10:56 +0100
commitaa50850225d70521ace3948a8e5858425a918f6a (patch)
tree311d607f4a7b5f177b00f2193802a219b80ccc5e /libcpp/macro.c
parentb6fa5b01018ac42682f8d69fff9e48f50b87c910 (diff)
re PR preprocessor/20078 (Gcc doesn't complain about non-benign macro definitions)
libcpp: PR preprocessor/20078 * include/cpp-id-data.h (struct cpp_macro): Add extra_tokens field. * include/cpplib.h (SP_DIGRAPH, SP_PREV_WHITE): Define. (struct cpp_token): Change flags to unsigned short. * lex.c (_cpp_lex_direct): Initialize arg_no for CPP_PASTE tokens. (_cpp_equiv_tokens): Check arg_no for CPP_PASTE tokens. (cpp_token_val_index): Return CPP_TOKEN_FLD_ARG_NO for CPP_PASTE tokens. * macro.c (macro_real_token_count): New. (enter_macro_context, replace_args): Use macro_real_token_count. (create_iso_definition): Record whitespace surrounding and digraph spelling of # and ## tokens using SP_PREV_WHITE and SP_DIGRAPH. Set extra_tokens and save CPP_PASTE tokens with arg_no set for multiple consecutive ## tokens. (_cpp_create_definition): Initialize extra_tokens. (cpp_macro_definition): Use macro_real_token_count. gcc/testsuite: * gcc.dg/cpp/paste16.c, gcc.dg/cpp/redef4.c: New tests. From-SVN: r146352
Diffstat (limited to 'libcpp/macro.c')
-rw-r--r--libcpp/macro.c73
1 files changed, 65 insertions, 8 deletions
diff --git a/libcpp/macro.c b/libcpp/macro.c
index 75c1c55e022..36853971780 100644
--- a/libcpp/macro.c
+++ b/libcpp/macro.c
@@ -802,6 +802,19 @@ funlike_invocation_p (cpp_reader *pfile, cpp_hashnode *node,
return NULL;
}
+/* Return the real number of tokens in the expansion of MACRO. */
+static inline unsigned int
+macro_real_token_count (const cpp_macro *macro)
+{
+ unsigned int i;
+ if (__builtin_expect (!macro->extra_tokens, true))
+ return macro->count;
+ for (i = 0; i < macro->count; i++)
+ if (macro->exp.tokens[i].type == CPP_PASTE)
+ return i;
+ abort ();
+}
+
/* Push the context of a macro with hash entry NODE onto the context
stack. If we can successfully expand the macro, we push a context
containing its yet-to-be-rescanned replacement list and return one.
@@ -874,7 +887,8 @@ enter_macro_context (cpp_reader *pfile, cpp_hashnode *node,
macro->used = 1;
if (macro->paramc == 0)
- _cpp_push_token_context (pfile, node, macro->exp.tokens, macro->count);
+ _cpp_push_token_context (pfile, node, macro->exp.tokens,
+ macro_real_token_count (macro));
if (pragma_buff)
{
@@ -914,13 +928,15 @@ replace_args (cpp_reader *pfile, cpp_hashnode *node, cpp_macro *macro, macro_arg
const cpp_token **dest, **first;
macro_arg *arg;
_cpp_buff *buff;
+ unsigned int count;
/* First, fully macro-expand arguments, calculating the number of
tokens in the final expansion as we go. The ordering of the if
statements below is subtle; we must handle stringification before
pasting. */
- total = macro->count;
- limit = macro->exp.tokens + macro->count;
+ count = macro_real_token_count (macro);
+ total = count;
+ limit = macro->exp.tokens + count;
for (src = macro->exp.tokens; src < limit; src++)
if (src->type == CPP_MACRO_ARG)
@@ -1630,6 +1646,7 @@ create_iso_definition (cpp_reader *pfile, cpp_macro *macro)
bool following_paste_op = false;
const char *paste_op_error_msg =
N_("'##' cannot appear at either end of a macro expansion");
+ unsigned int num_extra_tokens = 0;
/* Get the first token of the expansion (or the '(' of a
function-like macro). */
@@ -1707,6 +1724,10 @@ create_iso_definition (cpp_reader *pfile, cpp_macro *macro)
{
if (token->type == CPP_MACRO_ARG)
{
+ if (token->flags & PREV_WHITE)
+ token->flags |= SP_PREV_WHITE;
+ if (token[-1].flags & DIGRAPH)
+ token->flags |= SP_DIGRAPH;
token->flags &= ~PREV_WHITE;
token->flags |= STRINGIFY_ARG;
token->flags |= token[-1].flags & PREV_WHITE;
@@ -1746,8 +1767,21 @@ create_iso_definition (cpp_reader *pfile, cpp_macro *macro)
return false;
}
- --macro->count;
- token[-1].flags |= PASTE_LEFT;
+ if (token[-1].flags & PASTE_LEFT)
+ {
+ macro->extra_tokens = 1;
+ num_extra_tokens++;
+ token->val.arg_no = macro->count - 1;
+ }
+ else
+ {
+ --macro->count;
+ token[-1].flags |= PASTE_LEFT;
+ if (token->flags & DIGRAPH)
+ token[-1].flags |= SP_DIGRAPH;
+ if (token->flags & PREV_WHITE)
+ token[-1].flags |= SP_PREV_WHITE;
+ }
}
following_paste_op = (token->type == CPP_PASTE);
@@ -1770,7 +1804,27 @@ create_iso_definition (cpp_reader *pfile, cpp_macro *macro)
cpp_token *tokns =
(cpp_token *) pfile->hash_table->alloc_subobject (sizeof (cpp_token)
* macro->count);
- memcpy (tokns, macro->exp.tokens, sizeof (cpp_token) * macro->count);
+ if (num_extra_tokens)
+ {
+ /* Place second and subsequent ## or %:%: tokens in
+ sequences of consecutive such tokens at the end of the
+ list to preserve information about where they appear, how
+ they are spelt and whether they are preceded by
+ whitespace without otherwise interfering with macro
+ expansion. */
+ cpp_token *normal_dest = tokns;
+ cpp_token *extra_dest = tokns + macro->count - num_extra_tokens;
+ unsigned int i;
+ for (i = 0; i < macro->count; i++)
+ {
+ if (macro->exp.tokens[i].type == CPP_PASTE)
+ *extra_dest++ = macro->exp.tokens[i];
+ else
+ *normal_dest++ = macro->exp.tokens[i];
+ }
+ }
+ else
+ memcpy (tokns, macro->exp.tokens, sizeof (cpp_token) * macro->count);
macro->exp.tokens = tokns;
}
else
@@ -1799,6 +1853,7 @@ _cpp_create_definition (cpp_reader *pfile, cpp_hashnode *node)
macro->used = !CPP_OPTION (pfile, warn_unused_macros);
macro->count = 0;
macro->fun_like = 0;
+ macro->extra_tokens = 0;
/* To suppress some diagnostics. */
macro->syshdr = pfile->buffer && pfile->buffer->sysp != 0;
@@ -1946,7 +2001,8 @@ cpp_macro_definition (cpp_reader *pfile, const cpp_hashnode *node)
len += _cpp_replacement_text_len (macro);
else
{
- for (i = 0; i < macro->count; i++)
+ unsigned int count = macro_real_token_count (macro);
+ for (i = 0; i < count; i++)
{
cpp_token *token = &macro->exp.tokens[i];
@@ -2010,7 +2066,8 @@ cpp_macro_definition (cpp_reader *pfile, const cpp_hashnode *node)
else if (macro->count)
/* Expansion tokens. */
{
- for (i = 0; i < macro->count; i++)
+ unsigned int count = macro_real_token_count (macro);
+ for (i = 0; i < count; i++)
{
cpp_token *token = &macro->exp.tokens[i];