cpphash.h (struct_lexer_state): Delete was_skipping.
authorNeil Booth <neil@cat.daikokuya.demon.co.uk>
Thu, 26 Jul 2001 06:02:47 +0000 (06:02 +0000)
committerNeil Booth <neil@gcc.gnu.org>
Thu, 26 Jul 2001 06:02:47 +0000 (06:02 +0000)
* cpphash.h (struct_lexer_state): Delete was_skipping.
Move skipping here from struct cpp_reader.
* cpplex.c (parse_identifier): Update.
(_cpp_lex_token): Don't skip tokens in a directive.
* cpplib.c (struct if_stack): Update.
(start_directive, end_directive): Don't change skipping state.
(_cpp_handle_directive): Update.
(do_ifdef, do_ifndef, do_if, do_elif): Similarly.
(do_else, do_endif): Update; only check for excess tokens if not
in a skipped conditional block.
(push_conditional): Update for new struct if_stack.

* gcc.dg/cpp/extratokens.c: Fix.
* gcc.dg/cpp/skipping2.c: New tests.

From-SVN: r44380

gcc/ChangeLog
gcc/cpphash.h
gcc/cpplex.c
gcc/cpplib.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/cpp/extratokens.c
gcc/testsuite/gcc.dg/cpp/skipping2.c [new file with mode: 0644]

index 39e6022..35835ab 100644 (file)
@@ -1,3 +1,17 @@
+2001-07-26  Neil Booth  <neil@cat.daikokuya.demon.co.uk>
+
+       * cpphash.h (struct_lexer_state): Delete was_skipping.
+       Move skipping here from struct cpp_reader.
+       * cpplex.c (parse_identifier): Update.
+       (_cpp_lex_token): Don't skip tokens in a directive.
+       * cpplib.c (struct if_stack): Update.
+       (start_directive, end_directive): Don't change skipping state.
+       (_cpp_handle_directive): Update.
+       (do_ifdef, do_ifndef, do_if, do_elif): Similarly.
+       (do_else, do_endif): Update; only check for excess tokens if not
+       in a skipped conditional block.
+       (push_conditional): Update for new struct if_stack.
+
 2001-07-26  Graham Stott  <grahams@redhat.com>
 
        * function.c (locate_and_pad_parm): Also pad initial offset
index 56d9068..a8221d9 100644 (file)
@@ -126,6 +126,9 @@ struct lexer_state
   /* Nonzero if first token on line is CPP_HASH.  */
   unsigned char in_directive;
 
+  /* True if we are skipping a failed conditional group.  */
+  unsigned char skipping;
+
   /* Nonzero if in a directive that takes angle-bracketed headers.  */
   unsigned char angled_headers;
 
@@ -216,9 +219,6 @@ struct cpp_buffer
      buffers.  */
   unsigned char from_stage3;
 
-  /* Temporary storage for pfile->skipping whilst in a directive.  */
-  unsigned char was_skipping;
-
   /* 1 = system header file, 2 = C system header file used for C++.  */
   unsigned char sysp;
 
@@ -342,9 +342,6 @@ struct cpp_reader
   /* We're printed a warning recommending against using #import.  */
   unsigned char import_warning;
 
-  /* True if we are skipping a failed conditional group.  */
-  unsigned char skipping;
-
   /* Whether to print our version number.  Done this way so
      we don't get it twice for -v -version.  */
   unsigned char print_version;
index 7424827..4821745 100644 (file)
@@ -509,7 +509,7 @@ parse_identifier (pfile, c)
   /* $ is not a identifier character in the standard, but is commonly
      accepted as an extension.  Don't warn about it in skipped
      conditional blocks.  */
-  if (saw_dollar && CPP_PEDANTIC (pfile) && ! pfile->skipping)
+  if (saw_dollar && CPP_PEDANTIC (pfile) && ! pfile->state.skipping)
     cpp_pedwarn (pfile, "'$' character(s) in identifier");
 
   /* Identifiers are null-terminated.  */
