diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/cpptrad.c | 58 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/cpp/trad/argcount.c | 21 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/cpp/trad/assembler.S | 25 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/cpp/trad/directive.c | 2 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/cpp/trad/funlike-4.c | 26 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/cpp/trad/null-drctv.c | 6 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/cpp/trad/recurse-1.c | 10 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/cpp/trad/recurse-2.c | 16 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/cpp/trad/recurse-3.c | 16 |
11 files changed, 183 insertions, 13 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 25a13a36..717dcb0 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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. diff --git a/gcc/cpptrad.c b/gcc/cpptrad.c index 22320c4..7ae8819 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 9391915..32c9098 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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. 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 0000000..208cd44b --- /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 0000000..729162a --- /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 186cb30..5139c33 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 0000000..fcc65a8 --- /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 0000000..99fd251 --- /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 0000000..b5fd7af --- /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 0000000..5c6550f --- /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 0000000..8ff65cc --- /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" } */ |