cpplib.c (end_directive): Handle line skipping.
authorNeil Booth <neil@daikokuya.demon.co.uk>
Thu, 13 Jun 2002 06:25:28 +0000 (06:25 +0000)
committerNeil Booth <neil@gcc.gnu.org>
Thu, 13 Jun 2002 06:25:28 +0000 (06:25 +0000)
* cpplib.c (end_directive): Handle line skipping.  Only remove
the rest of the line if the directive was valid.
* cppmacro.c (_cpp_push_text_context): Set NODE_DISABLED when
expanding a traditional macro.
* cpptrad.c (recursive_macro): New.
(read_logical_line_trad): Handle skipping.
(scan_out_logical_line): Continue after a successful directive.
Don't expand macros whilst skipping, or if recursing.
(_cpp_create_trad_definition): scan_out_logical_line now sets
the output current position.

From-SVN: r54573

gcc/ChangeLog
gcc/cpplib.c
gcc/cppmacro.c
gcc/cpptrad.c

index 79dd06e583e21593094c87ccb7d30cefc2f87c31..626b0cbdda25b0fd46fbd7b2eeccf2be2c8f0980 100644 (file)
@@ -1,3 +1,16 @@
+2002-06-13  Neil Booth  <neil@daikokuya.demon.co.uk>
+
+       * cpplib.c (end_directive): Handle line skipping.  Only remove
+       the rest of the line if the directive was valid.
+       * cppmacro.c (_cpp_push_text_context): Set NODE_DISABLED when
+       expanding a traditional macro.
+       * cpptrad.c (recursive_macro): New.
+       (read_logical_line_trad): Handle skipping.
+       (scan_out_logical_line): Continue after a successful directive.
+       Don't expand macros whilst skipping, or if recursing.
+       (_cpp_create_trad_definition): scan_out_logical_line now sets
+       the output current position.
+
 2002-06-12  Eric Christopher  <echristo@redhat.com>
 
        From Chris Demetriou  <cgd@broadcom.com>
index 73e12b7d8d50f3c0033da7b0212a09030f4d6806..acc71e7120a6ae208336ead67ae146b74a60a1a0 100644 (file)
@@ -256,7 +256,7 @@ end_directive (pfile, skip_line)
 {
   if (CPP_OPTION (pfile, traditional))
     {
-      if (pfile->directive == &dtable[T_DEFINE])
+      if (!pfile->directive || pfile->directive == &dtable[T_DEFINE])
        skip_line = false;
       else
        _cpp_remove_overlay (pfile);
@@ -290,12 +290,15 @@ prepare_directive_trad (pfile)
   else
     {
       bool no_expand = ! (pfile->directive->flags & EXPAND);
+      bool was_skipping = pfile->state.skipping;
 
+      pfile->state.skipping = false;
       if (no_expand)
        pfile->state.prevent_expansion++;
       _cpp_read_logical_line_trad (pfile);
       if (no_expand)
        pfile->state.prevent_expansion--;
+      pfile->state.skipping = was_skipping;
       _cpp_overlay_buffer (pfile, pfile->out.base,
                           pfile->out.cur - pfile->out.base);
     }
index a9ca6cf2dbfe864b1fd2a8c6c175835468e16156..20149ec9b33bb0e512b6da0a91cf7a151081e627 100644 (file)
@@ -947,6 +947,7 @@ _cpp_push_text_context (pfile, macro, start, len)
   context->buff = NULL;
   CUR (context) = start;
   RLIMIT (context) = start + len;
+  macro->flags |= NODE_DISABLED;
 }
 
 /* Expand an argument ARG before replacing parameters in a
index 33e4575cf951fb6bb26fd088ed1f173de77d2690..03ee0e893a68a384e74acf5e8eec5b944521ff3f 100644 (file)
@@ -82,6 +82,7 @@ static void scan_out_logical_line PARAMS ((cpp_reader *pfile, cpp_macro *));
 static void check_output_buffer PARAMS ((cpp_reader *, size_t));
 static void push_replacement_text PARAMS ((cpp_reader *, cpp_hashnode *));
 static bool scan_parameters PARAMS ((cpp_reader *, cpp_macro *));
+static bool recursive_macro PARAMS ((cpp_reader *, cpp_hashnode *));
 static void save_replacement_text PARAMS ((cpp_reader *, cpp_macro *,
                                           unsigned int));
 static void maybe_start_funlike PARAMS ((cpp_reader *, cpp_hashnode *,
@@ -304,30 +305,31 @@ bool
 _cpp_read_logical_line_trad (pfile)
      cpp_reader *pfile;
 {
-  cpp_buffer *buffer;
+  cpp_buffer *buffer = pfile->buffer;
 
-  buffer = pfile->buffer;
-  if (buffer->cur == buffer->rlimit)
+  do
     {
-      bool stop = true;
-
-      /* Don't pop the last buffer.  */
-      if (buffer->prev)
+      if (buffer->cur == buffer->rlimit)
        {
-         stop = buffer->return_at_eof;
-         _cpp_pop_buffer (pfile);
+         bool stop = true;
+
+         /* Don't pop the last buffer.  */
+         if (buffer->prev)
+           {
+             stop = buffer->return_at_eof;
+             _cpp_pop_buffer (pfile);
+           }
+
+         if (stop)
+           return false;
        }
 
-      if (stop)
-       return false;
+      CUR (pfile->context) = buffer->cur;
+      RLIMIT (pfile->context) = buffer->rlimit;
+      scan_out_logical_line (pfile, NULL);
+      buffer->cur = CUR (pfile->context);
     }
