cppmain.c (scan_translation_unit): Don't worry about putting a space after hashes.
authorNeil Booth <neil@daikokuya.demon.co.uk>
Sun, 16 Sep 2001 11:23:56 +0000 (11:23 +0000)
committerNeil Booth <neil@gcc.gnu.org>
Sun, 16 Sep 2001 11:23:56 +0000 (11:23 +0000)
* cppmain.c (scan_translation_unit): Don't worry about
putting a space after hashes.
* cpplib.c (directive_diagnostics): New.
(_cpp_handle_directive): Update to use directive_diagnostics.
(run_directive): Don't toggle prevent_expansion.
(do_line): Backup in case of the line extension.
* cpplib.h (cpp_lexer_pos): Remove.
* cppmacro.c (_cpp_create_definition): Precede a leading #
with whitespace.

* gcc.dg/cpp/line5.c: New testcase.

From-SVN: r45645

gcc/ChangeLog
gcc/cpplib.c
gcc/cpplib.h
gcc/cppmacro.c
gcc/cppmain.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/cpp/line5.c [new file with mode: 0644]

index e36dcc210a3b679a737b4d85ffc65f857a1b1c4f..4f0ad86c6be69bb7bd01c6c9624f2e02e7be3588 100644 (file)
@@ -1,3 +1,15 @@
+2001-09-16  Neil Booth  <neil@daikokuya.demon.co.uk>
+
+       * cppmain.c (scan_translation_unit): Don't worry about
+       putting a space after hashes.
+       * cpplib.c (directive_diagnostics): New.
+       (_cpp_handle_directive): Update to use directive_diagnostics.
+       (run_directive): Don't toggle prevent_expansion.
+       (do_line): Backup in case of the line extension.
+       * cpplib.h (cpp_lexer_pos): Remove.
+       * cppmacro.c (_cpp_create_definition): Precede a leading #
+       with whitespace.
+
 2001-09-15  Richard Henderson  <rth@redhat.com>
 
        * c-typeck.c (comptypes): Handle zero-length arrays properly.
index e8065f6584e6f042d38dd99006ba504cd82b70c3..b3eb24daad4c9845a021ab7db322d778d319d37e 100644 (file)
@@ -82,6 +82,8 @@ static void skip_rest_of_line PARAMS ((cpp_reader *));
 static void check_eol          PARAMS ((cpp_reader *));
 static void start_directive    PARAMS ((cpp_reader *));
 static void end_directive      PARAMS ((cpp_reader *, int));
+static void directive_diagnostics
+       PARAMS ((cpp_reader *, const directive *, int));
 static void run_directive      PARAMS ((cpp_reader *, int,
                                         const char *, size_t));
 static int glue_header_name    PARAMS ((cpp_reader *, cpp_token *));
@@ -248,8 +250,57 @@ end_directive (pfile, skip_line)
   pfile->directive = 0;
 }
 
-/* Check if a token's name matches that of a known directive.  Put in
-   this file to save exporting dtable and other unneeded information.  */
+/* Output diagnostics for a directive DIR.  INDENTED is non-zero if
+   the '#' was indented.  */
+
+static void
+directive_diagnostics (pfile, dir, indented)
+     cpp_reader *pfile;
+     const directive *dir;
+     int indented;
+{
+  if (pfile->state.line_extension)
+    {
+      if (CPP_PEDANTIC (pfile)
+         && ! pfile->state.skipping)
+       cpp_pedwarn (pfile, "style of line directive is a GCC extension");
+    }
+  else
+    {
+      /* Issue -pedantic warnings for extensions.   */
+      if (CPP_PEDANTIC (pfile)
+         && ! pfile->state.skipping
+         && dir->origin == EXTENSION)
+       cpp_pedwarn (pfile, "#%s is a GCC extension", dir->name);
+
+      /* Traditionally, a directive is ignored unless its # is in
+        column 1.  Therefore in code intended to work with K+R
+        compilers, directives added by C89 must have their #
+        indented, and directives present in traditional C must not.
+        This is true even of directives in skipped conditional
+        blocks.  */
+      if (CPP_WTRADITIONAL (pfile))
+       {
+         if (dir == &dtable[T_ELIF])
+           cpp_warning (pfile, "suggest not using #elif in traditional C");
+         else if (indented && dir->origin == KANDR)
+           cpp_warning (pfile,
+                        "traditional C ignores #%s with the # indented",
+                        dir->name);
+         else if (!indented && dir->origin != KANDR)
+           cpp_warning (pfile,
+                "suggest hiding #%s from traditional C with an indented #",
+                        dir->name);
+       }
+    }
+}
+
+/* Check if we have a known directive.  INDENTED is non-zero if the
+   '#' of the directive was indented.  This function is in this file
+   to save unnecessarily exporting dtable etc. to cpplex.c.  Returns
+   non-zero if the line of tokens has been handled, zero if we should
+   continue processing the line.  */
+
 int
 _cpp_handle_directive (pfile, indented)
      cpp_reader *pfile;
@@ -260,125 +311,80 @@ _cpp_handle_directive (pfile, indented)
   int skip = 1;
 
   start_directive (pfile);
-
-  /* Lex the directive name directly.  */
   _cpp_lex_token (pfile, &dname);
 
   if (dname.type == CPP_NAME)
     {
-      unsigned int index = dname.val.node->directive_index;
-      if (index)
-       dir = &dtable[index - 1];
+      if (dname.val.node->directive_index)
+       dir = &dtable[dname.val.node->directive_index - 1];
     }
-  else if (dname.type == CPP_NUMBER)
+  /* We do not recognise the # followed by a number extension in
+     assembler code.  */
+  else if (dname.type == CPP_NUMBER && CPP_OPTION (pfile, lang) != CLK_ASM)
     {
-      /* # followed by a number is equivalent to #line.  Do not
-        recognize this form in assembly language source files or
-        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 (! pfile->state.skipping && CPP_OPTION (pfile, lang) != CLK_ASM)
-       {
-         dir = &dtable[T_LINE];
-         pfile->state.line_extension = 1;
-         _cpp_backup_tokens (pfile, 1);
-         if (CPP_PEDANTIC (pfile) && ! CPP_OPTION (pfile, preprocessed))
-           cpp_pedwarn (pfile, "# followed by integer");
-       }
+      dir = &dtable[T_LINE];
+      pfile->state.line_extension = 1;
     }
 
-  pfile->directive = dir;
   if (dir)
     {
-      /* Make sure we lex headers correctly, whether skipping or not.  */
-      pfile->state.angled_headers = dir->flags & INCL;
-
-      /* If we are rescanning preprocessed input, only directives tagged
-        with IN_I are honored, and the warnings below are suppressed.  */
-      if (CPP_OPTION (pfile, preprocessed))
+      /* If we have a directive that is not an opening conditional,
+        invalidate any control macro.  */
+      if (! (dir->flags & IF_COND))
+       pfile->mi_valid = false;
+
+      /* Kluge alert.  In order to be sure that code like this
+
+        #define HASH #
+        HASH define foo bar
+
+        does not cause '#define foo bar' to get executed when
+        compiled with -save-temps, we recognize directives in
+        -fpreprocessed mode only if the # is in column 1.  cppmacro.c
+        puts a space in fron of any '#' at the start of a macro.  */
+      if (CPP_OPTION (pfile, preprocessed)
+         && (indented || !(dir->flags & IN_I)))
        {
-         /* Kluge alert.  In order to be sure that code like this
-            #define HASH #
-            HASH define foo bar
-            does not cause '#define foo bar' to get executed when
-            compiled with -save-temps, we recognize directives in
-            -fpreprocessed mode only if the # is in column 1 and the
-            directive name starts in column 2.  This output can only
-            be generated by the directive callbacks in cppmain.c (see
-            also the special case in scan_buffer).  */
-         if (dir->flags & IN_I && !indented && !(dname.flags & PREV_WHITE))
-           (*dir->handler) (pfile);
-         /* That check misses '# 123' linemarkers.  Let them through too.  */
-         else if (dname.type == CPP_NUMBER)
-           (*dir->handler) (pfile);
-         else
-           {
-             /* We don't want to process this directive.  Put back the
-                tokens so caller will see them (and issue an error,
-                probably).  */
-             _cpp_backup_tokens (pfile, 1);
-             skip = 0;
-           }
+         skip = 0;
+         dir = 0;
        }
       else
        {
-         /* Traditionally, a directive is ignored unless its # is in
-            column 1.  Therefore in code intended to work with K+R
-            compilers, directives added by C89 must have their #
-            indented, and directives present in traditional C must
-            not.  This is true even of directives in skipped
-            conditional blocks.  */
-         if (CPP_WTRADITIONAL (pfile))
-           {
-             if (dir == &dtable[T_ELIF])
-               cpp_warning (pfile,
-                            "suggest not using #elif in traditional C");
-             else if (indented && dir->origin == KANDR)
-               cpp_warning (pfile,
-                            "traditional C ignores #%s with the # indented",
-                            dir->name);
-             else if (!indented && dir->origin != KANDR)
-               cpp_warning (pfile,
-            "suggest hiding #%s from traditional C with an indented #",
-                            dir->name);
-           }
-
-         /* If we are skipping a failed conditional group, all
-            non-conditional directives are ignored.  */
-         if (! pfile->state.skipping || (dir->flags & COND))
-           {
-             /* Issue -pedantic warnings for extensions.   */
-             if (CPP_PEDANTIC (pfile) && dir->origin == EXTENSION)
-               cpp_pedwarn (pfile, "#%s is a GCC extension", dir->name);
-
-             /* If we have a directive that is not an opening
-                conditional, invalidate any control macro.  */
-             if (! (dir->flags & IF_COND))
-               pfile->mi_valid = false;
-
-             (*dir->handler) (pfile);
-           }
+         /* In failed conditional groups, all non-conditional
+            directives are ignored.  Before doing that, whether
+            skipping or not, we should lex angle-bracketed headers
+            correctly, and maybe output some diagnostics.  */
+         pfile->state.angled_headers = dir->flags & INCL;
+         if (! CPP_OPTION (pfile, preprocessed))
+           directive_diagnostics (pfile, dir, indented);
+         if (pfile->state.skipping && !(dir->flags & COND))
+           dir = 0;
        }
     }
