cpptrad.c (scan_out_logical_line): Check recursing only when we know we have a macro invocation in the...

* cpptrad.c (scan_out_logical_line): Check recursing only when
	we know we have a macro invocation in the function-like case.
	Only call _cpp_handle_directive if we know we have a good
	directive, or we want to reject a bad directive.
testsuite:
	* gcc.dg/cpp/trad/argcout.c, gcc.dg/cpp/trad/assembler.S,
	gcc.dg/cpp/trad/argcout.c, gcc.dg/cpp/trad/funlike-4.c,
	gcc.dg/cpp/trad/null-drctv.c, gcc.dg/cpp/trad/recurse-1.c,
	gcc.dg/cpp/trad/recurse-2.c, gcc.dg/cpp/trad/recurse-3.c:
	New tests.
	* gcc.dg/cpp/trad/directive.c: Update.

From-SVN: r54942
This commit is contained in:
Neil Booth 2002-06-24 05:46:51 +00:00 committed by Neil Booth
parent 66443ad2fd
commit 2c088b53f9
11 changed files with 183 additions and 13 deletions

View File

@ -1,3 +1,10 @@
2002-06-24 Neil Booth <neil@daikokuya.co.uk>
* cpptrad.c (scan_out_logical_line): Check recursing only when
we know we have a macro invocation in the function-like case.
Only call _cpp_handle_directive if we know we have a good
directive, or we want to reject a bad directive.
2002-06-24 Alan Modra <amodra@bigpond.net.au>
* doloop.c (doloop_valid_p): Correct comment.

View File

