This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

cpplib: Fix line-map thinko


A call to add_line_map() can do a realloc of the map array, so it is
important that any previous map pointers are considered invalid from
that point on, including the immediate file_change callback.

Unforunately, cppmain.c was caching the previous value of the map
pointer and using it at the start of the callback to bring the current
line up-to-date.  Apologies if this tripped anyone up, for e.g. large
C++ compilations.

Fixed below.  This'll have to wait 12 hrs to be committed, since I
have to go to work.

Neil.

	* cpplib.h, line-map.h: Update comments.
	* cppmain.c (printer_init): Move inline.
	(maybe_print_line, print_line): Take a map pointer.
	(cb_ident, cb_define, cb_undef, cb_include, cb_def_pragma): Update.
	(cb_file_change): Don't use prior value of print.map.

Index: cpplib.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cpplib.h,v
retrieving revision 1.183
diff -u -p -r1.183 cpplib.h
--- cpplib.h	2001/08/06 21:07:39	1.183
+++ cpplib.h	2001/08/07 06:19:26
@@ -390,7 +390,7 @@ struct cpp_options
 typedef struct cpp_file_change cpp_file_change;
 struct cpp_file_change
 {
-  struct line_map *map;		/* Line map to use until next callback.  */
+  struct line_map *map;		/* Line map, valid until next callback.  */
   unsigned int line;		/* Logical line number of next line.  */
   enum lc_reason reason;	/* Reason for change.  */
   unsigned char sysp;		/* Nonzero if system header.  */
Index: cppmain.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cppmain.c,v
retrieving revision 1.73
diff -u -p -r1.73 cppmain.c
--- cppmain.c	2001/08/06 21:07:40	1.73
+++ cppmain.c	2001/08/07 06:19:26
@@ -32,9 +32,9 @@ struct printer
 {
   FILE *outf;			/* Stream to write to.  */
   const char *syshdr_flags;	/* System header flags, if any.  */
+  struct line_map *map;		/* Logical to physical line mappings.  */
   unsigned int line;		/* Line currently being written.  */
   unsigned char printed;	/* Nonzero if something output at line.  */
-  struct line_map *map;		/* Logical to physical line mappings.  */
 };
 
 int main		PARAMS ((int, char **));
@@ -45,11 +45,11 @@ static void setup_callbacks PARAMS ((voi
 /* General output routines.  */
 static void scan_translation_unit PARAMS ((cpp_reader *));
 static void check_multiline_token PARAMS ((cpp_string *));
-static void printer_init PARAMS ((void));
 static int dump_macro PARAMS ((cpp_reader *, cpp_hashnode *, void *));
 
-static void print_line PARAMS ((unsigned int, const char *));
-static void maybe_print_line PARAMS ((unsigned int));
+static void print_line PARAMS ((struct line_map *, unsigned int,
+				const char *));
+static void maybe_print_line PARAMS ((struct line_map *, unsigned int));
 
 /* Callback routines for the parser.   Most of these are active only
    in specific modes.  */
@@ -139,14 +139,26 @@ do_preprocessing (argc, argv)
   if (options->help_only)
     return;
 
+  /* Initialize the printer structure.  Setting print.line to -1 here
+     is a trick to guarantee that the first token of the file will
+     cause a linemarker to be output by maybe_print_line.  */
+  print.line = (unsigned int) -1;
+  print.printed = 0;
+  print.map = 0;
+  
   /* Open the output now.  We must do so even if no_output is on,
      because there may be other output than from the actual
      preprocessing (e.g. from -dM).  */
-  printer_init ();
-  if (print.outf == NULL)
+  if (options->out_fname[0] == '\0')
+    print.outf = stdout;
+  else
     {
-      cpp_notice_from_errno (pfile, options->out_fname);
-      return;
+      print.outf = fopen (options->out_fname, "w");
+      if (print.outf == NULL)
+	{
+	  cpp_notice_from_errno (pfile, options->out_fname);
+	  return;
+	}
     }
 
   setup_callbacks ();
@@ -226,7 +238,7 @@ scan_translation_unit (pfile)
 	     column.  Don't bother trying to reconstruct tabs; we can't
 	     get it right in general, and nothing ought to care.  (Yes,
 	     some things do care; the fault lies with them.)  */
-	  maybe_print_line (line);
+	  maybe_print_line (print.map, line);
 	  if (col > 1)
 	    {
 	      if (token->flags & PREV_WHITE)
@@ -267,29 +279,13 @@ check_multiline_token (str)
       print.line++;
 }
 
-/* Initialize a cpp_printer structure.  As a side effect, open the
-   output file.  If print.outf is NULL an error occurred.  */
-static void
-printer_init ()
-{
-  /* Setting print.line to -1 here guarantees that the first token of
-     the file will cause a linemarker to be output by maybe_print_line.  */
-  print.line = (unsigned int) -1;
-  print.printed = 0;
-  print.map = 0;
-
-  if (options->out_fname[0] == '\0')
-    print.outf = stdout;
-  else
-    print.outf = fopen (options->out_fname, "w");
-}
-
 /* If the token read on logical line LINE needs to be output on a
    different line to the current one, output the required newlines or
    a line marker, and return 1.  Otherwise return 0.  */
 
 static void
-maybe_print_line (line)
+maybe_print_line (map, line)
+     struct line_map *map;
      unsigned int line;
 {
   /* End the previous line of text.  */
@@ -309,11 +305,12 @@ maybe_print_line (line)
 	}
     }
   else
-    print_line (line, "");
+    print_line (map, line, "");
 }
 
 static void
-print_line (line, special_flags)
+print_line (map, line, special_flags)
+     struct line_map *map;
      unsigned int line;
      const char *special_flags;
 {
@@ -325,8 +322,8 @@ print_line (line, special_flags)
   print.line = line;
   if (! options->no_line_commands)
     fprintf (print.outf, "# %u \"%s\"%s%s\n",
-	     SOURCE_LINE (print.map, print.line),
-	     print.map->to_file, special_flags, print.syshdr_flags);
+	     SOURCE_LINE (map, print.line), map->to_file,
+	     special_flags, print.syshdr_flags);
 }
 
 /* Callbacks.  */
