diff --git a/libcpp/include/line-map.h b/libcpp/include/line-map.h index 44008be5c08..50b2e4ff91a 100644 --- a/libcpp/include/line-map.h +++ b/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 a/libcpp/internal.h b/libcpp/internal.h index d7780e49d27..3f5bafbccde 100644 --- a/libcpp/internal.h +++ b/libcpp/internal.h @@ -868,29 +868,7 @@ ufputs (const unsigned char *s, FILE *f) return fputs ((const char *)s, f); } - /* In line-map.c. */ - -/* 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 (class line_maps *, - struct cpp_hashnode*, - location_t, - unsigned int); +/* In line-map.c. */ /* Create and return a virtual location for a token that is part of a macro expansion-list at a macro expansion point. See the comment diff --git a/libcpp/line-map.c b/libcpp/line-map.c index 5a74174579f..bbb6963b8d9 100644 --- a/libcpp/line-map.c +++ b/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; @@ -436,13 +434,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 +594,56 @@ 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 (map)->included_from = from; + + location_t loc = linemap_line_start (set, 0, 0); + + return loc; +} + +/* The linemap containing LOC is being reparented to be + imported/included from ADOPTOR. This can happen when an + indirectly imported module is then directly imported, or when + partitions are involved. */ + +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 (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 (post_map)->included_from = inc_at; + } +} + /* Returns TRUE if the line table set tracks token locations across macro expansion, FALSE otherwise. */ @@ -1003,14 +1077,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 +1110,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 +1829,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;