@ -579,8 +579,7 @@ scan_out_logical_line (pfile, macro)
if (node->type == NT_MACRO
/* Should we expand for ls_answer? */
&& (lex_state == ls_none || lex_state == ls_fun_open)
&& !pfile->state.prevent_expansion
&& !recursive_macro (pfile, node))
&& !pfile->state.prevent_expansion)
{
/* Macros invalidate MI optimization. */
pfile->mi_valid = false;
@ -592,7 +591,7 @@ scan_out_logical_line (pfile, macro)
fmacro.line = pfile->line;
continue;
}
else
else if (!recursive_macro (pfile, node))
{
/* Remove the object-like macro's name from the
output, and push its replacement text. */
@ -630,10 +629,15 @@ scan_out_logical_line (pfile, macro)
paren_depth++;
if (lex_state == ls_fun_open)
{
lex_state = ls_fun_close;
paren_depth = 1;
out = pfile->out.base + fmacro.offset;
fmacro.args[0] = fmacro.offset;
if (recursive_macro (pfile, fmacro.node))
lex_state = ls_none;
else
{
lex_state = ls_fun_close;
paren_depth = 1;
out = pfile->out.base + fmacro.offset;
fmacro.args[0] = fmacro.offset;
}
}
else if (lex_state == ls_predicate)
lex_state = ls_answer;
@ -681,15 +685,43 @@ scan_out_logical_line (pfile, macro)
break;
case '#':
/* At start of a line it's a directive. */
if (out - 1 == pfile->out.base && !pfile->state.in_directive)
{
/* This is a kludge. We want to have the ISO
preprocessor lex the next token. */
pfile->buffer->cur = cur;
if (_cpp_handle_directive (pfile, false /* indented */))
goto start_logical_line;
/* A directive. With the way _cpp_handle_directive
currently works, we only want to call it if either we
know the directive is OK, or we want it to fail and
be removed from the output. If we want it to be
passed through (the assembler case) then we must not
call _cpp_handle_directive. */
pfile->out.cur = out;
cur = skip_whitespace (pfile, cur, true /* skip_comments */);
out = pfile->out.cur;
if (is_vspace (*cur))
/* Null directive ignored. */
out = pfile->out.base;
else
{
bool do_it = false;
if (is_numstart (*cur))
do_it = true;
else if (is_idstart (*cur))
/* Check whether we know this directive, but don't
advance. */
do_it = lex_identifier (pfile, cur)->directive_index != 0;
if (do_it || CPP_OPTION (pfile, lang) != CLK_ASM)
{
/* This is a kludge. We want to have the ISO
preprocessor lex the next token. */
pfile->buffer->cur = cur;
_cpp_handle_directive (pfile, false /* indented */);
goto start_logical_line;
}
}
}
if (pfile->state.in_expression)
{
lex_state = ls_hash;

View File

@ -1,3 +1,12 @@
2002-06-24 Neil Booth <neil@daikokuya.co.uk>
* gcc.dg/cpp/trad/argcout.c, gcc.dg/cpp/trad/assembler.S,
gcc.dg/cpp/trad/argcout.c, gcc.dg/cpp/trad/funlike-4.c,
gcc.dg/cpp/trad/null-drctv.c, gcc.dg/cpp/trad/recurse-1.c,
gcc.dg/cpp/trad/recurse-2.c, gcc.dg/cpp/trad/recurse-3.c:
New tests.
* gcc.dg/cpp/trad/directive.c: Update.
2002-06-23 Andreas Jaeger <aj@suse.de>
* gcc.c-torture/execute/complex-6.c: New.

View File

@ -0,0 +1,21 @@
/* Test that we correctly complain about an invalid number of macro
arguments. */
/* { dg-do preprocess } */
#define f(x) x
#define g(x, y) x y
#define h()
f(); /* { dg-bogus "requires 1" "no arg is 1 empty arg" } */
f( ); /* { dg-bogus "macro" "1 arg to 1 param macro" } */
f(1,); /* { dg-error "passed 2" "2 args to 1 param macro" } */
f(1,2); /* { dg-error "passed 2" "2 args to 1 param macro" } */
h(); /* { dg-bogus "macro" "no arg to 1 param macro" } */
h( ); /* { dg-error "passed 1" "1 arg to 0 param macro" } */
h(1,2); /* { dg-error "passed 2" "2 args to 0 param macro" } */
g(); /* { dg-error "requires 2" "0 args to 2 param macro" } */
g( ); /* { dg-error "requires 2" "1 args to 2 param macro" } */
g( ,2); /* { dg-bogus "requires 2" "2 args to 2 param macro" } */
g(,); /* { dg-bogus "requires 2" "2 args to 2 param macro" } */
g(1,2,3); /* { dg-error "passed 3" "3 args to 2 param macro" } */

View File

@ -0,0 +1,25 @@
/* Regression test - in assembly language, # may have some significance
other than 'stringize macro argument' and therefore must be preserved
in the output, and should not be warned about. */
/* { dg-do preprocess } */
#define foo() mov r0, #5 /* { dg-bogus "not followed" "spurious warning" } */
entry:
foo()
/* Check we don't EOF on an unknown directive. */
#unknown directive
#error a later diagnostic /* { dg-error "diagnostic" } */
/*
{ dg-final { if ![file exists 20000510-1.i] { return } } }
{ dg-final { set tmp [grep 20000510-1.i # line] } }
{ dg-final { if {[string length $tmp] > 0} \{ } }
{ dg-final { pass "20000510-1.S: # preservation" } }
{ dg-final { \} else \{ } }
{ dg-final { fail "20000510-1.S: # preservation" } }
{ dg-final { \} } }
*/

View File

@ -8,3 +8,5 @@
/* Directives with their #s indented are not recognized. */
#if 0 /* { dg-bogus "unterminated" } */
#wrong /* { dg-error "invalid" } */

View File

@ -0,0 +1,26 @@
/* Test that undefined names evaluate to zero, that macros after a
funlike macro are expanded, and that if it is a '(' the funlike
macro is not treated as such. */
/* { dg-do run } */
extern void abort (void);
#define f(x) x
int main ()
{
#if f(1) == f /**/ (/**/1/**/)
int x;
#endif
x = 0;
if (f
/**/ (
/**/ 0/**/
/**/)
)
abort ();
return 0;
}

View File

@ -0,0 +1,6 @@
/* Test that the null directive doesn't swallow the following line. */
/* { dg-do preprocess } */
#
#error OK /* { dg-error "OK" } */

View File

@ -0,0 +1,10 @@
/* Test for warning of and recovery from recursion in object-like
macros. */
/* { dg-do preprocess } */
#define foo foo
foo /* { dg-error "detected recursion" } */
#define bar a bar b
bar /* { dg-error "detected recursion" } */

View File

@ -0,0 +1,16 @@
/* Test for warning of and recovery from recursion in function-like
macros. */
/* { dg-do preprocess } */
#define foo() foo()
foo(); /* { dg-error "detected recursion" } */
#define bar() bar baz() bar
bar(); /* { dg-bogus "detected recursion" } */
#define baz() foo()
baz(); /* { dg-error "detected recursion" } */
#define a(x) x(a)
a(a); /* { dg-error "detected recursion" } */

View File

@ -0,0 +1,16 @@
/* Tests that macros that look recursive but are not are accepted. */
/* { dg-do preprocess } */
#define g(x) x
g(g(g(g(g(g(g)))))); /* { dg-bogus "detected recursion" } */
/* This macro gets longer with each loop, to thwart tests for
recursion based on length. */
#define f(a,b,c,d,e,f,g,h,i) a(b,c,d,e,f,g,h,i,2 3 4 5)
f(f,f,f,f,f,f,f,f,f) /* { dg-bogus "detected recursion" } */
/* The above cases should be enough, but this is taken from cccp
sources so let's try it too. */
#define foo(x,y) bar (x (y,0), y)
foo (foo, baz); /* { dg-bogus "detected recursion" } */