OSDN Git Service

* cpptrad.c (scan_out_logical_line): Check recursing only when
authorneil <neil@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 24 Jun 2002 05:46:51 +0000 (05:46 +0000)
committerneil <neil@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 24 Jun 2002 05:46:51 +0000 (05:46 +0000)
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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@54942 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/cpptrad.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/cpp/trad/argcount.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/cpp/trad/assembler.S [new file with mode: 0644]
gcc/testsuite/gcc.dg/cpp/trad/directive.c
gcc/testsuite/gcc.dg/cpp/trad/funlike-4.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/cpp/trad/null-drctv.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/cpp/trad/recurse-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/cpp/trad/recurse-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/cpp/trad/recurse-3.c [new file with mode: 0644]

index 25a13a3..717dcb0 100644 (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.
index 22320c4..7ae8819 100644 (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;
index 9391915..32c9098 100644 (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.
diff --git a/gcc/testsuite/gcc.dg/cpp/trad/argcount.c b/gcc/testsuite/gcc.dg/cpp/trad/argcount.c
new file mode 100644 (file)
index 0000000..208cd44
--- /dev/null
@@ -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 (file)
index 0000000..729162a
--- /dev/null
@@ -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 { \}                                             } }
+*/
+
index 186cb30..5139c33 100644 (file)
@@ -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 (file)
index 0000000..fcc65a8
--- /dev/null
@@ -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 (file)
index 0000000..99fd251
--- /dev/null
@@ -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 (file)
index 0000000..b5fd7af
--- /dev/null
@@ -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 (file)
index 0000000..5c6550f
--- /dev/null
@@ -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 (file)
index 0000000..8ff65cc
--- /dev/null
@@ -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" } */