/* Map (unsigned int) keys to (source file, line, column) triples. Copyright (C) 2001-2026 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify itunder the terms of the GNU General Public License as published by theFree Software Foundation; either version 3, or (at your option) anylater version. This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details. You should have received a copy of the GNU General Public Licensealong with this program; see the file COPYING3. If not see<http://www.gnu.org/licenses/>. In other words, you are welcome to use, share and improve this program. You are forbidden to forbid anyone else to use, share and improve what you give them. Help stamp out software-hoarding! */ #include "config.h"#include "system.h"#include "line-map.h"#include "cpplib.h"#include "internal.h"#include "hashtab.h" /* Useful for the bit manipulations in this file. */static constexpr location_t loc_one = 1; static void trace_include (const line_maps *, const line_map_ordinary *);static const line_map_ordinary * linemap_ordinary_map_lookup (const line_maps *, location_t);static const line_map_macro* linemap_macro_map_lookup (const line_maps *, location_t);static location_t linemap_macro_map_loc_to_def_point(const line_map_macro *, location_t);static location_t linemap_macro_map_loc_to_exp_point(const line_map_macro *, location_t);static location_t linemap_macro_loc_to_spelling_point(const line_maps *, location_t, const line_map_ordinary **);static location_t linemap_macro_loc_to_def_point (const line_maps *, location_t, const line_map_ordinary **);static location_t linemap_macro_loc_to_exp_point (const line_maps *, location_t, const line_map_ordinary **); /* Counters defined in macro.cc. */extern line_map_uint_t num_expanded_macros_counter;extern line_map_uint_t num_macro_tokens_counter; /* Destructor for class line_maps. Ensure non-GC-managed memory is released. */ line_maps::~line_maps (){ if (m_location_adhoc_data_map.htab) htab_delete (m_location_adhoc_data_map.htab);} /* Hash function for location_adhoc_data hashtable. */ static hashval_tlocation_adhoc_data_hash (const void *l){ const struct location_adhoc_data *lb = (const struct location_adhoc_data *) l; return lb->locus + lb->src_range.m_start + lb->src_range.m_finish + (size_t) lb->data + lb->discriminator;} /* Compare function for location_adhoc_data hashtable. */ static intlocation_adhoc_data_eq (const void *l1, const void *l2){ const struct location_adhoc_data *lb1 = (const struct location_adhoc_data *) l1; const struct location_adhoc_data *lb2 = (const struct location_adhoc_data *) l2; return (lb1->locus == lb2->locus && lb1->src_range.m_start == lb2->src_range.m_start && lb1->src_range.m_finish == lb2->src_range.m_finish && lb1->data == lb2->data && lb1->discriminator == lb2->discriminator);} /* Update the hashtable when location_adhoc_data_map::data is reallocated. The param is an array of two pointers, the previous value of the data pointer, and then the new value. The pointers stored in the hash map are then rebased to be relative to the new data pointer instead of the old one. */ static intlocation_adhoc_data_update (void **slot_v, void *param_v){ const auto slot = reinterpret_cast<location_adhoc_data **> (slot_v); const auto param = static_cast<location_adhoc_data **> (param_v); *slot = (*slot - param[0]) + param[1]; return 1;} /* The adhoc data hash table is not part of the GGC infrastructure, so it was not initialized when SET was reconstructed from PCH; take care of that by rebuilding it from scratch. */ voidrebuild_location_adhoc_htab (line_maps *set){ set->m_location_adhoc_data_map.htab = htab_create (100, location_adhoc_data_hash, location_adhoc_data_eq, NULL); for (auto p = set->m_location_adhoc_data_map.data, end = p + set->m_location_adhoc_data_map.curr_loc; p != end; ++p) { const auto slot = reinterpret_cast<location_adhoc_data **> (htab_find_slot (set->m_location_adhoc_data_map.htab, p, INSERT)); *slot = p; }} /* Helper function for get_combined_adhoc_loc. Can the given LOCUS + SRC_RANGE and DATA pointer be stored compactly within a location_t, without needing to use an ad-hoc location. */ boolline_maps::can_be_stored_compactly_p (location_t locus, source_range src_range, void *data, unsigned discriminator) const{ /* If there's an ad-hoc pointer, we can't store it directly in the location_t, we need the lookaside. */ if (data) return false; if (discriminator != 0) return false; /* We only store ranges that begin at the locus and that are sufficiently "sane". */ if (src_range.m_start != locus) return false; if (src_range.m_finish < src_range.m_start) return false; if (src_range.m_start < RESERVED_LOCATION_COUNT) return false; if (locus >= LINE_MAP_MAX_LOCATION_WITH_PACKED_RANGES) return false; /* All 3 locations must be within ordinary maps, typically, the same ordinary map. */ location_t lowest_macro_loc = LINEMAPS_MACRO_LOWEST_LOCATION (this); if (locus >= lowest_macro_loc) return false; if (src_range.m_start >= lowest_macro_loc) return false; if (src_range.m_finish >= lowest_macro_loc) return false; /* Passed all tests. */ return true;} /* Combine LOCUS and DATA to a combined adhoc loc. */ location_tline_maps::get_or_create_combined_loc (location_t locus, source_range src_range, void *data, unsigned discriminator){ struct location_adhoc_data lb; struct location_adhoc_data **slot; if (IS_ADHOC_LOC (locus)) locus = get_location_from_adhoc_loc (this, locus); if (locus == 0 && data == NULL) return 0; /* Any ordinary locations ought to be "pure" at this point: no compressed ranges. */ linemap_assert (locus < RESERVED_LOCATION_COUNT || locus >= LINE_MAP_MAX_LOCATION_WITH_PACKED_RANGES || locus >= LINEMAPS_MACRO_LOWEST_LOCATION (this) || pure_location_p (locus)); /* Consider short-range optimization. */ if (can_be_stored_compactly_p (locus, src_range, data, discriminator)) { /* The low bits ought to be clear. */ linemap_assert (pure_location_p (locus)); const line_map *map = linemap_lookup (this, locus); const line_map_ordinary *ordmap = linemap_check_ordinary (map); auto int_diff = src_range.m_finish - src_range.m_start; auto col_diff = (int_diff >> ordmap->m_range_bits); if (col_diff < (loc_one << ordmap->m_range_bits)) { location_t packed = locus | col_diff; m_num_optimized_ranges++; return packed; } } /* We can also compactly store locations when locus == start == finish (and data is NULL). */ if (locus == src_range.m_start && locus == src_range.m_finish && !data && discriminator == 0) return locus; if (!data && discriminator == 0) m_num_unoptimized_ranges++; lb.locus = locus; lb.src_range = src_range; lb.data = data; lb.discriminator = discriminator; slot = (struct location_adhoc_data **) htab_find_slot (m_location_adhoc_data_map.htab, &lb, INSERT); if (*slot == NULL) { if (m_location_adhoc_data_map.curr_loc >= m_location_adhoc_data_map.allocated) { const auto orig_data = m_location_adhoc_data_map.data; /* Cast away extern "C" from the type of xrealloc. */ line_map_realloc reallocator = (m_reallocator ? m_reallocator : (line_map_realloc) xrealloc); if (m_location_adhoc_data_map.allocated == 0) m_location_adhoc_data_map.allocated = 128; else m_location_adhoc_data_map.allocated *= 2; m_location_adhoc_data_map.data = (struct location_adhoc_data *) reallocator (m_location_adhoc_data_map.data, m_location_adhoc_data_map.allocated * sizeof (struct location_adhoc_data)); if (m_location_adhoc_data_map.allocated > 128) { location_adhoc_data *param[2] = {orig_data, m_location_adhoc_data_map.data}; htab_traverse (m_location_adhoc_data_map.htab, location_adhoc_data_update, param); } } *slot = m_location_adhoc_data_map.data + m_location_adhoc_data_map.curr_loc; m_location_adhoc_data_map.data[m_location_adhoc_data_map.curr_loc++] = lb; } return ((*slot) - m_location_adhoc_data_map.data) | (1 + MAX_LOCATION_T);} /* Construct a location with caret at CARET, ranging from START to FINISH. For example, consider: 11111111112 12345678901234567890 522 523 return foo + bar; ~~~~^~~~~ 524 The location's caret is at the "+", line 523 column 15, but starts earlier, at the "f" of "foo" at column 11. The finish is at the "r" of "bar" at column 19. */ location_tline_maps::make_location (location_t caret, location_t start, location_t finish){ location_t pure_loc = get_pure_location (caret); source_range src_range; src_range.m_start = get_start (start); src_range.m_finish = get_finish (finish); location_t combined_loc = get_or_create_combined_loc (pure_loc, src_range, nullptr, 0); return combined_loc;} /* Return the data for the adhoc loc. */ void *get_data_from_adhoc_loc (const line_maps *set, location_t loc){ linemap_assert (IS_ADHOC_LOC (loc)); return set->m_location_adhoc_data_map.data[loc & MAX_LOCATION_T].data;} unsignedget_discriminator_from_adhoc_loc (const line_maps *set, location_t loc){ linemap_assert (IS_ADHOC_LOC (loc)); return set->m_location_adhoc_data_map.data[loc & MAX_LOCATION_T].discriminator;} /* Return the location for the adhoc loc. */ location_tget_location_from_adhoc_loc (const line_maps *set, location_t loc){ linemap_assert (IS_ADHOC_LOC (loc)); return set->m_location_adhoc_data_map.data[loc & MAX_LOCATION_T].locus;} /* Return the source_range for adhoc location LOC. */ source_rangeline_maps::get_range_from_adhoc_loc (location_t loc) const{ linemap_assert (IS_ADHOC_LOC (loc)); return m_location_adhoc_data_map.data[loc & MAX_LOCATION_T].src_range;} /* Get the source_range of location LOC, either from the ad-hoc lookaside table, or embedded inside LOC itself. */ source_rangeline_maps::get_range_from_loc (location_t loc) const{ if (IS_ADHOC_LOC (loc)) return get_range_from_adhoc_loc (loc); /* For ordinary maps, extract packed range. */ if (loc >= RESERVED_LOCATION_COUNT && loc < LINEMAPS_MACRO_LOWEST_LOCATION (this) && loc <= LINE_MAP_MAX_LOCATION_WITH_PACKED_RANGES) { const line_map *map = linemap_lookup (this, loc); const line_map_ordinary *ordmap = linemap_check_ordinary (map); source_range result; auto offset = loc & ((loc_one << ordmap->m_range_bits) - 1); result.m_start = loc - offset; result.m_finish = result.m_start + (offset << ordmap->m_range_bits); return result; } return source_range::from_location (loc);} source_rangeget_range_from_loc (const line_maps *set, location_t loc){ return set->get_range_from_loc (loc);} unsignedget_discriminator_from_loc (const line_maps *set, location_t loc){ if (IS_ADHOC_LOC (loc)) return get_discriminator_from_adhoc_loc (set, loc); return 0;} /* Get whether location LOC is a "pure" location, or whether it is an ad-hoc location, or embeds range information. */ boolline_maps::pure_location_p (location_t loc) const{ if (IS_ADHOC_LOC (loc)) return false; const line_map *map = linemap_lookup (this, loc); if (map == NULL) return true; const line_map_ordinary *ordmap = linemap_check_ordinary (map); if (loc & ((loc_one << ordmap->m_range_bits) - 1)) return false; return true;} boolpure_location_p (const line_maps *set, location_t loc){ return set->pure_location_p (loc);} /* Given location LOC within SET, strip away any packed range information or ad-hoc information. */ location_tline_maps::get_pure_location (location_t loc) const{ if (IS_ADHOC_LOC (loc)) loc = get_location_from_adhoc_loc (this, loc); if (loc >= LINEMAPS_MACRO_LOWEST_LOCATION (this)) return loc; if (loc < RESERVED_LOCATION_COUNT) return loc; const line_map *map = linemap_lookup (this, loc); const line_map_ordinary *ordmap = linemap_check_ordinary (map); return loc & ~((loc_one << ordmap->m_range_bits) - 1);} location_tget_pure_location (const line_maps *set, location_t loc){ return set->get_pure_location (loc);} /* Initialize a line map set. */ voidlinemap_init (line_maps *set, location_t builtin_location){#if __GNUC__ == 4 && __GNUC_MINOR__ == 2 && !defined (__clang__) /* PR33916, needed to fix PR82939. */ memset (set, 0, sizeof (line_maps));#else new (set) line_maps();#endif /* Set default reallocator (used for initial alloc too). */ set->m_reallocator = xrealloc; set->highest_location = RESERVED_LOCATION_COUNT - 1; set->highest_line = RESERVED_LOCATION_COUNT - 1; set->m_location_adhoc_data_map.htab = htab_create (100, location_adhoc_data_hash, location_adhoc_data_eq, NULL); set->builtin_location = builtin_location;} /* Return the ordinary line map from whence MAP was included. Returns NULL if MAP was not an include. */ const line_map_ordinary *linemap_included_from_linemap (const line_maps *set, const line_map_ordinary *map){ return linemap_ordinary_map_lookup (set, linemap_included_from (map));} /* Check for and warn about line_maps entered but not exited. */ voidlinemap_check_files_exited (const line_maps *set){ /* Depending upon whether we are handling preprocessed input or not, this can be a user error or an ICE. */ for (const line_map_ordinary *map = LINEMAPS_LAST_ORDINARY_MAP (set); ! MAIN_FILE_P (map); map = linemap_included_from_linemap (set, map)) fprintf (stderr, "line-map.cc: file \"%s\" entered but not left\n", ORDINARY_MAP_FILE_NAME (map));} /* Create NUM zero-initialized maps of type MACRO_P. */ line_map *line_map_new_raw (line_maps *set, bool macro_p, line_map_uint_t num){ auto num_maps_allocated = LINEMAPS_ALLOCATED (set, macro_p); auto num_maps_used = LINEMAPS_USED (set, macro_p); 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; void *buffer; if (macro_p) { size_of_a_map = sizeof (line_map_macro); buffer = set->info_macro.maps; } else { size_of_a_map = sizeof (line_map_ordinary); buffer = set->info_ordinary.maps; } /* We are going to execute some dance to try to reduce the overhead of the memory allocator, in case we are using the ggc-page.cc one. Lines 1–500 of 2772. Load more
/* Map (unsigned int) keys to (source file, line, column) triples. Copyright (C) 2001-2026 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING3. If not see <http://www.gnu.org/licenses/>. In other words, you are welcome to use, share and improve this program. You are forbidden to forbid anyone else to use, share and improve what you give them. Help stamp out software-hoarding! */ #include "config.h" #include "system.h" #include "line-map.h" #include "cpplib.h" #include "internal.h" #include "hashtab.h" /* Useful for the bit manipulations in this file. */ static constexpr location_t loc_one = 1; static void trace_include (const line_maps *, const line_map_ordinary *); static const line_map_ordinary * linemap_ordinary_map_lookup (const line_maps *, location_t); static const line_map_macro* linemap_macro_map_lookup (const line_maps *, location_t); static location_t linemap_macro_map_loc_to_def_point (const line_map_macro *, location_t); static location_t linemap_macro_map_loc_to_exp_point (const line_map_macro *, location_t); static location_t linemap_macro_loc_to_spelling_point (const line_maps *, location_t, const line_map_ordinary **); static location_t linemap_macro_loc_to_def_point (const line_maps *, location_t, const line_map_ordinary **); static location_t linemap_macro_loc_to_exp_point (const line_maps *, location_t, const line_map_ordinary **); /* Counters defined in macro.cc. */ extern line_map_uint_t num_expanded_macros_counter; extern line_map_uint_t num_macro_tokens_counter; /* Destructor for class line_maps. Ensure non-GC-managed memory is released. */ line_maps::~line_maps () { if (m_location_adhoc_data_map.htab) htab_delete (m_location_adhoc_data_map.htab); } /* Hash function for location_adhoc_data hashtable. */ static hashval_t location_adhoc_data_hash (const void *l) { const struct location_adhoc_data *lb = (const struct location_adhoc_data *) l; return lb->locus + lb->src_range.m_start + lb->src_range.m_finish + (size_t) lb->data + lb->discriminator; } /* Compare function for location_adhoc_data hashtable. */ static int location_adhoc_data_eq (const void *l1, const void *l2) { const struct location_adhoc_data *lb1 = (const struct location_adhoc_data *) l1; const struct location_adhoc_data *lb2 = (const struct location_adhoc_data *) l2; return (lb1->locus == lb2->locus && lb1->src_range.m_start == lb2->src_range.m_start && lb1->src_range.m_finish == lb2->src_range.m_finish && lb1->data == lb2->data && lb1->discriminator == lb2->discriminator); } /* Update the hashtable when location_adhoc_data_map::data is reallocated. The param is an array of two pointers, the previous value of the data pointer, and then the new value. The pointers stored in the hash map are then rebased to be relative to the new data pointer instead of the old one. */ static int location_adhoc_data_update (void **slot_v, void *param_v) { const auto slot = reinterpret_cast<location_adhoc_data **> (slot_v); const auto param = static_cast<location_adhoc_data **> (param_v); *slot = (*slot - param[0]) + param[1]; return 1; } /* The adhoc data hash table is not part of the GGC infrastructure, so it was not initialized when SET was reconstructed from PCH; take care of that by rebuilding it from scratch. */ void rebuild_location_adhoc_htab (line_maps *set) { set->m_location_adhoc_data_map.htab = htab_create (100, location_adhoc_data_hash, location_adhoc_data_eq, NULL); for (auto p = set->m_location_adhoc_data_map.data, end = p + set->m_location_adhoc_data_map.curr_loc; p != end; ++p) { const auto slot = reinterpret_cast<location_adhoc_data **> (htab_find_slot (set->m_location_adhoc_data_map.htab, p, INSERT)); *slot = p; } } /* Helper function for get_combined_adhoc_loc. Can the given LOCUS + SRC_RANGE and DATA pointer be stored compactly within a location_t, without needing to use an ad-hoc location. */ bool line_maps::can_be_stored_compactly_p (location_t locus, source_range src_range, void *data, unsigned discriminator) const { /* If there's an ad-hoc pointer, we can't store it directly in the location_t, we need the lookaside. */ if (data) return false; if (discriminator != 0) return false; /* We only store ranges that begin at the locus and that are sufficiently "sane". */ if (src_range.m_start != locus) return false; if (src_range.m_finish < src_range.m_start) return false; if (src_range.m_start < RESERVED_LOCATION_COUNT) return false; if (locus >= LINE_MAP_MAX_LOCATION_WITH_PACKED_RANGES) return false; /* All 3 locations must be within ordinary maps, typically, the same ordinary map. */ location_t lowest_macro_loc = LINEMAPS_MACRO_LOWEST_LOCATION (this); if (locus >= lowest_macro_loc) return false; if (src_range.m_start >= lowest_macro_loc) return false; if (src_range.m_finish >= lowest_macro_loc) return false; /* Passed all tests. */ return true; } /* Combine LOCUS and DATA to a combined adhoc loc. */ location_t line_maps::get_or_create_combined_loc (location_t locus, source_range src_range, void *data, unsigned discriminator) { struct location_adhoc_data lb; struct location_adhoc_data **slot; if (IS_ADHOC_LOC (locus)) locus = get_location_from_adhoc_loc (this, locus); if (locus == 0 && data == NULL) return 0; /* Any ordinary locations ought to be "pure" at this point: no compressed ranges. */ linemap_assert (locus < RESERVED_LOCATION_COUNT || locus >= LINE_MAP_MAX_LOCATION_WITH_PACKED_RANGES || locus >= LINEMAPS_MACRO_LOWEST_LOCATION (this) || pure_location_p (locus)); /* Consider short-range optimization. */ if (can_be_stored_compactly_p (locus, src_range, data, discriminator)) { /* The low bits ought to be clear. */ linemap_assert (pure_location_p (locus)); const line_map *map = linemap_lookup (this, locus); const line_map_ordinary *ordmap = linemap_check_ordinary (map); auto int_diff = src_range.m_finish - src_range.m_start; auto col_diff = (int_diff >> ordmap->m_range_bits); if (col_diff < (loc_one << ordmap->m_range_bits)) { location_t packed = locus | col_diff; m_num_optimized_ranges++; return packed; } } /* We can also compactly store locations when locus == start == finish (and data is NULL). */ if (locus == src_range.m_start && locus == src_range.m_finish && !data && discriminator == 0) return locus; if (!data && discriminator == 0) m_num_unoptimized_ranges++; lb.locus = locus; lb.src_range = src_range; lb.data = data; lb.discriminator = discriminator; slot = (struct location_adhoc_data **) htab_find_slot (m_location_adhoc_data_map.htab, &lb, INSERT); if (*slot == NULL) { if (m_location_adhoc_data_map.curr_loc >= m_location_adhoc_data_map.allocated) { const auto orig_data = m_location_adhoc_data_map.data; /* Cast away extern "C" from the type of xrealloc. */ line_map_realloc reallocator = (m_reallocator ? m_reallocator : (line_map_realloc) xrealloc); if (m_location_adhoc_data_map.allocated == 0) m_location_adhoc_data_map.allocated = 128; else m_location_adhoc_data_map.allocated *= 2; m_location_adhoc_data_map.data = (struct location_adhoc_data *) reallocator (m_location_adhoc_data_map.data, m_location_adhoc_data_map.allocated * sizeof (struct location_adhoc_data)); if (m_location_adhoc_data_map.allocated > 128) { location_adhoc_data *param[2] = {orig_data, m_location_adhoc_data_map.data}; htab_traverse (m_location_adhoc_data_map.htab, location_adhoc_data_update, param); } } *slot = m_location_adhoc_data_map.data + m_location_adhoc_data_map.curr_loc; m_location_adhoc_data_map.data[m_location_adhoc_data_map.curr_loc++] = lb; } return ((*slot) - m_location_adhoc_data_map.data) | (1 + MAX_LOCATION_T); } /* Construct a location with caret at CARET, ranging from START to FINISH. For example, consider: 11111111112 12345678901234567890 522 523 return foo + bar; ~~~~^~~~~ 524 The location's caret is at the "+", line 523 column 15, but starts earlier, at the "f" of "foo" at column 11. The finish is at the "r" of "bar" at column 19. */ location_t line_maps::make_location (location_t caret, location_t start, location_t finish) { location_t pure_loc = get_pure_location (caret); source_range src_range; src_range.m_start = get_start (start); src_range.m_finish = get_finish (finish); location_t combined_loc = get_or_create_combined_loc (pure_loc, src_range, nullptr, 0); return combined_loc; } /* Return the data for the adhoc loc. */ void * get_data_from_adhoc_loc (const line_maps *set, location_t loc) { linemap_assert (IS_ADHOC_LOC (loc)); return set->m_location_adhoc_data_map.data[loc & MAX_LOCATION_T].data; } unsigned get_discriminator_from_adhoc_loc (const line_maps *set, location_t loc) { linemap_assert (IS_ADHOC_LOC (loc)); return set->m_location_adhoc_data_map.data[loc & MAX_LOCATION_T].discriminator; } /* Return the location for the adhoc loc. */ location_t get_location_from_adhoc_loc (const line_maps *set, location_t loc) { linemap_assert (IS_ADHOC_LOC (loc)); return set->m_location_adhoc_data_map.data[loc & MAX_LOCATION_T].locus; } /* Return the source_range for adhoc location LOC. */ source_range line_maps::get_range_from_adhoc_loc (location_t loc) const { linemap_assert (IS_ADHOC_LOC (loc)); return m_location_adhoc_data_map.data[loc & MAX_LOCATION_T].src_range; } /* Get the source_range of location LOC, either from the ad-hoc lookaside table, or embedded inside LOC itself. */ source_range line_maps::get_range_from_loc (location_t loc) const { if (IS_ADHOC_LOC (loc)) return get_range_from_adhoc_loc (loc); /* For ordinary maps, extract packed range. */ if (loc >= RESERVED_LOCATION_COUNT && loc < LINEMAPS_MACRO_LOWEST_LOCATION (this) && loc <= LINE_MAP_MAX_LOCATION_WITH_PACKED_RANGES) { const line_map *map = linemap_lookup (this, loc); const line_map_ordinary *ordmap = linemap_check_ordinary (map); source_range result; auto offset = loc & ((loc_one << ordmap->m_range_bits) - 1); result.m_start = loc - offset; result.m_finish = result.m_start + (offset << ordmap->m_range_bits); return result; } return source_range::from_location (loc); } source_range get_range_from_loc (const line_maps *set, location_t loc) { return set->get_range_from_loc (loc); } unsigned get_discriminator_from_loc (const line_maps *set, location_t loc) { if (IS_ADHOC_LOC (loc)) return get_discriminator_from_adhoc_loc (set, loc); return 0; } /* Get whether location LOC is a "pure" location, or whether it is an ad-hoc location, or embeds range information. */ bool line_maps::pure_location_p (location_t loc) const { if (IS_ADHOC_LOC (loc)) return false; const line_map *map = linemap_lookup (this, loc); if (map == NULL) return true; const line_map_ordinary *ordmap = linemap_check_ordinary (map); if (loc & ((loc_one << ordmap->m_range_bits) - 1)) return false; return true; } bool pure_location_p (const line_maps *set, location_t loc) { return set->pure_location_p (loc); } /* Given location LOC within SET, strip away any packed range information or ad-hoc information. */ location_t line_maps::get_pure_location (location_t loc) const { if (IS_ADHOC_LOC (loc)) loc = get_location_from_adhoc_loc (this, loc); if (loc >= LINEMAPS_MACRO_LOWEST_LOCATION (this)) return loc; if (loc < RESERVED_LOCATION_COUNT) return loc; const line_map *map = linemap_lookup (this, loc); const line_map_ordinary *ordmap = linemap_check_ordinary (map); return loc & ~((loc_one << ordmap->m_range_bits) - 1); } location_t get_pure_location (const line_maps *set, location_t loc) { return set->get_pure_location (loc); } /* Initialize a line map set. */ void linemap_init (line_maps *set, location_t builtin_location) { #if __GNUC__ == 4 && __GNUC_MINOR__ == 2 && !defined (__clang__) /* PR33916, needed to fix PR82939. */ memset (set, 0, sizeof (line_maps)); #else new (set) line_maps(); #endif /* Set default reallocator (used for initial alloc too). */ set->m_reallocator = xrealloc; set->highest_location = RESERVED_LOCATION_COUNT - 1; set->highest_line = RESERVED_LOCATION_COUNT - 1; set->m_location_adhoc_data_map.htab = htab_create (100, location_adhoc_data_hash, location_adhoc_data_eq, NULL); set->builtin_location = builtin_location; } /* Return the ordinary line map from whence MAP was included. Returns NULL if MAP was not an include. */ const line_map_ordinary * linemap_included_from_linemap (const line_maps *set, const line_map_ordinary *map) { return linemap_ordinary_map_lookup (set, linemap_included_from (map)); } /* Check for and warn about line_maps entered but not exited. */ void linemap_check_files_exited (const line_maps *set) { /* Depending upon whether we are handling preprocessed input or not, this can be a user error or an ICE. */ for (const line_map_ordinary *map = LINEMAPS_LAST_ORDINARY_MAP (set); ! MAIN_FILE_P (map); map = linemap_included_from_linemap (set, map)) fprintf (stderr, "line-map.cc: file \"%s\" entered but not left\n", ORDINARY_MAP_FILE_NAME (map)); } /* Create NUM zero-initialized maps of type MACRO_P. */ line_map * line_map_new_raw (line_maps *set, bool macro_p, line_map_uint_t num) { auto num_maps_allocated = LINEMAPS_ALLOCATED (set, macro_p); auto num_maps_used = LINEMAPS_USED (set, macro_p); 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; void *buffer; if (macro_p) { size_of_a_map = sizeof (line_map_macro); buffer = set->info_macro.maps; } else { size_of_a_map = sizeof (line_map_ordinary); buffer = set->info_ordinary.maps; } /* We are going to execute some dance to try to reduce the overhead of the memory allocator, in case we are using the ggc-page.cc one.