Wolfgang Thallergcc16 merge934c3885 months agoHistory
2772 lines · 84.8 KB · C++
RawDownload
/* 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.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t