OSDN Git Service

Index: ChangeLog
[pf3gnuchains/gcc-fork.git] / gcc / line-map.c
index 27bcf2f..8bbe863 100644 (file)
@@ -22,42 +22,57 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
 #include "config.h"
 #include "system.h"
+#include "coretypes.h"
+#include "tm.h"
 #include "line-map.h"
+#include "intl.h"
+
+static void trace_include (const struct line_maps *, const struct line_map *);
 
 /* Initialize a line map set.  */
 
 void
-init_line_maps (set)
-     struct line_maps *set;
+init_line_maps (struct line_maps *set)
 {
   set->maps = 0;
   set->allocated = 0;
   set->used = 0;
+  set->last_listed = -1;
+  set->trace_includes = false;
+  set->depth = 0;
 }
 
 /* Free a line map set.  */
 
-void free_line_maps (set)
-     struct line_maps *set;
+void
+free_line_maps (struct line_maps *set)
 {
   if (set->maps)
-    free (set->maps);
+    {
+      struct line_map *map;
+
+      /* Depending upon whether we are handling preprocessed input or
+        not, this can be a user error or an ICE.  */
+      for (map = CURRENT_LINE_MAP (set); ! MAIN_FILE_P (map);
+          map = INCLUDED_FROM (set, map))
+       fprintf (stderr, "line-map.c: file \"%s\" entered but not left\n",
+                map->to_file);
+
+      free (set->maps);
+    }
 }
 
 /* Add a mapping of logical source line to physical source file and
-   line number.  Ther text pointed to by TO_FILE must have a lifetime
+   line number.  The text pointed to by TO_FILE must have a lifetime
    at least as long as the final call to lookup_line ().
 
    FROM_LINE should be monotonic increasing across calls to this
    function.  */
 
-struct line_map *
-add_line_map (set, reason, from_line, to_file, to_line)
-     struct line_maps *set;
-     enum lc_reason reason;
-     unsigned int from_line;
-     const char *to_file;
-     unsigned int to_line;
+const struct line_map *
+add_line_map (struct line_maps *set, enum lc_reason reason,
+             unsigned int sysp, unsigned int from_line,
+             const char *to_file, unsigned int to_line)
 {
   struct line_map *map;
 
@@ -71,25 +86,65 @@ add_line_map (set, reason, from_line, to_file, to_line)
        xrealloc (set->maps, set->allocated * sizeof (struct line_map));
     }
 
-  map = &set->maps[set->used];
+  map = &set->maps[set->used++];
+
+  /* If we don't keep our line maps consistent, we can easily
+     segfault.  Don't rely on the client to do it for us.  */
+  if (set->depth == 0)
+    reason = LC_ENTER;
+  else if (reason == LC_LEAVE)
+    {
+      struct line_map *from;
+      bool error;
+
+      if (MAIN_FILE_P (map - 1))
+       {
+         set->depth--;
+         set->used--;
+         return NULL;
+       }
+      else
+       {
+         from = INCLUDED_FROM (set, map - 1);
+         error = to_file && strcmp (from->to_file, to_file);
+       }
+
+      /* Depending upon whether we are handling preprocessed input or
+        not, this can be a user error or an ICE.  */
+      if (error)
+       fprintf (stderr, "line-map.c: file \"%s\" left but not entered\n",
+                to_file);
+
+      /* A TO_FILE of NULL is special - we use the natural values.  */
+      if (error || to_file == NULL)
+       {
+         to_file = from->to_file;
+         to_line = LAST_SOURCE_LINE (from) + 1;
+         sysp = from->sysp;
+       }
+    }
+
+  map->reason = reason;
+  map->sysp = sysp;
   map->from_line = from_line;
   map->to_file = to_file;
   map->to_line = to_line;
 
-  if (set->used == 0)
-    map->included_from = -1;
-  else if (reason == LC_ENTER)
-    map->included_from = set->used - 1;
+  if (reason == LC_ENTER)
+    {
+      map->included_from = set->depth == 0 ? -1 : (int) (set->used - 2);
+      set->depth++;
+      if (set->trace_includes)
+       trace_include (set, map);
+    }
   else if (reason == LC_RENAME)
     map->included_from = map[-1].included_from;
   else if (reason == LC_LEAVE)
     {
-      if (map[-1].included_from < 0)
-       abort ();
-      map->included_from = set->maps[map[-1].included_from].included_from;
+      set->depth--;
+      map->included_from = INCLUDED_FROM (set, map - 1)->included_from;
     }
 
-  set->used++;
   return map;
 }
 
@@ -98,10 +153,8 @@ add_line_map (set, reason, from_line, to_file, to_line)
    chronologically, the logical lines are monotonic increasing, and so
    the list is sorted and we can use a binary search.  */
 
-struct line_map *
-lookup_line (set, line)
-     struct line_maps *set;
-     unsigned int line;
+const struct line_map *
+lookup_line (struct line_maps *set, unsigned int line)
 {
   unsigned int md, mn = 0, mx = set->used;
 
@@ -119,3 +172,53 @@ lookup_line (set, line)
 
   return &set->maps[mn];
 }
+
+/* Print the file names and line numbers of the #include commands
+   which led to the map MAP, if any, to stderr.  Nothing is output if
+   the most recently listed stack is the same as the current one.  */
+
+void
+print_containing_files (struct line_maps *set, const struct line_map *map)
+{
+  if (MAIN_FILE_P (map) || set->last_listed == map->included_from)
+    return;
+
+  set->last_listed = map->included_from;
+  map = INCLUDED_FROM (set, map);
+
+  fprintf (stderr,  _("In file included from %s:%u"),
+          map->to_file, LAST_SOURCE_LINE (map));
+
+  while (! MAIN_FILE_P (map))
+    {
+      map = INCLUDED_FROM (set, map);
+      /* Translators note: this message is used in conjunction
+        with "In file included from %s:%ld" and some other
+        tricks.  We want something like this:
+
+        | In file included from sys/select.h:123,
+        |                  from sys/types.h:234,
+        |                  from userfile.c:31:
+        | bits/select.h:45: <error message here>
+
+        with all the "from"s lined up.
+        The trailing comma is at the beginning of this message,
+        and the trailing colon is not translated.  */
+      fprintf (stderr, _(",\n                 from %s:%u"),
+              map->to_file, LAST_SOURCE_LINE (map));
+    }
+
+  fputs (":\n", stderr);
+}
+
+/* Print an include trace, for e.g. the -H option of the preprocessor.  */
+
+static void
+trace_include (const struct line_maps *set, const struct line_map *map)
+{
+  unsigned int i = set->depth;
+
+  while (--i)
+    putc ('.', stderr);
+  fprintf (stderr, " %s\n", map->to_file);
+}