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
BUFF_FRONT (pfile->a_buff) = (uchar *) &macro->params[macro->paramc];
macro->fun_like = 1;
} }
else if (ctoken->type != CPP_EOF && !(ctoken->flags & PREV_WHITE)) else if (token->type != CPP_EOF
&& !(token->type == CPP_COMMENT
&& ! CPP_OPTION (pfile, discard_comments_in_macro_exp)))
{ {
/* 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 (num_extra_tokens)
if (pfile->hash_table->alloc_subobject)
{ {
cpp_token *tokns = /* Place second and subsequent ## or %:%: tokens in sequences of
(cpp_token *) pfile->hash_table->alloc_subobject (sizeof (cpp_token) consecutive such tokens at the end of the list to preserve
* macro->count); information about where they appear, how they are spelt and
if (num_extra_tokens) whether they are preceded by whitespace without otherwise
{ interfering with macro expansion. Remember, this is
/* Place second and subsequent ## or %:%: tokens in extremely rare, so efficiency is not a priority. */
sequences of consecutive such tokens at the end of the cpp_token *temp = (cpp_token *)_cpp_reserve_room
list to preserve information about where they appear, how (pfile, 0, num_extra_tokens * sizeof (cpp_token));
they are spelt and whether they are preceded by unsigned extra_ix = 0, norm_ix = 0;
whitespace without otherwise interfering with macro cpp_token *exp = macro->exp.tokens;
expansion. */ for (unsigned ix = 0; ix != macro->count; ix++)
cpp_token *normal_dest = tokns; if (exp[ix].type == CPP_PASTE)
cpp_token *extra_dest = tokns + macro->count - num_extra_tokens; temp[extra_ix++] = exp[ix];
unsigned int i; else
for (i = 0; i < macro->count; i++) exp[norm_ix++] = exp[ix];
{ memcpy (&exp[norm_ix], temp, num_extra_tokens * sizeof (cpp_token));
if (macro->exp.tokens[i].type == CPP_PASTE)
*extra_dest++ = macro->exp.tokens[i]; /* Record there are extra tokens. */
else macro->extra_tokens = 1;
*normal_dest++ = macro->exp.tokens[i];
}
}
else
memcpy (tokns, macro->exp.tokens, sizeof (cpp_token) * macro->count);
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 = _cpp_new_macro (pfile, cmk_traditional,
macro = NULL; _cpp_aligned_alloc (pfile, sizeof (cpp_macro)));
else macro->params = params;
{ macro->paramc = nparms;
BUFF_FRONT (pfile->a_buff) = (uchar *) &macro->params[macro->paramc]; macro->fun_like = fun_like != 0;
macro->fun_like = 1;
}
} }
/* Skip leading whitespace in the replacement text. */ /* Skip leading whitespace in the replacement text. */
...@@ -1225,18 +1226,18 @@ _cpp_create_trad_definition (cpp_reader *pfile, cpp_macro *macro) ...@@ -1225,18 +1226,18 @@ _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; while (limit > cur && is_space (limit[-1]))
while (limit > cur && is_space (limit[-1])) 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