Location handling needs to add 2 things

1) a new kind of inclusion -- namely a module. We add LC_MODULE as a map kind,

2) the ability to allocate blocks of line-maps for both ordinary locations and macro locations, that are then filled in by the module loader.

--
Nathan Sidwell
diff --git c/libcpp/include/line-map.h w/libcpp/include/line-map.h
index 44008be5c08..50b2e4ff91a 100644
--- c/libcpp/include/line-map.h
+++ w/libcpp/include/line-map.h
@@ -72,6 +72,7 @@ enum lc_reason
   LC_RENAME,		/* Other reason for name change.  */
   LC_RENAME_VERBATIM,	/* Likewise, but "" != stdin.  */
   LC_ENTER_MACRO,	/* Begin macro expansion.  */
+  LC_MODULE,		/* A (C++) Module.  */
   /* FIXME: add support for stringize and paste.  */
   LC_HWM /* High Water Mark.  */
 };
@@ -439,7 +440,8 @@ struct GTY((tag ("1"))) line_map_ordinary : public line_map {
 
   /* Location from whence this line map was included.  For regular
      #includes, this location will be the last location of a map.  For
-     outermost file, this is 0.  */
+     outermost file, this is 0.  For modules it could be anywhere
+     within a map.  */
   location_t included_from;
 
   /* Size is 20 or 24 bytes, no padding  */
@@ -662,6 +664,15 @@ ORDINARY_MAP_IN_SYSTEM_HEADER_P (const line_map_ordinary *ord_map)
   return ord_map->sysp;
 }
 
+/* TRUE if this line map is for a module (not a source file).  */
+
+inline bool
+MAP_MODULE_P (const line_map *map)
+{
+  return (MAP_ORDINARY_P (map)
+	  && linemap_check_ordinary (map)->reason == LC_MODULE);
+}
+
 /* Get the filename of ordinary map MAP.  */
 
 inline const char *
@@ -1076,6 +1087,9 @@ extern void linemap_check_files_exited (class line_maps *);
 extern location_t linemap_line_start
 (class line_maps *set, linenum_type to_line,  unsigned int max_column_hint);
 
+/* Allocate a raw block of line maps, zero initialized.  */
+extern line_map *line_map_new_raw (line_maps *, bool, unsigned);
+
 /* Add a mapping of logical source line to physical source file and
    line number. This function creates an "ordinary map", which is a
    map that records locations of tokens that are not part of macro
@@ -1093,6 +1107,39 @@ extern const line_map *linemap_add
   (class line_maps *, enum lc_reason, unsigned int sysp,
    const char *to_file, linenum_type to_line);
 
+/* Create a macro map.  A macro map encodes source locations of tokens
+   that are part of a macro replacement-list, at a macro expansion
+   point. See the extensive comments of struct line_map and struct
+   line_map_macro, in line-map.h.
+
+   This map shall be created when the macro is expanded. The map
+   encodes the source location of the expansion point of the macro as
+   well as the "original" source location of each token that is part
+   of the macro replacement-list. If a macro is defined but never
+   expanded, it has no macro map.  SET is the set of maps the macro
+   map should be part of.  MACRO_NODE is the macro which the new macro
+   map should encode source locations for.  EXPANSION is the location
+   of the expansion point of MACRO. For function-like macros
+   invocations, it's best to make it point to the closing parenthesis
+   of the macro, rather than the the location of the first character
+   of the macro.  NUM_TOKENS is the number of tokens that are part of
+   the replacement-list of MACRO.  */
+const line_map_macro *linemap_enter_macro (line_maps *, cpp_hashnode *,
+					   location_t, unsigned int);
+
+/* Create a source location for a module.  The creator must either do
+   this after the TU is tokenized, or deal with saving and restoring
+   map state.  */
+
+extern location_t linemap_module_loc
+  (line_maps *, location_t from, const char *name);
+extern void linemap_module_reparent
+  (line_maps *, location_t loc, location_t new_parent);
+
+/* Restore the linemap state such that the map at LWM-1 continues.  */
+extern void linemap_module_restore
+  (line_maps *, unsigned lwm);
+
 /* Given a logical source location, returns the map which the
    corresponding (source file, line, column) triplet can be deduced
    from. Since the set is built chronologically, the logical lines are
@@ -1102,6 +1149,8 @@ extern const line_map *linemap_add
 extern const line_map *linemap_lookup
   (const line_maps *, location_t);
 
+unsigned linemap_lookup_macro_index (const line_maps *, location_t);
+
 /* Returns TRUE if the line table set tracks token locations across
    macro expansion, FALSE otherwise.  */
 bool linemap_tracks_macro_expansion_locs_p (class line_maps *);