@@ -521,7 +521,7 @@ parse_identifier (pfile, c)
     ht_lookup (pfile->hash_table, obstack_finish (stack), len, HT_ALLOCED);
 
   /* Some identifiers require diagnostics when lexed.  */
-  if (result->flags & NODE_DIAGNOSTIC && !pfile->skipping)
+  if (result->flags & NODE_DIAGNOSTIC && !pfile->state.skipping)
     {
       /* It is allowed to poison the same identifier twice.  */
       if ((result->flags & NODE_POISONED) && !pfile->state.poisoned_ok)
@@ -888,7 +888,7 @@ _cpp_lex_token (pfile, result)
       if (pfile->lexer_pos.col != 0 && !bol && !buffer->from_stage3)
        cpp_pedwarn (pfile, "no newline at end of file");
       pfile->state.next_bol = 1;
-      pfile->skipping = 0;     /* In case missing #endif.  */
+      pfile->state.skipping = 0;       /* In case missing #endif.  */
       result->type = CPP_EOF;
       /* Don't do MI optimisation.  */
       return;
@@ -915,7 +915,7 @@ _cpp_lex_token (pfile, result)
       buffer->read_ahead = c;
       pfile->state.next_bol = 1;
       result->type = CPP_EOF;
-      /* Don't break; pfile->skipping might be true.  */
+      /* Don't break; pfile->state.skipping might be true.  */
       return;
 
     case '?':
@@ -1261,7 +1261,7 @@ _cpp_lex_token (pfile, result)
       break;
     }
 
-  if (pfile->skipping)
+  if (!pfile->state.in_directive && pfile->state.skipping)
     goto skip;
 
   /* If not in a directive, this token invalidates controlling macros.  */
index e0f6124..c196c1f 100644 (file)
@@ -43,8 +43,9 @@ struct if_stack
   struct if_stack *next;
   cpp_lexer_pos pos;           /* line and column where condition started */
   const cpp_hashnode *mi_cmacro;/* macro name for #ifndef around entire file */
-  unsigned char was_skipping;  /* Value of pfile->skipping before this if.  */
-  int type;                    /* type of last directive seen in this group */
+  bool skip_elses;             /* Can future #else / #elif be skipped?  */
+  bool was_skipping;           /* If were skipping on entry.  */
+  int type;                    /* Most recent conditional, for diagnostics.  */
 };
 
 /* Values for the origin field of struct directive.  KANDR directives
@@ -220,8 +221,6 @@ static void
 start_directive (pfile)
      cpp_reader *pfile;
 {
-  cpp_buffer *buffer = pfile->buffer;
-
   /* Setup in-directive state.  */
   pfile->state.in_directive = 1;
   pfile->state.save_comments = 0;
@@ -232,10 +231,6 @@ start_directive (pfile)
   /* Don't save directive tokens for external clients.  */
   pfile->la_saved = pfile->la_write;
   pfile->la_write = 0;
-
-  /* Turn off skipping.  */
-  buffer->was_skipping = pfile->skipping;
-  pfile->skipping = 0;
 }
 
 /* Called when leaving a directive, _Pragma or command-line directive.  */