-  else if (dname.type != CPP_EOF && ! pfile->state.skipping)
+  else if (dname.type == CPP_EOF)
+    ;  /* CPP_EOF is the "null directive".  */
+  else
     {
       /* An unknown directive.  Don't complain about it in assembly
         source: we don't know where the comments are, and # may
         introduce assembler pseudo-ops.  Don't complain about invalid
         directives in skipped conditional groups (6.10 p4).  */
       if (CPP_OPTION (pfile, lang) == CLK_ASM)
-       {
-         /* Output the # and this token for the assembler.  */
-         _cpp_backup_tokens (pfile, 1);
-         skip = 0;
-       }
-      else
+       skip = 0;
+      else if (!pfile->state.skipping)
        cpp_error (pfile, "invalid preprocessing directive #%s",
                   cpp_token_as_text (pfile, &dname));
     }
 
-  if (pfile->state.in_directive)
-    end_directive (pfile, skip);
+  if (dir)
+    {
+      pfile->directive = dir;
+      (*pfile->directive->handler) (pfile);
+    }
+  else if (skip == 0)
+    _cpp_backup_tokens (pfile, 1);
+
+  end_directive (pfile, skip);
   return skip;
 }
 
@@ -394,11 +400,10 @@ run_directive (pfile, dir_no, buf, count)
   cpp_push_buffer (pfile, (const U_CHAR *) buf, count,
                   /* from_stage3 */ true, 1);
   start_directive (pfile);
-  pfile->buffer->saved_flags = 0; /* We don't want to recognise directives.  */
-  pfile->state.prevent_expansion++;
+  /* We don't want a leading # to be interpreted as a directive.  */
+  pfile->buffer->saved_flags = 0;
   pfile->directive = &dtable[dir_no];
   (void) (*pfile->directive->handler) (pfile);
-  pfile->state.prevent_expansion--;
   end_directive (pfile, 1);
   _cpp_pop_buffer (pfile);
 }
@@ -708,6 +713,11 @@ do_line (pfile)
   /* C99 raised the minimum limit on #line numbers.  */
   cap = CPP_OPTION (pfile, c99) ? 2147483647 : 32767;
 
