Commit e808ec9c by Neil Booth Committed by Neil Booth

cpplex.c (_cpp_lex_token): Handle directives in macro arguments.

	* cpplex.c (_cpp_lex_token): Handle directives in macro
	arguments.
	* cpplib.c (_cpp_handle_directive): Save and restore state
	if parsing macro args when entering a directive.
	* cppmacro.c (collect_args): No need to handle directives
	in macro arguments.
	(enter_macro_context, replace_args): Use the original macro
	definition in case it was redefined whilst collecting arguments.
doc:
	* cpp.texi: Update.
testsuite:
	* gcc.dg/cpp/undef1.c: Remove.
	* gcc.dg/cpp/directiv.c: Update.
	* gcc.dg/cpp/mac-dir-1.c, mac-dir-2.c: New tests.

From-SVN: r50091
parent f585a356
2002-02-27 Neil Booth <neil@daikokuya.demon.co.uk>
* cpplex.c (_cpp_lex_token): Handle directives in macro
arguments.
* cpplib.c (_cpp_handle_directive): Save and restore state
if parsing macro args when entering a directive.
* cppmacro.c (collect_args): No need to handle directives
in macro arguments.
(enter_macro_context, replace_args): Use the original macro
definition in case it was redefined whilst collecting arguments.
doc:
* cpp.texi: Update.
2002-02-26 David Edelsohn <edelsohn@gnu.org>
* config/rs6000/aix43.h (THREAD_MODEL_SPEC): Delete.
......
......@@ -828,7 +828,10 @@ _cpp_lex_token (pfile)
/* Is this a directive. If _cpp_handle_directive returns
false, it is an assembler #. */
if (result->type == CPP_HASH
&& !pfile->state.parsing_args
/* 6.10.3 p 11: Directives in a list of macro arguments
gives undefined behavior. This implementation
handles the directive as normal. */
&& pfile->state.parsing_args != 1
&& _cpp_handle_directive (pfile, result->flags & PREV_WHITE))
continue;
if (pfile->cb.line_change && !pfile->state.skipping)
......
......@@ -316,8 +316,17 @@ _cpp_handle_directive (pfile, indented)
{
const directive *dir = 0;
const cpp_token *dname;
bool was_parsing_args = pfile->state.parsing_args;
int skip = 1;
if (was_parsing_args)
{
if (CPP_OPTION (pfile, pedantic))
cpp_pedwarn (pfile,
"embedding a directive within macro arguments is not portable");
pfile->state.parsing_args = 0;
pfile->state.prevent_expansion = 0;
}
start_directive (pfile);
dname = _cpp_lex_token (pfile);
......@@ -393,6 +402,13 @@ _cpp_handle_directive (pfile, indented)
_cpp_backup_tokens (pfile, 1);
end_directive (pfile, skip);
if (was_parsing_args)
{
/* Restore state when within macro args. */
pfile->state.parsing_args = 2;
pfile->state.prevent_expansion = 1;
pfile->buffer->saved_flags |= PREV_WHITE;
}
return skip;
}
......
......@@ -74,7 +74,8 @@ static const cpp_token *stringify_arg PARAMS ((cpp_reader *, macro_arg *));
static void paste_all_tokens PARAMS ((cpp_reader *, const cpp_token *));
static bool paste_tokens PARAMS ((cpp_reader *, const cpp_token **,
const cpp_token *));
static void replace_args PARAMS ((cpp_reader *, cpp_hashnode *, macro_arg *));
static void replace_args PARAMS ((cpp_reader *, cpp_hashnode *, cpp_macro *,
macro_arg *));
static _cpp_buff *funlike_invocation_p PARAMS ((cpp_reader *, cpp_hashnode *));
/* #define directive parsing and handling. */
......@@ -546,34 +547,15 @@ collect_args (pfile, node)
arg++;
}
}
while (token->type != CPP_CLOSE_PAREN
&& token->type != CPP_EOF
&& token->type != CPP_HASH);
while (token->type != CPP_CLOSE_PAREN && token->type != CPP_EOF);
if (token->type == CPP_EOF || token->type == CPP_HASH)
if (token->type == CPP_EOF)
{
bool step_back = false;
/* 6.10.3 paragraph 11: If there are sequences of preprocessing
tokens within the list of arguments that would otherwise act
as preprocessing directives, the behavior is undefined.
This implementation will report a hard error, terminate the
macro invocation, and proceed to process the directive. */
if (token->type == CPP_HASH)
{
cpp_error (pfile,
"directives may not be used inside a macro argument");
step_back = true;
}
else
step_back = (pfile->context->prev || pfile->state.in_directive);
/* We still need the CPP_EOF to end directives, and to end
pre-expansion of a macro argument. Step back is not
unconditional, since we don't want to return a CPP_EOF to our
callers at the end of an -include-d file. */
if (step_back)
if (pfile->context->prev || pfile->state.in_directive)
_cpp_backup_tokens (pfile, 1);
cpp_error (pfile, "unterminated argument list invoking macro \"%s\"",
NODE_NAME (node));
......@@ -697,8 +679,8 @@ enter_macro_context (pfile, node)
return 0;
}
if (node->value.macro->paramc > 0)
replace_args (pfile, node, (macro_arg *) buff->base);
if (macro->paramc > 0)
replace_args (pfile, node, macro, (macro_arg *) buff->base);
_cpp_release_buff (pfile, buff);
}
......@@ -720,9 +702,10 @@ enter_macro_context (pfile, node)
Expand each argument before replacing, unless it is operated upon
by the # or ## operators. */
static void
replace_args (pfile, node, args)
replace_args (pfile, node, macro, args)
cpp_reader *pfile;
cpp_hashnode *node;
cpp_macro *macro;
macro_arg *args;
{
unsigned int i, total;
......@@ -730,13 +713,11 @@ replace_args (pfile, node, args)
const cpp_token **dest, **first;
macro_arg *arg;
_cpp_buff *buff;
cpp_macro *macro;
/* 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. */
macro = node->value.macro;
total = macro->count;
limit = macro->expansion + macro->count;
......
......@@ -121,6 +121,7 @@ Macros
* Variadic Macros::
* Predefined Macros::
* Undefining and Redefining Macros::
* Directives Within Macro Arguments::
* Macro Pitfalls::
Predefined Macros
......@@ -1115,6 +1116,7 @@ macros when you are compiling C++.
* Variadic Macros::
* Predefined Macros::
* Undefining and Redefining Macros::
* Directives Within Macro Arguments::
* Macro Pitfalls::
@end menu
......@@ -2116,6 +2118,48 @@ the same, the redefinition is silently ignored. This allows, for
instance, two different headers to define a common macro. The
preprocessor will only complain if the definitions do not match.
@node Directives Within Macro Arguments
@section Directives Within Macro Arguments
@cindex macro arguments and directives
Occasionally it is convenient to use preprocessor directives within
the arguments of a macro. The C and C++ standards declare that
behavior in these cases is undefined.
Versions of GNU CPP prior to 3.2 would reject such constructs with an
error message. This was the only syntactic difference between normal
functions and function-like macros, so it seemed attractive to remove
this limitation, and people would often be surprised that they could
not use macros in this way. Moreover, sometimes people would use
conditional compilation in the argument list to a normal library
function like @samp{printf}, only to find that after a library upgrade
@samp{printf} had changed to be a function-like macro, and their code
would no longer compile. So from version 3.2 we changed CPP to
successfully process arbitrary directives within macro arguments in
exactly the same way as it would have processed the directive were the
function-like macro invocation not present.
If, within a macro invocation, that macro is redefined, then the new
definition takes effect in time for argument pre-expansion, but the
original definition is still used for argument replacement. Here is a
pathological example:
@smallexample
#define f(x) x x
f (1
#undef f
#define f 2
f)
@end smallexample
@noindent which expands to
@smallexample
1 2 1 2
@end smallexample
@noindent with the semantics described above.
@node Macro Pitfalls
@section Macro Pitfalls
@cindex problems with macros
......
2002-02-27 Neil Booth <neil@daikokuya.demon.co.uk>
* gcc.dg/cpp/undef1.c: Remove.
* gcc.dg/cpp/directiv.c: Update.
* gcc.dg/cpp/mac-dir-1.c, mac-dir-2.c: New tests.
2002-02-27 Michael Meissner <meissner@redhat.com>
* gcc.c-torture/execute/20020226-1.c: New test.
......
......@@ -25,16 +25,11 @@ EMPTY #define bar
/* Our friend the null directive OK? */
#
/* Check that directives always start a line, even if in middle of
macro expansion. */
#define func(x) x
func (2 /* { dg-error "unterminated" "" } */
#define foobar /* { dg-error "directives may not" } */
/* Check newlines end directives, even in function-like macro
invocations. 6.10 paragraph 1.
Note that the #if is still treated as a conditional, so there
should be no errors about #endif without #if. */
#define func(x) x
#if func ( /* { dg-error "unterminated argument" } */
#endif
/* Copyright (C) 2002 Free Software Foundation, Inc. */
/* { dg-do preprocess } */
/* Source: Neil Booth, 26 Feb 2002.
Test that we allow directives in macro arguments. */
/* { dg-do run } */
/* { dg-options "" } */
#define f(x) x
extern void abort (void);
int main ()
{
if (f (
#if f(1) /* True. */
0)) /* False. */
#else
1))
#endif
abort ();
/* Outer f expands to original definition, f in argument expands
to new definition, so result is: if (1 != 2 - 1). */
if (1 != f(2
#undef f
#define f - 1
f))
abort ();
return 0;
}
/* Copyright (C) 2002 Free Software Foundation, Inc. */
/* { dg-do preprocess } */
/* Source: Neil Booth, 26 Feb 2002.
Test that we allow directives in macro arguments. */
/* { dg-do preprocess } */
#define f(x) x
f (
#if 1 /* { dg-warning "not portable" } */
1)
#endif
/* { dg-do preprocess } */
/* 6.9.3.11: ...If there are sequences of preprocessing tokens within
the list of arguments that would otherwise act as preprocessing
directives, the behavior is undefined.
I choose to make this a hard error. It definitely should not cause
a core dump. */
#define foo(bar) bar
foo( blah /* { dg-error "unterminated" "" } */
#undef foo /* { dg-error "may not be used inside" "foo(#undef foo)" } */
blah )
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