Commit 10f04917 by Nathan Sidwell Committed by Nathan Sidwell

[PATCH] Macro body is trailing array

https://gcc.gnu.org/ml/gcc-patches/2018-08/msg01037.html
	* include/cpplib.h (enum cpp_macro_kind): New.
	(struct cpp_macro): Make body trailing array.  Add kind field,
	delete traditional flag.
	* internal.h (_cpp_new_macro): Declare.
	(_cpp_reserve_room): New inline.
	(_cpp_commit_buf): Declare.
	(_cpp_create_trad_definition): Return new macro.
	* lex.c (_cpp_commit_buff): New.
	* macro.c (macro_real_token_count): Count backwards.
	(replace_args): Pointer equality not orderedness.
	(_cpp_save_parameter): Use _cpp_reserve_room.
	(alloc_expansion_token): Delete.
	(lex_expansion_token): Return macro pointer.  Use _cpp_reserve_room.
	(create_iso_definition): Allocate macro itself.  Adjust for
	different allocation ordering.
	(_cpp_new_macro): New.
	(_cpp_create_definition): Adjust for API changes.
	* traditional.c (push_replacement_text): Don't set traditional
	flag.
	(save_replacement_text): Likewise.
	(_cpp_create_trad_definition): Allocate macro itself, Adjust for
	different allocation ordering.

