aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/cpptrad.c58
-rw-r--r--gcc/testsuite/ChangeLog9
-rw-r--r--gcc/testsuite/gcc.dg/cpp/trad/argcount.c21
-rw-r--r--gcc/testsuite/gcc.dg/cpp/trad/assembler.S25
-rw-r--r--gcc/testsuite/gcc.dg/cpp/trad/directive.c2
-rw-r--r--gcc/testsuite/gcc.dg/cpp/trad/funlike-4.c26
-rw-r--r--gcc/testsuite/gcc.dg/cpp/trad/null-drctv.c6
-rw-r--r--gcc/testsuite/gcc.dg/cpp/trad/recurse-1.c10
-rw-r--r--gcc/testsuite/gcc.dg/cpp/trad/recurse-2.c16
-rw-r--r--gcc/testsuite/gcc.dg/cpp/trad/recurse-3.c16
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" } */