@@ -337,7 +334,7 @@ cb_ident (pfile, line, str)
      unsigned int line;
      const cpp_string * str;
 {
-  maybe_print_line (line);
+  maybe_print_line (print.map, line);
   fprintf (print.outf, "#ident \"%s\"\n", str->text);
   print.line++;
 }
@@ -348,7 +345,7 @@ cb_define (pfile, line, node)
      unsigned int line;
      cpp_hashnode *node;
 {
-  maybe_print_line (line);
+  maybe_print_line (print.map, line);
   fputs ("#define ", print.outf);
 
   /* -dD command line option.  */
@@ -367,7 +364,7 @@ cb_undef (pfile, line, node)
      unsigned int line;
      cpp_hashnode *node;
 {
-  maybe_print_line (line);
+  maybe_print_line (print.map, line);
   fprintf (print.outf, "#undef %s\n", NODE_NAME (node));
   print.line++;
 }
@@ -379,11 +376,14 @@ cb_include (pfile, line, dir, header)
      const unsigned char *dir;
      const cpp_token *header;
 {
-  maybe_print_line (line);
+  maybe_print_line (print.map, line);
   fprintf (print.outf, "#%s %s\n", dir, cpp_token_as_text (pfile, header));
   print.line++;
 }
 
+/* The file name, line number or system header flags have changed, as
+   described in FC.  NB: the old print.map must be considered invalid.  */
+
 static void
 cb_file_change (pfile, fc)
      cpp_reader *pfile ATTRIBUTE_UNUSED;
@@ -395,7 +395,7 @@ cb_file_change (pfile, fc)
      change callback specially, so that a first line of "# 1 "foo.c"
      in file foo.i outputs just the foo.c line, and not a foo.i line.  */
   if (fc->reason == LC_ENTER && !first_time)
-    maybe_print_line (fc->line - 1);
+    maybe_print_line (fc->map - 1, fc->line - 1);
 
   print.map = fc->map;
   if (fc->externc)
@@ -414,7 +414,7 @@ cb_file_change (pfile, fc)
       else if (fc->reason == LC_LEAVE)
 	flags = " 2";
 
-      print_line (fc->line, flags);
+      print_line (print.map, fc->line, flags);
     }
 }
 
@@ -425,7 +425,7 @@ cb_def_pragma (pfile, line)
      cpp_reader *pfile;
      unsigned int line;
 {
-  maybe_print_line (line);
+  maybe_print_line (print.map, line);
   fputs ("#pragma ", print.outf);
   cpp_output_line (pfile, print.outf);
   print.line++;
Index: line-map.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/line-map.h,v
retrieving revision 1.5
diff -u -p -r1.5 line-map.h
--- line-map.h	2001/08/06 21:07:40	1.5
+++ line-map.h	2001/08/07 06:19:34
@@ -69,7 +69,8 @@ extern void free_line_maps
    at least as long as the final call to lookup_line ().
 
    FROM_LINE should be monotonic increasing across calls to this
-   function.  */
+   function.  A call to this function can relocate the previous set of
+   maps, so any stored line_map pointers should not be used.  */
 extern struct line_map *add_line_map
   PARAMS ((struct line_maps *, enum lc_reason,
 	   unsigned int from_line, const char *to_file, unsigned int to_line));


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]