@@ -244,12 +239,6 @@ end_directive (pfile, skip_line)
      cpp_reader *pfile;
      int skip_line;
 {
-  cpp_buffer *buffer = pfile->buffer;
-
-  /* Restore pfile->skipping before skip_rest_of_line, so that e.g.
-     __VA_ARGS__ in the rest of the directive doesn't warn.  */
-  pfile->skipping = buffer->was_skipping;
-
   /* We don't skip for an assembler #.  */
   if (skip_line)
     skip_rest_of_line (pfile);
@@ -270,7 +259,6 @@ _cpp_handle_directive (pfile, indented)
      cpp_reader *pfile;
      int indented;
 {
-  cpp_buffer *buffer = pfile->buffer;
   const directive *dir = 0;
   cpp_token dname;
   int skip = 1;
@@ -293,7 +281,7 @@ _cpp_handle_directive (pfile, indented)
         skipped conditional groups.  Complain about this form if
         we're being pedantic, but not if this is regurgitated input
         (preprocessed or fed back in by the C++ frontend).  */
-      if (! buffer->was_skipping && CPP_OPTION (pfile, lang) != CLK_ASM)
+      if (! pfile->state.skipping && CPP_OPTION (pfile, lang) != CLK_ASM)
        {
          dir = &dtable[T_LINE];
          pfile->state.line_extension = 1;
@@ -361,7 +349,7 @@ _cpp_handle_directive (pfile, indented)
 
          /* If we are skipping a failed conditional group, all
             non-conditional directives are ignored.  */
-         if (! buffer->was_skipping || (dir->flags & COND))
+         if (! pfile->state.skipping || (dir->flags & COND))
            {
              /* Issue -pedantic warnings for extensions.   */
              if (CPP_PEDANTIC (pfile) && dir->origin == EXTENSION)
@@ -376,7 +364,7 @@ _cpp_handle_directive (pfile, indented)
            }
        }
     }
-  else if (dname.type != CPP_EOF && ! buffer->was_skipping)
+  else if (dname.type != CPP_EOF && ! pfile->state.skipping)
     {
       /* An unknown directive.  Don't complain about it in assembly
         source: we don't know where the comments are, and # may
@@ -1256,7 +1244,7 @@ do_ifdef (pfile)
 {
   int skip = 1;
 
-  if (! pfile->buffer->was_skipping)
+  if (! pfile->state.skipping)
     {
       const cpp_hashnode *node = lex_macro_node (pfile);
 
@@ -1277,7 +1265,7 @@ do_ifndef (pfile)
   int skip = 1;
   const cpp_hashnode *node = 0;
 
-  if (! pfile->buffer->was_skipping)
+  if (! pfile->state.skipping)
     {
       node = lex_macro_node (pfile);
       if (node)
@@ -1302,7 +1290,7 @@ do_if (pfile)
   int skip = 1;
   const cpp_hashnode *cmacro = 0;
 
-  if (! pfile->buffer->was_skipping)
+  if (! pfile->state.skipping)
     {
       /* Controlling macro of #if ! defined ()  */
       pfile->mi_ind_cmacro = 0;
@@ -1336,16 +1324,17 @@ do_else (pfile)
        }
       ifs->type = T_ELSE;
 
-      /* Buffer->was_skipping is 1 if all conditionals in this chain
-        have been false, 2 if a conditional has been true.  */
-      if (! ifs->was_skipping && buffer->was_skipping != 2)
-       buffer->was_skipping = ! buffer->was_skipping;
+      /* Skip any future (erroneous) #elses or #elifs.  */
+      pfile->state.skipping = ifs->skip_elses;
+      ifs->skip_elses = true;
 
       /* Invalidate any controlling macro.  */
       ifs->mi_cmacro = 0;
-    }
 
-  check_eol (pfile);
+      /* Only check EOL if was not originally skipping.  */
+      if (!ifs->was_skipping)
+       check_eol (pfile);
+    }
 }
 
 /* handle a #elif directive by not changing if_stack either.  see the
@@ -1370,23 +1359,23 @@ do_elif (pfile)
        }
       ifs->type = T_ELIF;
 
-      /* Don't evaluate #elif if our higher level is skipping.  */
-      if (! ifs->was_skipping)
+      /* Only evaluate this if we aren't skipping elses.  During
+        evaluation, set skipping to false to get lexer warnings.  */
+      if (ifs->skip_elses)
+       pfile->state.skipping = 1;
+      else
        {
-         /* Buffer->was_skipping is 1 if all conditionals in this
-            chain have been false, 2 if a conditional has been true.  */
-         if (buffer->was_skipping == 1)
-           buffer->was_skipping = ! _cpp_parse_expr (pfile);
-         else
-           buffer->was_skipping = 2;
-
-         /* Invalidate any controlling macro.  */
-         ifs->mi_cmacro = 0;
+         pfile->state.skipping = 0;
+         pfile->state.skipping = ! _cpp_parse_expr (pfile);
+         ifs->skip_elses = ! pfile->state.skipping;
        }
