Commit 2c088b53 by Neil Booth Committed by Neil Booth

cpptrad.c (scan_out_logical_line): Check recursing only when we know we have a…

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
parent 66443ad2
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> 2002-06-24 Alan Modra <amodra@bigpond.net.au>
* doloop.c (doloop_valid_p): Correct comment. * doloop.c (doloop_valid_p): Correct comment.
......
...@@ -579,8 +579,7 @@ scan_out_logical_line (pfile, macro) ...@@ -579,8 +579,7 @@ scan_out_logical_line (pfile, macro)
if (node->type == NT_MACRO if (node->type == NT_MACRO
/* Should we expand for ls_answer? */ /* Should we expand for ls_answer? */
&& (lex_state == ls_none || lex_state == ls_fun_open) && (lex_state == ls_none || lex_state == ls_fun_open)
&& !pfile->state.prevent_expansion && !pfile->state.prevent_expansion)
&& !recursive_macro (pfile, node))
{ {
/* Macros invalidate MI optimization. */ /* Macros invalidate MI optimization. */
pfile->mi_valid = false; pfile->mi_valid = false;
...@@ -592,7 +591,7 @@ scan_out_logical_line (pfile, macro) ...@@ -592,7 +591,7 @@ scan_out_logical_line (pfile, macro)
fmacro.line = pfile->line; fmacro.line = pfile->line;
continue; continue;
} }
else else if (!recursive_macro (pfile, node))
{ {
/* Remove the object-like macro's name from the /* Remove the object-like macro's name from the
output, and push its replacement text. */ output, and push its replacement text. */
...@@ -630,11 +629,16 @@ scan_out_logical_line (pfile, macro) ...@@ -630,11 +629,16 @@ scan_out_logical_line (pfile, macro)
paren_depth++; paren_depth++;
if (lex_state == ls_fun_open) if (lex_state == ls_fun_open)
{ {
if (recursive_macro (pfile, fmacro.node))
lex_state = ls_none;
else
{
lex_state = ls_fun_close; lex_state = ls_fun_close;
paren_depth = 1; paren_depth = 1;
out = pfile->out.base + fmacro.offset; out = pfile->out.base + fmacro.offset;
fmacro.args[0] = fmacro.offset; fmacro.args[0] = fmacro.offset;
} }
}
else if (lex_state == ls_predicate) else if (lex_state == ls_predicate)
lex_state = ls_answer; lex_state = ls_answer;
else if (lex_state == ls_defined) else if (lex_state == ls_defined)
...@@ -681,15 +685,43 @@ scan_out_logical_line (pfile, macro) ...@@ -681,15 +685,43 @@ scan_out_logical_line (pfile, macro)
break; break;
case '#': case '#':
/* At start of a line it's a directive. */
if (out - 1 == pfile->out.base && !pfile->state.in_directive) if (out - 1 == pfile->out.base && !pfile->state.in_directive)
{ {
/* 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 /* This is a kludge. We want to have the ISO
preprocessor lex the next token. */ preprocessor lex the next token. */
pfile->buffer->cur = cur; pfile->buffer->cur = cur;
if (_cpp_handle_directive (pfile, false /* indented */)) _cpp_handle_directive (pfile, false /* indented */);
goto start_logical_line; goto start_logical_line;
} }
}
}
if (pfile->state.in_expression) if (pfile->state.in_expression)
{ {
lex_state = ls_hash; lex_state = ls_hash;
......
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> 2002-06-23 Andreas Jaeger <aj@suse.de>
* gcc.c-torture/execute/complex-6.c: New. * gcc.c-torture/execute/complex-6.c: New.
......
/* 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" } */
/* 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 { \} } }
*/
...@@ -8,3 +8,5 @@ ...@@ -8,3 +8,5 @@
/* Directives with their #s indented are not recognized. */ /* Directives with their #s indented are not recognized. */
#if 0 /* { dg-bogus "unterminated" } */ #if 0 /* { dg-bogus "unterminated" } */
#wrong /* { dg-error "invalid" } */
/* 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;
}
/* Test that the null directive doesn't swallow the following line. */
/* { dg-do preprocess } */
#
#error OK /* { dg-error "OK" } */
/* 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" } */
/* 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" } */
/* 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" } */
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