-
-  CUR (pfile->context) = buffer->cur;
-  RLIMIT (pfile->context) = buffer->rlimit;
-  pfile->out.cur = pfile->out.base;
-  pfile->out.first_line = pfile->line;
-  scan_out_logical_line (pfile, NULL);
-  buffer->cur = CUR (pfile->context);
+  while (pfile->state.skipping);
 
   return true;
 }
@@ -384,6 +386,10 @@ scan_out_logical_line (pfile, macro)
   struct fun_macro fmacro;
 
   fmacro.buff = NULL;
+
+ start_logical_line:
+  pfile->out.cur = pfile->out.base;
+  pfile->out.first_line = pfile->line;
  new_context:
   context = pfile->context;
   cur = CUR (context);
@@ -483,8 +489,10 @@ scan_out_logical_line (pfile, macro)
              node = lex_identifier (pfile, cur - 1);
 
              if (node->type == NT_MACRO
+                 && !pfile->state.skipping
                  && pfile->state.parsing_args != 2
-                 && !pfile->state.prevent_expansion)
+                 && !pfile->state.prevent_expansion
+                 && !recursive_macro (pfile, node))
                {
                  if (node->value.macro->fun_like)
                    maybe_start_funlike (pfile, node, out, &fmacro);
@@ -582,10 +590,7 @@ scan_out_logical_line (pfile, macro)
                 preprocessor lex the next token.  */
              pfile->buffer->cur = cur;
              if (_cpp_handle_directive (pfile, false /* indented */))
-               {
-                 cur = CUR (context);
-                 goto done;
-               }
+               goto start_logical_line;
            }
          break;
 
@@ -615,6 +620,48 @@ push_replacement_text (pfile, node)
   _cpp_push_text_context (pfile, node, macro->exp.text, macro->count);
 }
 
+/* Returns TRUE if traditional macro recursion is detected.  */
+static bool
+recursive_macro (pfile, node)
+     cpp_reader *pfile;
+     cpp_hashnode *node;
+{
+  bool recursing = node->flags & NODE_DISABLED;
+
+  /* Object-like macros that are already expanding are necessarily
+     recursive.
+
+     However, it is possible to have traditional function-like macros
+     that are not infinitely recursive but recurse to any given depth.
+     Further, it is easy to construct examples that get ever longer
+     until the point they stop recursing.  So there is no easy way to
+     detect true recursion; instead we assume any expansion more than
+     20 deep since the first invocation of this macro must be
+     recursing.  */
+  if (recursing && node->value.macro->fun_like)
+    {
+      size_t depth = 0;
+      cpp_context *context = pfile->context;
+
+      do
+       {
+         depth++;
+         if (context->macro == node && depth > 20)
+           break;
+         context = context->prev;
+       }
+      while (context);
+      recursing = context != NULL;
+    }
+
+  if (recursing)
+    cpp_error (pfile, DL_ERROR,
+              "detected recursion whilst expanding macro \"%s\"",
+              NODE_NAME (node));
+
+  return recursing;
+}
+
 /* Push a context holding the replacement text of the macro NODE on
    the context stack.  NODE is either object-like, or a function-like
    macro with no arguments.  */
@@ -804,7 +851,6 @@ _cpp_create_trad_definition (pfile, macro)
   /* Skip leading whitespace in the replacement text.  */
   CUR (pfile->context) = skip_whitespace (pfile, CUR (pfile->context));
 
-  pfile->out.cur = pfile->out.base;
   pfile->state.prevent_expansion++;
   scan_out_logical_line (pfile, macro);
   pfile->state.prevent_expansion--;