/* If LOC is the virtual location of a token coming from the expansion of a macro M and if its spelling location is reserved (e.g, a location for a built-in token), then this function unwinds (using linemap_unwind_toward_expansion) the location until a location that is not reserved and is not in a system header is reached. In other words, this unwinds the reserved location until a location that is in real source code is reached. Otherwise, if the spelling location for LOC is not reserved or if LOC doesn't come from the expansion of a macro, the function returns LOC as is and *MAP is not touched. *MAP is set to the map of the returned location if the later is different from LOC. */ source_location linemap_unwind_to_first_non_reserved_loc (struct line_maps *set, source_location loc, const struct line_map **map) { source_location resolved_loc; const struct line_map *map0 = NULL, *map1 = NULL; map0 = linemap_lookup (set, loc); if (!linemap_macro_expansion_map_p (map0)) return loc; resolved_loc = linemap_resolve_location (set, loc, LRK_SPELLING_LOCATION, &map1); if (resolved_loc >= RESERVED_LOCATION_COUNT && !LINEMAP_SYSP (map1)) return loc; while (linemap_macro_expansion_map_p (map0) && (resolved_loc < RESERVED_LOCATION_COUNT || LINEMAP_SYSP (map1))) { loc = linemap_unwind_toward_expansion (set, loc, &map0); resolved_loc = linemap_resolve_location (set, loc, LRK_SPELLING_LOCATION, &map1); } if (map != NULL) *map = map0; return loc; }
int linemap_compare_locations (struct line_maps *set, source_location pre, source_location post) { bool pre_virtual_p, post_virtual_p; source_location l0 = pre, l1 = post; if (l0 == l1) return 0; if ((pre_virtual_p = linemap_location_from_macro_expansion_p (set, l0))) l0 = linemap_resolve_location (set, l0, LRK_MACRO_EXPANSION_POINT, NULL); if ((post_virtual_p = linemap_location_from_macro_expansion_p (set, l1))) l1 = linemap_resolve_location (set, l1, LRK_MACRO_EXPANSION_POINT, NULL); if (l0 == l1 && pre_virtual_p && post_virtual_p) { /* So pre and post represent two tokens that are present in a same macro expansion. Let's see if the token for pre was before the token for post in that expansion. */ unsigned i0, i1; const struct line_map *map = first_map_in_common (set, pre, post, &l0, &l1); if (map == NULL) /* This should not be possible. */ abort (); i0 = l0 - MAP_START_LOCATION (map); i1 = l1 - MAP_START_LOCATION (map); return i1 - i0; } return l1 - l0; }
static expanded_location expand_location_1 (source_location loc, bool expansion_point_p) { expanded_location xloc; const struct line_map *map; enum location_resolution_kind lrk = LRK_MACRO_EXPANSION_POINT; tree block = NULL; if (IS_ADHOC_LOC (loc)) { block = LOCATION_BLOCK (loc); loc = LOCATION_LOCUS (loc); } /* If LOC describes a location with a discriminator, extract the discriminator and map it to the real location. */ if (min_discriminator_location != UNKNOWN_LOCATION && loc >= min_discriminator_location && loc < next_discriminator_location) loc = map_discriminator_location (loc); memset (&xloc, 0, sizeof (xloc)); if (loc >= RESERVED_LOCATION_COUNT) { if (!expansion_point_p) { /* We want to resolve LOC to its spelling location. But if that spelling location is a reserved location that appears in the context of a macro expansion (like for a location for a built-in token), let's consider the first location (toward the expansion point) that is not reserved; that is, the first location that is in real source code. */ loc = linemap_unwind_to_first_non_reserved_loc (line_table, loc, &map); lrk = LRK_SPELLING_LOCATION; } loc = linemap_resolve_location (line_table, loc, lrk, &map); xloc = linemap_expand_location (line_table, map, loc); } xloc.data = block; if (loc <= BUILTINS_LOCATION) xloc.file = loc == UNKNOWN_LOCATION ? NULL : _("<built-in>"); return xloc; }
int linemap_location_in_system_header_p (struct line_maps *set, source_location location) { const struct line_map *map = NULL; location = linemap_resolve_location (set, location, LRK_SPELLING_LOCATION, &map); if (location < RESERVED_LOCATION_COUNT) return false; return LINEMAP_SYSP (map); }
expanded_location expand_location (source_location loc) { expanded_location xloc; const struct line_map *map; loc = linemap_resolve_location (line_table, loc, LRK_SPELLING_LOCATION, &map); xloc = linemap_expand_location (line_table, map, loc); if (loc <= BUILTINS_LOCATION) xloc.file = loc == UNKNOWN_LOCATION ? NULL : _("<built-in>"); return xloc; }
void diagnostic_report_current_module (diagnostic_context *context, location_t where) { const struct line_map *map = NULL; if (pp_needs_newline (context->printer)) { pp_newline (context->printer); pp_needs_newline (context->printer) = false; } if (where <= BUILTINS_LOCATION) return; linemap_resolve_location (line_table, where, LRK_MACRO_DEFINITION_LOCATION, &map); if (map && diagnostic_last_module_changed (context, map)) { diagnostic_set_last_module (context, map); if (! MAIN_FILE_P (map)) { map = INCLUDED_FROM (line_table, map); if (context->show_column) pp_verbatim (context->printer, "In file included from %s:%d:%d", LINEMAP_FILE (map), LAST_SOURCE_LINE (map), LAST_SOURCE_COLUMN (map)); else pp_verbatim (context->printer, "In file included from %s:%d", LINEMAP_FILE (map), LAST_SOURCE_LINE (map)); while (! MAIN_FILE_P (map)) { map = INCLUDED_FROM (line_table, map); pp_verbatim (context->printer, ",\n from %s:%d", LINEMAP_FILE (map), LAST_SOURCE_LINE (map)); } pp_verbatim (context->printer, ":"); pp_newline (context->printer); } } }
void linemap_dump_location (struct line_maps *set, source_location loc, FILE *stream) { const struct line_map *map; source_location location; const char *path = "", *from = ""; int l = -1, c = -1, s = -1, e = -1; if (loc == 0) return; location = linemap_resolve_location (set, loc, LRK_MACRO_DEFINITION_LOCATION, &map); if (map == NULL) /* Only reserved locations can be tolerated in this case. */ linemap_assert (location < RESERVED_LOCATION_COUNT); else { path = LINEMAP_FILE (map); l = SOURCE_LINE (map, location); c = SOURCE_COLUMN (map, location); s = LINEMAP_SYSP (map) != 0; e = location != loc; if (e) from = "N/A"; else from = (INCLUDED_FROM (set, map)) ? LINEMAP_FILE (INCLUDED_FROM (set, map)) : "<NULL>"; } /* P: path, L: line, C: column, S: in-system-header, M: map address, E: macro expansion?, LOC: original location, R: resolved location */ fprintf (stream, "{P:%s;F:%s;L:%d;C:%d;S:%d;M:%p;E:%d,LOC:%d,R:%d}", path, from, l, c, s, (void*)map, e, loc, location); }