+  /* Putting this in _cpp_handle_directive risks two calls to
+     _cpp_backup_tokens in some circumstances, which can segfault.  */
+  if (pfile->state.line_extension)
+    _cpp_backup_tokens (pfile, 1);
+
   /* #line commands expand macros.  */
   cpp_get_token (pfile, &token);
   if (token.type != CPP_NUMBER
index 77199956765b81ce21706dda3444988685ee8e05..ad7418755a5c28b1d329a0812967b1e43b1e62c2 100644 (file)
@@ -41,7 +41,6 @@ typedef struct cpp_token cpp_token;
 typedef struct cpp_string cpp_string;
 typedef struct cpp_hashnode cpp_hashnode;
 typedef struct cpp_macro cpp_macro;
-typedef struct cpp_lexer_pos cpp_lexer_pos;
 typedef struct cpp_callbacks cpp_callbacks;
 
 struct answer;
@@ -186,13 +185,6 @@ struct cpp_token
   } val;
 };
 
-/* The position of a token in the current file.  */
-struct cpp_lexer_pos
-{
-  unsigned int line;
-  unsigned short col;
-};
-
 /* A standalone character.  We may want to make it unsigned for the
    same reason we use unsigned char - to avoid signedness issues.  */
 typedef int cppchar_t;
index 5c64767b656cefd5bd47c99db7fc36659a310be7..80c01541cef8406e9f6b254ca82e67383f3127ce 100644 (file)
@@ -1321,8 +1321,12 @@ _cpp_create_definition (pfile, node)
   /* Don't count the CPP_EOF.  */
   macro->count--;
 
-  /* Clear the whitespace flag from the leading token.  */
-  macro->expansion[0].flags &= ~PREV_WHITE;
+  /* Clear the whitespace flag from the leading token, but put a space
+     in front of a leading # which might be used to fake a directive.  */
+  if (macro->expansion[0].type == CPP_HASH)
+    macro->expansion[0].flags |= PREV_WHITE;
+  else
+    macro->expansion[0].flags &= ~PREV_WHITE;
 
   /* Implement the macro-defined-to-itself optimisation.  */
   macro->disabled = (macro->count == 1 && !macro->fun_like
index 18bd7fd256b556a1369ba1ed7a520f4f64bd1c96..5451ccc31f4474ad38f094b00bea7cd4ed78ed76 100644 (file)
@@ -233,13 +233,6 @@ scan_translation_unit (pfile)
       if ((token->flags & (PREV_WHITE | AVOID_LPASTE | BOL)) == AVOID_LPASTE
          && cpp_avoid_paste (pfile, &tokens[1 - index], token))
        token->flags |= PREV_WHITE;
-      /* Special case '# <directive name>': insert a space between
-        the # and the token.  This will prevent it from being
-        treated as a directive when this code is re-preprocessed.
-        XXX Should do this only at the beginning of a line, but how?  */
-      else if (token->type == CPP_NAME && token->val.node->directive_index
-              && tokens[1 - index].type == CPP_HASH)
-       token->flags |= PREV_WHITE;
 
       cpp_output_token (token, print.outf);
       if (token->type == CPP_STRING || token->type == CPP_WSTRING
index 0aea5b73aae26d4b44fac63f288cd434c313eb2f..40333a375d396c29559c79c9361422c24a4c2556 100644 (file)
@@ -1,3 +1,7 @@
+2001-09-16  Neil Booth  <neil@daikokuya.demon.co.uk>
+
+       * gcc.dg/cpp/line5.c: New testcase.
+
 2001-09-15  Neil Booth  <neil@daikokuya.demon.co.uk>
 
        * gcc.dg/cpp/macro9.c: New test.
diff --git a/gcc/testsuite/gcc.dg/cpp/line5.c b/gcc/testsuite/gcc.dg/cpp/line5.c
new file mode 100644 (file)
index 0000000..d0c04b7
--- /dev/null
@@ -0,0 +1,15 @@
+/* Copyright (C) 2001 Free Software Foundation, Inc.  */
+
+/* { dg-do preprocess } */
+/* { dg-options "-fpreprocessed" } */
+
+/* Source: Neil Booth, 16 Sep 2001.
+
+   This file, with an indented line marker, is not possible without
+   user editing of preprocessed output, or the user using
+   -fpreprocessed on raw source.  Nevertheless, we should not
+   segfault.  This is a test that we don't back up two tokens in
+   cpplib.c - one to back up over the number, and one when we
+   recognise that it's not a valid directive in preprocessed input.  */
+
+ # 1 "foo.c"