+
+      /* Invalidate any controlling macro.  */
+      ifs->mi_cmacro = 0;
     }
 }
 
-/* #endif pops the if stack and resets pfile->skipping.  */
+/* #endif pops the if stack and resets pfile->state.skipping.  */
 
 static void
 do_endif (pfile)
@@ -1399,6 +1388,10 @@ do_endif (pfile)
     cpp_error (pfile, "#endif without #if");
   else
     {
+      /* Only check EOL if was not originally skipping.  */
+      if (!ifs->was_skipping)
+       check_eol (pfile);
+
       /* If potential control macro, we go back outside again.  */
       if (ifs->next == 0 && ifs->mi_cmacro)
        {
@@ -1407,14 +1400,12 @@ do_endif (pfile)
        }
 
       buffer->if_stack = ifs->next;
-      buffer->was_skipping = ifs->was_skipping;
+      pfile->state.skipping = ifs->was_skipping;
       obstack_free (&pfile->buffer_ob, ifs);
     }
-
-  check_eol (pfile);
 }
 
-/* Push an if_stack entry and set pfile->skipping accordingly.
+/* Push an if_stack entry and set pfile->state.skipping accordingly.
    If this is a #ifndef starting at the beginning of a file,
    CMACRO is the macro name tested by the #ifndef.  */
 
@@ -1431,14 +1422,15 @@ push_conditional (pfile, skip, type, cmacro)
   ifs = xobnew (&pfile->buffer_ob, struct if_stack);
   ifs->pos = pfile->directive_pos;
   ifs->next = buffer->if_stack;
-  ifs->was_skipping = buffer->was_skipping;
+  ifs->skip_elses = pfile->state.skipping || !skip;
+  ifs->was_skipping = pfile->state.skipping;
   ifs->type = type;
   if (pfile->mi_state == MI_OUTSIDE && pfile->mi_cmacro == 0)
     ifs->mi_cmacro = cmacro;
   else
     ifs->mi_cmacro = 0;
 
-  buffer->was_skipping = skip;
+  pfile->state.skipping = skip;
   buffer->if_stack = ifs;
 }
 
index 5a6aea2..805bbb5 100644 (file)
@@ -1,3 +1,8 @@
+2001-07-26  Neil Booth  <neil@cat.daikokuya.demon.co.uk>
+
+       * gcc.dg/cpp/extratokens.c: Fix.
+       * gcc.dg/cpp/skipping2.c: New tests.
+
 2001-07-25  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
 
        * gcc.c-torture/execute/20010724-1.c: New file.
index 0941be7..c06a41d 100644 (file)
@@ -15,7 +15,7 @@
 #ifndef foo bar  /* { dg-error "extra tokens" "tokens after #ifndef" } */
 #endif
 
-#if 0
+#if 
 #if 0
 #else foo      /* { dg-warning "extra tokens" "tokens after #else" } */
 #endif /       /* { dg-warning "extra tokens" "tokens after #endif" } */
diff --git a/gcc/testsuite/gcc.dg/cpp/skipping2.c b/gcc/testsuite/gcc.dg/cpp/skipping2.c
new file mode 100644 (file)
index 0000000..3b0d0f3
--- /dev/null
@@ -0,0 +1,14 @@
+/* Copyright (C) 2001 Free Software Foundation, Inc.  */
+
+/* { dg-do preprocess } */
+
+/* Tests that excess tokens in skipped conditional blocks don't warn.  */
+
+/* Source: Neil Booth, 25 Jul 2001.  */
+
+#if 0
+#if foo
+#else foo   /* { dg-bogus "extra tokens" "extra tokens in skipped block" } */
+#endif foo  /* { dg-bogus "extra tokens" "extra tokens in skipped block" } */
+#endif bar  /* { dg-warning "extra tokens" "tokens after #endif" } */
+