diff --git c/libcpp/line-map.c w/libcpp/line-map.c
index 5a74174579f..4b2b7ef4394 100644
--- c/libcpp/line-map.c
+++ w/libcpp/line-map.c
@@ -378,23 +378,21 @@ linemap_check_files_exited (line_maps *set)
 	     ORDINARY_MAP_FILE_NAME (map));
 }
 
-/* Create a new line map in the line map set SET, and return it.
-   REASON is the reason of creating the map. It determines the type
-   of map created (ordinary or macro map). Note that ordinary maps and
-   macro maps are allocated in different memory location.  */
+/* Create NUM zero-initialized maps of type MACRO_P.  */
 
-static struct line_map *
-new_linemap (line_maps *set,  location_t start_location)
+line_map *
+line_map_new_raw (line_maps *set, bool macro_p, unsigned num)
 {
-  bool macro_p = start_location >= LINE_MAP_MAX_LOCATION;
   unsigned num_maps_allocated = LINEMAPS_ALLOCATED (set, macro_p);
   unsigned num_maps_used = LINEMAPS_USED (set, macro_p);
-
-  if (num_maps_used == num_maps_allocated)
+  
+  if (num > num_maps_allocated - num_maps_used)
     {
       /* We need more space!  */
       if (!num_maps_allocated)
 	num_maps_allocated = 128;
+      if (num_maps_allocated < num_maps_used + num)
+	num_maps_allocated = num_maps_used + num;
       num_maps_allocated *= 2;
 
       size_t size_of_a_map;
@@ -429,6 +427,7 @@ new_linemap (line_maps *set,  location_t start_location)
 	      (num_maps - num_maps_used) * size_of_a_map);
       if (macro_p)
 	set->info_macro.maps = (line_map_macro *)buffer;
+
       else
 	set->info_ordinary.maps = (line_map_ordinary *)buffer;
       LINEMAPS_ALLOCATED (set, macro_p) = num_maps;
@@ -436,13 +435,39 @@ new_linemap (line_maps *set,  location_t start_location)
 
   line_map *result = (macro_p ? (line_map *)&set->info_macro.maps[num_maps_used]
 		      : (line_map *)&set->info_ordinary.maps[num_maps_used]);
-  LINEMAPS_USED (set, macro_p)++;
+  LINEMAPS_USED (set, macro_p) += num;
+
+  return result;
+}
+
+/* Create a new line map in the line map set SET, and return it.
+   REASON is the reason of creating the map. It determines the type
+   of map created (ordinary or macro map). Note that ordinary maps and
+   macro maps are allocated in different memory location.  */
+
+static struct line_map *
+new_linemap (line_maps *set, location_t start_location)
+{
+  line_map *result = line_map_new_raw (set,
+				       start_location >= LINE_MAP_MAX_LOCATION,
+				       1);
 
   result->start_location = start_location;
 
   return result;
 }
 
+/* Return the location of the last source line within an ordinary
+   map.  */
+inline location_t
+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.
 
@@ -570,6 +595,51 @@ linemap_add (line_maps *set, enum lc_reason reason,
   return map;
 }
 
+/* Create a location for a module NAME imported at FROM.  */
+
+location_t
+linemap_module_loc (line_maps *set, location_t from, const char *name)
+{
+  const line_map_ordinary *map
+    = linemap_check_ordinary (linemap_add (set, LC_MODULE, false, name, 0));
+  const_cast <line_map_ordinary *> (map)->included_from = from;
+
+  location_t loc = linemap_line_start (set, 0, 0);
+
+  return loc;
+}
+
+void
+linemap_module_reparent (line_maps *set, location_t loc, location_t adoptor)
+{
+  const line_map_ordinary *map = linemap_ordinary_map_lookup (set, loc);
+  const_cast<line_map_ordinary *> (map)->included_from = adoptor;
+}
+
+/* A linemap at LWM-1 was interrupted to insert module locations & imports.
+   Append a new map, continuing the interrupted one.  */
+
+void
+linemap_module_restore (line_maps *set, unsigned lwm)
+{
+  if (lwm && lwm != LINEMAPS_USED (set, false))
+    {
+      const line_map_ordinary *pre_map
+	= linemap_check_ordinary (LINEMAPS_MAP_AT (set, false, lwm - 1));
+      unsigned src_line = SOURCE_LINE (pre_map,
+				       LAST_SOURCE_LINE_LOCATION (pre_map));
+      location_t inc_at = pre_map->included_from;
+      if (const line_map_ordinary *post_map
+	  = (linemap_check_ordinary
+	     (linemap_add (set, LC_RENAME_VERBATIM,
+			   ORDINARY_MAP_IN_SYSTEM_HEADER_P (pre_map),
+			   ORDINARY_MAP_FILE_NAME (pre_map), src_line))))
+	/* linemap_add will think we were included from the same as
+	   the preceeding map.  */
+	const_cast <line_map_ordinary *> (post_map)->included_from = inc_at;
+    }
+}
+
 /* Returns TRUE if the line table set tracks token locations across
    macro expansion, FALSE otherwise.  */
 
@@ -1003,14 +1073,25 @@ linemap_macro_map_lookup (const line_maps *set, location_t line)
   if (set == NULL)
     return NULL;
 
+  unsigned ix = linemap_lookup_macro_index (set, line);
+  const struct line_map_macro *result = LINEMAPS_MACRO_MAP_AT (set, ix);
+  linemap_assert (MAP_START_LOCATION (result) <= line);
+
+  return result;
+}
+
+unsigned
+linemap_lookup_macro_index (const line_maps *set, location_t line)
+{
   unsigned mn = LINEMAPS_MACRO_CACHE (set);
   unsigned mx = LINEMAPS_MACRO_USED (set);
   const struct line_map_macro *cached = LINEMAPS_MACRO_MAP_AT (set, mn);
 
   if (line >= MAP_START_LOCATION (cached))
     {
-      if (mn == 0 || line < MAP_START_LOCATION (&cached[-1]))
-	return cached;
+      if (line < (MAP_START_LOCATION (cached)
+		  + MACRO_MAP_NUM_MACRO_TOKENS (cached)))
+	return mn;
       mx = mn - 1;
       mn = 0;
     }
@@ -1025,10 +1106,7 @@ linemap_macro_map_lookup (const line_maps *set, location_t line)
     }
 
   LINEMAPS_MACRO_CACHE (set) = mx;
-  const struct line_map_macro *result = LINEMAPS_MACRO_MAP_AT (set, mx);
-  linemap_assert (MAP_START_LOCATION (result) <= line);
-
-  return result;
+  return mx;
 }
 
 /* Return TRUE if MAP encodes locations coming from a macro
@@ -1747,7 +1825,7 @@ linemap_dump (FILE *stream, class line_maps *set, unsigned ix, bool is_macro)
 {
   const char *const lc_reasons_v[LC_HWM]
       = { "LC_ENTER", "LC_LEAVE", "LC_RENAME", "LC_RENAME_VERBATIM",
-	  "LC_ENTER_MACRO" };
+	  "LC_ENTER_MACRO", "LC_MODULE" };
   const line_map *map;
   unsigned reason;
 

Reply via email to