line-map include-from representation

Message ID eb3707e4-c7a7-6276-ceb3-95fb2de9595b@acm.org
State New
Headers show
Series
  • line-map include-from representation
Related show

Commit Message

Nathan Sidwell Aug. 8, 2018, 1:06 p.m.
This patch changes the way line-maps hold the included-from information. 
  Currently this is an index to another (earlier) line-map, and relies 
on the fact that #include cause the termination of the current map and 
emission of a new map.  It's then possible to determine the location of 
the include directive as the last line of the just terminated line map 
(by examining the first location of the next map).

With modules, I'd like to show the import path in a similar way.  But 
importing a module doesn't (necessarily) cause termination of a line map 
-- the imported module's 'imported-from' location is in the middle of 
some other map.  Here's what that looks like:
In file of module bob,
           imported at loc-2_b.C:5,
         of module stuart,
           imported at loc-2_d.C:2:
loc-2_a.C:5:18: note:   initializing argument 1 of 'int frob(int*)'

[included-from lines may appear in the middle of that stack too]

Thus, this patch uses a source_location to represent the included from 
location.  No data size changes, as old and new forms are really ints. 
IMHO it makes the interface somewhat cleaner, as we stop exposing the 
map indexes to the library users.

[I noticed that a piece of this patch already escaped, we were using 
LAST_SOURCE_COLUMN in diagnostic_report_current_module, but I'd 
inadvertently changed that in the prepatch that was intended to prepare 
the ground for this one.  Sorry.]

booted & tested on x86_64-linux, ok?

nathan

Comments

David Malcolm Aug. 8, 2018, 2:46 p.m. | #1
On Wed, 2018-08-08 at 09:06 -0400, Nathan Sidwell wrote:
> This patch changes the way line-maps hold the included-from
> information. 
>   Currently this is an index to another (earlier) line-map, and
> relies 
> on the fact that #include cause the termination of the current map
> and 
> emission of a new map.  It's then possible to determine the location
> of 
> the include directive as the last line of the just terminated line
> map 
> (by examining the first location of the next map).
> 
> With modules, I'd like to show the import path in a similar
> way.  But 
> importing a module doesn't (necessarily) cause termination of a line
> map 
> -- the imported module's 'imported-from' location is in the middle
> of 
> some other map.  Here's what that looks like:
> In file of module bob,
>            imported at loc-2_b.C:5,
>          of module stuart,
>            imported at loc-2_d.C:2:
> loc-2_a.C:5:18: note:   initializing argument 1 of 'int frob(int*)'
> 
> [included-from lines may appear in the middle of that stack too]
> 
> Thus, this patch uses a source_location to represent the included
> from 
> location.  No data size changes, as old and new forms are really
> ints. 
> IMHO it makes the interface somewhat cleaner, as we stop exposing
> the 
> map indexes to the library users.
> 
> [I noticed that a piece of this patch already escaped, we were using 
> LAST_SOURCE_COLUMN in diagnostic_report_current_module, but I'd 
> inadvertently changed that in the prepatch that was intended to
> prepare 
> the ground for this one.  Sorry.]
> 
> booted & tested on x86_64-linux, ok?

> 2018-08-08  Nathan Sidwell  <nathan@acm.org>
> 
> 	Make linemap::included_at a location
> 	libcpp/
> 	* include/line-map.h (struct line_map_ordinary): Replace
> 	included_from map index with included_at source_location.
> 	(ORDINARY_MAP_INCLUDER_FILE_INDEX): Delete.
> 	(LAST_SOURCE_LINE_LOCATION): Move to line-map.c.

Looks like LAST_SOURCE_LINE was also deleted.

> 	(LAST_SOURCE_COLUMN): Delete.
> 	(INCLUDED_AT): New.
> 	(linemap_included_at): Declare.
> 	(MAIN_FILE_P): Adjust.
> 	* line-map.c (linemap_included_at): New.
> 	(lonemap_check_files_exited): Use linemap_included_at.
> 	(LAST_SOURCE_LINE_LOCATION): Made internal from header file.
> 	(linemap_add): Adjust inclusion setting.
> 	(linemap_dump, linemap_dump_location): Adjust.
> 	* directives.c (do_linemarker): Use linemap_included_at.
> 	gcc/
> 	* diagnostic.c (diagnostic_report_current_module): Use INCLUDED_AT
> 	& linemap_included_at.
> 	gcc/c-family/
> 	* c-common.c (try_to_locate_new_include_inertion_point): Use
> 	linemap_included_at.
> 	* c-lex.c (fe_file_change): Use INCLUDED_AT.
> 	* c-ppoutput.c (pp_file_change): Likewise.
> 	gcc/fortran/
> 	* cpp.c (cb_file_change): Use INCLUDED_AT.
> 
> Index: gcc/c-family/c-common.c
> ===================================================================
> --- gcc/c-family/c-common.c	(revision 263365)
> +++ gcc/c-family/c-common.c	(working copy)
> @@ -8413,8 +8413,8 @@ try_to_locate_new_include_insertion_poin
>        const line_map_ordinary *ord_map
>  	= LINEMAPS_ORDINARY_MAP_AT (line_table, i);
>  
> -      const line_map_ordinary *from = INCLUDED_FROM (line_table, ord_map);
> -      if (from)
> +      if (const line_map_ordinary *from
> +	  = linemap_included_at (line_table, ord_map))

I think "linemap_included_from" would be a better name for what this
patch calls "linemap_included_at".

Doing so would make a better distinction between the location at which
the include happened, vs the linemap in which it happened.

[...snip...]

> Index: libcpp/include/line-map.h
> ===================================================================
> --- libcpp/include/line-map.h	(revision 263365)
> +++ libcpp/include/line-map.h	(working copy)

[...snip...]

> -/* Return the last column number within an ordinary map.  */
> -
> -inline linenum_type
> -LAST_SOURCE_COLUMN (const line_map_ordinary *map)
> +inline source_location
> +INCLUDED_AT (const line_map_ordinary *ord_map)
>  {
> -  return SOURCE_COLUMN (map, LAST_SOURCE_LINE_LOCATION (map));
> +  return ord_map->included_at;
>  }

These used to be macros, hence the SCARY_UPPER_CASE; I converted them
to inline functions as a precursor to adding range support to
locations; I didn't rename them at the time, to minimize churn.

This is a new inline function, and so doesn't need to be in upper case.
How about "linemap_included_at" - which you're already using for
something else, but which I think should be renamed...

> -/* Returns the map a given map was included from, or NULL if the map
> -   belongs to the main file, i.e, a file that wasn't included by
> -   another one.  */
> -inline line_map_ordinary *
> -INCLUDED_FROM (struct line_maps *set, const line_map_ordinary *ord_map)
> -{
> -  return ((ord_map->included_from == -1)
> -	  ? NULL
> -	  : LINEMAPS_ORDINARY_MAP_AT (set, ord_map->included_from));
> -}
> +/* The linemap containing the included-from location.  */
> +const line_map_ordinary *linemap_included_at (line_maps *set,
> +					      const line_map_ordinary *);

...indeed, please rename this one to "linemap_included_from".

[...snip...]

>  /* Encode and return a source_location from a column number. The
> Index: libcpp/line-map.c
> ===================================================================
> --- libcpp/line-map.c	(revision 263366)
> +++ libcpp/line-map.c	(working copy)
> @@ -355,17 +355,25 @@ linemap_init (struct line_maps *set,
>    set->builtin_location = builtin_location;
>  }
>  
> +/* Return the ordinary line map from whence MAP was included.  Returns
> +   NULL if MAP was not an included.  */
> +
> +const line_map_ordinary *
> +linemap_included_at (line_maps *set, const line_map_ordinary *map)
> +{
> +  return linemap_ordinary_map_lookup (set, INCLUDED_AT (map));
> +}

So, with the renamings, this would look like:

const line_map_ordinary *
linemap_included_from (line_maps *set, const line_map_ordinary *map)
{
  return linemap_ordinary_map_lookup (set, linemap_included_at (map));
}

[...snip...]