From-SVN: r263622
parent c5d725c0
2018-08-17 Nathan Sidwell <nathan@acm.org> 2018-08-17 Nathan Sidwell <nathan@acm.org>
* c-ada-spec.c (macro_length, dump_ada_macros): Constify.
* c-ada-spec.c: Don't #include "cpp-id-data.h" * c-ada-spec.c: Don't #include "cpp-id-data.h"
* c-cppbuiltin.c: Likewise. * c-cppbuiltin.c: Likewise.
......
...@@ -88,7 +88,7 @@ macro_length (const cpp_macro *macro, int *supported, int *buffer_len, ...@@ -88,7 +88,7 @@ macro_length (const cpp_macro *macro, int *supported, int *buffer_len,
for (j = 0; j < macro->count; j++) for (j = 0; j < macro->count; j++)
{ {
cpp_token *token = &macro->exp.tokens[j]; const cpp_token *token = &macro->exp.tokens[j];
if (token->flags & PREV_WHITE) if (token->flags & PREV_WHITE)
(*buffer_len)++; (*buffer_len)++;
...@@ -274,7 +274,7 @@ dump_ada_macros (pretty_printer *pp, const char* file) ...@@ -274,7 +274,7 @@ dump_ada_macros (pretty_printer *pp, const char* file)
for (i = 0; supported && i < macro->count; i++) for (i = 0; supported && i < macro->count; i++)
{ {
cpp_token *token = &macro->exp.tokens[i]; const cpp_token *token = &macro->exp.tokens[i];
int is_one = 0; int is_one = 0;
if (token->flags & PREV_WHITE) if (token->flags & PREV_WHITE)
......
2018-08-17 Nathan Sidwell <nathan@acm.org> 2018-08-17 Nathan Sidwell <nathan@acm.org>
* include/cpplib.h (enum cpp_macro_kind): New.
(struct cpp_macro): Make body trailing array. Add kind field,
delete traditional flag.
* internal.h (_cpp_new_macro): Declare.
(_cpp_reserve_room): New inline.
(_cpp_commit_buf): Declare.
(_cpp_create_trad_definition): Return new macro.
* lex.c (_cpp_commit_buff): New.
* macro.c (macro_real_token_count): Count backwards.
(replace_args): Pointer equality not orderedness.
(_cpp_save_parameter): Use _cpp_reserve_room.
(alloc_expansion_token): Delete.
(lex_expansion_token): Return macro pointer. Use _cpp_reserve_room.
(create_iso_definition): Allocate macro itself. Adjust for
different allocation ordering.
(_cpp_new_macro): New.
(_cpp_create_definition): Adjust for API changes.
* traditional.c (push_replacement_text): Don't set traditional
flag.
(save_replacement_text): Likewise.
(_cpp_create_trad_definition): Allocate macro itself, Adjust for
different allocation ordering.
* cpp-id-data.h (uchar, UC): Move to internal.h * cpp-id-data.h (uchar, UC): Move to internal.h
(struct cpp_macro): Move to cpplib.h. (struct cpp_macro): Move to cpplib.h.
* internal.h (uchar, UC): From cpp-id-data.h. * internal.h (uchar, UC): From cpp-id-data.h.
......
...@@ -671,6 +671,12 @@ struct cpp_dir ...@@ -671,6 +671,12 @@ struct cpp_dir
dev_t dev; dev_t dev;
}; };
/* The kind of the cpp_macro. */
enum cpp_macro_kind {
cmk_macro, /* An ISO macro (token expansion). */
cmk_traditional, /* A traditional macro (text expansion). */
};
/* Each macro definition is recorded in a cpp_macro structure. /* Each macro definition is recorded in a cpp_macro structure.
Variadic macros cannot occur with traditional cpp. */ Variadic macros cannot occur with traditional cpp. */
struct GTY(()) cpp_macro { struct GTY(()) cpp_macro {
...@@ -683,15 +689,6 @@ struct GTY(()) cpp_macro { ...@@ -683,15 +689,6 @@ struct GTY(()) cpp_macro {
length ("%h.paramc"))) length ("%h.paramc")))
params; params;
/* Replacement tokens (ISO) or replacement text (traditional). See
comment at top of cpptrad.c for how traditional function-like
macros are encoded. */
union cpp_macro_u
{
cpp_token * GTY ((tag ("0"), length ("%0.count"))) tokens;
const unsigned char * GTY ((tag ("1"))) text;
} GTY ((desc ("%1.traditional"))) exp;
/* Definition line number. */ /* Definition line number. */
source_location line; source_location line;
...@@ -701,6 +698,9 @@ struct GTY(()) cpp_macro { ...@@ -701,6 +698,9 @@ struct GTY(()) cpp_macro {
/* Number of parameters. */ /* Number of parameters. */
unsigned short paramc; unsigned short paramc;
/* The kind of this macro (ISO, trad or assert) */
unsigned kind : 2;
/* If a function-like macro. */ /* If a function-like macro. */
unsigned int fun_like : 1; unsigned int fun_like : 1;
...@@ -713,13 +713,23 @@ struct GTY(()) cpp_macro { ...@@ -713,13 +713,23 @@ struct GTY(()) cpp_macro {
/* Nonzero if it has been expanded or had its existence tested. */ /* Nonzero if it has been expanded or had its existence tested. */
unsigned int used : 1; unsigned int used : 1;
/* Indicate which field of 'exp' is in use. */
unsigned int traditional : 1;
/* Indicate whether the tokens include extra CPP_PASTE tokens at the /* Indicate whether the tokens include extra CPP_PASTE tokens at the
end to track invalid redefinitions with consecutive CPP_PASTE end to track invalid redefinitions with consecutive CPP_PASTE
tokens. */ tokens. */
unsigned int extra_tokens : 1; unsigned int extra_tokens : 1;
/* 1 bits spare (32-bit). 33 on 64-bit target. */
union cpp_exp_u
{
/* Trailing array of replacement tokens (ISO), or assertion body value. */
cpp_token GTY ((tag ("false"), length ("%1.count"))) tokens[1];
/* Pointer to replacement text (traditional). See comment at top
of cpptrad.c for how traditional function-like macros are
encoded. */
const unsigned char *GTY ((tag ("true"))) text;
} GTY ((desc ("%1.kind == cmk_traditional"))) exp;
}; };
/* The structure of a node in the hash table. The hash table has /* The structure of a node in the hash table. The hash table has
......
...@@ -633,6 +633,7 @@ inline void _cpp_maybe_notify_macro_use (cpp_reader *pfile, cpp_hashnode *node) ...@@ -633,6 +633,7 @@ inline void _cpp_maybe_notify_macro_use (cpp_reader *pfile, cpp_hashnode *node)
if (!(node->flags & NODE_USED)) if (!(node->flags & NODE_USED))
_cpp_notify_macro_use (pfile, node); _cpp_notify_macro_use (pfile, node);
} }
extern cpp_macro *_cpp_new_macro (cpp_reader *, cpp_macro_kind, void *);
extern void _cpp_free_definition (cpp_hashnode *); extern void _cpp_free_definition (cpp_hashnode *);
extern bool _cpp_create_definition (cpp_reader *, cpp_hashnode *); extern bool _cpp_create_definition (cpp_reader *, cpp_hashnode *);
extern void _cpp_pop_context (cpp_reader *); extern void _cpp_pop_context (cpp_reader *);
...@@ -697,6 +698,14 @@ extern void _cpp_init_tokenrun (tokenrun *, unsigned int); ...@@ -697,6 +698,14 @@ extern void _cpp_init_tokenrun (tokenrun *, unsigned int);
extern cpp_hashnode *_cpp_lex_identifier (cpp_reader *, const char *); extern cpp_hashnode *_cpp_lex_identifier (cpp_reader *, const char *);
extern int _cpp_remaining_tokens_num_in_context (cpp_context *); extern int _cpp_remaining_tokens_num_in_context (cpp_context *);
extern void _cpp_init_lexer (void); extern void _cpp_init_lexer (void);
static inline void *_cpp_reserve_room (cpp_reader *pfile, size_t have,
size_t extra)
{
if (BUFF_ROOM (pfile->a_buff) < (have + extra))
_cpp_extend_buff (pfile, &pfile->a_buff, extra);
return BUFF_FRONT (pfile->a_buff);
}
extern void *_cpp_commit_buff (cpp_reader *pfile, size_t size);
/* In init.c. */ /* In init.c. */
extern void _cpp_maybe_push_include_file (cpp_reader *); extern void _cpp_maybe_push_include_file (cpp_reader *);
...@@ -733,7 +742,7 @@ extern bool _cpp_read_logical_line_trad (cpp_reader *); ...@@ -733,7 +742,7 @@ extern bool _cpp_read_logical_line_trad (cpp_reader *);
extern void _cpp_overlay_buffer (cpp_reader *pfile, const unsigned char *, extern void _cpp_overlay_buffer (cpp_reader *pfile, const unsigned char *,
size_t); size_t);
extern void _cpp_remove_overlay (cpp_reader *); extern void _cpp_remove_overlay (cpp_reader *);
extern bool _cpp_create_trad_definition (cpp_reader *, cpp_macro *); extern cpp_macro *_cpp_create_trad_definition (cpp_reader *);
extern bool _cpp_expansions_different_trad (const cpp_macro *, extern bool _cpp_expansions_different_trad (const cpp_macro *,
const cpp_macro *); const cpp_macro *);
extern unsigned char *_cpp_copy_replacement_text (const cpp_macro *, extern unsigned char *_cpp_copy_replacement_text (const cpp_macro *,
......
...@@ -3725,6 +3725,25 @@ _cpp_aligned_alloc (cpp_reader *pfile, size_t len) ...@@ -3725,6 +3725,25 @@ _cpp_aligned_alloc (cpp_reader *pfile, size_t len)
return result; return result;
} }
/* Commit or allocate storage from a buffer. */
void *
_cpp_commit_buff (cpp_reader *pfile, size_t size)
{
void *ptr = BUFF_FRONT (pfile->a_buff);
if (pfile->hash_table->alloc_subobject)
{
void *copy = pfile->hash_table->alloc_subobject (size);
memcpy (copy, ptr, size);
ptr = copy;
}
else
BUFF_FRONT (pfile->a_buff) += size;
return ptr;
}
/* Say which field of TOK is in use. */ /* Say which field of TOK is in use. */
enum cpp_token_fld_kind enum cpp_token_fld_kind
......
...@@ -308,12 +308,11 @@ static void replace_args (cpp_reader *, cpp_hashnode *, cpp_macro *, ...@@ -308,12 +308,11 @@ static void replace_args (cpp_reader *, cpp_hashnode *, cpp_macro *,
macro_arg *, source_location); macro_arg *, source_location);
static _cpp_buff *funlike_invocation_p (cpp_reader *, cpp_hashnode *, static _cpp_buff *funlike_invocation_p (cpp_reader *, cpp_hashnode *,
_cpp_buff **, unsigned *); _cpp_buff **, unsigned *);
static bool create_iso_definition (cpp_reader *, cpp_macro *); static cpp_macro *create_iso_definition (cpp_reader *);
/* #define directive parsing and handling. */ /* #define directive parsing and handling. */
static cpp_token *alloc_expansion_token (cpp_reader *, cpp_macro *); static cpp_macro *lex_expansion_token (cpp_reader *, cpp_macro *);
static cpp_token *lex_expansion_token (cpp_reader *, cpp_macro *);
static bool warn_of_redefinition (cpp_reader *, cpp_hashnode *, static bool warn_of_redefinition (cpp_reader *, cpp_hashnode *,
const cpp_macro *); const cpp_macro *);
static bool parse_params (cpp_reader *, unsigned *, bool *); static bool parse_params (cpp_reader *, unsigned *, bool *);
...@@ -1235,13 +1234,14 @@ funlike_invocation_p (cpp_reader *pfile, cpp_hashnode *node, ...@@ -1235,13 +1234,14 @@ funlike_invocation_p (cpp_reader *pfile, cpp_hashnode *node,
static inline unsigned int static inline unsigned int
macro_real_token_count (const cpp_macro *macro) macro_real_token_count (const cpp_macro *macro)
{ {
unsigned int i;
if (__builtin_expect (!macro->extra_tokens, true)) if (__builtin_expect (!macro->extra_tokens, true))
return macro->count; return macro->count;
for (i = 0; i < macro->count; i++)
if (macro->exp.tokens[i].type == CPP_PASTE) for (unsigned i = macro->count; i--;)
return i; if (macro->exp.tokens[i].type != CPP_PASTE)
abort (); return i + 1;
return 0;
} }
/* Push the context of a macro with hash entry NODE onto the context /* Push the context of a macro with hash entry NODE onto the context
...@@ -1773,7 +1773,7 @@ replace_args (cpp_reader *pfile, cpp_hashnode *node, cpp_macro *macro, ...@@ -1773,7 +1773,7 @@ replace_args (cpp_reader *pfile, cpp_hashnode *node, cpp_macro *macro,
arg->stringified = stringify_arg (pfile, arg); arg->stringified = stringify_arg (pfile, arg);
} }
else if ((src->flags & PASTE_LEFT) else if ((src->flags & PASTE_LEFT)
|| (src > macro->exp.tokens && (src[-1].flags & PASTE_LEFT))) || (src != macro->exp.tokens && (src[-1].flags & PASTE_LEFT)))
total += arg->count - 1; total += arg->count - 1;
else else
{ {
...@@ -3078,10 +3078,9 @@ _cpp_save_parameter (cpp_reader *pfile, unsigned n, cpp_hashnode *node, ...@@ -3078,10 +3078,9 @@ _cpp_save_parameter (cpp_reader *pfile, unsigned n, cpp_hashnode *node,
saved[n].canonical_node = node; saved[n].canonical_node = node;
saved[n].value = node->value; saved[n].value = node->value;
if (BUFF_ROOM (pfile->a_buff) < (n + 1) * sizeof (cpp_hashnode *)) void *base = _cpp_reserve_room (pfile, n * sizeof (cpp_hashnode *),
_cpp_extend_buff (pfile, &pfile->a_buff, sizeof (cpp_hashnode *)); sizeof (cpp_hashnode *));
((cpp_hashnode **)base)[n] = spelling;
((cpp_hashnode **) BUFF_FRONT (pfile->a_buff))[n] = spelling;
/* Morph into a macro arg. */ /* Morph into a macro arg. */
node->flags |= NODE_MACRO_ARG; node->flags |= NODE_MACRO_ARG;
...@@ -3226,26 +3225,18 @@ parse_params (cpp_reader *pfile, unsigned *n_ptr, bool *varadic_ptr) ...@@ -3226,26 +3225,18 @@ parse_params (cpp_reader *pfile, unsigned *n_ptr, bool *varadic_ptr)
return ok; return ok;
} }
/* Allocate room for a token from a macro's replacement list. */
static cpp_token *
alloc_expansion_token (cpp_reader *pfile, cpp_macro *macro)
{
if (BUFF_ROOM (pfile->a_buff) < (macro->count + 1) * sizeof (cpp_token))
_cpp_extend_buff (pfile, &pfile->a_buff, sizeof (cpp_token));
return &((cpp_token *) BUFF_FRONT (pfile->a_buff))[macro->count++];
}
/* Lex a token from the expansion of MACRO, but mark parameters as we /* Lex a token from the expansion of MACRO, but mark parameters as we
find them and warn of traditional stringification. */ find them and warn of traditional stringification. */
static cpp_token * static cpp_macro *
lex_expansion_token (cpp_reader *pfile, cpp_macro *macro) lex_expansion_token (cpp_reader *pfile, cpp_macro *macro)
{ {
cpp_token *token, *saved_cur_token; macro = (cpp_macro *)_cpp_reserve_room (pfile,
sizeof (cpp_macro) - sizeof (cpp_token)
saved_cur_token = pfile->cur_token; + macro->count * sizeof (cpp_token),
pfile->cur_token = alloc_expansion_token (pfile, macro); sizeof (cpp_token));
token = _cpp_lex_direct (pfile); cpp_token *saved_cur_token = pfile->cur_token;
pfile->cur_token = &macro->exp.tokens[macro->count];
cpp_token *token = _cpp_lex_direct (pfile);
pfile->cur_token = saved_cur_token; pfile->cur_token = saved_cur_token;
/* Is this a parameter? */ /* Is this a parameter? */
...@@ -3261,52 +3252,45 @@ lex_expansion_token (cpp_reader *pfile, cpp_macro *macro) ...@@ -3261,52 +3252,45 @@ lex_expansion_token (cpp_reader *pfile, cpp_macro *macro)
&& (token->type == CPP_STRING || token->type == CPP_CHAR)) && (token->type == CPP_STRING || token->type == CPP_CHAR))
check_trad_stringification (pfile, macro, &token->val.str); check_trad_stringification (pfile, macro, &token->val.str);
return token; return macro;
} }
static bool static cpp_macro *
create_iso_definition (cpp_reader *pfile, cpp_macro *macro) create_iso_definition (cpp_reader *pfile)
{ {
cpp_token *token;
const cpp_token *ctoken;
bool following_paste_op = false; bool following_paste_op = false;
const char *paste_op_error_msg = const char *paste_op_error_msg =
N_("'##' cannot appear at either end of a macro expansion"); N_("'##' cannot appear at either end of a macro expansion");
unsigned int num_extra_tokens = 0; unsigned int num_extra_tokens = 0;
unsigned nparms = 0; unsigned nparms = 0;
cpp_hashnode **params = NULL;
bool varadic = false; bool varadic = false;
bool ok = false; bool ok = false;
cpp_macro *macro = NULL;
/* Get the first token of the expansion (or the '(' of a /* Look at the first token, to see if this is a function-like
function-like macro). */ macro. */
ctoken = _cpp_lex_token (pfile); cpp_token first;
cpp_token *saved_cur_token = pfile->cur_token;
pfile->cur_token = &first;
cpp_token *token = _cpp_lex_direct (pfile);
pfile->cur_token = saved_cur_token;
if (ctoken->flags & PREV_WHITE) if (token->flags & PREV_WHITE)
/* Preceeded by space, must be part of expansion. */; /* Preceeded by space, must be part of expansion. */;
else if (ctoken->type == CPP_OPEN_PAREN) else if (token->type == CPP_OPEN_PAREN)
{ {
/* An open-paren, get a parameter list. */ /* An open-paren, get a parameter list. */
if (!parse_params (pfile, &nparms, &varadic)) if (!parse_params (pfile, &nparms, &varadic))
goto out; goto out;
macro->variadic = varadic;
macro->paramc = nparms;
macro->params = (cpp_hashnode **) BUFF_FRONT (pfile->a_buff);
/* Success. Commit or allocate the parameter array. */ params = (cpp_hashnode **)_cpp_commit_buff
if (pfile->hash_table->alloc_subobject) (pfile, sizeof (cpp_hashnode *) * nparms);
{ token = NULL;
cpp_hashnode **params =
(cpp_hashnode **) pfile->hash_table->alloc_subobject
(sizeof (cpp_hashnode *) * macro->paramc);
memcpy (params, macro->params,
sizeof (cpp_hashnode *) * macro->paramc);
macro->params = params;
} }
else else if (token->type != CPP_EOF
BUFF_FRONT (pfile->a_buff) = (uchar *) &macro->params[macro->paramc]; && !(token->type == CPP_COMMENT
macro->fun_like = 1; && ! CPP_OPTION (pfile, discard_comments_in_macro_exp)))
}
else if (ctoken->type != CPP_EOF && !(ctoken->flags & PREV_WHITE))
{ {
/* While ISO C99 requires whitespace before replacement text /* While ISO C99 requires whitespace before replacement text
in a macro definition, ISO C90 with TC1 allows characters in a macro definition, ISO C90 with TC1 allows characters
...@@ -3319,7 +3303,7 @@ create_iso_definition (cpp_reader *pfile, cpp_macro *macro) ...@@ -3319,7 +3303,7 @@ create_iso_definition (cpp_reader *pfile, cpp_macro *macro)
else else
{ {
int warntype = CPP_DL_WARNING; int warntype = CPP_DL_WARNING;
switch (ctoken->type) switch (token->type)
{ {
case CPP_ATSIGN: case CPP_ATSIGN:
case CPP_AT_NAME: case CPP_AT_NAME:
...@@ -3330,7 +3314,7 @@ create_iso_definition (cpp_reader *pfile, cpp_macro *macro) ...@@ -3330,7 +3314,7 @@ create_iso_definition (cpp_reader *pfile, cpp_macro *macro)
case CPP_OTHER: case CPP_OTHER:
/* Basic character set sans letters, digits and _. */ /* Basic character set sans letters, digits and _. */
if (strchr ("!\"#%&'()*+,-./:;<=>?[\\]^{|}~", if (strchr ("!\"#%&'()*+,-./:;<=>?[\\]^{|}~",
ctoken->val.str.text[0]) == NULL) token->val.str.text[0]) == NULL)
warntype = CPP_DL_PEDWARN; warntype = CPP_DL_PEDWARN;
break; break;
default: default:
...@@ -3343,16 +3327,32 @@ create_iso_definition (cpp_reader *pfile, cpp_macro *macro) ...@@ -3343,16 +3327,32 @@ create_iso_definition (cpp_reader *pfile, cpp_macro *macro)
} }
} }
if (macro->fun_like) macro = _cpp_new_macro (pfile, cmk_macro,
token = lex_expansion_token (pfile, macro); _cpp_reserve_room (pfile, 0, sizeof (cpp_macro)));
if (!token)
{
macro->variadic = varadic;
macro->paramc = nparms;
macro->params = params;
macro->fun_like = true;
}
else else
{ {
token = alloc_expansion_token (pfile, macro); /* Preserve the token we peeked, there is already a single slot for it. */
*token = *ctoken; macro->exp.tokens[0] = *token;
token = &macro->exp.tokens[0];
macro->count = 1;
} }
for ( vaopt_state vaopt_tracker (pfile, macro->variadic, true);;) for (vaopt_state vaopt_tracker (pfile, macro->variadic, true);; token = NULL)
{
if (!token)
{ {
macro = lex_expansion_token (pfile, macro);
token = &macro->exp.tokens[macro->count++];
}
/* Check the stringifying # constraint 6.10.3.2.1 of /* Check the stringifying # constraint 6.10.3.2.1 of
function-like macros when lexing the subsequent token. */ function-like macros when lexing the subsequent token. */
if (macro->count > 1 && token[-1].type == CPP_HASH && macro->fun_like) if (macro->count > 1 && token[-1].type == CPP_HASH && macro->fun_like)
...@@ -3404,14 +3404,16 @@ create_iso_definition (cpp_reader *pfile, cpp_macro *macro) ...@@ -3404,14 +3404,16 @@ create_iso_definition (cpp_reader *pfile, cpp_macro *macro)
goto out; goto out;
} }
if (token[-1].flags & PASTE_LEFT) if (following_paste_op)
{ {
macro->extra_tokens = 1; /* Consecutive paste operators. This one will be moved
to the end. */
num_extra_tokens++; num_extra_tokens++;
token->val.token_no = macro->count - 1; token->val.token_no = macro->count - 1;
} }
else else
{ {
/* Drop the paste operator. */
--macro->count; --macro->count;
token[-1].flags |= PASTE_LEFT; token[-1].flags |= PASTE_LEFT;
if (token->flags & DIGRAPH) if (token->flags & DIGRAPH)
...@@ -3419,79 +3421,64 @@ create_iso_definition (cpp_reader *pfile, cpp_macro *macro) ...@@ -3419,79 +3421,64 @@ create_iso_definition (cpp_reader *pfile, cpp_macro *macro)
if (token->flags & PREV_WHITE) if (token->flags & PREV_WHITE)
token[-1].flags |= SP_PREV_WHITE; token[-1].flags |= SP_PREV_WHITE;
} }
following_paste_op = true;
} }
else
following_paste_op = false;
if (vaopt_tracker.update (token) == vaopt_state::ERROR) if (vaopt_tracker.update (token) == vaopt_state::ERROR)
goto out; goto out;
following_paste_op = (token->type == CPP_PASTE);
token = lex_expansion_token (pfile, macro);
} }
/* We're committed to winning now. */ /* We're committed to winning now. */
ok = true; ok = true;
macro->exp.tokens = (cpp_token *) BUFF_FRONT (pfile->a_buff);
macro->traditional = 0;
/* Don't count the CPP_EOF. */ /* Don't count the CPP_EOF. */
macro->count--; macro->count--;
macro = (cpp_macro *)_cpp_commit_buff
(pfile, sizeof (cpp_macro) - sizeof (cpp_token)
+ sizeof (cpp_token) * macro->count);
/* Clear whitespace on first token for warn_of_redefinition(). */ /* Clear whitespace on first token for warn_of_redefinition(). */
if (macro->count) if (macro->count)
macro->exp.tokens[0].flags &= ~PREV_WHITE; macro->exp.tokens[0].flags &= ~PREV_WHITE;
/* Commit or allocate the memory. */
if (pfile->hash_table->alloc_subobject)
{
cpp_token *tokns =
(cpp_token *) pfile->hash_table->alloc_subobject (sizeof (cpp_token)
* macro->count);
if (num_extra_tokens) if (num_extra_tokens)
{ {
/* Place second and subsequent ## or %:%: tokens in /* Place second and subsequent ## or %:%: tokens in sequences of
sequences of consecutive such tokens at the end of the consecutive such tokens at the end of the list to preserve
list to preserve information about where they appear, how information about where they appear, how they are spelt and
they are spelt and whether they are preceded by whether they are preceded by whitespace without otherwise
whitespace without otherwise interfering with macro interfering with macro expansion. Remember, this is
expansion. */ extremely rare, so efficiency is not a priority. */
cpp_token *normal_dest = tokns; cpp_token *temp = (cpp_token *)_cpp_reserve_room
cpp_token *extra_dest = tokns + macro->count - num_extra_tokens; (pfile, 0, num_extra_tokens * sizeof (cpp_token));
unsigned int i; unsigned extra_ix = 0, norm_ix = 0;
for (i = 0; i < macro->count; i++) cpp_token *exp = macro->exp.tokens;
{ for (unsigned ix = 0; ix != macro->count; ix++)
if (macro->exp.tokens[i].type == CPP_PASTE) if (exp[ix].type == CPP_PASTE)
*extra_dest++ = macro->exp.tokens[i]; temp[extra_ix++] = exp[ix];
else else
*normal_dest++ = macro->exp.tokens[i]; exp[norm_ix++] = exp[ix];
} memcpy (&exp[norm_ix], temp, num_extra_tokens * sizeof (cpp_token));
}
else /* Record there are extra tokens. */
memcpy (tokns, macro->exp.tokens, sizeof (cpp_token) * macro->count); macro->extra_tokens = 1;
macro->exp.tokens = tokns;
} }
else
BUFF_FRONT (pfile->a_buff) = (uchar *) &macro->exp.tokens[macro->count];
out: out:
pfile->state.va_args_ok = 0; pfile->state.va_args_ok = 0;
_cpp_unsave_parameters (pfile, nparms); _cpp_unsave_parameters (pfile, nparms);
return ok; return ok ? macro : NULL;
} }
/* Parse a macro and save its expansion. Returns nonzero on success. */ cpp_macro *
bool _cpp_new_macro (cpp_reader *pfile, cpp_macro_kind kind, void *placement)
_cpp_create_definition (cpp_reader *pfile, cpp_hashnode *node)
{ {
cpp_macro *macro; cpp_macro *macro = (cpp_macro *) placement;
bool ok;
if (pfile->hash_table->alloc_subobject)
macro = (cpp_macro *) pfile->hash_table->alloc_subobject
(sizeof (cpp_macro));
else
macro = (cpp_macro *) _cpp_aligned_alloc (pfile, sizeof (cpp_macro));
macro->line = pfile->directive_line; macro->line = pfile->directive_line;
macro->params = 0; macro->params = 0;
macro->paramc = 0; macro->paramc = 0;
...@@ -3503,15 +3490,26 @@ _cpp_create_definition (cpp_reader *pfile, cpp_hashnode *node) ...@@ -3503,15 +3490,26 @@ _cpp_create_definition (cpp_reader *pfile, cpp_hashnode *node)
/* To suppress some diagnostics. */ /* To suppress some diagnostics. */
macro->syshdr = pfile->buffer && pfile->buffer->sysp != 0; macro->syshdr = pfile->buffer && pfile->buffer->sysp != 0;
macro->kind = kind;
return macro;
}
/* Parse a macro and save its expansion. Returns nonzero on success. */
bool
_cpp_create_definition (cpp_reader *pfile, cpp_hashnode *node)
{
cpp_macro *macro;
if (CPP_OPTION (pfile, traditional)) if (CPP_OPTION (pfile, traditional))
ok = _cpp_create_trad_definition (pfile, macro); macro = _cpp_create_trad_definition (pfile);
else else
ok = create_iso_definition (pfile, macro); macro = create_iso_definition (pfile);
if (!ok) if (!macro)
return ok; return false;
if (node->type == NT_MACRO) if (cpp_macro_p (node))
{ {
if (CPP_OPTION (pfile, warn_unused_macros)) if (CPP_OPTION (pfile, warn_unused_macros))
_cpp_warn_if_unused_macro (pfile, node, NULL); _cpp_warn_if_unused_macro (pfile, node, NULL);
...@@ -3552,7 +3550,7 @@ _cpp_create_definition (cpp_reader *pfile, cpp_hashnode *node) ...@@ -3552,7 +3550,7 @@ _cpp_create_definition (cpp_reader *pfile, cpp_hashnode *node)
conditional flag */ conditional flag */
node->flags &= ~NODE_CONDITIONAL; node->flags &= ~NODE_CONDITIONAL;
return ok; return true;
} }
/* Notify the use of NODE in a macro-aware context (i.e. expanding it, /* Notify the use of NODE in a macro-aware context (i.e. expanding it,
...@@ -3678,7 +3676,7 @@ cpp_macro_definition (cpp_reader *pfile, cpp_hashnode *node) ...@@ -3678,7 +3676,7 @@ cpp_macro_definition (cpp_reader *pfile, cpp_hashnode *node)
unsigned int count = macro_real_token_count (macro); unsigned int count = macro_real_token_count (macro);
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
{ {
cpp_token *token = &macro->exp.tokens[i]; const cpp_token *token = &macro->exp.tokens[i];
if (token->type == CPP_MACRO_ARG) if (token->type == CPP_MACRO_ARG)
len += NODE_LEN (token->val.macro_arg.spelling); len += NODE_LEN (token->val.macro_arg.spelling);
...@@ -3742,7 +3740,7 @@ cpp_macro_definition (cpp_reader *pfile, cpp_hashnode *node) ...@@ -3742,7 +3740,7 @@ cpp_macro_definition (cpp_reader *pfile, cpp_hashnode *node)
unsigned int count = macro_real_token_count (macro); unsigned int count = macro_real_token_count (macro);
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
{ {
cpp_token *token = &macro->exp.tokens[i]; const cpp_token *token = &macro->exp.tokens[i];
if (token->flags & PREV_WHITE) if (token->flags & PREV_WHITE)
*buffer++ = ' '; *buffer++ = ' ';
......
...@@ -853,7 +853,6 @@ push_replacement_text (cpp_reader *pfile, cpp_hashnode *node) ...@@ -853,7 +853,6 @@ push_replacement_text (cpp_reader *pfile, cpp_hashnode *node)
cpp_macro *macro = node->value.macro; cpp_macro *macro = node->value.macro;
macro->used = 1; macro->used = 1;
text = macro->exp.text; text = macro->exp.text;
macro->traditional = 1;
len = macro->count; len = macro->count;
} }
...@@ -1143,7 +1142,6 @@ save_replacement_text (cpp_reader *pfile, cpp_macro *macro, ...@@ -1143,7 +1142,6 @@ save_replacement_text (cpp_reader *pfile, cpp_macro *macro,
memcpy (exp, pfile->out.base, len); memcpy (exp, pfile->out.base, len);
exp[len] = '\n'; exp[len] = '\n';
macro->exp.text = exp; macro->exp.text = exp;
macro->traditional = 1;
macro->count = len; macro->count = len;
} }
else else
...@@ -1159,7 +1157,6 @@ save_replacement_text (cpp_reader *pfile, cpp_macro *macro, ...@@ -1159,7 +1157,6 @@ save_replacement_text (cpp_reader *pfile, cpp_macro *macro,
exp = BUFF_FRONT (pfile->a_buff); exp = BUFF_FRONT (pfile->a_buff);
block = (struct block *) (exp + macro->count); block = (struct block *) (exp + macro->count);
macro->exp.text = exp; macro->exp.text = exp;
macro->traditional = 1;
/* Write out the block information. */ /* Write out the block information. */
block->text_len = len; block->text_len = len;
...@@ -1179,13 +1176,15 @@ save_replacement_text (cpp_reader *pfile, cpp_macro *macro, ...@@ -1179,13 +1176,15 @@ save_replacement_text (cpp_reader *pfile, cpp_macro *macro,
/* Analyze and save the replacement text of a macro. Returns true on /* Analyze and save the replacement text of a macro. Returns true on
success. */ success. */
bool cpp_macro *
_cpp_create_trad_definition (cpp_reader *pfile, cpp_macro *macro) _cpp_create_trad_definition (cpp_reader *pfile)
{ {
const uchar *cur; const uchar *cur;
uchar *limit; uchar *limit;
cpp_context *context = pfile->context; cpp_context *context = pfile->context;
unsigned nparms = 0; unsigned nparms = 0;
int fun_like = 0;
cpp_hashnode **params = NULL;
/* The context has not been set up for command line defines, and CUR /* The context has not been set up for command line defines, and CUR
has not been updated for the macro name for in-file defines. */ has not been updated for the macro name for in-file defines. */
...@@ -1197,21 +1196,23 @@ _cpp_create_trad_definition (cpp_reader *pfile, cpp_macro *macro) ...@@ -1197,21 +1196,23 @@ _cpp_create_trad_definition (cpp_reader *pfile, cpp_macro *macro)
/* Is this a function-like macro? */ /* Is this a function-like macro? */
if (* CUR (context) == '(') if (* CUR (context) == '(')
{ {
bool ok = scan_parameters (pfile, &nparms); fun_like = +1;
macro->paramc = nparms; if (scan_parameters (pfile, &nparms))
params = (cpp_hashnode **)_cpp_commit_buff
(pfile, sizeof (cpp_hashnode *) * nparms);
else
fun_like = -1;
}
/* Remember the params so we can clear NODE_MACRO_ARG flags. */ cpp_macro *macro = NULL;
macro->params = (cpp_hashnode **) BUFF_FRONT (pfile->a_buff);
/* Setting macro to NULL indicates an error occurred, and if (fun_like >= 0)
prevents unnecessary work in _cpp_scan_out_logical_line. */
if (!ok)
macro = NULL;
else
{ {
BUFF_FRONT (pfile->a_buff) = (uchar *) &macro->params[macro->paramc]; macro = _cpp_new_macro (pfile, cmk_traditional,
macro->fun_like = 1; _cpp_aligned_alloc (pfile, sizeof (cpp_macro)));
} macro->params = params;
macro->paramc = nparms;
macro->fun_like = fun_like != 0;
} }
/* Skip leading whitespace in the replacement text. */ /* Skip leading whitespace in the replacement text. */
...@@ -1225,9 +1226,8 @@ _cpp_create_trad_definition (cpp_reader *pfile, cpp_macro *macro) ...@@ -1225,9 +1226,8 @@ _cpp_create_trad_definition (cpp_reader *pfile, cpp_macro *macro)
_cpp_unsave_parameters (pfile, nparms); _cpp_unsave_parameters (pfile, nparms);
if (!macro) if (macro)
return false; {
/* Skip trailing white space. */ /* Skip trailing white space. */
cur = pfile->out.base; cur = pfile->out.base;
limit = pfile->out.cur; limit = pfile->out.cur;
...@@ -1235,8 +1235,9 @@ _cpp_create_trad_definition (cpp_reader *pfile, cpp_macro *macro) ...@@ -1235,8 +1235,9 @@ _cpp_create_trad_definition (cpp_reader *pfile, cpp_macro *macro)
limit--; limit--;
pfile->out.cur = limit; pfile->out.cur = limit;
save_replacement_text (pfile, macro, 0); save_replacement_text (pfile, macro, 0);
}
return true; return macro;
} }
/* Copy SRC of length LEN to DEST, but convert all contiguous /* Copy SRC of length LEN to DEST, but convert all contiguous
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment