From 2c088b53f9633f073f02656eba0033c68ab65f31 Mon Sep 17 00:00:00 2001 From: Neil Booth Date: Mon, 24 Jun 2002 05:46:51 +0000 Subject: [PATCH] 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 --- gcc/ChangeLog | 7 +++ gcc/cpptrad.c | 58 +++++++++++++++++----- gcc/testsuite/ChangeLog | 9 ++++ gcc/testsuite/gcc.dg/cpp/trad/argcount.c | 21 ++++++++ gcc/testsuite/gcc.dg/cpp/trad/assembler.S | 25 ++++++++++ gcc/testsuite/gcc.dg/cpp/trad/directive.c | 2 + gcc/testsuite/gcc.dg/cpp/trad/funlike-4.c | 26 ++++++++++ gcc/testsuite/gcc.dg/cpp/trad/null-drctv.c | 6 +++ gcc/testsuite/gcc.dg/cpp/trad/recurse-1.c | 10 ++++ gcc/testsuite/gcc.dg/cpp/trad/recurse-2.c | 16 ++++++ gcc/testsuite/gcc.dg/cpp/trad/recurse-3.c | 16 ++++++ 11 files changed, 183 insertions(+), 13 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/cpp/trad/argcount.c create mode 100644 gcc/testsuite/gcc.dg/cpp/trad/assembler.S create mode 100644 gcc/testsuite/gcc.dg/cpp/trad/funlike-4.c create mode 100644 gcc/testsuite/gcc.dg/cpp/trad/null-drctv.c create mode 100644 gcc/testsuite/gcc.dg/cpp/trad/recurse-1.c create mode 100644 gcc/testsuite/gcc.dg/cpp/trad/recurse-2.c create mode 100644 gcc/testsuite/gcc.dg/cpp/trad/recurse-3.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 25a13a3627c2..717dcb085810 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2002-06-24 Neil Booth + + * 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 * doloop.c (doloop_valid_p): Correct comment. diff --git a/gcc/cpptrad.c b/gcc/cpptrad.c index 22320c49edcd..7ae8819f028c 100644 --- a/gcc/cpptrad.c +++ b/gcc/cpptrad.c @@ -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; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 9391915b7337..32c90983f523 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,12 @@ +2002-06-24 Neil Booth + + * 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 * gcc.c-torture/execute/complex-6.c: New. diff --git a/gcc/testsuite/gcc.dg/cpp/trad/argcount.c b/gcc/testsuite/gcc.dg/cpp/trad/argcount.c new file mode 100644 index 000000000000..208cd44b3b07 --- /dev/null +++ b/gcc/testsuite/gcc.dg/cpp/trad/argcount.c @@ -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" } */ diff --git a/gcc/testsuite/gcc.dg/cpp/trad/assembler.S b/gcc/testsuite/gcc.dg/cpp/trad/assembler.S new file mode 100644 index 000000000000..729162a5120d --- /dev/null +++ b/gcc/testsuite/gcc.dg/cpp/trad/assembler.S @@ -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 { \} } } +*/ + diff --git a/gcc/testsuite/gcc.dg/cpp/trad/directive.c b/gcc/testsuite/gcc.dg/cpp/trad/directive.c index 186cb30bbeda..5139c3322f9f 100644 --- a/gcc/testsuite/gcc.dg/cpp/trad/directive.c +++ b/gcc/testsuite/gcc.dg/cpp/trad/directive.c @@ -8,3 +8,5 @@ /* Directives with their #s indented are not recognized. */ #if 0 /* { dg-bogus "unterminated" } */ + +#wrong /* { dg-error "invalid" } */ diff --git a/gcc/testsuite/gcc.dg/cpp/trad/funlike-4.c b/gcc/testsuite/gcc.dg/cpp/trad/funlike-4.c new file mode 100644 index 000000000000..fcc65a8d60db --- /dev/null +++ b/gcc/testsuite/gcc.dg/cpp/trad/funlike-4.c @@ -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; +} diff --git a/gcc/testsuite/gcc.dg/cpp/trad/null-drctv.c b/gcc/testsuite/gcc.dg/cpp/trad/null-drctv.c new file mode 100644 index 000000000000..99fd251f2e31 --- /dev/null +++ b/gcc/testsuite/gcc.dg/cpp/trad/null-drctv.c @@ -0,0 +1,6 @@ +/* Test that the null directive doesn't swallow the following line. */ + +/* { dg-do preprocess } */ + +# +#error OK /* { dg-error "OK" } */ diff --git a/gcc/testsuite/gcc.dg/cpp/trad/recurse-1.c b/gcc/testsuite/gcc.dg/cpp/trad/recurse-1.c new file mode 100644 index 000000000000..b5fd7af7f5ff --- /dev/null +++ b/gcc/testsuite/gcc.dg/cpp/trad/recurse-1.c @@ -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" } */ diff --git a/gcc/testsuite/gcc.dg/cpp/trad/recurse-2.c b/gcc/testsuite/gcc.dg/cpp/trad/recurse-2.c new file mode 100644 index 000000000000..5c6550fae2ac --- /dev/null +++ b/gcc/testsuite/gcc.dg/cpp/trad/recurse-2.c @@ -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" } */ diff --git a/gcc/testsuite/gcc.dg/cpp/trad/recurse-3.c b/gcc/testsuite/gcc.dg/cpp/trad/recurse-3.c new file mode 100644 index 000000000000..8ff65cc801f5 --- /dev/null +++ b/gcc/testsuite/gcc.dg/cpp/trad/recurse-3.c @@ -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" } */