> @@ -435,6 +443,17 @@ new_linemap (struct line_maps *set,  sou
>    return result;
>  }
>  
> +/* Return the location of the last source line within an ordinary
> +   map.  */
> +inline source_location
> +LAST_SOURCE_LINE_LOCATION (const line_map_ordinary *map)
> +{
> +  return (((map[1].start_location - 1
> +	    - map->start_location)
> +	   & ~((1 << map->m_column_and_range_bits) - 1))
> +	  + map->start_location);
> +}

Can this be made "static" now?  (and maybe lose the "inline" hint?)  I
think it's only used in one place after your patch.

[...snip...]

We don't seem to have much test coverage for this code.  Sorry to be a
pain, but could you please try adding a testcase of a diagnostic issued
from within a couple of levels of nested includes, perhaps using

/* { dg-options "-fdiagnostics-show-caret" } */

and

/* { dg-begin-multiline-output "" }
   { dg-end-multiline-output "" } */

(or dg-regexp if need be for dealing with arbitrary paths in filenames)

to give us some explicit test coverage of what the user sees? (and to
verify that this doesn't change the output).  None of our existing test
cases directly verify this, as far as I can tell. (I did some grepping,
but I only found a few dg-message directives referring to parts of the
output, and the stuff in prune.exp)

We'd presumably want something similar when you add modules support, to
verify that the "imported from" and "included from" stuff interact
appropriately and look sane to the end-user, so it'd be nice to test
the simple case first.

Thanks
Dave
Nathan Sidwell Aug. 8, 2018, 3:28 p.m. | #2
On 08/08/2018 10:46 AM, David Malcolm wrote:

> [...snip...]
> 
> We don't seem to have much test coverage for this code.  Sorry to be a
> pain, but could you please try adding a testcase of a diagnostic issued
> from within a couple of levels of nested includes, perhaps using
> 
> /* { dg-options "-fdiagnostics-show-caret" } */
> 
> and
> 
> /* { dg-begin-multiline-output "" }
>     { dg-end-multiline-output "" } */
> 
> (or dg-regexp if need be for dealing with arbitrary paths in filenames)

I could never get existing dejagnu check this particular piece of 
output.  AFAICT this is all unconditionally pruned before the output 
scanners get a look-see.  On the modules branch I ended up hacking in a 
pre-pruned-output hook.  It's not pretty.

nathan
David Malcolm Aug. 8, 2018, 3:36 p.m. | #3
On Wed, 2018-08-08 at 11:28 -0400, Nathan Sidwell wrote:
> On 08/08/2018 10:46 AM, David Malcolm wrote:
> 
> > [...snip...]
> > 
> > We don't seem to have much test coverage for this code.  Sorry to
> > be a
> > pain, but could you please try adding a testcase of a diagnostic
> > issued
> > from within a couple of levels of nested includes, perhaps using
> > 
> > /* { dg-options "-fdiagnostics-show-caret" } */
> > 
> > and
> > 
> > /* { dg-begin-multiline-output "" }
> >     { dg-end-multiline-output "" } */
> > 
> > (or dg-regexp if need be for dealing with arbitrary paths in
> > filenames)
> 
> I could never get existing dejagnu check this particular piece of 
> output.  AFAICT this is all unconditionally pruned before the output 
> scanners get a look-see.  On the modules branch I ended up hacking in
> a 
> pre-pruned-output hook.  It's not pretty.

In r255786 I adjusted prune.exp to move the dg-regexp handling to
before the pruning.  Unfortunately, handle-multiline-outputs is still
after the pruning.  I guess we could try moving that to before as well,
but I suspect it might break some things.

Dave
David Malcolm Aug. 8, 2018, 3:39 p.m. | #4
On Wed, 2018-08-08 at 11:36 -0400, David Malcolm wrote:
> On Wed, 2018-08-08 at 11:28 -0400, Nathan Sidwell wrote:
> > On 08/08/2018 10:46 AM, David Malcolm wrote:
> > 
> > > [...snip...]
> > > 
> > > We don't seem to have much test coverage for this code.  Sorry to
> > > be a
> > > pain, but could you please try adding a testcase of a diagnostic
> > > issued
> > > from within a couple of levels of nested includes, perhaps using
> > > 
> > > /* { dg-options "-fdiagnostics-show-caret" } */
> > > 
> > > and
> > > 
> > > /* { dg-begin-multiline-output "" }
> > >     { dg-end-multiline-output "" } */
> > > 
> > > (or dg-regexp if need be for dealing with arbitrary paths in
> > > filenames)
> > 
> > I could never get existing dejagnu check this particular piece of 
> > output.  AFAICT this is all unconditionally pruned before the
> > output 
> > scanners get a look-see.  On the modules branch I ended up hacking
> > in
> > a 
> > pre-pruned-output hook.  It's not pretty.
> 
> In r255786 I adjusted prune.exp to move the dg-regexp handling to
> before the pruning.  Unfortunately, handle-multiline-outputs is still
> after the pruning.  I guess we could try moving that to before as
> well,
> but I suspect it might break some things.

Alternatively, could the test cases in r255786 (aka
6d8c9f39007790df9c08fca1e4c458a22b04e9c4) be adapted to provide some
test coverage of this?  (they use dg-regexp for the awkward lines)
Nathan Sidwell Aug. 8, 2018, 6:08 p.m. | #5
On 08/08/2018 11:36 AM, David Malcolm wrote:

> In r255786 I adjusted prune.exp to move the dg-regexp handling to
> before the pruning.  Unfortunately, handle-multiline-outputs is still
> after the pruning.  I guess we could try moving that to before as well,
> but I suspect it might break some things.

Ah, that shows how to use dg-regexp, which does the trick.  I guess I 
can go kill the hack I did on the modules branch for this.

Here's what I'll commit

nathan

Patch

2018-08-08  Nathan Sidwell  <nathan@acm.org>

	Make linemap::included_at a location
	libcpp/
	* include/line-map.h (struct line_map_ordinary): Replace
	included_from map index with included_at source_location.
	(ORDINARY_MAP_INCLUDER_FILE_INDEX): Delete.
	(LAST_SOURCE_LINE_LOCATION): Move to line-map.c.
	(LAST_SOURCE_COLUMN): Delete.
	(INCLUDED_AT): New.
	(linemap_included_at): Declare.
	(MAIN_FILE_P): Adjust.
	* line-map.c (linemap_included_at): New.
	(lonemap_check_files_exited): Use linemap_included_at.
	(LAST_SOURCE_LINE_LOCATION): Made internal from header file.
	(linemap_add): Adjust inclusion setting.
	(linemap_dump, linemap_dump_location): Adjust.
	* directives.c (do_linemarker): Use linemap_included_at.
	gcc/
	* diagnostic.c (diagnostic_report_current_module): Use INCLUDED_AT
	& linemap_included_at.
	gcc/c-family/
	* c-common.c (try_to_locate_new_include_inertion_point): Use
	linemap_included_at.
	* c-lex.c (fe_file_change): Use INCLUDED_AT.
	* c-ppoutput.c (pp_file_change): Likewise.
	gcc/fortran/
	* cpp.c (cb_file_change): Use INCLUDED_AT.

Index: gcc/c-family/c-common.c
===================================================================
--- gcc/c-family/c-common.c	(revision 263365)
+++ gcc/c-family/c-common.c	(working copy)
@@ -8413,8 +8413,8 @@  try_to_locate_new_include_insertion_poin
       const line_map_ordinary *ord_map
 	= LINEMAPS_ORDINARY_MAP_AT (line_table, i);
 
-      const line_map_ordinary *from = INCLUDED_FROM (line_table, ord_map);
-      if (from)
+      if (const line_map_ordinary *from
+	  = linemap_included_at (line_table, ord_map))
 	if (from->to_file == file)
 	  {
 	    last_include_ord_map = from;
Index: gcc/c-family/c-lex.c
===================================================================
--- gcc/c-family/c-lex.c	(revision 263365)
+++ gcc/c-family/c-lex.c	(working copy)
@@ -199,7 +199,7 @@  fe_file_change (const line_map_ordinary
 	 we already did in compile_file.  */
       if (!MAIN_FILE_P (new_map))
 	{
-	  unsigned int included_at = LAST_SOURCE_LINE_LOCATION (new_map - 1);
+	  location_t included_at = INCLUDED_AT (new_map);
 	  int line = 0;
 	  if (included_at > BUILTINS_LOCATION)
 	    line = SOURCE_LINE (new_map - 1, included_at);
Index: gcc/c-family/c-ppoutput.c
===================================================================
--- gcc/c-family/c-ppoutput.c	(revision 263365)
+++ gcc/c-family/c-ppoutput.c	(working copy)
@@ -663,11 +663,9 @@  pp_file_change (const line_map_ordinary
 	  /* Bring current file to correct line when entering a new file.  */
 	  if (map->reason == LC_ENTER)
 	    {
-	      const line_map_ordinary *from = INCLUDED_FROM (line_table, map);
-	      maybe_print_line (LAST_SOURCE_LINE_LOCATION (from));
+	      maybe_print_line (INCLUDED_AT (map));
+	      flags = " 1";
 	    }
-	  if (map->reason == LC_ENTER)
-	    flags = " 1";
 	  else if (map->reason == LC_LEAVE)
 	    flags = " 2";
 	  print_line (map->start_location, flags);
Index: gcc/diagnostic.c
===================================================================
--- gcc/diagnostic.c	(revision 263365)
+++ gcc/diagnostic.c	(working copy)
@@ -590,9 +590,10 @@  diagnostic_report_current_module (diagno
 	  bool first = true;
 	  do
 	    {
-	      map = INCLUDED_FROM (line_table, map);
+	      where = INCLUDED_AT (map);
+	      map = linemap_included_at (line_table, map);
 	      const char *line_col
-		= maybe_line_and_column (LAST_SOURCE_LINE (map),
+		= maybe_line_and_column (SOURCE_LINE (map, where),
 					 first && context->show_column
 					 ? SOURCE_COLUMN (map, where) : 0);
 	      static const char *const msgs[] =
Index: gcc/fortran/cpp.c
===================================================================
--- gcc/fortran/cpp.c	(revision 263365)
+++ gcc/fortran/cpp.c	(working copy)
@@ -881,10 +881,7 @@  cb_file_change (cpp_reader * ARG_UNUSED
 	{
 	  /* Bring current file to correct line when entering a new file.  */
 	  if (map->reason == LC_ENTER)
-	    {
-	      const line_map_ordinary *from = INCLUDED_FROM (line_table, map);
-	      maybe_print_line (LAST_SOURCE_LINE_LOCATION (from));
-	    }
+	    maybe_print_line (INCLUDED_AT (map));
 	  if (map->reason == LC_ENTER)
 	    flags = " 1";
 	  else if (map->reason == LC_LEAVE)
Index: libcpp/directives.c
===================================================================
--- libcpp/directives.c	(revision 263365)
+++ libcpp/directives.c	(working copy)
@@ -1088,10 +1088,9 @@  do_linemarker (cpp_reader *pfile)
       /* Reread map since cpp_get_token can invalidate it with a
 	 reallocation.  */
       map = LINEMAPS_LAST_ORDINARY_MAP (line_table);
-      const line_map_ordinary *from;      
+      const line_map_ordinary *from = linemap_included_at (line_table, map);
       if (MAIN_FILE_P (map)
-	  || (new_file
-	      && (from = INCLUDED_FROM (pfile->line_table, map)) != NULL
+	  || (from
 	      && filename_cmp (ORDINARY_MAP_FILE_NAME (from), new_file) != 0))
 	{
 	  cpp_warning (pfile, CPP_W_NONE,
Index: libcpp/include/line-map.h
===================================================================
--- libcpp/include/line-map.h	(revision 263365)
+++ libcpp/include/line-map.h	(working copy)
@@ -440,10 +440,10 @@  struct GTY((tag ("1"))) line_map_ordinar
   const char *to_file;
   linenum_type to_line;
 
-  /* An index into the set that gives the line mapping at whose end
-     the current one was included.  File(s) at the bottom of the
-     include stack have this set to -1.  */
-  int included_from;
+  /* Location at which this line map was included from.  For regular
+     #includes, this location will be the last location of a map.  For
+     outermost file, this is 0.  */
+  source_location included_at;
 
   /* Size is 20 or 24 bytes, no padding  */
 };
@@ -634,17 +634,6 @@  ORDINARY_MAP_STARTING_LINE_NUMBER (const
   return ord_map->to_line;
 }
 
-/* Get the index of the ordinary map at whose end
-   ordinary map MAP was included.
-
-   File(s) at the bottom of the include stack have this set.  */
-
-inline int
-ORDINARY_MAP_INCLUDER_FILE_INDEX (const line_map_ordinary *ord_map)
-{
-  return ord_map->included_from;
-}
-
 /* Return a positive value if map encodes locations from a system
    header, 0 otherwise. Returns 1 if ordinary map MAP encodes locations
    in a system header and 2 if it encodes locations in a C system header
@@ -1192,51 +1181,23 @@  SOURCE_COLUMN (const line_map_ordinary *
 	  & ((1 << ord_map->m_column_and_range_bits) - 1)) >> ord_map->m_range_bits;
 }
 
-/* Return the location of the last source line within an ordinary
-   map.  */
-inline source_location
-LAST_SOURCE_LINE_LOCATION (const line_map_ordinary *map)
-{
-  return (((map[1].start_location - 1
-	    - map->start_location)
-	   & ~((1 << map->m_column_and_range_bits) - 1))
-	  + map->start_location);
-}
-
-/* Returns the last source line number within an ordinary map.  This
-   is the (last) line of the #include, or other directive, that caused
-   a map change.  */
-inline linenum_type
-LAST_SOURCE_LINE (const line_map_ordinary *map)
-{
-  return SOURCE_LINE (map, LAST_SOURCE_LINE_LOCATION (map));
-}
 
-/* Return the last column number within an ordinary map.  */
-
-inline linenum_type
-LAST_SOURCE_COLUMN (const line_map_ordinary *map)
+inline source_location
+INCLUDED_AT (const line_map_ordinary *ord_map)
 {
-  return SOURCE_COLUMN (map, LAST_SOURCE_LINE_LOCATION (map));
+  return ord_map->included_at;
 }
 
-/* Returns the map a given map was included from, or NULL if the map
-   belongs to the main file, i.e, a file that wasn't included by
-   another one.  */
-inline line_map_ordinary *
-INCLUDED_FROM (struct line_maps *set, const line_map_ordinary *ord_map)
-{
-  return ((ord_map->included_from == -1)
-	  ? NULL
-	  : LINEMAPS_ORDINARY_MAP_AT (set, ord_map->included_from));
-}
+/* The linemap containing the included-from location.  */
+const line_map_ordinary *linemap_included_at (line_maps *set,
+					      const line_map_ordinary *);
 
 /* True if the map is at the bottom of the include stack.  */
 
 inline bool
 MAIN_FILE_P (const line_map_ordinary *ord_map)
 {
-  return ord_map->included_from < 0;
+  return ord_map->included_at == 0;
 }
 
 /* Encode and return a source_location from a column number. The
Index: libcpp/line-map.c
===================================================================
--- libcpp/line-map.c	(revision 263366)
+++ libcpp/line-map.c	(working copy)
@@ -355,17 +355,25 @@  linemap_init (struct line_maps *set,
   set->builtin_location = builtin_location;
 }
 
+/* Return the ordinary line map from whence MAP was included.  Returns
+   NULL if MAP was not an included.  */
+
+const line_map_ordinary *
+linemap_included_at (line_maps *set, const line_map_ordinary *map)
+{
+  return linemap_ordinary_map_lookup (set, INCLUDED_AT (map));
+}
+
 /* Check for and warn about line_maps entered but not exited.  */
 
 void
 linemap_check_files_exited (struct line_maps *set)
 {
-  const line_map_ordinary *map;
   /* Depending upon whether we are handling preprocessed input or
      not, this can be a user error or an ICE.  */
-  for (map = LINEMAPS_LAST_ORDINARY_MAP (set);
+  for (const line_map_ordinary *map = LINEMAPS_LAST_ORDINARY_MAP (set);
        ! MAIN_FILE_P (map);
-       map = INCLUDED_FROM (set, map))
+       map = linemap_included_at (set, map))
     fprintf (stderr, "line-map.c: file \"%s\" entered but not left\n",
 	     ORDINARY_MAP_FILE_NAME (map));
 }
@@ -435,6 +443,17 @@  new_linemap (struct line_maps *set,  sou
   return result;
 }
 
+/* Return the location of the last source line within an ordinary
+   map.  */
+inline source_location
+LAST_SOURCE_LINE_LOCATION (const line_map_ordinary *map)
+{
+  return (((map[1].start_location - 1
+	    - map->start_location)
+	   & ~((1 << map->m_column_and_range_bits) - 1))
+	  + map->start_location);
+}
+
 /* Add a mapping of logical source line to physical source file and
    line number.
 
@@ -494,19 +513,19 @@  linemap_add (struct line_maps *set, enum
   if (reason == LC_RENAME_VERBATIM)
     reason = LC_RENAME;
 
+  const line_map_ordinary *from = NULL;
   if (reason == LC_LEAVE)
     {
       /* When we are just leaving an "included" file, and jump to the next
 	 location inside the "includer" right after the #include
 	 "included", this variable points the map in use right before the
 	 #include "included", inside the same "includer" file.  */
-      line_map_ordinary *from;
 
       linemap_assert (!MAIN_FILE_P (map - 1));
       /* (MAP - 1) points to the map we are leaving. The
 	 map from which (MAP - 1) got included should be the map
 	 that comes right before MAP in the same file.  */
-      from = INCLUDED_FROM (set, map - 1);
+      from = linemap_included_at (set, map - 1);
 
       /* A TO_FILE of NULL is special - we use the natural values.  */
       if (to_file == NULL)
@@ -538,19 +557,20 @@  linemap_add (struct line_maps *set, enum
 
   if (reason == LC_ENTER)
     {
-      map->included_from =
-	set->depth == 0 ? -1 : (int) (LINEMAPS_ORDINARY_USED (set) - 2);
+      if (set->depth == 0)
+	map->included_at = 0;
+      else
+	map->included_at = LAST_SOURCE_LINE_LOCATION (map - 1);
       set->depth++;
       if (set->trace_includes)
 	trace_include (set, map);
     }
   else if (reason == LC_RENAME)
-    map->included_from = ORDINARY_MAP_INCLUDER_FILE_INDEX (&map[-1]);
+    map->included_at = INCLUDED_AT (&map[-1]);
   else if (reason == LC_LEAVE)
     {
       set->depth--;
-      map->included_from =
-	ORDINARY_MAP_INCLUDER_FILE_INDEX (INCLUDED_FROM (set, map - 1));
+      map->included_at = INCLUDED_AT (from);
     }
 
   return map;
@@ -1761,17 +1781,12 @@  linemap_dump (FILE *stream, struct line_
   if (!is_macro)
     {
       const line_map_ordinary *ord_map = linemap_check_ordinary (map);
-      unsigned includer_ix;
-      const line_map_ordinary *includer_map;
-
-      includer_ix = ORDINARY_MAP_INCLUDER_FILE_INDEX (ord_map);
-      includer_map = includer_ix < LINEMAPS_ORDINARY_USED (set)
-		     ? LINEMAPS_ORDINARY_MAP_AT (set, includer_ix)
-		     : NULL;
+      const line_map_ordinary *includer_map = linemap_included_at (set, ord_map);
 
       fprintf (stream, "File: %s:%d\n", ORDINARY_MAP_FILE_NAME (ord_map),
 	       ORDINARY_MAP_STARTING_LINE_NUMBER (ord_map));
-      fprintf (stream, "Included from: [%d] %s\n", includer_ix,
+      fprintf (stream, "Included from: [%d] %s\n",
+	       includer_map ? int (includer_map - set->info_ordinary.maps) : -1,
 	       includer_map ? ORDINARY_MAP_FILE_NAME (includer_map) : "None");
     }
   else
@@ -1821,9 +1836,10 @@  linemap_dump_location (struct line_maps
       if (e)
 	from = "N/A";
       else
-	from = (INCLUDED_FROM (set, map))
-	  ? LINEMAP_FILE (INCLUDED_FROM (set, map))
-	  : "<NULL>";
+	{
+	  const line_map_ordinary *from_map = linemap_included_at (set, map);
+	  from = from_map ? LINEMAP_FILE (from_map) : "<NULL>";
+	}
     }
 
   /* P: path, L: line, C: column, S: in-system-header, M: map address,