[PATCH] Macro definition parameter parsing
https://gcc.gnu.org/ml/gcc-patches/2018-08/msg00977.html libcpp/ * internal.h (_cpp_save_parameter): Take parmno, not macro. (_cpp_unsave_parameters): Declare. * macro.c (_cpp_save_parameter): Take parm number, not macro. Return true on success. (_cpp_unsave_parameters): New. (parse_params): Take parm_no and variadic pointers, not macro. Reimplement parsing logic. (create_iso_definition): Adjust parse_params changes. Call _cpp_unsave_parameters here. (_cpp_create_definition): Don't unsave params here. * traditional.c (scan_parameters): Take n_param pointer, adjust. (_cpp_create_trad_definition): Ajust scan_parameters change. Call _cpp_unsave_parameters. gcc/testsuite/ * gcc.dg/cpp/macsyntx.c: Adjust expected errors. * gcc.dg/cpp/macsyntx2.c: likewise. From-SVN: r263600
This commit is contained in:
parent
c37da7c0e8
commit
729a01f72c
@ -1,3 +1,8 @@
|
||||
2018-08-16 Nathan Sidwell <nathan@acm.org>
|
||||
|
||||
* gcc.dg/cpp/macsyntx.c: Adjust expected errors.
|
||||
* gcc.dg/cpp/macsyntx2.c: likewise.
|
||||
|
||||
2018-08-15 Uros Bizjak <ubizjak@gmail.com>
|
||||
|
||||
PR testsuite/86745
|
||||
|
@ -21,14 +21,14 @@
|
||||
|
||||
#define ; /* { dg-error "identifier" } */
|
||||
#define SEMI; /* { dg-warning "space" } */
|
||||
#define foo(X /* { dg-error "missing" } */
|
||||
#define foo(X /* { dg-error "expected" } */
|
||||
#define foo\
|
||||
(X,) /* { dg-error "parameter name" } */
|
||||
#define foo(, X) /* { dg-error "parameter name" } */
|
||||
#define foo(X, X) /* { dg-error "duplicate" } */
|
||||
#define foo(X Y) /* { dg-error "comma" } */
|
||||
#define foo(() /* { dg-error "may not appear" } */
|
||||
#define foo(..., X) /* { dg-error "missing" } */
|
||||
#define foo(X Y) /* { dg-error "expected" } */
|
||||
#define foo(() /* { dg-error "parameter name" } */
|
||||
#define foo(..., X) /* { dg-error "expected" } */
|
||||
#define foo \
|
||||
__VA_ARGS__ /* { dg-warning "__VA_ARGS__" } */
|
||||
#define goo(__VA_ARGS__) /* { dg-warning "__VA_ARGS__" } */
|
||||
|
@ -21,14 +21,14 @@
|
||||
|
||||
#define ; /* { dg-error "identifier" } */
|
||||
#define SEMI; /* { dg-warning "space" } */
|
||||
#define foo(X /* { dg-error "missing" } */
|
||||
#define foo(X /* { dg-error "expected" } */
|
||||
#define foo\
|
||||
(X,) /* { dg-error "parameter name" } */
|
||||
#define foo(, X) /* { dg-error "parameter name" } */
|
||||
#define foo(X, X) /* { dg-error "duplicate" } */
|
||||
#define foo(X Y) /* { dg-error "comma" } */
|
||||
#define foo(() /* { dg-error "may not appear" } */
|
||||
#define foo(..., X) /* { dg-error "missing" } */
|
||||
#define foo(X Y) /* { dg-error "expected" } */
|
||||
#define foo(() /* { dg-error "parameter name" } */
|
||||
#define foo(..., X) /* { dg-error "expected" } */
|
||||
#define foo \
|
||||
__VA_ARGS__ /* { dg-warning "__VA_ARGS__" } */
|
||||
#define goo(__VA_ARGS__) /* { dg-warning "__VA_ARGS__" } */
|
||||
|
@ -1,6 +1,19 @@
|
||||
2018-08-16 Nathan Sidwell <nathan@acm.org>
|
||||
|
||||
libcpp/
|
||||
* internal.h (_cpp_save_parameter): Take parmno, not macro.
|
||||
(_cpp_unsave_parameters): Declare.
|
||||
* macro.c (_cpp_save_parameter): Take parm number, not macro.
|
||||
Return true on success.
|
||||
(_cpp_unsave_parameters): New.
|
||||
(parse_params): Take parm_no and variadic pointers, not macro.
|
||||
Reimplement parsing logic.
|
||||
(create_iso_definition): Adjust parse_params changes. Call
|
||||
_cpp_unsave_parameters here.
|
||||
(_cpp_create_definition): Don't unsave params here.
|
||||
* traditional.c (scan_parameters): Take n_param pointer, adjust.
|
||||
(_cpp_create_trad_definition): Ajust scan_parameters change. Call
|
||||
_cpp_unsave_parameters.
|
||||
|
||||
* include/cpplib.h (cpp_user_macro_p, cpp_builtin_macro_p)
|
||||
(cpp_macro_p): New inlines.
|
||||
* directives.c (do_pragma_poison): Use cpp_macro_p.
|
||||
|
@ -632,8 +632,9 @@ extern bool _cpp_create_definition (cpp_reader *, cpp_hashnode *);
|
||||
extern void _cpp_pop_context (cpp_reader *);
|
||||
extern void _cpp_push_text_context (cpp_reader *, cpp_hashnode *,
|
||||
const unsigned char *, size_t);
|
||||
extern bool _cpp_save_parameter (cpp_reader *, cpp_macro *, cpp_hashnode *,
|
||||
extern bool _cpp_save_parameter (cpp_reader *, unsigned, cpp_hashnode *,
|
||||
cpp_hashnode *);
|
||||
extern void _cpp_unsave_parameters (cpp_reader *, unsigned);
|
||||
extern bool _cpp_arguments_ok (cpp_reader *, cpp_macro *, const cpp_hashnode *,
|
||||
unsigned int);
|
||||
extern const unsigned char *_cpp_builtin_macro_text (cpp_reader *,
|
||||
|
280
libcpp/macro.c
280
libcpp/macro.c
@ -316,7 +316,7 @@ static cpp_token *alloc_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 *,
|
||||
const cpp_macro *);
|
||||
static bool parse_params (cpp_reader *, cpp_macro *);
|
||||
static bool parse_params (cpp_reader *, unsigned *, bool *);
|
||||
static void check_trad_stringification (cpp_reader *, const cpp_macro *,
|
||||
const cpp_string *);
|
||||
static bool reached_end_of_context (cpp_context *);
|
||||
@ -3053,119 +3053,158 @@ _cpp_free_definition (cpp_hashnode *h)
|
||||
}
|
||||
|
||||
/* Save parameter NODE (spelling SPELLING) to the parameter list of
|
||||
macro MACRO. Returns zero on success, nonzero if the parameter is
|
||||
a duplicate. */
|
||||
macro MACRO. Returns true on success, false on failure. */
|
||||
bool
|
||||
_cpp_save_parameter (cpp_reader *pfile, cpp_macro *macro, cpp_hashnode *node,
|
||||
_cpp_save_parameter (cpp_reader *pfile, unsigned n, cpp_hashnode *node,
|
||||
cpp_hashnode *spelling)
|
||||
{
|
||||
unsigned int len;
|
||||
/* Constraint 6.10.3.6 - duplicate parameter names. */
|
||||
if (node->flags & NODE_MACRO_ARG)
|
||||
{
|
||||
cpp_error (pfile, CPP_DL_ERROR, "duplicate macro parameter \"%s\"",
|
||||
NODE_NAME (node));
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (BUFF_ROOM (pfile->a_buff)
|
||||
< (macro->paramc + 1) * sizeof (cpp_hashnode *))
|
||||
_cpp_extend_buff (pfile, &pfile->a_buff, sizeof (cpp_hashnode *));
|
||||
|
||||
((cpp_hashnode **) BUFF_FRONT (pfile->a_buff))[macro->paramc++] = spelling;
|
||||
node->flags |= NODE_MACRO_ARG;
|
||||
len = macro->paramc * sizeof (struct macro_arg_saved_data);
|
||||
unsigned len = (n + 1) * sizeof (struct macro_arg_saved_data);
|
||||
if (len > pfile->macro_buffer_len)
|
||||
{
|
||||
pfile->macro_buffer = XRESIZEVEC (unsigned char, pfile->macro_buffer,
|
||||
len);
|
||||
pfile->macro_buffer
|
||||
= XRESIZEVEC (unsigned char, pfile->macro_buffer, len);
|
||||
pfile->macro_buffer_len = len;
|
||||
}
|
||||
struct macro_arg_saved_data save;
|
||||
save.value = node->value;
|
||||
save.canonical_node = node;
|
||||
((struct macro_arg_saved_data *) pfile->macro_buffer)[macro->paramc - 1]
|
||||
= save;
|
||||
|
||||
node->value.arg_index = macro->paramc;
|
||||
return false;
|
||||
macro_arg_saved_data *saved = (macro_arg_saved_data *)pfile->macro_buffer;
|
||||
saved[n].canonical_node = node;
|
||||
saved[n].value = node->value;
|
||||
|
||||
if (BUFF_ROOM (pfile->a_buff) < (n + 1) * sizeof (cpp_hashnode *))
|
||||
_cpp_extend_buff (pfile, &pfile->a_buff, sizeof (cpp_hashnode *));
|
||||
|
||||
((cpp_hashnode **) BUFF_FRONT (pfile->a_buff))[n] = spelling;
|
||||
|
||||
/* Morph into a macro arg. */
|
||||
node->flags |= NODE_MACRO_ARG;
|
||||
/* Index is 1 based. */
|
||||
node->value.arg_index = n + 1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Check the syntax of the parameters in a MACRO definition. Returns
|
||||
false if an error occurs. */
|
||||
static bool
|
||||
parse_params (cpp_reader *pfile, cpp_macro *macro)
|
||||
/* Restore the parameters to their previous state. */
|
||||
void
|
||||
_cpp_unsave_parameters (cpp_reader *pfile, unsigned n)
|
||||
{
|
||||
unsigned int prev_ident = 0;
|
||||
/* Clear the fast argument lookup indices. */
|
||||
while (n--)
|
||||
{
|
||||
struct macro_arg_saved_data *save =
|
||||
&((struct macro_arg_saved_data *) pfile->macro_buffer)[n];
|
||||
|
||||
for (;;)
|
||||
struct cpp_hashnode *node = save->canonical_node;
|
||||
node->value = save->value;
|
||||
node->flags &= ~NODE_MACRO_ARG;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check the syntax of the parameters in a MACRO definition. Return
|
||||
false on failure. Set *N_PTR and *VARADIC_PTR as appropriate.
|
||||
'(' ')'
|
||||
'(' parm-list ',' last-parm ')'
|
||||
'(' last-parm ')'
|
||||
parm-list: name
|
||||
| parm-list, name
|
||||
last-parm: name
|
||||
| name '...'
|
||||
| '...'
|
||||
*/
|
||||
static bool
|
||||
parse_params (cpp_reader *pfile, unsigned *n_ptr, bool *varadic_ptr)
|
||||
{
|
||||
unsigned nparms = 0;
|
||||
bool ok = false;
|
||||
|
||||
for (bool prev_ident = false;;)
|
||||
{
|
||||
const cpp_token *token = _cpp_lex_token (pfile);
|
||||
|
||||
switch (token->type)
|
||||
{
|
||||
default:
|
||||
case CPP_COMMENT:
|
||||
/* Allow/ignore comments in parameter lists if we are
|
||||
preserving comments in macro expansions. */
|
||||
if (token->type == CPP_COMMENT
|
||||
&& ! CPP_OPTION (pfile, discard_comments_in_macro_exp))
|
||||
continue;
|
||||
if (!CPP_OPTION (pfile, discard_comments_in_macro_exp))
|
||||
break;
|
||||
|
||||
cpp_error (pfile, CPP_DL_ERROR,
|
||||
"\"%s\" may not appear in macro parameter list",
|
||||
cpp_token_as_text (pfile, token));
|
||||
return false;
|
||||
/* FALLTHRU */
|
||||
default:
|
||||
bad:
|
||||
{
|
||||
const char *const msgs[5] =
|
||||
{
|
||||
N_("expected parameter name, found \"%s\""),
|
||||
N_("expected ',' or ')', found \"%s\""),
|
||||
N_("expected parameter name before end of line"),
|
||||
N_("expected ')' before end of line"),
|
||||
N_("expected ')' after \"...\"")
|
||||
};
|
||||
unsigned ix = prev_ident;
|
||||
const unsigned char *as_text = NULL;
|
||||
if (*varadic_ptr)
|
||||
ix = 4;
|
||||
else if (token->type == CPP_EOF)
|
||||
ix += 2;
|
||||
else
|
||||
as_text = cpp_token_as_text (pfile, token);
|
||||
cpp_error (pfile, CPP_DL_ERROR, msgs[ix], as_text);
|
||||
}
|
||||
goto out;
|
||||
|
||||
case CPP_NAME:
|
||||
if (prev_ident)
|
||||
{
|
||||
cpp_error (pfile, CPP_DL_ERROR,
|
||||
"macro parameters must be comma-separated");
|
||||
return false;
|
||||
}
|
||||
prev_ident = 1;
|
||||
if (prev_ident || *varadic_ptr)
|
||||
goto bad;
|
||||
prev_ident = true;
|
||||
|
||||
if (_cpp_save_parameter (pfile, macro, token->val.node.node,
|
||||
token->val.node.spelling))
|
||||
return false;
|
||||
continue;
|
||||
if (!_cpp_save_parameter (pfile, nparms, token->val.node.node,
|
||||
token->val.node.spelling))
|
||||
goto out;
|
||||
nparms++;
|
||||
break;
|
||||
|
||||
case CPP_CLOSE_PAREN:
|
||||
if (prev_ident || macro->paramc == 0)
|
||||
return true;
|
||||
if (prev_ident || !nparms || *varadic_ptr)
|
||||
{
|
||||
ok = true;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Fall through to pick up the error. */
|
||||
/* FALLTHRU */
|
||||
case CPP_COMMA:
|
||||
if (!prev_ident)
|
||||
{
|
||||
cpp_error (pfile, CPP_DL_ERROR, "parameter name missing");
|
||||
return false;
|
||||
}
|
||||
prev_ident = 0;
|
||||
continue;
|
||||
if (!prev_ident || *varadic_ptr)
|
||||
goto bad;
|
||||
prev_ident = false;
|
||||
break;
|
||||
|
||||
case CPP_ELLIPSIS:
|
||||
macro->variadic = 1;
|
||||
if (*varadic_ptr)
|
||||
goto bad;
|
||||
*varadic_ptr = true;
|
||||
if (!prev_ident)
|
||||
{
|
||||
_cpp_save_parameter (pfile, macro,
|
||||
/* An ISO bare ellipsis. */
|
||||
_cpp_save_parameter (pfile, nparms,
|
||||
pfile->spec_nodes.n__VA_ARGS__,
|
||||
pfile->spec_nodes.n__VA_ARGS__);
|
||||
nparms++;
|
||||
pfile->state.va_args_ok = 1;
|
||||
if (! CPP_OPTION (pfile, c99)
|
||||
&& CPP_OPTION (pfile, cpp_pedantic)
|
||||
&& CPP_OPTION (pfile, warn_variadic_macros))
|
||||
{
|
||||
if (CPP_OPTION (pfile, cplusplus))
|
||||
cpp_pedwarning
|
||||
(pfile, CPP_W_VARIADIC_MACROS,
|
||||
"anonymous variadic macros were introduced in C++11");
|
||||
else
|
||||
cpp_pedwarning
|
||||
(pfile, CPP_W_VARIADIC_MACROS,
|
||||
"anonymous variadic macros were introduced in C99");
|
||||
}
|
||||
cpp_pedwarning
|
||||
(pfile, CPP_W_VARIADIC_MACROS,
|
||||
CPP_OPTION (pfile, cplusplus)
|
||||
? N_("anonymous variadic macros were introduced in C++11")
|
||||
: N_("anonymous variadic macros were introduced in C99"));
|
||||
else if (CPP_OPTION (pfile, cpp_warn_c90_c99_compat) > 0
|
||||
&& ! CPP_OPTION (pfile, cplusplus))
|
||||
cpp_error (pfile, CPP_DL_WARNING,
|
||||
@ -3173,26 +3212,18 @@ parse_params (cpp_reader *pfile, cpp_macro *macro)
|
||||
}
|
||||
else if (CPP_OPTION (pfile, cpp_pedantic)
|
||||
&& CPP_OPTION (pfile, warn_variadic_macros))
|
||||
{
|
||||
if (CPP_OPTION (pfile, cplusplus))
|
||||
cpp_pedwarning (pfile, CPP_W_VARIADIC_MACROS,
|
||||
"ISO C++ does not permit named variadic macros");
|
||||
else
|
||||
cpp_pedwarning (pfile, CPP_W_VARIADIC_MACROS,
|
||||
"ISO C does not permit named variadic macros");
|
||||
}
|
||||
|
||||
/* We're at the end, and just expect a closing parenthesis. */
|
||||
token = _cpp_lex_token (pfile);
|
||||
if (token->type == CPP_CLOSE_PAREN)
|
||||
return true;
|
||||
/* Fall through. */
|
||||
|
||||
case CPP_EOF:
|
||||
cpp_error (pfile, CPP_DL_ERROR, "missing ')' in macro parameter list");
|
||||
return false;
|
||||
cpp_pedwarning (pfile, CPP_W_VARIADIC_MACROS,
|
||||
CPP_OPTION (pfile, cplusplus)
|
||||
? N_("ISO C++ does not permit named variadic macros")
|
||||
: N_("ISO C does not permit named variadic macros"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
*n_ptr = nparms;
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
/* Allocate room for a token from a macro's replacement list. */
|
||||
@ -3242,17 +3273,24 @@ create_iso_definition (cpp_reader *pfile, cpp_macro *macro)
|
||||
const char *paste_op_error_msg =
|
||||
N_("'##' cannot appear at either end of a macro expansion");
|
||||
unsigned int num_extra_tokens = 0;
|
||||
unsigned nparms = 0;
|
||||
bool varadic = false;
|
||||
bool ok = false;
|
||||
|
||||
/* Get the first token of the expansion (or the '(' of a
|
||||
function-like macro). */
|
||||
ctoken = _cpp_lex_token (pfile);
|
||||
|
||||
if (ctoken->type == CPP_OPEN_PAREN && !(ctoken->flags & PREV_WHITE))
|
||||
if (ctoken->flags & PREV_WHITE)
|
||||
/* Preceeded by space, must be part of expansion. */;
|
||||
else if (ctoken->type == CPP_OPEN_PAREN)
|
||||
{
|
||||
bool ok = parse_params (pfile, macro);
|
||||
/* An open-paren, get a parameter list. */
|
||||
if (!parse_params (pfile, &nparms, &varadic))
|
||||
goto out;
|
||||
macro->variadic = varadic;
|
||||
macro->paramc = nparms;
|
||||
macro->params = (cpp_hashnode **) BUFF_FRONT (pfile->a_buff);
|
||||
if (!ok)
|
||||
return false;
|
||||
|
||||
/* Success. Commit or allocate the parameter array. */
|
||||
if (pfile->hash_table->alloc_subobject)
|
||||
@ -3274,14 +3312,10 @@ create_iso_definition (cpp_reader *pfile, cpp_macro *macro)
|
||||
in a macro definition, ISO C90 with TC1 allows characters
|
||||
from the basic source character set there. */
|
||||
if (CPP_OPTION (pfile, c99))
|
||||
{
|
||||
if (CPP_OPTION (pfile, cplusplus))
|
||||
cpp_error (pfile, CPP_DL_PEDWARN,
|
||||
"ISO C++11 requires whitespace after the macro name");
|
||||
else
|
||||
cpp_error (pfile, CPP_DL_PEDWARN,
|
||||
"ISO C99 requires whitespace after the macro name");
|
||||
}
|
||||
cpp_error (pfile, CPP_DL_PEDWARN,
|
||||
CPP_OPTION (pfile, cplusplus)
|
||||
? N_("ISO C++11 requires whitespace after the macro name")
|
||||
: N_("ISO C99 requires whitespace after the macro name"));
|
||||
else
|
||||
{
|
||||
int warntype = CPP_DL_WARNING;
|
||||
@ -3317,10 +3351,7 @@ create_iso_definition (cpp_reader *pfile, cpp_macro *macro)
|
||||
*token = *ctoken;
|
||||
}
|
||||
|
||||
/* The argument doesn't matter here. */
|
||||
vaopt_state vaopt_tracker (pfile, macro->variadic, true);
|
||||
|
||||
for (;;)
|
||||
for ( vaopt_state vaopt_tracker (pfile, macro->variadic, true);;)
|
||||
{
|
||||
/* Check the stringifying # constraint 6.10.3.2.1 of
|
||||
function-like macros when lexing the subsequent token. */
|
||||
@ -3343,7 +3374,7 @@ create_iso_definition (cpp_reader *pfile, cpp_macro *macro)
|
||||
{
|
||||
cpp_error (pfile, CPP_DL_ERROR,
|
||||
"'#' is not followed by a macro parameter");
|
||||
return false;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
@ -3355,8 +3386,10 @@ create_iso_definition (cpp_reader *pfile, cpp_macro *macro)
|
||||
if (following_paste_op)
|
||||
{
|
||||
cpp_error (pfile, CPP_DL_ERROR, paste_op_error_msg);
|
||||
return false;
|
||||
goto out;
|
||||
}
|
||||
if (!vaopt_tracker.completed ())
|
||||
goto out;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -3368,7 +3401,7 @@ create_iso_definition (cpp_reader *pfile, cpp_macro *macro)
|
||||
if (macro->count == 1)
|
||||
{
|
||||
cpp_error (pfile, CPP_DL_ERROR, paste_op_error_msg);
|
||||
return false;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (token[-1].flags & PASTE_LEFT)
|
||||
@ -3389,14 +3422,14 @@ create_iso_definition (cpp_reader *pfile, cpp_macro *macro)
|
||||
}
|
||||
|
||||
if (vaopt_tracker.update (token) == vaopt_state::ERROR)
|
||||
return false;
|
||||
goto out;
|
||||
|
||||
following_paste_op = (token->type == CPP_PASTE);
|
||||
token = lex_expansion_token (pfile, macro);
|
||||
}
|
||||
|
||||
if (!vaopt_tracker.completed ())
|
||||
return false;
|
||||
/* We're committed to winning now. */
|
||||
ok = true;
|
||||
|
||||
macro->exp.tokens = (cpp_token *) BUFF_FRONT (pfile->a_buff);
|
||||
macro->traditional = 0;
|
||||
@ -3440,7 +3473,11 @@ create_iso_definition (cpp_reader *pfile, cpp_macro *macro)
|
||||
else
|
||||
BUFF_FRONT (pfile->a_buff) = (uchar *) ¯o->exp.tokens[macro->count];
|
||||
|
||||
return true;
|
||||
out:
|
||||
pfile->state.va_args_ok = 0;
|
||||
_cpp_unsave_parameters (pfile, nparms);
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
/* Parse a macro and save its expansion. Returns nonzero on success. */
|
||||
@ -3448,7 +3485,6 @@ bool
|
||||
_cpp_create_definition (cpp_reader *pfile, cpp_hashnode *node)
|
||||
{
|
||||
cpp_macro *macro;
|
||||
unsigned int i;
|
||||
bool ok;
|
||||
|
||||
if (pfile->hash_table->alloc_subobject)
|
||||
@ -3470,27 +3506,7 @@ _cpp_create_definition (cpp_reader *pfile, cpp_hashnode *node)
|
||||
if (CPP_OPTION (pfile, traditional))
|
||||
ok = _cpp_create_trad_definition (pfile, macro);
|
||||
else
|
||||
{
|
||||
ok = create_iso_definition (pfile, macro);
|
||||
|
||||
/* We set the type for SEEN_EOL() in directives.c.
|
||||
|
||||
Longer term we should lex the whole line before coming here,
|
||||
and just copy the expansion. */
|
||||
|
||||
/* Stop the lexer accepting __VA_ARGS__. */
|
||||
pfile->state.va_args_ok = 0;
|
||||
}
|
||||
|
||||
/* Clear the fast argument lookup indices. */
|
||||
for (i = macro->paramc; i-- > 0; )
|
||||
{
|
||||
struct macro_arg_saved_data *save =
|
||||
&((struct macro_arg_saved_data *) pfile->macro_buffer)[i];
|
||||
struct cpp_hashnode *node = save->canonical_node;
|
||||
node->flags &= ~ NODE_MACRO_ARG;
|
||||
node->value = save->value;
|
||||
}
|
||||
ok = create_iso_definition (pfile, macro);
|
||||
|
||||
if (!ok)
|
||||
return ok;
|
||||
|
@ -89,7 +89,7 @@ static cpp_hashnode *lex_identifier (cpp_reader *, const uchar *);
|
||||
static const uchar *copy_comment (cpp_reader *, const uchar *, int);
|
||||
static void check_output_buffer (cpp_reader *, size_t);
|
||||
static void push_replacement_text (cpp_reader *, cpp_hashnode *);
|
||||
static bool scan_parameters (cpp_reader *, cpp_macro *);
|
||||
static bool scan_parameters (cpp_reader *, unsigned *);
|
||||
static bool recursive_macro (cpp_reader *, cpp_hashnode *);
|
||||
static void save_replacement_text (cpp_reader *, cpp_macro *, unsigned int);
|
||||
static void maybe_start_funlike (cpp_reader *, cpp_hashnode *, const uchar *,
|
||||
@ -1082,11 +1082,12 @@ replace_args_and_push (cpp_reader *pfile, struct fun_macro *fmacro)
|
||||
duplicate parameter). On success, CUR (pfile->context) is just
|
||||
past the closing parenthesis. */
|
||||
static bool
|
||||
scan_parameters (cpp_reader *pfile, cpp_macro *macro)
|
||||
scan_parameters (cpp_reader *pfile, unsigned *n_ptr)
|
||||
{
|
||||
const uchar *cur = CUR (pfile->context) + 1;
|
||||
bool ok;
|
||||
|
||||
unsigned nparms = 0;
|
||||
for (;;)
|
||||
{
|
||||
cur = skip_whitespace (pfile, cur, true /* skip_comments */);
|
||||
@ -1095,8 +1096,9 @@ scan_parameters (cpp_reader *pfile, cpp_macro *macro)
|
||||
{
|
||||
struct cpp_hashnode *id = lex_identifier (pfile, cur);
|
||||
ok = false;
|
||||
if (_cpp_save_parameter (pfile, macro, id, id))
|
||||
if (!_cpp_save_parameter (pfile, nparms, id, id))
|
||||
break;
|
||||
nparms++;
|
||||
cur = skip_whitespace (pfile, CUR (pfile->context),
|
||||
true /* skip_comments */);
|
||||
if (*cur == ',')
|
||||
@ -1108,10 +1110,12 @@ scan_parameters (cpp_reader *pfile, cpp_macro *macro)
|
||||
break;
|
||||
}
|
||||
|
||||
ok = (*cur == ')' && macro->paramc == 0);
|
||||
ok = (*cur == ')' && !nparms);
|
||||
break;
|
||||
}
|
||||
|
||||
*n_ptr = nparms;
|
||||
|
||||
if (!ok)
|
||||
cpp_error (pfile, CPP_DL_ERROR, "syntax error in macro parameter list");
|
||||
|
||||
@ -1181,6 +1185,7 @@ _cpp_create_trad_definition (cpp_reader *pfile, cpp_macro *macro)
|
||||
const uchar *cur;
|
||||
uchar *limit;
|
||||
cpp_context *context = pfile->context;
|
||||
unsigned nparms = 0;
|
||||
|
||||
/* 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. */
|
||||
@ -1192,7 +1197,8 @@ _cpp_create_trad_definition (cpp_reader *pfile, cpp_macro *macro)
|
||||
/* Is this a function-like macro? */
|
||||
if (* CUR (context) == '(')
|
||||
{
|
||||
bool ok = scan_parameters (pfile, macro);
|
||||
bool ok = scan_parameters (pfile, &nparms);
|
||||
macro->paramc = nparms;
|
||||
|
||||
/* Remember the params so we can clear NODE_MACRO_ARG flags. */
|
||||
macro->params = (cpp_hashnode **) BUFF_FRONT (pfile->a_buff);
|
||||
@ -1217,6 +1223,8 @@ _cpp_create_trad_definition (cpp_reader *pfile, cpp_macro *macro)
|
||||
_cpp_scan_out_logical_line (pfile, macro, false);
|
||||
pfile->state.prevent_expansion--;
|
||||
|
||||
_cpp_unsave_parameters (pfile, nparms);
|
||||
|
||||
if (!macro)
|
||||
return false;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user