diff options
author | Joseph Myers <joseph@codesourcery.com> | 2009-04-19 18:10:56 +0100 |
---|---|---|
committer | Joseph Myers <jsm28@gcc.gnu.org> | 2009-04-19 18:10:56 +0100 |
commit | aa50850225d70521ace3948a8e5858425a918f6a (patch) | |
tree | 311d607f4a7b5f177b00f2193802a219b80ccc5e /libcpp/macro.c | |
parent | b6fa5b01018ac42682f8d69fff9e48f50b87c910 (diff) | |
download | gcc-aa50850225d70521ace3948a8e5858425a918f6a.zip gcc-aa50850225d70521ace3948a8e5858425a918f6a.tar.gz gcc-aa50850225d70521ace3948a8e5858425a918f6a.tar.bz2 |
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.c | 73 |
1 files changed, 65 insertions, 8 deletions
diff --git a/libcpp/macro.c b/libcpp/macro.c index 75c1c55..3685397 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 = ¯o->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 = ¯o->exp.tokens[i]; |