xref: /dflybsd-src/contrib/gcc-8.0/libcpp/line-map.c (revision 95059079af47f9a66a175f374f2da1a5020e3255)
138fd1498Szrj /* Map (unsigned int) keys to (source file, line, column) triples.
238fd1498Szrj    Copyright (C) 2001-2018 Free Software Foundation, Inc.
338fd1498Szrj 
438fd1498Szrj This program is free software; you can redistribute it and/or modify it
538fd1498Szrj under the terms of the GNU General Public License as published by the
638fd1498Szrj Free Software Foundation; either version 3, or (at your option) any
738fd1498Szrj later version.
838fd1498Szrj 
938fd1498Szrj This program is distributed in the hope that it will be useful,
1038fd1498Szrj but WITHOUT ANY WARRANTY; without even the implied warranty of
1138fd1498Szrj MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1238fd1498Szrj GNU General Public License for more details.
1338fd1498Szrj 
1438fd1498Szrj You should have received a copy of the GNU General Public License
1538fd1498Szrj along with this program; see the file COPYING3.  If not see
1638fd1498Szrj <http://www.gnu.org/licenses/>.
1738fd1498Szrj 
1838fd1498Szrj  In other words, you are welcome to use, share and improve this program.
1938fd1498Szrj  You are forbidden to forbid anyone else to use, share and improve
2038fd1498Szrj  what you give them.   Help stamp out software-hoarding!  */
2138fd1498Szrj 
2238fd1498Szrj #include "config.h"
2338fd1498Szrj #include "system.h"
2438fd1498Szrj #include "line-map.h"
2538fd1498Szrj #include "cpplib.h"
2638fd1498Szrj #include "internal.h"
2738fd1498Szrj #include "hashtab.h"
2838fd1498Szrj 
2938fd1498Szrj /* Highest possible source location encoded within an ordinary or
3038fd1498Szrj    macro map.  */
3138fd1498Szrj const source_location LINE_MAP_MAX_SOURCE_LOCATION = 0x70000000;
3238fd1498Szrj 
3338fd1498Szrj static void trace_include (const struct line_maps *, const line_map_ordinary *);
3438fd1498Szrj static const line_map_ordinary * linemap_ordinary_map_lookup (struct line_maps *,
3538fd1498Szrj 							      source_location);
3638fd1498Szrj static const line_map_macro* linemap_macro_map_lookup (struct line_maps *,
3738fd1498Szrj 						       source_location);
3838fd1498Szrj static source_location linemap_macro_map_loc_to_def_point
3938fd1498Szrj (const line_map_macro *, source_location);
4038fd1498Szrj static source_location linemap_macro_map_loc_to_exp_point
4138fd1498Szrj (const line_map_macro *, source_location);
4238fd1498Szrj static source_location linemap_macro_loc_to_spelling_point
4338fd1498Szrj (struct line_maps *, source_location, const line_map_ordinary **);
4438fd1498Szrj static source_location linemap_macro_loc_to_def_point (struct line_maps *,
4538fd1498Szrj 						       source_location,
4638fd1498Szrj 						       const line_map_ordinary **);
4738fd1498Szrj static source_location linemap_macro_loc_to_exp_point (struct line_maps *,
4838fd1498Szrj 						       source_location,
4938fd1498Szrj 						       const line_map_ordinary **);
5038fd1498Szrj 
5138fd1498Szrj /* Counters defined in macro.c.  */
5238fd1498Szrj extern unsigned num_expanded_macros_counter;
5338fd1498Szrj extern unsigned num_macro_tokens_counter;
5438fd1498Szrj 
5538fd1498Szrj /* Destructor for class line_maps.
5638fd1498Szrj    Ensure non-GC-managed memory is released.  */
5738fd1498Szrj 
~line_maps()5838fd1498Szrj line_maps::~line_maps ()
5938fd1498Szrj {
6038fd1498Szrj   if (location_adhoc_data_map.htab)
6138fd1498Szrj     htab_delete (location_adhoc_data_map.htab);
6238fd1498Szrj }
6338fd1498Szrj 
6438fd1498Szrj /* Hash function for location_adhoc_data hashtable.  */
6538fd1498Szrj 
6638fd1498Szrj static hashval_t
location_adhoc_data_hash(const void * l)6738fd1498Szrj location_adhoc_data_hash (const void *l)
6838fd1498Szrj {
6938fd1498Szrj   const struct location_adhoc_data *lb =
7038fd1498Szrj       (const struct location_adhoc_data *) l;
7138fd1498Szrj   return ((hashval_t) lb->locus
7238fd1498Szrj 	  + (hashval_t) lb->src_range.m_start
7338fd1498Szrj 	  + (hashval_t) lb->src_range.m_finish
7438fd1498Szrj 	  + (size_t) lb->data);
7538fd1498Szrj }
7638fd1498Szrj 
7738fd1498Szrj /* Compare function for location_adhoc_data hashtable.  */
7838fd1498Szrj 
7938fd1498Szrj static int
location_adhoc_data_eq(const void * l1,const void * l2)8038fd1498Szrj location_adhoc_data_eq (const void *l1, const void *l2)
8138fd1498Szrj {
8238fd1498Szrj   const struct location_adhoc_data *lb1 =
8338fd1498Szrj       (const struct location_adhoc_data *) l1;
8438fd1498Szrj   const struct location_adhoc_data *lb2 =
8538fd1498Szrj       (const struct location_adhoc_data *) l2;
8638fd1498Szrj   return (lb1->locus == lb2->locus
8738fd1498Szrj 	  && lb1->src_range.m_start == lb2->src_range.m_start
8838fd1498Szrj 	  && lb1->src_range.m_finish == lb2->src_range.m_finish
8938fd1498Szrj 	  && lb1->data == lb2->data);
9038fd1498Szrj }
9138fd1498Szrj 
9238fd1498Szrj /* Update the hashtable when location_adhoc_data is reallocated.  */
9338fd1498Szrj 
9438fd1498Szrj static int
location_adhoc_data_update(void ** slot,void * data)9538fd1498Szrj location_adhoc_data_update (void **slot, void *data)
9638fd1498Szrj {
9738fd1498Szrj   *((char **) slot)
9838fd1498Szrj     = (char *) ((uintptr_t) *((char **) slot) + *((ptrdiff_t *) data));
9938fd1498Szrj   return 1;
10038fd1498Szrj }
10138fd1498Szrj 
10238fd1498Szrj /* Rebuild the hash table from the location adhoc data.  */
10338fd1498Szrj 
10438fd1498Szrj void
rebuild_location_adhoc_htab(struct line_maps * set)10538fd1498Szrj rebuild_location_adhoc_htab (struct line_maps *set)
10638fd1498Szrj {
10738fd1498Szrj   unsigned i;
10838fd1498Szrj   set->location_adhoc_data_map.htab =
10938fd1498Szrj       htab_create (100, location_adhoc_data_hash, location_adhoc_data_eq, NULL);
11038fd1498Szrj   for (i = 0; i < set->location_adhoc_data_map.curr_loc; i++)
11138fd1498Szrj     htab_find_slot (set->location_adhoc_data_map.htab,
11238fd1498Szrj 		    set->location_adhoc_data_map.data + i, INSERT);
11338fd1498Szrj }
11438fd1498Szrj 
11538fd1498Szrj /* Helper function for get_combined_adhoc_loc.
11638fd1498Szrj    Can the given LOCUS + SRC_RANGE and DATA pointer be stored compactly
11738fd1498Szrj    within a source_location, without needing to use an ad-hoc location.  */
11838fd1498Szrj 
11938fd1498Szrj static bool
can_be_stored_compactly_p(struct line_maps * set,source_location locus,source_range src_range,void * data)12038fd1498Szrj can_be_stored_compactly_p (struct line_maps *set,
12138fd1498Szrj 			   source_location locus,
12238fd1498Szrj 			   source_range src_range,
12338fd1498Szrj 			   void *data)
12438fd1498Szrj {
12538fd1498Szrj   /* If there's an ad-hoc pointer, we can't store it directly in the
12638fd1498Szrj      source_location, we need the lookaside.  */
12738fd1498Szrj   if (data)
12838fd1498Szrj     return false;
12938fd1498Szrj 
13038fd1498Szrj   /* We only store ranges that begin at the locus and that are sufficiently
13138fd1498Szrj      "sane".  */
13238fd1498Szrj   if (src_range.m_start != locus)
13338fd1498Szrj     return false;
13438fd1498Szrj 
13538fd1498Szrj   if (src_range.m_finish < src_range.m_start)
13638fd1498Szrj     return false;
13738fd1498Szrj 
13838fd1498Szrj   if (src_range.m_start < RESERVED_LOCATION_COUNT)
13938fd1498Szrj     return false;
14038fd1498Szrj 
14138fd1498Szrj   if (locus >= LINE_MAP_MAX_LOCATION_WITH_PACKED_RANGES)
14238fd1498Szrj     return false;
14338fd1498Szrj 
14438fd1498Szrj   /* All 3 locations must be within ordinary maps, typically, the same
14538fd1498Szrj      ordinary map.  */
14638fd1498Szrj   source_location lowest_macro_loc = LINEMAPS_MACRO_LOWEST_LOCATION (set);
14738fd1498Szrj   if (locus >= lowest_macro_loc)
14838fd1498Szrj     return false;
14938fd1498Szrj   if (src_range.m_start >= lowest_macro_loc)
15038fd1498Szrj     return false;
15138fd1498Szrj   if (src_range.m_finish >= lowest_macro_loc)
15238fd1498Szrj     return false;
15338fd1498Szrj 
15438fd1498Szrj   /* Passed all tests.  */
15538fd1498Szrj   return true;
15638fd1498Szrj }
15738fd1498Szrj 
15838fd1498Szrj /* Combine LOCUS and DATA to a combined adhoc loc.  */
15938fd1498Szrj 
16038fd1498Szrj source_location
get_combined_adhoc_loc(struct line_maps * set,source_location locus,source_range src_range,void * data)16138fd1498Szrj get_combined_adhoc_loc (struct line_maps *set,
16238fd1498Szrj 			source_location locus,
16338fd1498Szrj 			source_range src_range,
16438fd1498Szrj 			void *data)
16538fd1498Szrj {
16638fd1498Szrj   struct location_adhoc_data lb;
16738fd1498Szrj   struct location_adhoc_data **slot;
16838fd1498Szrj 
16938fd1498Szrj   if (IS_ADHOC_LOC (locus))
17038fd1498Szrj     locus
17138fd1498Szrj       = set->location_adhoc_data_map.data[locus & MAX_SOURCE_LOCATION].locus;
17238fd1498Szrj   if (locus == 0 && data == NULL)
17338fd1498Szrj     return 0;
17438fd1498Szrj 
17538fd1498Szrj   /* Any ordinary locations ought to be "pure" at this point: no
17638fd1498Szrj      compressed ranges.  */
17738fd1498Szrj   linemap_assert (locus < RESERVED_LOCATION_COUNT
17838fd1498Szrj 		  || locus >= LINE_MAP_MAX_LOCATION_WITH_PACKED_RANGES
17938fd1498Szrj 		  || locus >= LINEMAPS_MACRO_LOWEST_LOCATION (set)
18038fd1498Szrj 		  || pure_location_p (set, locus));
18138fd1498Szrj 
18238fd1498Szrj   /* Consider short-range optimization.  */
18338fd1498Szrj   if (can_be_stored_compactly_p (set, locus, src_range, data))
18438fd1498Szrj     {
18538fd1498Szrj       /* The low bits ought to be clear.  */
18638fd1498Szrj       linemap_assert (pure_location_p (set, locus));
18738fd1498Szrj       const line_map *map = linemap_lookup (set, locus);
18838fd1498Szrj       const line_map_ordinary *ordmap = linemap_check_ordinary (map);
18938fd1498Szrj       unsigned int int_diff = src_range.m_finish - src_range.m_start;
19038fd1498Szrj       unsigned int col_diff = (int_diff >> ordmap->m_range_bits);
19138fd1498Szrj       if (col_diff < (1U << ordmap->m_range_bits))
19238fd1498Szrj 	{
19338fd1498Szrj 	  source_location packed = locus | col_diff;
19438fd1498Szrj 	  set->num_optimized_ranges++;
19538fd1498Szrj 	  return packed;
19638fd1498Szrj 	}
19738fd1498Szrj     }
19838fd1498Szrj 
19938fd1498Szrj   /* We can also compactly store locations
20038fd1498Szrj      when locus == start == finish (and data is NULL).  */
20138fd1498Szrj   if (locus == src_range.m_start
20238fd1498Szrj       && locus == src_range.m_finish
20338fd1498Szrj       && !data)
20438fd1498Szrj     return locus;
20538fd1498Szrj 
20638fd1498Szrj   if (!data)
20738fd1498Szrj     set->num_unoptimized_ranges++;
20838fd1498Szrj 
20938fd1498Szrj   lb.locus = locus;
21038fd1498Szrj   lb.src_range = src_range;
21138fd1498Szrj   lb.data = data;
21238fd1498Szrj   slot = (struct location_adhoc_data **)
21338fd1498Szrj       htab_find_slot (set->location_adhoc_data_map.htab, &lb, INSERT);
21438fd1498Szrj   if (*slot == NULL)
21538fd1498Szrj     {
21638fd1498Szrj       if (set->location_adhoc_data_map.curr_loc >=
21738fd1498Szrj 	  set->location_adhoc_data_map.allocated)
21838fd1498Szrj 	{
21938fd1498Szrj 	  char *orig_data = (char *) set->location_adhoc_data_map.data;
22038fd1498Szrj 	  ptrdiff_t offset;
22138fd1498Szrj 	  /* Cast away extern "C" from the type of xrealloc.  */
22238fd1498Szrj 	  line_map_realloc reallocator = (set->reallocator
22338fd1498Szrj 					  ? set->reallocator
22438fd1498Szrj 					  : (line_map_realloc) xrealloc);
22538fd1498Szrj 
22638fd1498Szrj 	  if (set->location_adhoc_data_map.allocated == 0)
22738fd1498Szrj 	    set->location_adhoc_data_map.allocated = 128;
22838fd1498Szrj 	  else
22938fd1498Szrj 	    set->location_adhoc_data_map.allocated *= 2;
23038fd1498Szrj 	  set->location_adhoc_data_map.data = (struct location_adhoc_data *)
23138fd1498Szrj 	      reallocator (set->location_adhoc_data_map.data,
23238fd1498Szrj 			   set->location_adhoc_data_map.allocated
23338fd1498Szrj 			   * sizeof (struct location_adhoc_data));
23438fd1498Szrj 	  offset = (char *) (set->location_adhoc_data_map.data) - orig_data;
23538fd1498Szrj 	  if (set->location_adhoc_data_map.allocated > 128)
23638fd1498Szrj 	    htab_traverse (set->location_adhoc_data_map.htab,
23738fd1498Szrj 			   location_adhoc_data_update, &offset);
23838fd1498Szrj 	}
23938fd1498Szrj       *slot = set->location_adhoc_data_map.data
24038fd1498Szrj 	      + set->location_adhoc_data_map.curr_loc;
24138fd1498Szrj       set->location_adhoc_data_map.data[set->location_adhoc_data_map.curr_loc++]
24238fd1498Szrj 	= lb;
24338fd1498Szrj     }
24438fd1498Szrj   return ((*slot) - set->location_adhoc_data_map.data) | 0x80000000;
24538fd1498Szrj }
24638fd1498Szrj 
24738fd1498Szrj /* Return the data for the adhoc loc.  */
24838fd1498Szrj 
24938fd1498Szrj void *
get_data_from_adhoc_loc(struct line_maps * set,source_location loc)25038fd1498Szrj get_data_from_adhoc_loc (struct line_maps *set, source_location loc)
25138fd1498Szrj {
25238fd1498Szrj   linemap_assert (IS_ADHOC_LOC (loc));
25338fd1498Szrj   return set->location_adhoc_data_map.data[loc & MAX_SOURCE_LOCATION].data;
25438fd1498Szrj }
25538fd1498Szrj 
25638fd1498Szrj /* Return the location for the adhoc loc.  */
25738fd1498Szrj 
25838fd1498Szrj source_location
get_location_from_adhoc_loc(struct line_maps * set,source_location loc)25938fd1498Szrj get_location_from_adhoc_loc (struct line_maps *set, source_location loc)
26038fd1498Szrj {
26138fd1498Szrj   linemap_assert (IS_ADHOC_LOC (loc));
26238fd1498Szrj   return set->location_adhoc_data_map.data[loc & MAX_SOURCE_LOCATION].locus;
26338fd1498Szrj }
26438fd1498Szrj 
26538fd1498Szrj /* Return the source_range for adhoc location LOC.  */
26638fd1498Szrj 
26738fd1498Szrj static source_range
get_range_from_adhoc_loc(struct line_maps * set,source_location loc)26838fd1498Szrj get_range_from_adhoc_loc (struct line_maps *set, source_location loc)
26938fd1498Szrj {
27038fd1498Szrj   linemap_assert (IS_ADHOC_LOC (loc));
27138fd1498Szrj   return set->location_adhoc_data_map.data[loc & MAX_SOURCE_LOCATION].src_range;
27238fd1498Szrj }
27338fd1498Szrj 
27438fd1498Szrj /* Get the source_range of location LOC, either from the ad-hoc
27538fd1498Szrj    lookaside table, or embedded inside LOC itself.  */
27638fd1498Szrj 
27738fd1498Szrj source_range
get_range_from_loc(struct line_maps * set,source_location loc)27838fd1498Szrj get_range_from_loc (struct line_maps *set,
27938fd1498Szrj 		    source_location loc)
28038fd1498Szrj {
28138fd1498Szrj   if (IS_ADHOC_LOC (loc))
28238fd1498Szrj     return get_range_from_adhoc_loc (set, loc);
28338fd1498Szrj 
28438fd1498Szrj   /* For ordinary maps, extract packed range.  */
28538fd1498Szrj   if (loc >= RESERVED_LOCATION_COUNT
28638fd1498Szrj       && loc < LINEMAPS_MACRO_LOWEST_LOCATION (set)
28738fd1498Szrj       && loc <= LINE_MAP_MAX_LOCATION_WITH_PACKED_RANGES)
28838fd1498Szrj     {
28938fd1498Szrj       const line_map *map = linemap_lookup (set, loc);
29038fd1498Szrj       const line_map_ordinary *ordmap = linemap_check_ordinary (map);
29138fd1498Szrj       source_range result;
29238fd1498Szrj       int offset = loc & ((1 << ordmap->m_range_bits) - 1);
29338fd1498Szrj       result.m_start = loc - offset;
29438fd1498Szrj       result.m_finish = result.m_start + (offset << ordmap->m_range_bits);
29538fd1498Szrj       return result;
29638fd1498Szrj     }
29738fd1498Szrj 
29838fd1498Szrj   return source_range::from_location (loc);
29938fd1498Szrj }
30038fd1498Szrj 
30138fd1498Szrj /* Get whether location LOC is a "pure" location, or
30238fd1498Szrj    whether it is an ad-hoc location, or embeds range information.  */
30338fd1498Szrj 
30438fd1498Szrj bool
pure_location_p(line_maps * set,source_location loc)30538fd1498Szrj pure_location_p (line_maps *set, source_location loc)
30638fd1498Szrj {
30738fd1498Szrj   if (IS_ADHOC_LOC (loc))
30838fd1498Szrj     return false;
30938fd1498Szrj 
31038fd1498Szrj   const line_map *map = linemap_lookup (set, loc);
31138fd1498Szrj   const line_map_ordinary *ordmap = linemap_check_ordinary (map);
31238fd1498Szrj 
31338fd1498Szrj   if (loc & ((1U << ordmap->m_range_bits) - 1))
31438fd1498Szrj     return false;
31538fd1498Szrj 
31638fd1498Szrj   return true;
31738fd1498Szrj }
31838fd1498Szrj 
31938fd1498Szrj /* Given location LOC within SET, strip away any packed range information
32038fd1498Szrj    or ad-hoc information.  */
32138fd1498Szrj 
32238fd1498Szrj source_location
get_pure_location(line_maps * set,source_location loc)32338fd1498Szrj get_pure_location (line_maps *set, source_location loc)
32438fd1498Szrj {
32538fd1498Szrj   if (IS_ADHOC_LOC (loc))
32638fd1498Szrj     loc
32738fd1498Szrj       = set->location_adhoc_data_map.data[loc & MAX_SOURCE_LOCATION].locus;
32838fd1498Szrj 
32938fd1498Szrj   if (loc >= LINEMAPS_MACRO_LOWEST_LOCATION (set))
33038fd1498Szrj     return loc;
33138fd1498Szrj 
33238fd1498Szrj   if (loc < RESERVED_LOCATION_COUNT)
33338fd1498Szrj     return loc;
33438fd1498Szrj 
33538fd1498Szrj   const line_map *map = linemap_lookup (set, loc);
33638fd1498Szrj   const line_map_ordinary *ordmap = linemap_check_ordinary (map);
33738fd1498Szrj 
33838fd1498Szrj   return loc & ~((1 << ordmap->m_range_bits) - 1);
33938fd1498Szrj }
34038fd1498Szrj 
34138fd1498Szrj /* Initialize a line map set.  */
34238fd1498Szrj 
34338fd1498Szrj void
linemap_init(struct line_maps * set,source_location builtin_location)34438fd1498Szrj linemap_init (struct line_maps *set,
34538fd1498Szrj 	      source_location builtin_location)
34638fd1498Szrj {
34738fd1498Szrj #if __GNUC__ == 4 && __GNUC_MINOR__ == 2 && !defined (__clang__)
34838fd1498Szrj   /* PR33916, needed to fix PR82939.  */
34938fd1498Szrj   memset (set, 0, sizeof (struct line_maps));
35038fd1498Szrj #else
35138fd1498Szrj   *set = line_maps ();
35238fd1498Szrj #endif
35338fd1498Szrj   set->highest_location = RESERVED_LOCATION_COUNT - 1;
35438fd1498Szrj   set->highest_line = RESERVED_LOCATION_COUNT - 1;
35538fd1498Szrj   set->location_adhoc_data_map.htab =
35638fd1498Szrj       htab_create (100, location_adhoc_data_hash, location_adhoc_data_eq, NULL);
35738fd1498Szrj   set->builtin_location = builtin_location;
35838fd1498Szrj }
35938fd1498Szrj 
36038fd1498Szrj /* Check for and warn about line_maps entered but not exited.  */
36138fd1498Szrj 
36238fd1498Szrj void
linemap_check_files_exited(struct line_maps * set)36338fd1498Szrj linemap_check_files_exited (struct line_maps *set)
36438fd1498Szrj {
36538fd1498Szrj   const line_map_ordinary *map;
36638fd1498Szrj   /* Depending upon whether we are handling preprocessed input or
36738fd1498Szrj      not, this can be a user error or an ICE.  */
36838fd1498Szrj   for (map = LINEMAPS_LAST_ORDINARY_MAP (set);
36938fd1498Szrj        ! MAIN_FILE_P (map);
37038fd1498Szrj        map = INCLUDED_FROM (set, map))
37138fd1498Szrj     fprintf (stderr, "line-map.c: file \"%s\" entered but not left\n",
37238fd1498Szrj 	     ORDINARY_MAP_FILE_NAME (map));
37338fd1498Szrj }
37438fd1498Szrj 
37538fd1498Szrj /* Create a new line map in the line map set SET, and return it.
37638fd1498Szrj    REASON is the reason of creating the map. It determines the type
37738fd1498Szrj    of map created (ordinary or macro map). Note that ordinary maps and
37838fd1498Szrj    macro maps are allocated in different memory location.  */
37938fd1498Szrj 
38038fd1498Szrj static struct line_map *
new_linemap(struct line_maps * set,enum lc_reason reason)38138fd1498Szrj new_linemap (struct line_maps *set,
38238fd1498Szrj 	     enum lc_reason reason)
38338fd1498Szrj {
38438fd1498Szrj   /* Depending on this variable, a macro map would be allocated in a
38538fd1498Szrj      different memory location than an ordinary map.  */
38638fd1498Szrj   bool macro_map_p = (reason == LC_ENTER_MACRO);
38738fd1498Szrj   struct line_map *result;
38838fd1498Szrj 
38938fd1498Szrj   if (LINEMAPS_USED (set, macro_map_p) == LINEMAPS_ALLOCATED (set, macro_map_p))
39038fd1498Szrj     {
39138fd1498Szrj       /* We ran out of allocated line maps. Let's allocate more.  */
39238fd1498Szrj       size_t alloc_size;
39338fd1498Szrj 
39438fd1498Szrj       /* Cast away extern "C" from the type of xrealloc.  */
39538fd1498Szrj       line_map_realloc reallocator = (set->reallocator
39638fd1498Szrj 				      ? set->reallocator
39738fd1498Szrj 				      : (line_map_realloc) xrealloc);
39838fd1498Szrj       line_map_round_alloc_size_func round_alloc_size =
39938fd1498Szrj 	set->round_alloc_size;
40038fd1498Szrj 
40138fd1498Szrj       size_t map_size = (macro_map_p
40238fd1498Szrj 			 ? sizeof (line_map_macro)
40338fd1498Szrj 			 : sizeof (line_map_ordinary));
40438fd1498Szrj 
40538fd1498Szrj       /* We are going to execute some dance to try to reduce the
40638fd1498Szrj 	 overhead of the memory allocator, in case we are using the
40738fd1498Szrj 	 ggc-page.c one.
40838fd1498Szrj 
40938fd1498Szrj 	 The actual size of memory we are going to get back from the
41038fd1498Szrj 	 allocator is the smallest power of 2 that is greater than the
41138fd1498Szrj 	 size we requested.  So let's consider that size then.  */
41238fd1498Szrj 
41338fd1498Szrj       alloc_size =
41438fd1498Szrj 	(2 * LINEMAPS_ALLOCATED (set, macro_map_p) +  256)
41538fd1498Szrj 	* map_size;
41638fd1498Szrj 
41738fd1498Szrj       /* Get the actual size of memory that is going to be allocated
41838fd1498Szrj 	 by the allocator.  */
41938fd1498Szrj       alloc_size = round_alloc_size (alloc_size);
42038fd1498Szrj 
42138fd1498Szrj       /* Now alloc_size contains the exact memory size we would get if
42238fd1498Szrj 	 we have asked for the initial alloc_size amount of memory.
42338fd1498Szrj 	 Let's get back to the number of macro map that amounts
42438fd1498Szrj 	 to.  */
42538fd1498Szrj       LINEMAPS_ALLOCATED (set, macro_map_p) =
42638fd1498Szrj 	alloc_size / map_size;
42738fd1498Szrj 
42838fd1498Szrj       /* And now let's really do the re-allocation.  */
42938fd1498Szrj       if (macro_map_p)
43038fd1498Szrj 	{
43138fd1498Szrj 	  set->info_macro.maps
43238fd1498Szrj 	    = (line_map_macro *) (*reallocator) (set->info_macro.maps,
43338fd1498Szrj 						 (LINEMAPS_ALLOCATED (set, macro_map_p)
43438fd1498Szrj 						  * map_size));
43538fd1498Szrj 	  result = &set->info_macro.maps[LINEMAPS_USED (set, macro_map_p)];
43638fd1498Szrj 	}
43738fd1498Szrj       else
43838fd1498Szrj 	{
43938fd1498Szrj 	  set->info_ordinary.maps =
44038fd1498Szrj 	    (line_map_ordinary *) (*reallocator) (set->info_ordinary.maps,
44138fd1498Szrj 						  (LINEMAPS_ALLOCATED (set, macro_map_p)
44238fd1498Szrj 						   * map_size));
44338fd1498Szrj 	  result = &set->info_ordinary.maps[LINEMAPS_USED (set, macro_map_p)];
44438fd1498Szrj 	}
44538fd1498Szrj       memset (result, 0,
44638fd1498Szrj 	      ((LINEMAPS_ALLOCATED (set, macro_map_p)
44738fd1498Szrj 		- LINEMAPS_USED (set, macro_map_p))
44838fd1498Szrj 	       * map_size));
44938fd1498Szrj     }
45038fd1498Szrj   else
45138fd1498Szrj     {
45238fd1498Szrj       if (macro_map_p)
45338fd1498Szrj 	result = &set->info_macro.maps[LINEMAPS_USED (set, macro_map_p)];
45438fd1498Szrj       else
45538fd1498Szrj 	result = &set->info_ordinary.maps[LINEMAPS_USED (set, macro_map_p)];
45638fd1498Szrj     }
45738fd1498Szrj 
45838fd1498Szrj   LINEMAPS_USED (set, macro_map_p)++;
45938fd1498Szrj 
46038fd1498Szrj   result->reason = reason;
46138fd1498Szrj   return result;
46238fd1498Szrj }
46338fd1498Szrj 
46438fd1498Szrj /* Add a mapping of logical source line to physical source file and
46538fd1498Szrj    line number.
46638fd1498Szrj 
46738fd1498Szrj    The text pointed to by TO_FILE must have a lifetime
46838fd1498Szrj    at least as long as the final call to lookup_line ().  An empty
46938fd1498Szrj    TO_FILE means standard input.  If reason is LC_LEAVE, and
47038fd1498Szrj    TO_FILE is NULL, then TO_FILE, TO_LINE and SYSP are given their
47138fd1498Szrj    natural values considering the file we are returning to.
47238fd1498Szrj 
47338fd1498Szrj    FROM_LINE should be monotonic increasing across calls to this
47438fd1498Szrj    function.  A call to this function can relocate the previous set of
47538fd1498Szrj    maps, so any stored line_map pointers should not be used.  */
47638fd1498Szrj 
47738fd1498Szrj const struct line_map *
linemap_add(struct line_maps * set,enum lc_reason reason,unsigned int sysp,const char * to_file,linenum_type to_line)47838fd1498Szrj linemap_add (struct line_maps *set, enum lc_reason reason,
47938fd1498Szrj 	     unsigned int sysp, const char *to_file, linenum_type to_line)
48038fd1498Szrj {
48138fd1498Szrj   /* Generate a start_location above the current highest_location.
48238fd1498Szrj      If possible, make the low range bits be zero.  */
48338fd1498Szrj   source_location start_location;
48438fd1498Szrj   if (set->highest_location < LINE_MAP_MAX_LOCATION_WITH_COLS)
48538fd1498Szrj     {
48638fd1498Szrj       start_location = set->highest_location + (1 << set->default_range_bits);
48738fd1498Szrj       if (set->default_range_bits)
48838fd1498Szrj 	start_location &= ~((1 << set->default_range_bits) - 1);
48938fd1498Szrj       linemap_assert (0 == (start_location
49038fd1498Szrj 			    & ((1 << set->default_range_bits) - 1)));
49138fd1498Szrj     }
49238fd1498Szrj   else
49338fd1498Szrj     start_location = set->highest_location + 1;
49438fd1498Szrj 
49538fd1498Szrj   linemap_assert (!(LINEMAPS_ORDINARY_USED (set)
49638fd1498Szrj 		    && (start_location
49738fd1498Szrj 			< MAP_START_LOCATION (LINEMAPS_LAST_ORDINARY_MAP (set)))));
49838fd1498Szrj 
49938fd1498Szrj   /* When we enter the file for the first time reason cannot be
50038fd1498Szrj      LC_RENAME.  */
50138fd1498Szrj   linemap_assert (!(set->depth == 0 && reason == LC_RENAME));
50238fd1498Szrj 
50338fd1498Szrj   /* If we are leaving the main file, return a NULL map.  */
50438fd1498Szrj   if (reason == LC_LEAVE
50538fd1498Szrj       && MAIN_FILE_P (LINEMAPS_LAST_ORDINARY_MAP (set))
50638fd1498Szrj       && to_file == NULL)
50738fd1498Szrj     {
50838fd1498Szrj       set->depth--;
50938fd1498Szrj       return NULL;
51038fd1498Szrj     }
51138fd1498Szrj 
51238fd1498Szrj   linemap_assert (reason != LC_ENTER_MACRO);
51338fd1498Szrj   line_map_ordinary *map = linemap_check_ordinary (new_linemap (set, reason));
51438fd1498Szrj 
51538fd1498Szrj   if (to_file && *to_file == '\0' && reason != LC_RENAME_VERBATIM)
51638fd1498Szrj     to_file = "<stdin>";
51738fd1498Szrj 
51838fd1498Szrj   if (reason == LC_RENAME_VERBATIM)
51938fd1498Szrj     reason = LC_RENAME;
52038fd1498Szrj 
52138fd1498Szrj   if (reason == LC_LEAVE)
52238fd1498Szrj     {
52338fd1498Szrj       /* When we are just leaving an "included" file, and jump to the next
52438fd1498Szrj 	 location inside the "includer" right after the #include
52538fd1498Szrj 	 "included", this variable points the map in use right before the
52638fd1498Szrj 	 #include "included", inside the same "includer" file.  */
52738fd1498Szrj       line_map_ordinary *from;
52838fd1498Szrj 
52938fd1498Szrj       linemap_assert (!MAIN_FILE_P (map - 1));
53038fd1498Szrj       /* (MAP - 1) points to the map we are leaving. The
53138fd1498Szrj 	 map from which (MAP - 1) got included should be the map
53238fd1498Szrj 	 that comes right before MAP in the same file.  */
53338fd1498Szrj       from = INCLUDED_FROM (set, map - 1);
53438fd1498Szrj 
53538fd1498Szrj       /* A TO_FILE of NULL is special - we use the natural values.  */
53638fd1498Szrj       if (to_file == NULL)
53738fd1498Szrj 	{
53838fd1498Szrj 	  to_file = ORDINARY_MAP_FILE_NAME (from);
53938fd1498Szrj 	  to_line = SOURCE_LINE (from, from[1].start_location);
54038fd1498Szrj 	  sysp = ORDINARY_MAP_IN_SYSTEM_HEADER_P (from);
54138fd1498Szrj 	}
54238fd1498Szrj       else
54338fd1498Szrj 	linemap_assert (filename_cmp (ORDINARY_MAP_FILE_NAME (from),
54438fd1498Szrj 				      to_file) == 0);
54538fd1498Szrj     }
54638fd1498Szrj 
54738fd1498Szrj   map->sysp = sysp;
54838fd1498Szrj   map->start_location = start_location;
54938fd1498Szrj   map->to_file = to_file;
55038fd1498Szrj   map->to_line = to_line;
55138fd1498Szrj   LINEMAPS_ORDINARY_CACHE (set) = LINEMAPS_ORDINARY_USED (set) - 1;
55238fd1498Szrj   map->m_column_and_range_bits = 0;
55338fd1498Szrj   map->m_range_bits = 0;
55438fd1498Szrj   set->highest_location = start_location;
55538fd1498Szrj   set->highest_line = start_location;
55638fd1498Szrj   set->max_column_hint = 0;
55738fd1498Szrj 
55838fd1498Szrj   /* This assertion is placed after set->highest_location has
55938fd1498Szrj      been updated, since the latter affects
56038fd1498Szrj      linemap_location_from_macro_expansion_p, which ultimately affects
56138fd1498Szrj      pure_location_p.  */
56238fd1498Szrj   linemap_assert (pure_location_p (set, start_location));
56338fd1498Szrj 
56438fd1498Szrj   if (reason == LC_ENTER)
56538fd1498Szrj     {
56638fd1498Szrj       map->included_from =
56738fd1498Szrj 	set->depth == 0 ? -1 : (int) (LINEMAPS_ORDINARY_USED (set) - 2);
56838fd1498Szrj       set->depth++;
56938fd1498Szrj       if (set->trace_includes)
57038fd1498Szrj 	trace_include (set, map);
57138fd1498Szrj     }
57238fd1498Szrj   else if (reason == LC_RENAME)
57338fd1498Szrj     map->included_from = ORDINARY_MAP_INCLUDER_FILE_INDEX (&map[-1]);
57438fd1498Szrj   else if (reason == LC_LEAVE)
57538fd1498Szrj     {
57638fd1498Szrj       set->depth--;
57738fd1498Szrj       map->included_from =
57838fd1498Szrj 	ORDINARY_MAP_INCLUDER_FILE_INDEX (INCLUDED_FROM (set, map - 1));
57938fd1498Szrj     }
58038fd1498Szrj 
58138fd1498Szrj   return map;
58238fd1498Szrj }
58338fd1498Szrj 
58438fd1498Szrj /* Returns TRUE if the line table set tracks token locations across
58538fd1498Szrj    macro expansion, FALSE otherwise.  */
58638fd1498Szrj 
58738fd1498Szrj bool
linemap_tracks_macro_expansion_locs_p(struct line_maps * set)58838fd1498Szrj linemap_tracks_macro_expansion_locs_p (struct line_maps *set)
58938fd1498Szrj {
59038fd1498Szrj   return LINEMAPS_MACRO_MAPS (set) != NULL;
59138fd1498Szrj }
59238fd1498Szrj 
59338fd1498Szrj /* Create a macro map.  A macro map encodes source locations of tokens
59438fd1498Szrj    that are part of a macro replacement-list, at a macro expansion
59538fd1498Szrj    point.  See the extensive comments of struct line_map and struct
59638fd1498Szrj    line_map_macro, in line-map.h.
59738fd1498Szrj 
59838fd1498Szrj    This map shall be created when the macro is expanded.  The map
59938fd1498Szrj    encodes the source location of the expansion point of the macro as
60038fd1498Szrj    well as the "original" source location of each token that is part
60138fd1498Szrj    of the macro replacement-list.  If a macro is defined but never
60238fd1498Szrj    expanded, it has no macro map.  SET is the set of maps the macro
60338fd1498Szrj    map should be part of.  MACRO_NODE is the macro which the new macro
60438fd1498Szrj    map should encode source locations for.  EXPANSION is the location
60538fd1498Szrj    of the expansion point of MACRO. For function-like macros
60638fd1498Szrj    invocations, it's best to make it point to the closing parenthesis
60738fd1498Szrj    of the macro, rather than the the location of the first character
60838fd1498Szrj    of the macro.  NUM_TOKENS is the number of tokens that are part of
60938fd1498Szrj    the replacement-list of MACRO.
61038fd1498Szrj 
61138fd1498Szrj    Note that when we run out of the integer space available for source
61238fd1498Szrj    locations, this function returns NULL.  In that case, callers of
61338fd1498Szrj    this function cannot encode {line,column} pairs into locations of
61438fd1498Szrj    macro tokens anymore.  */
61538fd1498Szrj 
61638fd1498Szrj const line_map_macro *
linemap_enter_macro(struct line_maps * set,struct cpp_hashnode * macro_node,source_location expansion,unsigned int num_tokens)61738fd1498Szrj linemap_enter_macro (struct line_maps *set, struct cpp_hashnode *macro_node,
61838fd1498Szrj 		     source_location expansion, unsigned int num_tokens)
61938fd1498Szrj {
62038fd1498Szrj   line_map_macro *map;
62138fd1498Szrj   source_location start_location;
62238fd1498Szrj   /* Cast away extern "C" from the type of xrealloc.  */
62338fd1498Szrj   line_map_realloc reallocator = (set->reallocator
62438fd1498Szrj 				  ? set->reallocator
62538fd1498Szrj 				  : (line_map_realloc) xrealloc);
62638fd1498Szrj 
62738fd1498Szrj   start_location = LINEMAPS_MACRO_LOWEST_LOCATION (set) - num_tokens;
62838fd1498Szrj 
62938fd1498Szrj   if (start_location <= set->highest_line
63038fd1498Szrj       || start_location > LINEMAPS_MACRO_LOWEST_LOCATION (set))
63138fd1498Szrj     /* We ran out of macro map space.   */
63238fd1498Szrj     return NULL;
63338fd1498Szrj 
63438fd1498Szrj   map = linemap_check_macro (new_linemap (set, LC_ENTER_MACRO));
63538fd1498Szrj 
63638fd1498Szrj   map->start_location = start_location;
63738fd1498Szrj   map->macro = macro_node;
63838fd1498Szrj   map->n_tokens = num_tokens;
63938fd1498Szrj   map->macro_locations
64038fd1498Szrj     = (source_location*) reallocator (NULL,
64138fd1498Szrj 				      2 * num_tokens
64238fd1498Szrj 				      * sizeof (source_location));
64338fd1498Szrj   map->expansion = expansion;
64438fd1498Szrj   memset (MACRO_MAP_LOCATIONS (map), 0,
64538fd1498Szrj 	  num_tokens * sizeof (source_location));
64638fd1498Szrj 
64738fd1498Szrj   LINEMAPS_MACRO_CACHE (set) = LINEMAPS_MACRO_USED (set) - 1;
64838fd1498Szrj 
64938fd1498Szrj   return map;
65038fd1498Szrj }
65138fd1498Szrj 
65238fd1498Szrj /* Create and return a virtual location for a token that is part of a
65338fd1498Szrj    macro expansion-list at a macro expansion point.  See the comment
65438fd1498Szrj    inside struct line_map_macro to see what an expansion-list exactly
65538fd1498Szrj    is.
65638fd1498Szrj 
65738fd1498Szrj    A call to this function must come after a call to
65838fd1498Szrj    linemap_enter_macro.
65938fd1498Szrj 
66038fd1498Szrj    MAP is the map into which the source location is created.  TOKEN_NO
66138fd1498Szrj    is the index of the token in the macro replacement-list, starting
66238fd1498Szrj    at number 0.
66338fd1498Szrj 
66438fd1498Szrj    ORIG_LOC is the location of the token outside of this macro
66538fd1498Szrj    expansion.  If the token comes originally from the macro
66638fd1498Szrj    definition, it is the locus in the macro definition; otherwise it
66738fd1498Szrj    is a location in the context of the caller of this macro expansion
66838fd1498Szrj    (which is a virtual location or a source location if the caller is
66938fd1498Szrj    itself a macro expansion or not).
67038fd1498Szrj 
67138fd1498Szrj    ORIG_PARM_REPLACEMENT_LOC is the location in the macro definition,
67238fd1498Szrj    either of the token itself or of a macro parameter that it
67338fd1498Szrj    replaces.  */
67438fd1498Szrj 
67538fd1498Szrj source_location
linemap_add_macro_token(const line_map_macro * map,unsigned int token_no,source_location orig_loc,source_location orig_parm_replacement_loc)67638fd1498Szrj linemap_add_macro_token (const line_map_macro *map,
67738fd1498Szrj 			 unsigned int token_no,
67838fd1498Szrj 			 source_location orig_loc,
67938fd1498Szrj 			 source_location orig_parm_replacement_loc)
68038fd1498Szrj {
68138fd1498Szrj   source_location result;
68238fd1498Szrj 
68338fd1498Szrj   linemap_assert (linemap_macro_expansion_map_p (map));
68438fd1498Szrj   linemap_assert (token_no < MACRO_MAP_NUM_MACRO_TOKENS (map));
68538fd1498Szrj 
68638fd1498Szrj   MACRO_MAP_LOCATIONS (map)[2 * token_no] = orig_loc;
68738fd1498Szrj   MACRO_MAP_LOCATIONS (map)[2 * token_no + 1] = orig_parm_replacement_loc;
68838fd1498Szrj 
68938fd1498Szrj   result = MAP_START_LOCATION (map) + token_no;
69038fd1498Szrj   return result;
69138fd1498Szrj }
69238fd1498Szrj 
69338fd1498Szrj /* Return a source_location for the start (i.e. column==0) of
69438fd1498Szrj    (physical) line TO_LINE in the current source file (as in the
69538fd1498Szrj    most recent linemap_add).   MAX_COLUMN_HINT is the highest column
69638fd1498Szrj    number we expect to use in this line (but it does not change
69738fd1498Szrj    the highest_location).  */
69838fd1498Szrj 
69938fd1498Szrj source_location
linemap_line_start(struct line_maps * set,linenum_type to_line,unsigned int max_column_hint)70038fd1498Szrj linemap_line_start (struct line_maps *set, linenum_type to_line,
70138fd1498Szrj 		    unsigned int max_column_hint)
70238fd1498Szrj {
70338fd1498Szrj   line_map_ordinary *map = LINEMAPS_LAST_ORDINARY_MAP (set);
70438fd1498Szrj   source_location highest = set->highest_location;
70538fd1498Szrj   source_location r;
70638fd1498Szrj   linenum_type last_line =
70738fd1498Szrj     SOURCE_LINE (map, set->highest_line);
70838fd1498Szrj   int line_delta = to_line - last_line;
70938fd1498Szrj   bool add_map = false;
71038fd1498Szrj   linemap_assert (map->m_column_and_range_bits >= map->m_range_bits);
71138fd1498Szrj   int effective_column_bits = map->m_column_and_range_bits - map->m_range_bits;
71238fd1498Szrj 
71338fd1498Szrj   if (line_delta < 0
71438fd1498Szrj       || (line_delta > 10
71538fd1498Szrj 	  && line_delta * map->m_column_and_range_bits > 1000)
71638fd1498Szrj       || (max_column_hint >= (1U << effective_column_bits))
71738fd1498Szrj       || (max_column_hint <= 80 && effective_column_bits >= 10)
71838fd1498Szrj       || (highest > LINE_MAP_MAX_LOCATION_WITH_PACKED_RANGES
71938fd1498Szrj 	  && map->m_range_bits > 0)
72038fd1498Szrj       || (highest > LINE_MAP_MAX_LOCATION_WITH_COLS
72138fd1498Szrj 	  && (set->max_column_hint || highest >= LINE_MAP_MAX_SOURCE_LOCATION)))
72238fd1498Szrj     add_map = true;
72338fd1498Szrj   else
72438fd1498Szrj     max_column_hint = set->max_column_hint;
72538fd1498Szrj   if (add_map)
72638fd1498Szrj     {
72738fd1498Szrj       int column_bits;
72838fd1498Szrj       int range_bits;
72938fd1498Szrj       if (max_column_hint > LINE_MAP_MAX_COLUMN_NUMBER
73038fd1498Szrj 	  || highest > LINE_MAP_MAX_LOCATION_WITH_COLS)
73138fd1498Szrj 	{
73238fd1498Szrj 	  /* If the column number is ridiculous or we've allocated a huge
73338fd1498Szrj 	     number of source_locations, give up on column numbers
73438fd1498Szrj 	     (and on packed ranges).  */
73538fd1498Szrj 	  max_column_hint = 0;
73638fd1498Szrj 	  column_bits = 0;
73738fd1498Szrj 	  range_bits = 0;
73838fd1498Szrj 	  if (highest > LINE_MAP_MAX_SOURCE_LOCATION)
73938fd1498Szrj 	    return 0;
74038fd1498Szrj 	}
74138fd1498Szrj       else
74238fd1498Szrj 	{
74338fd1498Szrj 	  column_bits = 7;
74438fd1498Szrj 	  if (highest <= LINE_MAP_MAX_LOCATION_WITH_PACKED_RANGES)
74538fd1498Szrj 	    range_bits = set->default_range_bits;
74638fd1498Szrj 	  else
74738fd1498Szrj 	    range_bits = 0;
74838fd1498Szrj 	  while (max_column_hint >= (1U << column_bits))
74938fd1498Szrj 	    column_bits++;
75038fd1498Szrj 	  max_column_hint = 1U << column_bits;
75138fd1498Szrj 	  column_bits += range_bits;
75238fd1498Szrj 	}
75338fd1498Szrj       /* Allocate the new line_map.  However, if the current map only has a
75438fd1498Szrj 	 single line we can sometimes just increase its column_bits instead. */
75538fd1498Szrj       if (line_delta < 0
75638fd1498Szrj 	  || last_line != ORDINARY_MAP_STARTING_LINE_NUMBER (map)
75738fd1498Szrj 	  || SOURCE_COLUMN (map, highest) >= (1U << (column_bits - range_bits))
758*e215fc28Szrj 	  || ( /* We can't reuse the map if the line offset is sufficiently
759*e215fc28Szrj 		  large to cause overflow when computing location_t values.  */
760*e215fc28Szrj 	      (to_line - ORDINARY_MAP_STARTING_LINE_NUMBER (map))
761*e215fc28Szrj 	      >= (((uint64_t) 1)
762*e215fc28Szrj 		  << (CHAR_BIT * sizeof (linenum_type) - column_bits)))
76338fd1498Szrj 	  || range_bits < map->m_range_bits)
76438fd1498Szrj 	map = linemap_check_ordinary
76538fd1498Szrj 	        (const_cast <line_map *>
76638fd1498Szrj 		  (linemap_add (set, LC_RENAME,
76738fd1498Szrj 				ORDINARY_MAP_IN_SYSTEM_HEADER_P (map),
76838fd1498Szrj 				ORDINARY_MAP_FILE_NAME (map),
76938fd1498Szrj 				to_line)));
77038fd1498Szrj       map->m_column_and_range_bits = column_bits;
77138fd1498Szrj       map->m_range_bits = range_bits;
77238fd1498Szrj       r = (MAP_START_LOCATION (map)
77338fd1498Szrj 	   + ((to_line - ORDINARY_MAP_STARTING_LINE_NUMBER (map))
77438fd1498Szrj 	      << column_bits));
77538fd1498Szrj     }
77638fd1498Szrj   else
77738fd1498Szrj     r = set->highest_line + (line_delta << map->m_column_and_range_bits);
77838fd1498Szrj 
77938fd1498Szrj   /* Locations of ordinary tokens are always lower than locations of
78038fd1498Szrj      macro tokens.  */
78138fd1498Szrj   if (r >= LINEMAPS_MACRO_LOWEST_LOCATION (set))
78238fd1498Szrj     return 0;
78338fd1498Szrj 
78438fd1498Szrj   set->highest_line = r;
78538fd1498Szrj   if (r > set->highest_location)
78638fd1498Szrj     set->highest_location = r;
78738fd1498Szrj   set->max_column_hint = max_column_hint;
78838fd1498Szrj 
78938fd1498Szrj   /* At this point, we expect one of:
79038fd1498Szrj      (a) the normal case: a "pure" location with 0 range bits, or
79138fd1498Szrj      (b) we've gone past LINE_MAP_MAX_LOCATION_WITH_COLS so can't track
79238fd1498Szrj         columns anymore (or ranges), or
79338fd1498Szrj      (c) we're in a region with a column hint exceeding
79438fd1498Szrj         LINE_MAP_MAX_COLUMN_NUMBER, so column-tracking is off,
79538fd1498Szrj 	with column_bits == 0.  */
79638fd1498Szrj   linemap_assert (pure_location_p (set, r)
79738fd1498Szrj 		  || r >= LINE_MAP_MAX_LOCATION_WITH_COLS
79838fd1498Szrj 		  || map->m_column_and_range_bits == 0);
79938fd1498Szrj   linemap_assert (SOURCE_LINE (map, r) == to_line);
80038fd1498Szrj   return r;
80138fd1498Szrj }
80238fd1498Szrj 
80338fd1498Szrj /* Encode and return a source_location from a column number. The
80438fd1498Szrj    source line considered is the last source line used to call
80538fd1498Szrj    linemap_line_start, i.e, the last source line which a location was
80638fd1498Szrj    encoded from.  */
80738fd1498Szrj 
80838fd1498Szrj source_location
linemap_position_for_column(struct line_maps * set,unsigned int to_column)80938fd1498Szrj linemap_position_for_column (struct line_maps *set, unsigned int to_column)
81038fd1498Szrj {
81138fd1498Szrj   source_location r = set->highest_line;
81238fd1498Szrj 
81338fd1498Szrj   linemap_assert
81438fd1498Szrj     (!linemap_macro_expansion_map_p (LINEMAPS_LAST_ORDINARY_MAP (set)));
81538fd1498Szrj 
81638fd1498Szrj   if (to_column >= set->max_column_hint)
81738fd1498Szrj     {
81838fd1498Szrj       if (r > LINE_MAP_MAX_LOCATION_WITH_COLS
81938fd1498Szrj 	  || to_column > LINE_MAP_MAX_COLUMN_NUMBER)
82038fd1498Szrj 	{
82138fd1498Szrj 	  /* Running low on source_locations - disable column numbers.  */
82238fd1498Szrj 	  return r;
82338fd1498Szrj 	}
82438fd1498Szrj       else
82538fd1498Szrj 	{
82638fd1498Szrj 	  /* Otherwise, attempt to start a new line that can hold TO_COLUMN,
82738fd1498Szrj 	     with some space to spare.  This may or may not lead to a new
82838fd1498Szrj 	     linemap being created.  */
82938fd1498Szrj 	  line_map_ordinary *map = LINEMAPS_LAST_ORDINARY_MAP (set);
83038fd1498Szrj 	  r = linemap_line_start (set, SOURCE_LINE (map, r), to_column + 50);
83138fd1498Szrj 	  map = LINEMAPS_LAST_ORDINARY_MAP (set);
83238fd1498Szrj 	  if (map->m_column_and_range_bits == 0)
83338fd1498Szrj 	    {
83438fd1498Szrj 	      /* ...then the linemap has column-tracking disabled,
83538fd1498Szrj 		 presumably due to exceeding either
83638fd1498Szrj 		 LINE_MAP_MAX_LOCATION_WITH_COLS (overall) or
83738fd1498Szrj 		 LINE_MAP_MAX_COLUMN_NUMBER (within this line).
83838fd1498Szrj 		 Return the start of the linemap, which encodes column 0, for
83938fd1498Szrj 		 the whole line.  */
84038fd1498Szrj 	      return r;
84138fd1498Szrj 	    }
84238fd1498Szrj 	}
84338fd1498Szrj     }
84438fd1498Szrj   line_map_ordinary *map = LINEMAPS_LAST_ORDINARY_MAP (set);
84538fd1498Szrj   r = r + (to_column << map->m_range_bits);
84638fd1498Szrj   if (r >= set->highest_location)
84738fd1498Szrj     set->highest_location = r;
84838fd1498Szrj   return r;
84938fd1498Szrj }
85038fd1498Szrj 
85138fd1498Szrj /* Encode and return a source location from a given line and
85238fd1498Szrj    column.  */
85338fd1498Szrj 
85438fd1498Szrj source_location
linemap_position_for_line_and_column(line_maps * set,const line_map_ordinary * ord_map,linenum_type line,unsigned column)85538fd1498Szrj linemap_position_for_line_and_column (line_maps *set,
85638fd1498Szrj 				      const line_map_ordinary *ord_map,
85738fd1498Szrj 				      linenum_type line,
85838fd1498Szrj 				      unsigned column)
85938fd1498Szrj {
86038fd1498Szrj   linemap_assert (ORDINARY_MAP_STARTING_LINE_NUMBER (ord_map) <= line);
86138fd1498Szrj 
86238fd1498Szrj   source_location r = MAP_START_LOCATION (ord_map);
86338fd1498Szrj   r += ((line - ORDINARY_MAP_STARTING_LINE_NUMBER (ord_map))
86438fd1498Szrj 	<< ord_map->m_column_and_range_bits);
86538fd1498Szrj   if (r <= LINE_MAP_MAX_LOCATION_WITH_COLS)
86638fd1498Szrj     r += ((column & ((1 << ord_map->m_column_and_range_bits) - 1))
86738fd1498Szrj 	  << ord_map->m_range_bits);
86838fd1498Szrj   source_location upper_limit = LINEMAPS_MACRO_LOWEST_LOCATION (set);
86938fd1498Szrj   if (r >= upper_limit)
87038fd1498Szrj     r = upper_limit - 1;
87138fd1498Szrj   if (r > set->highest_location)
87238fd1498Szrj     set->highest_location = r;
87338fd1498Szrj   return r;
87438fd1498Szrj }
87538fd1498Szrj 
87638fd1498Szrj /* Encode and return a source_location starting from location LOC and
87738fd1498Szrj    shifting it by COLUMN_OFFSET columns.  This function does not support
87838fd1498Szrj    virtual locations.  */
87938fd1498Szrj 
88038fd1498Szrj source_location
linemap_position_for_loc_and_offset(struct line_maps * set,source_location loc,unsigned int column_offset)88138fd1498Szrj linemap_position_for_loc_and_offset (struct line_maps *set,
88238fd1498Szrj 				     source_location loc,
88338fd1498Szrj 				     unsigned int column_offset)
88438fd1498Szrj {
88538fd1498Szrj   const line_map_ordinary * map = NULL;
88638fd1498Szrj 
88738fd1498Szrj   if (IS_ADHOC_LOC (loc))
88838fd1498Szrj     loc = set->location_adhoc_data_map.data[loc & MAX_SOURCE_LOCATION].locus;
88938fd1498Szrj 
89038fd1498Szrj   /* This function does not support virtual locations yet.  */
89138fd1498Szrj   if (linemap_location_from_macro_expansion_p (set, loc))
89238fd1498Szrj     return loc;
89338fd1498Szrj 
89438fd1498Szrj   if (column_offset == 0
89538fd1498Szrj       /* Adding an offset to a reserved location (like
89638fd1498Szrj 	 UNKNOWN_LOCATION for the C/C++ FEs) does not really make
89738fd1498Szrj 	 sense.  So let's leave the location intact in that case.  */
89838fd1498Szrj       || loc < RESERVED_LOCATION_COUNT)
89938fd1498Szrj     return loc;
90038fd1498Szrj 
90138fd1498Szrj   /* We find the real location and shift it.  */
90238fd1498Szrj   loc = linemap_resolve_location (set, loc, LRK_SPELLING_LOCATION, &map);
90338fd1498Szrj   /* The new location (loc + offset) should be higher than the first
90438fd1498Szrj      location encoded by MAP.  This can fail if the line information
90538fd1498Szrj      is messed up because of line directives (see PR66415).  */
90638fd1498Szrj   if (MAP_START_LOCATION (map) >= loc + (column_offset << map->m_range_bits))
90738fd1498Szrj     return loc;
90838fd1498Szrj 
90938fd1498Szrj   linenum_type line = SOURCE_LINE (map, loc);
91038fd1498Szrj   unsigned int column = SOURCE_COLUMN (map, loc);
91138fd1498Szrj 
91238fd1498Szrj   /* If MAP is not the last line map of its set, then the new location
91338fd1498Szrj      (loc + offset) should be less than the first location encoded by
91438fd1498Szrj      the next line map of the set.  Otherwise, we try to encode the
91538fd1498Szrj      location in the next map.  */
91638fd1498Szrj   while (map != LINEMAPS_LAST_ORDINARY_MAP (set)
91738fd1498Szrj 	 && (loc + (column_offset << map->m_range_bits)
91838fd1498Szrj 	     >= MAP_START_LOCATION (&map[1])))
91938fd1498Szrj     {
92038fd1498Szrj       map = &map[1];
92138fd1498Szrj       /* If the next map starts in a higher line, we cannot encode the
92238fd1498Szrj 	 location there.  */
92338fd1498Szrj       if (line < ORDINARY_MAP_STARTING_LINE_NUMBER (map))
92438fd1498Szrj 	return loc;
92538fd1498Szrj     }
92638fd1498Szrj 
92738fd1498Szrj   column += column_offset;
92838fd1498Szrj 
92938fd1498Szrj   /* Bail out if the column is not representable within the existing
93038fd1498Szrj      linemap.  */
93138fd1498Szrj   if (column >= (1u << (map->m_column_and_range_bits - map->m_range_bits)))
93238fd1498Szrj     return loc;
93338fd1498Szrj 
93438fd1498Szrj   source_location r =
93538fd1498Szrj     linemap_position_for_line_and_column (set, map, line, column);
93638fd1498Szrj   if (linemap_assert_fails (r <= set->highest_location)
93738fd1498Szrj       || linemap_assert_fails (map == linemap_lookup (set, r)))
93838fd1498Szrj     return loc;
93938fd1498Szrj 
94038fd1498Szrj   return r;
94138fd1498Szrj }
94238fd1498Szrj 
94338fd1498Szrj /* Given a virtual source location yielded by a map (either an
94438fd1498Szrj    ordinary or a macro map), returns that map.  */
94538fd1498Szrj 
94638fd1498Szrj const struct line_map*
linemap_lookup(struct line_maps * set,source_location line)94738fd1498Szrj linemap_lookup (struct line_maps *set, source_location line)
94838fd1498Szrj {
94938fd1498Szrj   if (IS_ADHOC_LOC (line))
95038fd1498Szrj     line = set->location_adhoc_data_map.data[line & MAX_SOURCE_LOCATION].locus;
95138fd1498Szrj   if (linemap_location_from_macro_expansion_p (set, line))
95238fd1498Szrj     return linemap_macro_map_lookup (set, line);
95338fd1498Szrj   return linemap_ordinary_map_lookup (set, line);
95438fd1498Szrj }
95538fd1498Szrj 
95638fd1498Szrj /* Given a source location yielded by an ordinary map, returns that
95738fd1498Szrj    map.  Since the set is built chronologically, the logical lines are
95838fd1498Szrj    monotonic increasing, and so the list is sorted and we can use a
95938fd1498Szrj    binary search.  */
96038fd1498Szrj 
96138fd1498Szrj static const line_map_ordinary *
linemap_ordinary_map_lookup(struct line_maps * set,source_location line)96238fd1498Szrj linemap_ordinary_map_lookup (struct line_maps *set, source_location line)
96338fd1498Szrj {
96438fd1498Szrj   unsigned int md, mn, mx;
96538fd1498Szrj   const line_map_ordinary *cached, *result;
96638fd1498Szrj 
96738fd1498Szrj   if (IS_ADHOC_LOC (line))
96838fd1498Szrj     line = set->location_adhoc_data_map.data[line & MAX_SOURCE_LOCATION].locus;
96938fd1498Szrj 
97038fd1498Szrj   if (set ==  NULL || line < RESERVED_LOCATION_COUNT)
97138fd1498Szrj     return NULL;
97238fd1498Szrj 
97338fd1498Szrj   mn = LINEMAPS_ORDINARY_CACHE (set);
97438fd1498Szrj   mx = LINEMAPS_ORDINARY_USED (set);
97538fd1498Szrj 
97638fd1498Szrj   cached = LINEMAPS_ORDINARY_MAP_AT (set, mn);
97738fd1498Szrj   /* We should get a segfault if no line_maps have been added yet.  */
97838fd1498Szrj   if (line >= MAP_START_LOCATION (cached))
97938fd1498Szrj     {
98038fd1498Szrj       if (mn + 1 == mx || line < MAP_START_LOCATION (&cached[1]))
98138fd1498Szrj 	return cached;
98238fd1498Szrj     }
98338fd1498Szrj   else
98438fd1498Szrj     {
98538fd1498Szrj       mx = mn;
98638fd1498Szrj       mn = 0;
98738fd1498Szrj     }
98838fd1498Szrj 
98938fd1498Szrj   while (mx - mn > 1)
99038fd1498Szrj     {
99138fd1498Szrj       md = (mn + mx) / 2;
99238fd1498Szrj       if (MAP_START_LOCATION (LINEMAPS_ORDINARY_MAP_AT (set, md)) > line)
99338fd1498Szrj 	mx = md;
99438fd1498Szrj       else
99538fd1498Szrj 	mn = md;
99638fd1498Szrj     }
99738fd1498Szrj 
99838fd1498Szrj   LINEMAPS_ORDINARY_CACHE (set) = mn;
99938fd1498Szrj   result = LINEMAPS_ORDINARY_MAP_AT (set, mn);
100038fd1498Szrj   linemap_assert (line >= MAP_START_LOCATION (result));
100138fd1498Szrj   return result;
100238fd1498Szrj }
100338fd1498Szrj 
100438fd1498Szrj /* Given a source location yielded by a macro map, returns that map.
100538fd1498Szrj    Since the set is built chronologically, the logical lines are
100638fd1498Szrj    monotonic decreasing, and so the list is sorted and we can use a
100738fd1498Szrj    binary search.  */
100838fd1498Szrj 
100938fd1498Szrj static const line_map_macro *
linemap_macro_map_lookup(struct line_maps * set,source_location line)101038fd1498Szrj linemap_macro_map_lookup (struct line_maps *set, source_location line)
101138fd1498Szrj {
101238fd1498Szrj   unsigned int md, mn, mx;
101338fd1498Szrj   const struct line_map_macro *cached, *result;
101438fd1498Szrj 
101538fd1498Szrj   if (IS_ADHOC_LOC (line))
101638fd1498Szrj     line = set->location_adhoc_data_map.data[line & MAX_SOURCE_LOCATION].locus;
101738fd1498Szrj 
101838fd1498Szrj   linemap_assert (line >= LINEMAPS_MACRO_LOWEST_LOCATION (set));
101938fd1498Szrj 
102038fd1498Szrj   if (set ==  NULL)
102138fd1498Szrj     return NULL;
102238fd1498Szrj 
102338fd1498Szrj   mn = LINEMAPS_MACRO_CACHE (set);
102438fd1498Szrj   mx = LINEMAPS_MACRO_USED (set);
102538fd1498Szrj   cached = LINEMAPS_MACRO_MAP_AT (set, mn);
102638fd1498Szrj 
102738fd1498Szrj   if (line >= MAP_START_LOCATION (cached))
102838fd1498Szrj     {
102938fd1498Szrj       if (mn == 0 || line < MAP_START_LOCATION (&cached[-1]))
103038fd1498Szrj 	return cached;
103138fd1498Szrj       mx = mn - 1;
103238fd1498Szrj       mn = 0;
103338fd1498Szrj     }
103438fd1498Szrj 
103538fd1498Szrj   while (mn < mx)
103638fd1498Szrj     {
103738fd1498Szrj       md = (mx + mn) / 2;
103838fd1498Szrj       if (MAP_START_LOCATION (LINEMAPS_MACRO_MAP_AT (set, md)) > line)
103938fd1498Szrj 	mn = md + 1;
104038fd1498Szrj       else
104138fd1498Szrj 	mx = md;
104238fd1498Szrj     }
104338fd1498Szrj 
104438fd1498Szrj   LINEMAPS_MACRO_CACHE (set) = mx;
104538fd1498Szrj   result = LINEMAPS_MACRO_MAP_AT (set, LINEMAPS_MACRO_CACHE (set));
104638fd1498Szrj   linemap_assert (MAP_START_LOCATION (result) <= line);
104738fd1498Szrj 
104838fd1498Szrj   return result;
104938fd1498Szrj }
105038fd1498Szrj 
105138fd1498Szrj /* Return TRUE if MAP encodes locations coming from a macro
105238fd1498Szrj    replacement-list at macro expansion point.  */
105338fd1498Szrj 
105438fd1498Szrj bool
linemap_macro_expansion_map_p(const struct line_map * map)105538fd1498Szrj linemap_macro_expansion_map_p (const struct line_map *map)
105638fd1498Szrj {
105738fd1498Szrj   if (!map)
105838fd1498Szrj     return false;
105938fd1498Szrj   return (map->reason == LC_ENTER_MACRO);
106038fd1498Szrj }
106138fd1498Szrj 
106238fd1498Szrj /* If LOCATION is the locus of a token in a replacement-list of a
106338fd1498Szrj    macro expansion return the location of the macro expansion point.
106438fd1498Szrj 
106538fd1498Szrj    Read the comments of struct line_map and struct line_map_macro in
106638fd1498Szrj    line-map.h to understand what a macro expansion point is.  */
106738fd1498Szrj 
106838fd1498Szrj static source_location
linemap_macro_map_loc_to_exp_point(const line_map_macro * map,source_location location ATTRIBUTE_UNUSED)106938fd1498Szrj linemap_macro_map_loc_to_exp_point (const line_map_macro *map,
107038fd1498Szrj 				    source_location location ATTRIBUTE_UNUSED)
107138fd1498Szrj {
107238fd1498Szrj   linemap_assert (linemap_macro_expansion_map_p (map)
107338fd1498Szrj 		  && location >= MAP_START_LOCATION (map));
107438fd1498Szrj 
107538fd1498Szrj   /* Make sure LOCATION is correct.  */
107638fd1498Szrj   linemap_assert ((location - MAP_START_LOCATION (map))
107738fd1498Szrj 		  <  MACRO_MAP_NUM_MACRO_TOKENS (map));
107838fd1498Szrj 
107938fd1498Szrj   return MACRO_MAP_EXPANSION_POINT_LOCATION (map);
108038fd1498Szrj }
108138fd1498Szrj 
108238fd1498Szrj /* LOCATION is the source location of a token that belongs to a macro
108338fd1498Szrj    replacement-list as part of the macro expansion denoted by MAP.
108438fd1498Szrj 
108538fd1498Szrj    Return the location of the token at the definition point of the
108638fd1498Szrj    macro.  */
108738fd1498Szrj 
108838fd1498Szrj static source_location
linemap_macro_map_loc_to_def_point(const line_map_macro * map,source_location location)108938fd1498Szrj linemap_macro_map_loc_to_def_point (const line_map_macro *map,
109038fd1498Szrj 				    source_location location)
109138fd1498Szrj {
109238fd1498Szrj   unsigned token_no;
109338fd1498Szrj 
109438fd1498Szrj   linemap_assert (linemap_macro_expansion_map_p (map)
109538fd1498Szrj 		  && location >= MAP_START_LOCATION (map));
109638fd1498Szrj   linemap_assert (location >= RESERVED_LOCATION_COUNT);
109738fd1498Szrj 
109838fd1498Szrj   token_no = location - MAP_START_LOCATION (map);
109938fd1498Szrj   linemap_assert (token_no < MACRO_MAP_NUM_MACRO_TOKENS (map));
110038fd1498Szrj 
110138fd1498Szrj   location = MACRO_MAP_LOCATIONS (map)[2 * token_no + 1];
110238fd1498Szrj 
110338fd1498Szrj   return location;
110438fd1498Szrj }
110538fd1498Szrj 
110638fd1498Szrj /* If LOCATION is the locus of a token that is an argument of a
110738fd1498Szrj    function-like macro M and appears in the expansion of M, return the
110838fd1498Szrj    locus of that argument in the context of the caller of M.
110938fd1498Szrj 
111038fd1498Szrj    In other words, this returns the xI location presented in the
111138fd1498Szrj    comments of line_map_macro above.  */
111238fd1498Szrj source_location
linemap_macro_map_loc_unwind_toward_spelling(line_maps * set,const line_map_macro * map,source_location location)111338fd1498Szrj linemap_macro_map_loc_unwind_toward_spelling (line_maps *set,
111438fd1498Szrj 					      const line_map_macro* map,
111538fd1498Szrj 					      source_location location)
111638fd1498Szrj {
111738fd1498Szrj   unsigned token_no;
111838fd1498Szrj 
111938fd1498Szrj   if (IS_ADHOC_LOC (location))
112038fd1498Szrj     location = get_location_from_adhoc_loc (set, location);
112138fd1498Szrj 
112238fd1498Szrj   linemap_assert (linemap_macro_expansion_map_p (map)
112338fd1498Szrj 		  && location >= MAP_START_LOCATION (map));
112438fd1498Szrj   linemap_assert (location >= RESERVED_LOCATION_COUNT);
112538fd1498Szrj   linemap_assert (!IS_ADHOC_LOC (location));
112638fd1498Szrj 
112738fd1498Szrj   token_no = location - MAP_START_LOCATION (map);
112838fd1498Szrj   linemap_assert (token_no < MACRO_MAP_NUM_MACRO_TOKENS (map));
112938fd1498Szrj 
113038fd1498Szrj   location = MACRO_MAP_LOCATIONS (map)[2 * token_no];
113138fd1498Szrj 
113238fd1498Szrj   return location;
113338fd1498Szrj }
113438fd1498Szrj 
113538fd1498Szrj /* Return the source line number corresponding to source location
113638fd1498Szrj    LOCATION.  SET is the line map set LOCATION comes from.  If
113738fd1498Szrj    LOCATION is the source location of token that is part of the
113838fd1498Szrj    replacement-list of a macro expansion return the line number of the
113938fd1498Szrj    macro expansion point.  */
114038fd1498Szrj 
114138fd1498Szrj int
linemap_get_expansion_line(struct line_maps * set,source_location location)114238fd1498Szrj linemap_get_expansion_line (struct line_maps *set,
114338fd1498Szrj 			    source_location location)
114438fd1498Szrj {
114538fd1498Szrj   const line_map_ordinary *map = NULL;
114638fd1498Szrj 
114738fd1498Szrj   if (IS_ADHOC_LOC (location))
114838fd1498Szrj     location = set->location_adhoc_data_map.data[location
114938fd1498Szrj 						 & MAX_SOURCE_LOCATION].locus;
115038fd1498Szrj 
115138fd1498Szrj   if (location < RESERVED_LOCATION_COUNT)
115238fd1498Szrj     return 0;
115338fd1498Szrj 
115438fd1498Szrj   location =
115538fd1498Szrj     linemap_macro_loc_to_exp_point (set, location, &map);
115638fd1498Szrj 
115738fd1498Szrj   return SOURCE_LINE (map, location);
115838fd1498Szrj }
115938fd1498Szrj 
116038fd1498Szrj /* Return the path of the file corresponding to source code location
116138fd1498Szrj    LOCATION.
116238fd1498Szrj 
116338fd1498Szrj    If LOCATION is the source location of token that is part of the
116438fd1498Szrj    replacement-list of a macro expansion return the file path of the
116538fd1498Szrj    macro expansion point.
116638fd1498Szrj 
116738fd1498Szrj    SET is the line map set LOCATION comes from.  */
116838fd1498Szrj 
116938fd1498Szrj const char*
linemap_get_expansion_filename(struct line_maps * set,source_location location)117038fd1498Szrj linemap_get_expansion_filename (struct line_maps *set,
117138fd1498Szrj 				source_location location)
117238fd1498Szrj {
117338fd1498Szrj   const struct line_map_ordinary *map = NULL;
117438fd1498Szrj 
117538fd1498Szrj   if (IS_ADHOC_LOC (location))
117638fd1498Szrj     location = set->location_adhoc_data_map.data[location
117738fd1498Szrj 						 & MAX_SOURCE_LOCATION].locus;
117838fd1498Szrj 
117938fd1498Szrj   if (location < RESERVED_LOCATION_COUNT)
118038fd1498Szrj     return NULL;
118138fd1498Szrj 
118238fd1498Szrj   location =
118338fd1498Szrj     linemap_macro_loc_to_exp_point (set, location, &map);
118438fd1498Szrj 
118538fd1498Szrj   return LINEMAP_FILE (map);
118638fd1498Szrj }
118738fd1498Szrj 
118838fd1498Szrj /* Return the name of the macro associated to MACRO_MAP.  */
118938fd1498Szrj 
119038fd1498Szrj const char*
linemap_map_get_macro_name(const line_map_macro * macro_map)119138fd1498Szrj linemap_map_get_macro_name (const line_map_macro *macro_map)
119238fd1498Szrj {
119338fd1498Szrj   linemap_assert (macro_map && linemap_macro_expansion_map_p (macro_map));
119438fd1498Szrj   return (const char*) NODE_NAME (MACRO_MAP_MACRO (macro_map));
119538fd1498Szrj }
119638fd1498Szrj 
119738fd1498Szrj /* Return a positive value if LOCATION is the locus of a token that is
119838fd1498Szrj    located in a system header, O otherwise. It returns 1 if LOCATION
119938fd1498Szrj    is the locus of a token that is located in a system header, and 2
120038fd1498Szrj    if LOCATION is the locus of a token located in a C system header
120138fd1498Szrj    that therefore needs to be extern "C" protected in C++.
120238fd1498Szrj 
120338fd1498Szrj    Note that this function returns 1 if LOCATION belongs to a token
120438fd1498Szrj    that is part of a macro replacement-list defined in a system
120538fd1498Szrj    header, but expanded in a non-system file.  */
120638fd1498Szrj 
120738fd1498Szrj int
linemap_location_in_system_header_p(struct line_maps * set,source_location location)120838fd1498Szrj linemap_location_in_system_header_p (struct line_maps *set,
120938fd1498Szrj 				     source_location location)
121038fd1498Szrj {
121138fd1498Szrj   const struct line_map *map = NULL;
121238fd1498Szrj 
121338fd1498Szrj   if (IS_ADHOC_LOC (location))
121438fd1498Szrj     location = set->location_adhoc_data_map.data[location
121538fd1498Szrj 						 & MAX_SOURCE_LOCATION].locus;
121638fd1498Szrj 
121738fd1498Szrj   if (location < RESERVED_LOCATION_COUNT)
121838fd1498Szrj     return false;
121938fd1498Szrj 
122038fd1498Szrj   /* Let's look at where the token for LOCATION comes from.  */
122138fd1498Szrj   while (true)
122238fd1498Szrj     {
122338fd1498Szrj       map = linemap_lookup (set, location);
122438fd1498Szrj       if (map != NULL)
122538fd1498Szrj 	{
122638fd1498Szrj 	  if (!linemap_macro_expansion_map_p (map))
122738fd1498Szrj 	    /* It's a normal token.  */
122838fd1498Szrj 	    return LINEMAP_SYSP (linemap_check_ordinary (map));
122938fd1498Szrj 	  else
123038fd1498Szrj 	    {
123138fd1498Szrj 	      const line_map_macro *macro_map = linemap_check_macro (map);
123238fd1498Szrj 
123338fd1498Szrj 	      /* It's a token resulting from a macro expansion.  */
123438fd1498Szrj 	      source_location loc =
123538fd1498Szrj 		linemap_macro_map_loc_unwind_toward_spelling (set, macro_map, location);
123638fd1498Szrj 	      if (loc < RESERVED_LOCATION_COUNT)
123738fd1498Szrj 		/* This token might come from a built-in macro.  Let's
123838fd1498Szrj 		   look at where that macro got expanded.  */
123938fd1498Szrj 		location = linemap_macro_map_loc_to_exp_point (macro_map, location);
124038fd1498Szrj 	      else
124138fd1498Szrj 		location = loc;
124238fd1498Szrj 	    }
124338fd1498Szrj 	}
124438fd1498Szrj       else
124538fd1498Szrj 	break;
124638fd1498Szrj     }
124738fd1498Szrj   return false;
124838fd1498Szrj }
124938fd1498Szrj 
125038fd1498Szrj /* Return TRUE if LOCATION is a source code location of a token that is part of
125138fd1498Szrj    a macro expansion, FALSE otherwise.  */
125238fd1498Szrj 
125338fd1498Szrj bool
linemap_location_from_macro_expansion_p(const struct line_maps * set,source_location location)125438fd1498Szrj linemap_location_from_macro_expansion_p (const struct line_maps *set,
125538fd1498Szrj 					 source_location location)
125638fd1498Szrj {
125738fd1498Szrj   if (IS_ADHOC_LOC (location))
125838fd1498Szrj     location = set->location_adhoc_data_map.data[location
125938fd1498Szrj 						 & MAX_SOURCE_LOCATION].locus;
126038fd1498Szrj 
126138fd1498Szrj   linemap_assert (location <= MAX_SOURCE_LOCATION
126238fd1498Szrj 		  && (set->highest_location
126338fd1498Szrj 		      < LINEMAPS_MACRO_LOWEST_LOCATION (set)));
126438fd1498Szrj   if (set == NULL)
126538fd1498Szrj     return false;
126638fd1498Szrj   return (location > set->highest_location);
126738fd1498Szrj }
126838fd1498Szrj 
126938fd1498Szrj /* Given two virtual locations *LOC0 and *LOC1, return the first
127038fd1498Szrj    common macro map in their macro expansion histories.  Return NULL
127138fd1498Szrj    if no common macro was found.  *LOC0 (resp. *LOC1) is set to the
127238fd1498Szrj    virtual location of the token inside the resulting macro.  */
127338fd1498Szrj 
127438fd1498Szrj static const struct line_map*
first_map_in_common_1(struct line_maps * set,source_location * loc0,source_location * loc1)127538fd1498Szrj first_map_in_common_1 (struct line_maps *set,
127638fd1498Szrj 		       source_location *loc0,
127738fd1498Szrj 		       source_location *loc1)
127838fd1498Szrj {
127938fd1498Szrj   source_location l0 = *loc0, l1 = *loc1;
128038fd1498Szrj   const struct line_map *map0 = linemap_lookup (set, l0),
128138fd1498Szrj     *map1 = linemap_lookup (set, l1);
128238fd1498Szrj 
128338fd1498Szrj   while (linemap_macro_expansion_map_p (map0)
128438fd1498Szrj 	 && linemap_macro_expansion_map_p (map1)
128538fd1498Szrj 	 && (map0 != map1))
128638fd1498Szrj     {
128738fd1498Szrj       if (MAP_START_LOCATION (map0) < MAP_START_LOCATION (map1))
128838fd1498Szrj 	{
128938fd1498Szrj 	  l0 = linemap_macro_map_loc_to_exp_point (linemap_check_macro (map0),
129038fd1498Szrj 						   l0);
129138fd1498Szrj 	  map0 = linemap_lookup (set, l0);
129238fd1498Szrj 	}
129338fd1498Szrj       else
129438fd1498Szrj 	{
129538fd1498Szrj 	  l1 = linemap_macro_map_loc_to_exp_point (linemap_check_macro (map1),
129638fd1498Szrj 						   l1);
129738fd1498Szrj 	  map1 = linemap_lookup (set, l1);
129838fd1498Szrj 	}
129938fd1498Szrj     }
130038fd1498Szrj 
130138fd1498Szrj   if (map0 == map1)
130238fd1498Szrj     {
130338fd1498Szrj       *loc0 = l0;
130438fd1498Szrj       *loc1 = l1;
130538fd1498Szrj       return map0;
130638fd1498Szrj     }
130738fd1498Szrj   return NULL;
130838fd1498Szrj }
130938fd1498Szrj 
131038fd1498Szrj /* Given two virtual locations LOC0 and LOC1, return the first common
131138fd1498Szrj    macro map in their macro expansion histories.  Return NULL if no
131238fd1498Szrj    common macro was found.  *RES_LOC0 (resp. *RES_LOC1) is set to the
131338fd1498Szrj    virtual location of the token inside the resulting macro, upon
131438fd1498Szrj    return of a non-NULL result.  */
131538fd1498Szrj 
131638fd1498Szrj static const struct line_map*
first_map_in_common(struct line_maps * set,source_location loc0,source_location loc1,source_location * res_loc0,source_location * res_loc1)131738fd1498Szrj first_map_in_common (struct line_maps *set,
131838fd1498Szrj 		     source_location loc0,
131938fd1498Szrj 		     source_location loc1,
132038fd1498Szrj 		     source_location  *res_loc0,
132138fd1498Szrj 		     source_location  *res_loc1)
132238fd1498Szrj {
132338fd1498Szrj   *res_loc0 = loc0;
132438fd1498Szrj   *res_loc1 = loc1;
132538fd1498Szrj 
132638fd1498Szrj   return first_map_in_common_1 (set, res_loc0, res_loc1);
132738fd1498Szrj }
132838fd1498Szrj 
132938fd1498Szrj /* Return a positive value if PRE denotes the location of a token that
133038fd1498Szrj    comes before the token of POST, 0 if PRE denotes the location of
133138fd1498Szrj    the same token as the token for POST, and a negative value
133238fd1498Szrj    otherwise.  */
133338fd1498Szrj 
133438fd1498Szrj int
linemap_compare_locations(struct line_maps * set,source_location pre,source_location post)133538fd1498Szrj linemap_compare_locations (struct line_maps *set,
133638fd1498Szrj 			   source_location  pre,
133738fd1498Szrj 			   source_location post)
133838fd1498Szrj {
133938fd1498Szrj   bool pre_virtual_p, post_virtual_p;
134038fd1498Szrj   source_location l0 = pre, l1 = post;
134138fd1498Szrj 
134238fd1498Szrj   if (IS_ADHOC_LOC (l0))
134338fd1498Szrj     l0 = get_location_from_adhoc_loc (set, l0);
134438fd1498Szrj   if (IS_ADHOC_LOC (l1))
134538fd1498Szrj     l1 = get_location_from_adhoc_loc (set, l1);
134638fd1498Szrj 
134738fd1498Szrj   if (l0 == l1)
134838fd1498Szrj     return 0;
134938fd1498Szrj 
135038fd1498Szrj   if ((pre_virtual_p = linemap_location_from_macro_expansion_p (set, l0)))
135138fd1498Szrj     l0 = linemap_resolve_location (set, l0,
135238fd1498Szrj 				   LRK_MACRO_EXPANSION_POINT,
135338fd1498Szrj 				   NULL);
135438fd1498Szrj 
135538fd1498Szrj   if ((post_virtual_p = linemap_location_from_macro_expansion_p (set, l1)))
135638fd1498Szrj     l1 = linemap_resolve_location (set, l1,
135738fd1498Szrj 				   LRK_MACRO_EXPANSION_POINT,
135838fd1498Szrj 				   NULL);
135938fd1498Szrj 
136038fd1498Szrj   if (l0 == l1
136138fd1498Szrj       && pre_virtual_p
136238fd1498Szrj       && post_virtual_p)
136338fd1498Szrj     {
136438fd1498Szrj       /* So pre and post represent two tokens that are present in a
136538fd1498Szrj 	 same macro expansion.  Let's see if the token for pre was
136638fd1498Szrj 	 before the token for post in that expansion.  */
136738fd1498Szrj       unsigned i0, i1;
136838fd1498Szrj       const struct line_map *map =
136938fd1498Szrj 	first_map_in_common (set, pre, post, &l0, &l1);
137038fd1498Szrj 
137138fd1498Szrj       if (map == NULL)
137238fd1498Szrj 	/* This should not be possible.  */
137338fd1498Szrj 	abort ();
137438fd1498Szrj 
137538fd1498Szrj       i0 = l0 - MAP_START_LOCATION (map);
137638fd1498Szrj       i1 = l1 - MAP_START_LOCATION (map);
137738fd1498Szrj       return i1 - i0;
137838fd1498Szrj     }
137938fd1498Szrj 
138038fd1498Szrj   if (IS_ADHOC_LOC (l0))
138138fd1498Szrj     l0 = get_location_from_adhoc_loc (set, l0);
138238fd1498Szrj   if (IS_ADHOC_LOC (l1))
138338fd1498Szrj     l1 = get_location_from_adhoc_loc (set, l1);
138438fd1498Szrj 
138538fd1498Szrj   return l1 - l0;
138638fd1498Szrj }
138738fd1498Szrj 
138838fd1498Szrj /* Print an include trace, for e.g. the -H option of the preprocessor.  */
138938fd1498Szrj 
139038fd1498Szrj static void
trace_include(const struct line_maps * set,const line_map_ordinary * map)139138fd1498Szrj trace_include (const struct line_maps *set, const line_map_ordinary *map)
139238fd1498Szrj {
139338fd1498Szrj   unsigned int i = set->depth;
139438fd1498Szrj 
139538fd1498Szrj   while (--i)
139638fd1498Szrj     putc ('.', stderr);
139738fd1498Szrj 
139838fd1498Szrj   fprintf (stderr, " %s\n", ORDINARY_MAP_FILE_NAME (map));
139938fd1498Szrj }
140038fd1498Szrj 
140138fd1498Szrj /* Return the spelling location of the token wherever it comes from,
140238fd1498Szrj    whether part of a macro definition or not.
140338fd1498Szrj 
140438fd1498Szrj    This is a subroutine for linemap_resolve_location.  */
140538fd1498Szrj 
140638fd1498Szrj static source_location
linemap_macro_loc_to_spelling_point(struct line_maps * set,source_location location,const line_map_ordinary ** original_map)140738fd1498Szrj linemap_macro_loc_to_spelling_point (struct line_maps *set,
140838fd1498Szrj 				     source_location location,
140938fd1498Szrj 				     const line_map_ordinary **original_map)
141038fd1498Szrj {
141138fd1498Szrj   struct line_map *map;
141238fd1498Szrj   linemap_assert (set && location >= RESERVED_LOCATION_COUNT);
141338fd1498Szrj 
141438fd1498Szrj   while (true)
141538fd1498Szrj     {
141638fd1498Szrj       map = const_cast <line_map *> (linemap_lookup (set, location));
141738fd1498Szrj       if (!linemap_macro_expansion_map_p (map))
141838fd1498Szrj 	break;
141938fd1498Szrj 
142038fd1498Szrj       location
142138fd1498Szrj 	= linemap_macro_map_loc_unwind_toward_spelling
142238fd1498Szrj 	    (set, linemap_check_macro (map),
142338fd1498Szrj 	     location);
142438fd1498Szrj     }
142538fd1498Szrj 
142638fd1498Szrj   if (original_map)
142738fd1498Szrj     *original_map = linemap_check_ordinary (map);
142838fd1498Szrj   return location;
142938fd1498Szrj }
143038fd1498Szrj 
143138fd1498Szrj /* If LOCATION is the source location of a token that belongs to a
143238fd1498Szrj    macro replacement-list -- as part of a macro expansion -- then
143338fd1498Szrj    return the location of the token at the definition point of the
143438fd1498Szrj    macro.  Otherwise, return LOCATION.  SET is the set of maps
143538fd1498Szrj    location come from.  ORIGINAL_MAP is an output parm. If non NULL,
143638fd1498Szrj    the function sets *ORIGINAL_MAP to the ordinary (non-macro) map the
143738fd1498Szrj    returned location comes from.
143838fd1498Szrj 
143938fd1498Szrj    This is a subroutine of linemap_resolve_location.  */
144038fd1498Szrj 
144138fd1498Szrj static source_location
linemap_macro_loc_to_def_point(struct line_maps * set,source_location location,const line_map_ordinary ** original_map)144238fd1498Szrj linemap_macro_loc_to_def_point (struct line_maps *set,
144338fd1498Szrj 				source_location location,
144438fd1498Szrj 				const line_map_ordinary **original_map)
144538fd1498Szrj {
144638fd1498Szrj   struct line_map *map;
144738fd1498Szrj 
144838fd1498Szrj   linemap_assert (set && location >= RESERVED_LOCATION_COUNT);
144938fd1498Szrj 
145038fd1498Szrj   while (true)
145138fd1498Szrj     {
145238fd1498Szrj       source_location caret_loc;
145338fd1498Szrj       if (IS_ADHOC_LOC (location))
145438fd1498Szrj 	caret_loc = get_location_from_adhoc_loc (set, location);
145538fd1498Szrj       else
145638fd1498Szrj 	caret_loc = location;
145738fd1498Szrj 
145838fd1498Szrj       map = const_cast <line_map *> (linemap_lookup (set, caret_loc));
145938fd1498Szrj       if (!linemap_macro_expansion_map_p (map))
146038fd1498Szrj 	break;
146138fd1498Szrj 
146238fd1498Szrj       location =
146338fd1498Szrj 	linemap_macro_map_loc_to_def_point (linemap_check_macro (map),
146438fd1498Szrj 					    caret_loc);
146538fd1498Szrj     }
146638fd1498Szrj 
146738fd1498Szrj   if (original_map)
146838fd1498Szrj     *original_map = linemap_check_ordinary (map);
146938fd1498Szrj   return location;
147038fd1498Szrj }
147138fd1498Szrj 
147238fd1498Szrj /* If LOCATION is the source location of a token that belongs to a
147338fd1498Szrj    macro replacement-list -- at a macro expansion point -- then return
147438fd1498Szrj    the location of the topmost expansion point of the macro.  We say
147538fd1498Szrj    topmost because if we are in the context of a nested macro
147638fd1498Szrj    expansion, the function returns the source location of the first
147738fd1498Szrj    macro expansion that triggered the nested expansions.
147838fd1498Szrj 
147938fd1498Szrj    Otherwise, return LOCATION.  SET is the set of maps location come
148038fd1498Szrj    from.  ORIGINAL_MAP is an output parm. If non NULL, the function
148138fd1498Szrj    sets *ORIGINAL_MAP to the ordinary (non-macro) map the returned
148238fd1498Szrj    location comes from.
148338fd1498Szrj 
148438fd1498Szrj    This is a subroutine of linemap_resolve_location.  */
148538fd1498Szrj 
148638fd1498Szrj static source_location
linemap_macro_loc_to_exp_point(struct line_maps * set,source_location location,const line_map_ordinary ** original_map)148738fd1498Szrj linemap_macro_loc_to_exp_point (struct line_maps *set,
148838fd1498Szrj 				source_location location,
148938fd1498Szrj 				const line_map_ordinary **original_map)
149038fd1498Szrj {
149138fd1498Szrj   struct line_map *map;
149238fd1498Szrj 
149338fd1498Szrj   if (IS_ADHOC_LOC (location))
149438fd1498Szrj     location = set->location_adhoc_data_map.data[location
149538fd1498Szrj 						 & MAX_SOURCE_LOCATION].locus;
149638fd1498Szrj 
149738fd1498Szrj   linemap_assert (set && location >= RESERVED_LOCATION_COUNT);
149838fd1498Szrj 
149938fd1498Szrj   while (true)
150038fd1498Szrj     {
150138fd1498Szrj       map = const_cast <line_map *> (linemap_lookup (set, location));
150238fd1498Szrj       if (!linemap_macro_expansion_map_p (map))
150338fd1498Szrj 	break;
150438fd1498Szrj       location = linemap_macro_map_loc_to_exp_point (linemap_check_macro (map),
150538fd1498Szrj 						     location);
150638fd1498Szrj     }
150738fd1498Szrj 
150838fd1498Szrj   if (original_map)
150938fd1498Szrj     *original_map = linemap_check_ordinary (map);
151038fd1498Szrj   return location;
151138fd1498Szrj }
151238fd1498Szrj 
151338fd1498Szrj /* Resolve a virtual location into either a spelling location, an
151438fd1498Szrj    expansion point location or a token argument replacement point
151538fd1498Szrj    location.  Return the map that encodes the virtual location as well
151638fd1498Szrj    as the resolved location.
151738fd1498Szrj 
151838fd1498Szrj    If LOC is *NOT* the location of a token resulting from the
151938fd1498Szrj    expansion of a macro, then the parameter LRK (which stands for
152038fd1498Szrj    Location Resolution Kind) is ignored and the resulting location
152138fd1498Szrj    just equals the one given in argument.
152238fd1498Szrj 
152338fd1498Szrj    Now if LOC *IS* the location of a token resulting from the
152438fd1498Szrj    expansion of a macro, this is what happens.
152538fd1498Szrj 
152638fd1498Szrj    * If LRK is set to LRK_MACRO_EXPANSION_POINT
152738fd1498Szrj    -------------------------------
152838fd1498Szrj 
152938fd1498Szrj    The virtual location is resolved to the first macro expansion point
153038fd1498Szrj    that led to this macro expansion.
153138fd1498Szrj 
153238fd1498Szrj    * If LRK is set to LRK_SPELLING_LOCATION
153338fd1498Szrj    -------------------------------------
153438fd1498Szrj 
153538fd1498Szrj    The virtual location is resolved to the locus where the token has
153638fd1498Szrj    been spelled in the source.   This can follow through all the macro
153738fd1498Szrj    expansions that led to the token.
153838fd1498Szrj 
153938fd1498Szrj    * If LRK is set to LRK_MACRO_DEFINITION_LOCATION
154038fd1498Szrj    --------------------------------------
154138fd1498Szrj 
154238fd1498Szrj    The virtual location is resolved to the locus of the token in the
154338fd1498Szrj    context of the macro definition.
154438fd1498Szrj 
154538fd1498Szrj    If LOC is the locus of a token that is an argument of a
154638fd1498Szrj    function-like macro [replacing a parameter in the replacement list
154738fd1498Szrj    of the macro] the virtual location is resolved to the locus of the
154838fd1498Szrj    parameter that is replaced, in the context of the definition of the
154938fd1498Szrj    macro.
155038fd1498Szrj 
155138fd1498Szrj    If LOC is the locus of a token that is not an argument of a
155238fd1498Szrj    function-like macro, then the function behaves as if LRK was set to
155338fd1498Szrj    LRK_SPELLING_LOCATION.
155438fd1498Szrj 
155538fd1498Szrj    If MAP is not NULL, *MAP is set to the map encoding the
155638fd1498Szrj    returned location.  Note that if the returned location wasn't originally
155738fd1498Szrj    encoded by a map, then *MAP is set to NULL.  This can happen if LOC
155838fd1498Szrj    resolves to a location reserved for the client code, like
155938fd1498Szrj    UNKNOWN_LOCATION or BUILTINS_LOCATION in GCC.  */
156038fd1498Szrj 
156138fd1498Szrj source_location
linemap_resolve_location(struct line_maps * set,source_location loc,enum location_resolution_kind lrk,const line_map_ordinary ** map)156238fd1498Szrj linemap_resolve_location (struct line_maps *set,
156338fd1498Szrj 			  source_location loc,
156438fd1498Szrj 			  enum location_resolution_kind lrk,
156538fd1498Szrj 			  const line_map_ordinary **map)
156638fd1498Szrj {
156738fd1498Szrj   source_location locus = loc;
156838fd1498Szrj   if (IS_ADHOC_LOC (loc))
156938fd1498Szrj     locus = set->location_adhoc_data_map.data[loc & MAX_SOURCE_LOCATION].locus;
157038fd1498Szrj 
157138fd1498Szrj   if (locus < RESERVED_LOCATION_COUNT)
157238fd1498Szrj     {
157338fd1498Szrj       /* A reserved location wasn't encoded in a map.  Let's return a
157438fd1498Szrj 	 NULL map here, just like what linemap_ordinary_map_lookup
157538fd1498Szrj 	 does.  */
157638fd1498Szrj       if (map)
157738fd1498Szrj 	*map = NULL;
157838fd1498Szrj       return loc;
157938fd1498Szrj     }
158038fd1498Szrj 
158138fd1498Szrj   switch (lrk)
158238fd1498Szrj     {
158338fd1498Szrj     case LRK_MACRO_EXPANSION_POINT:
158438fd1498Szrj       loc = linemap_macro_loc_to_exp_point (set, loc, map);
158538fd1498Szrj       break;
158638fd1498Szrj     case LRK_SPELLING_LOCATION:
158738fd1498Szrj       loc = linemap_macro_loc_to_spelling_point (set, loc, map);
158838fd1498Szrj       break;
158938fd1498Szrj     case LRK_MACRO_DEFINITION_LOCATION:
159038fd1498Szrj       loc = linemap_macro_loc_to_def_point (set, loc, map);
159138fd1498Szrj       break;
159238fd1498Szrj     default:
159338fd1498Szrj       abort ();
159438fd1498Szrj     }
159538fd1498Szrj   return loc;
159638fd1498Szrj }
159738fd1498Szrj 
159838fd1498Szrj /* TRUE if LOCATION is a source code location of a token that is part of the
159938fd1498Szrj    definition of a macro, FALSE otherwise.  */
160038fd1498Szrj 
160138fd1498Szrj bool
linemap_location_from_macro_definition_p(struct line_maps * set,source_location loc)160238fd1498Szrj linemap_location_from_macro_definition_p (struct line_maps *set,
160338fd1498Szrj 					  source_location loc)
160438fd1498Szrj {
160538fd1498Szrj   if (IS_ADHOC_LOC (loc))
160638fd1498Szrj     loc = get_location_from_adhoc_loc (set, loc);
160738fd1498Szrj 
160838fd1498Szrj   if (!linemap_location_from_macro_expansion_p (set, loc))
160938fd1498Szrj     return false;
161038fd1498Szrj 
161138fd1498Szrj   while (true)
161238fd1498Szrj     {
161338fd1498Szrj       const struct line_map_macro *map
161438fd1498Szrj 	= linemap_check_macro (linemap_lookup (set, loc));
161538fd1498Szrj 
161638fd1498Szrj       source_location s_loc
161738fd1498Szrj 	= linemap_macro_map_loc_unwind_toward_spelling (set, map, loc);
161838fd1498Szrj       if (linemap_location_from_macro_expansion_p (set, s_loc))
161938fd1498Szrj 	loc = s_loc;
162038fd1498Szrj       else
162138fd1498Szrj 	{
162238fd1498Szrj 	  source_location def_loc
162338fd1498Szrj 	    = linemap_macro_map_loc_to_def_point (map, loc);
162438fd1498Szrj 	  return s_loc == def_loc;
162538fd1498Szrj 	}
162638fd1498Szrj     }
162738fd1498Szrj }
162838fd1498Szrj 
162938fd1498Szrj /*
163038fd1498Szrj    Suppose that LOC is the virtual location of a token T coming from
163138fd1498Szrj    the expansion of a macro M.  This function then steps up to get the
163238fd1498Szrj    location L of the point where M got expanded.  If L is a spelling
163338fd1498Szrj    location inside a macro expansion M', then this function returns
163438fd1498Szrj    the locus of the point where M' was expanded.  Said otherwise, this
163538fd1498Szrj    function returns the location of T in the context that triggered
163638fd1498Szrj    the expansion of M.
163738fd1498Szrj 
163838fd1498Szrj    *LOC_MAP must be set to the map of LOC.  This function then sets it
163938fd1498Szrj    to the map of the returned location.  */
164038fd1498Szrj 
164138fd1498Szrj source_location
linemap_unwind_toward_expansion(struct line_maps * set,source_location loc,const struct line_map ** map)164238fd1498Szrj linemap_unwind_toward_expansion (struct line_maps *set,
164338fd1498Szrj 				 source_location loc,
164438fd1498Szrj 				 const struct line_map **map)
164538fd1498Szrj {
164638fd1498Szrj   source_location resolved_location;
164738fd1498Szrj   const line_map_macro *macro_map = linemap_check_macro (*map);
164838fd1498Szrj   const struct line_map *resolved_map;
164938fd1498Szrj 
165038fd1498Szrj   if (IS_ADHOC_LOC (loc))
165138fd1498Szrj     loc = set->location_adhoc_data_map.data[loc & MAX_SOURCE_LOCATION].locus;
165238fd1498Szrj 
165338fd1498Szrj   resolved_location =
165438fd1498Szrj     linemap_macro_map_loc_unwind_toward_spelling (set, macro_map, loc);
165538fd1498Szrj   resolved_map = linemap_lookup (set, resolved_location);
165638fd1498Szrj 
165738fd1498Szrj   if (!linemap_macro_expansion_map_p (resolved_map))
165838fd1498Szrj     {
165938fd1498Szrj       resolved_location = linemap_macro_map_loc_to_exp_point (macro_map, loc);
166038fd1498Szrj       resolved_map = linemap_lookup (set, resolved_location);
166138fd1498Szrj     }
166238fd1498Szrj 
166338fd1498Szrj   *map = resolved_map;
166438fd1498Szrj   return resolved_location;
166538fd1498Szrj }
166638fd1498Szrj 
166738fd1498Szrj /* If LOC is the virtual location of a token coming from the expansion
166838fd1498Szrj    of a macro M and if its spelling location is reserved (e.g, a
166938fd1498Szrj    location for a built-in token), then this function unwinds (using
167038fd1498Szrj    linemap_unwind_toward_expansion) the location until a location that
167138fd1498Szrj    is not reserved and is not in a system header is reached.  In other
167238fd1498Szrj    words, this unwinds the reserved location until a location that is
167338fd1498Szrj    in real source code is reached.
167438fd1498Szrj 
167538fd1498Szrj    Otherwise, if the spelling location for LOC is not reserved or if
167638fd1498Szrj    LOC doesn't come from the expansion of a macro, the function
167738fd1498Szrj    returns LOC as is and *MAP is not touched.
167838fd1498Szrj 
167938fd1498Szrj    *MAP is set to the map of the returned location if the later is
168038fd1498Szrj    different from LOC.  */
168138fd1498Szrj source_location
linemap_unwind_to_first_non_reserved_loc(struct line_maps * set,source_location loc,const struct line_map ** map)168238fd1498Szrj linemap_unwind_to_first_non_reserved_loc (struct line_maps *set,
168338fd1498Szrj 					  source_location loc,
168438fd1498Szrj 					  const struct line_map **map)
168538fd1498Szrj {
168638fd1498Szrj   source_location resolved_loc;
168738fd1498Szrj   const struct line_map *map0 = NULL;
168838fd1498Szrj   const line_map_ordinary *map1 = NULL;
168938fd1498Szrj 
169038fd1498Szrj   if (IS_ADHOC_LOC (loc))
169138fd1498Szrj     loc = set->location_adhoc_data_map.data[loc & MAX_SOURCE_LOCATION].locus;
169238fd1498Szrj 
169338fd1498Szrj   map0 = linemap_lookup (set, loc);
169438fd1498Szrj   if (!linemap_macro_expansion_map_p (map0))
169538fd1498Szrj     return loc;
169638fd1498Szrj 
169738fd1498Szrj   resolved_loc = linemap_resolve_location (set, loc,
169838fd1498Szrj 					   LRK_SPELLING_LOCATION,
169938fd1498Szrj 					   &map1);
170038fd1498Szrj 
170138fd1498Szrj   if (resolved_loc >= RESERVED_LOCATION_COUNT
170238fd1498Szrj       && !LINEMAP_SYSP (map1))
170338fd1498Szrj     return loc;
170438fd1498Szrj 
170538fd1498Szrj   while (linemap_macro_expansion_map_p (map0)
170638fd1498Szrj 	 && (resolved_loc < RESERVED_LOCATION_COUNT
170738fd1498Szrj 	     || LINEMAP_SYSP (map1)))
170838fd1498Szrj     {
170938fd1498Szrj       loc = linemap_unwind_toward_expansion (set, loc, &map0);
171038fd1498Szrj       resolved_loc = linemap_resolve_location (set, loc,
171138fd1498Szrj 					       LRK_SPELLING_LOCATION,
171238fd1498Szrj 					       &map1);
171338fd1498Szrj     }
171438fd1498Szrj 
171538fd1498Szrj   if (map != NULL)
171638fd1498Szrj     *map = map0;
171738fd1498Szrj   return loc;
171838fd1498Szrj }
171938fd1498Szrj 
172038fd1498Szrj /* Expand source code location LOC and return a user readable source
172138fd1498Szrj    code location.  LOC must be a spelling (non-virtual) location.  If
172238fd1498Szrj    it's a location < RESERVED_LOCATION_COUNT a zeroed expanded source
172338fd1498Szrj    location is returned.  */
172438fd1498Szrj 
172538fd1498Szrj expanded_location
linemap_expand_location(struct line_maps * set,const struct line_map * map,source_location loc)172638fd1498Szrj linemap_expand_location (struct line_maps *set,
172738fd1498Szrj 			 const struct line_map *map,
172838fd1498Szrj 			 source_location loc)
172938fd1498Szrj 
173038fd1498Szrj {
173138fd1498Szrj   expanded_location xloc;
173238fd1498Szrj 
173338fd1498Szrj   memset (&xloc, 0, sizeof (xloc));
173438fd1498Szrj   if (IS_ADHOC_LOC (loc))
173538fd1498Szrj     {
173638fd1498Szrj       xloc.data
173738fd1498Szrj 	= set->location_adhoc_data_map.data[loc & MAX_SOURCE_LOCATION].data;
173838fd1498Szrj       loc = set->location_adhoc_data_map.data[loc & MAX_SOURCE_LOCATION].locus;
173938fd1498Szrj     }
174038fd1498Szrj 
174138fd1498Szrj   if (loc < RESERVED_LOCATION_COUNT)
174238fd1498Szrj     /* The location for this token wasn't generated from a line map.
174338fd1498Szrj        It was probably a location for a builtin token, chosen by some
174438fd1498Szrj        client code.  Let's not try to expand the location in that
174538fd1498Szrj        case.  */;
174638fd1498Szrj   else if (map == NULL)
174738fd1498Szrj     /* We shouldn't be getting a NULL map with a location that is not
174838fd1498Szrj        reserved by the client code.  */
174938fd1498Szrj     abort ();
175038fd1498Szrj   else
175138fd1498Szrj     {
175238fd1498Szrj       /* MAP must be an ordinary map and LOC must be non-virtual,
175338fd1498Szrj 	 encoded into this map, obviously; the accessors used on MAP
175438fd1498Szrj 	 below ensure it is ordinary.  Let's just assert the
175538fd1498Szrj 	 non-virtualness of LOC here.  */
175638fd1498Szrj       if (linemap_location_from_macro_expansion_p (set, loc))
175738fd1498Szrj 	abort ();
175838fd1498Szrj 
175938fd1498Szrj       const line_map_ordinary *ord_map = linemap_check_ordinary (map);
176038fd1498Szrj 
176138fd1498Szrj       xloc.file = LINEMAP_FILE (ord_map);
176238fd1498Szrj       xloc.line = SOURCE_LINE (ord_map, loc);
176338fd1498Szrj       xloc.column = SOURCE_COLUMN (ord_map, loc);
176438fd1498Szrj       xloc.sysp = LINEMAP_SYSP (ord_map) != 0;
176538fd1498Szrj     }
176638fd1498Szrj 
176738fd1498Szrj   return xloc;
176838fd1498Szrj }
176938fd1498Szrj 
177038fd1498Szrj 
177138fd1498Szrj /* Dump line map at index IX in line table SET to STREAM.  If STREAM
177238fd1498Szrj    is NULL, use stderr.  IS_MACRO is true if the caller wants to
177338fd1498Szrj    dump a macro map, false otherwise.  */
177438fd1498Szrj 
177538fd1498Szrj void
linemap_dump(FILE * stream,struct line_maps * set,unsigned ix,bool is_macro)177638fd1498Szrj linemap_dump (FILE *stream, struct line_maps *set, unsigned ix, bool is_macro)
177738fd1498Szrj {
177838fd1498Szrj   const char *lc_reasons_v[LC_ENTER_MACRO + 1]
177938fd1498Szrj       = { "LC_ENTER", "LC_LEAVE", "LC_RENAME", "LC_RENAME_VERBATIM",
178038fd1498Szrj 	  "LC_ENTER_MACRO" };
178138fd1498Szrj   const char *reason;
178238fd1498Szrj   const line_map *map;
178338fd1498Szrj 
178438fd1498Szrj   if (stream == NULL)
178538fd1498Szrj     stream = stderr;
178638fd1498Szrj 
178738fd1498Szrj   if (!is_macro)
178838fd1498Szrj     map = LINEMAPS_ORDINARY_MAP_AT (set, ix);
178938fd1498Szrj   else
179038fd1498Szrj     map = LINEMAPS_MACRO_MAP_AT (set, ix);
179138fd1498Szrj 
179238fd1498Szrj   reason = (map->reason <= LC_ENTER_MACRO) ? lc_reasons_v[map->reason] : "???";
179338fd1498Szrj 
179438fd1498Szrj   fprintf (stream, "Map #%u [%p] - LOC: %u - REASON: %s - SYSP: %s\n",
179538fd1498Szrj 	   ix, (void *) map, map->start_location, reason,
179638fd1498Szrj 	   ((!is_macro
179738fd1498Szrj 	     && ORDINARY_MAP_IN_SYSTEM_HEADER_P (linemap_check_ordinary (map)))
179838fd1498Szrj 	    ? "yes" : "no"));
179938fd1498Szrj   if (!is_macro)
180038fd1498Szrj     {
180138fd1498Szrj       const line_map_ordinary *ord_map = linemap_check_ordinary (map);
180238fd1498Szrj       unsigned includer_ix;
180338fd1498Szrj       const line_map_ordinary *includer_map;
180438fd1498Szrj 
180538fd1498Szrj       includer_ix = ORDINARY_MAP_INCLUDER_FILE_INDEX (ord_map);
180638fd1498Szrj       includer_map = includer_ix < LINEMAPS_ORDINARY_USED (set)
180738fd1498Szrj 		     ? LINEMAPS_ORDINARY_MAP_AT (set, includer_ix)
180838fd1498Szrj 		     : NULL;
180938fd1498Szrj 
181038fd1498Szrj       fprintf (stream, "File: %s:%d\n", ORDINARY_MAP_FILE_NAME (ord_map),
181138fd1498Szrj 	       ORDINARY_MAP_STARTING_LINE_NUMBER (ord_map));
181238fd1498Szrj       fprintf (stream, "Included from: [%d] %s\n", includer_ix,
181338fd1498Szrj 	       includer_map ? ORDINARY_MAP_FILE_NAME (includer_map) : "None");
181438fd1498Szrj     }
181538fd1498Szrj   else
181638fd1498Szrj     {
181738fd1498Szrj       const line_map_macro *macro_map = linemap_check_macro (map);
181838fd1498Szrj       fprintf (stream, "Macro: %s (%u tokens)\n",
181938fd1498Szrj 	       linemap_map_get_macro_name (macro_map),
182038fd1498Szrj 	       MACRO_MAP_NUM_MACRO_TOKENS (macro_map));
182138fd1498Szrj     }
182238fd1498Szrj 
182338fd1498Szrj   fprintf (stream, "\n");
182438fd1498Szrj }
182538fd1498Szrj 
182638fd1498Szrj 
182738fd1498Szrj /* Dump debugging information about source location LOC into the file
182838fd1498Szrj    stream STREAM. SET is the line map set LOC comes from.  */
182938fd1498Szrj 
183038fd1498Szrj void
linemap_dump_location(struct line_maps * set,source_location loc,FILE * stream)183138fd1498Szrj linemap_dump_location (struct line_maps *set,
183238fd1498Szrj 		       source_location loc,
183338fd1498Szrj 		       FILE *stream)
183438fd1498Szrj {
183538fd1498Szrj   const line_map_ordinary *map;
183638fd1498Szrj   source_location location;
183738fd1498Szrj   const char *path = "", *from = "";
183838fd1498Szrj   int l = -1, c = -1, s = -1, e = -1;
183938fd1498Szrj 
184038fd1498Szrj   if (IS_ADHOC_LOC (loc))
184138fd1498Szrj     loc = set->location_adhoc_data_map.data[loc & MAX_SOURCE_LOCATION].locus;
184238fd1498Szrj 
184338fd1498Szrj   if (loc == 0)
184438fd1498Szrj     return;
184538fd1498Szrj 
184638fd1498Szrj   location =
184738fd1498Szrj     linemap_resolve_location (set, loc, LRK_MACRO_DEFINITION_LOCATION, &map);
184838fd1498Szrj 
184938fd1498Szrj   if (map == NULL)
185038fd1498Szrj     /* Only reserved locations can be tolerated in this case.  */
185138fd1498Szrj     linemap_assert (location < RESERVED_LOCATION_COUNT);
185238fd1498Szrj   else
185338fd1498Szrj     {
185438fd1498Szrj       path = LINEMAP_FILE (map);
185538fd1498Szrj       l = SOURCE_LINE (map, location);
185638fd1498Szrj       c = SOURCE_COLUMN (map, location);
185738fd1498Szrj       s = LINEMAP_SYSP (map) != 0;
185838fd1498Szrj       e = location != loc;
185938fd1498Szrj       if (e)
186038fd1498Szrj 	from = "N/A";
186138fd1498Szrj       else
186238fd1498Szrj 	from = (INCLUDED_FROM (set, map))
186338fd1498Szrj 	  ? LINEMAP_FILE (INCLUDED_FROM (set, map))
186438fd1498Szrj 	  : "<NULL>";
186538fd1498Szrj     }
186638fd1498Szrj 
186738fd1498Szrj   /* P: path, L: line, C: column, S: in-system-header, M: map address,
186838fd1498Szrj      E: macro expansion?, LOC: original location, R: resolved location   */
186938fd1498Szrj   fprintf (stream, "{P:%s;F:%s;L:%d;C:%d;S:%d;M:%p;E:%d,LOC:%d,R:%d}",
187038fd1498Szrj 	   path, from, l, c, s, (void*)map, e, loc, location);
187138fd1498Szrj }
187238fd1498Szrj 
187338fd1498Szrj /* Return the highest location emitted for a given file for which
187438fd1498Szrj    there is a line map in SET.  FILE_NAME is the file name to
187538fd1498Szrj    consider.  If the function returns TRUE, *LOC is set to the highest
187638fd1498Szrj    location emitted for that file.  */
187738fd1498Szrj 
187838fd1498Szrj bool
linemap_get_file_highest_location(struct line_maps * set,const char * file_name,source_location * loc)187938fd1498Szrj linemap_get_file_highest_location (struct line_maps *set,
188038fd1498Szrj 				   const char *file_name,
188138fd1498Szrj 				   source_location *loc)
188238fd1498Szrj {
188338fd1498Szrj   /* If the set is empty or no ordinary map has been created then
188438fd1498Szrj      there is no file to look for ...  */
188538fd1498Szrj   if (set == NULL || set->info_ordinary.used == 0)
188638fd1498Szrj     return false;
188738fd1498Szrj 
188838fd1498Szrj   /* Now look for the last ordinary map created for FILE_NAME.  */
188938fd1498Szrj   int i;
189038fd1498Szrj   for (i = set->info_ordinary.used - 1; i >= 0; --i)
189138fd1498Szrj     {
189238fd1498Szrj       const char *fname = set->info_ordinary.maps[i].to_file;
189338fd1498Szrj       if (fname && !filename_cmp (fname, file_name))
189438fd1498Szrj 	break;
189538fd1498Szrj     }
189638fd1498Szrj 
189738fd1498Szrj   if (i < 0)
189838fd1498Szrj     return false;
189938fd1498Szrj 
190038fd1498Szrj   /* The highest location for a given map is either the starting
190138fd1498Szrj      location of the next map minus one, or -- if the map is the
190238fd1498Szrj      latest one -- the highest location of the set.  */
190338fd1498Szrj   source_location result;
190438fd1498Szrj   if (i == (int) set->info_ordinary.used - 1)
190538fd1498Szrj     result = set->highest_location;
190638fd1498Szrj   else
190738fd1498Szrj     result = set->info_ordinary.maps[i + 1].start_location - 1;
190838fd1498Szrj 
190938fd1498Szrj   *loc = result;
191038fd1498Szrj   return true;
191138fd1498Szrj }
191238fd1498Szrj 
191338fd1498Szrj /* Compute and return statistics about the memory consumption of some
191438fd1498Szrj    parts of the line table SET.  */
191538fd1498Szrj 
191638fd1498Szrj void
linemap_get_statistics(struct line_maps * set,struct linemap_stats * s)191738fd1498Szrj linemap_get_statistics (struct line_maps *set,
191838fd1498Szrj 			struct linemap_stats *s)
191938fd1498Szrj {
192038fd1498Szrj   long ordinary_maps_allocated_size, ordinary_maps_used_size,
192138fd1498Szrj     macro_maps_allocated_size, macro_maps_used_size,
192238fd1498Szrj     macro_maps_locations_size = 0, duplicated_macro_maps_locations_size = 0;
192338fd1498Szrj 
192438fd1498Szrj   const line_map_macro *cur_map;
192538fd1498Szrj 
192638fd1498Szrj   ordinary_maps_allocated_size =
192738fd1498Szrj     LINEMAPS_ORDINARY_ALLOCATED (set) * sizeof (struct line_map_ordinary);
192838fd1498Szrj 
192938fd1498Szrj   ordinary_maps_used_size =
193038fd1498Szrj     LINEMAPS_ORDINARY_USED (set) * sizeof (struct line_map_ordinary);
193138fd1498Szrj 
193238fd1498Szrj   macro_maps_allocated_size =
193338fd1498Szrj     LINEMAPS_MACRO_ALLOCATED (set) * sizeof (struct line_map_macro);
193438fd1498Szrj 
193538fd1498Szrj   for (cur_map = LINEMAPS_MACRO_MAPS (set);
193638fd1498Szrj        cur_map && cur_map <= LINEMAPS_LAST_MACRO_MAP (set);
193738fd1498Szrj        ++cur_map)
193838fd1498Szrj     {
193938fd1498Szrj       unsigned i;
194038fd1498Szrj 
194138fd1498Szrj       linemap_assert (linemap_macro_expansion_map_p (cur_map));
194238fd1498Szrj 
194338fd1498Szrj       macro_maps_locations_size +=
194438fd1498Szrj 	2 * MACRO_MAP_NUM_MACRO_TOKENS (cur_map) * sizeof (source_location);
194538fd1498Szrj 
194638fd1498Szrj       for (i = 0; i < 2 * MACRO_MAP_NUM_MACRO_TOKENS (cur_map); i += 2)
194738fd1498Szrj 	{
194838fd1498Szrj 	  if (MACRO_MAP_LOCATIONS (cur_map)[i] ==
194938fd1498Szrj 	      MACRO_MAP_LOCATIONS (cur_map)[i + 1])
195038fd1498Szrj 	    duplicated_macro_maps_locations_size +=
195138fd1498Szrj 	      sizeof (source_location);
195238fd1498Szrj 	}
195338fd1498Szrj     }
195438fd1498Szrj 
195538fd1498Szrj   macro_maps_used_size =
195638fd1498Szrj     LINEMAPS_MACRO_USED (set) * sizeof (struct line_map_macro);
195738fd1498Szrj 
195838fd1498Szrj   s->num_ordinary_maps_allocated = LINEMAPS_ORDINARY_ALLOCATED (set);
195938fd1498Szrj   s->num_ordinary_maps_used = LINEMAPS_ORDINARY_USED (set);
196038fd1498Szrj   s->ordinary_maps_allocated_size = ordinary_maps_allocated_size;
196138fd1498Szrj   s->ordinary_maps_used_size = ordinary_maps_used_size;
196238fd1498Szrj   s->num_expanded_macros = num_expanded_macros_counter;
196338fd1498Szrj   s->num_macro_tokens = num_macro_tokens_counter;
196438fd1498Szrj   s->num_macro_maps_used = LINEMAPS_MACRO_USED (set);
196538fd1498Szrj   s->macro_maps_allocated_size = macro_maps_allocated_size;
196638fd1498Szrj   s->macro_maps_locations_size = macro_maps_locations_size;
196738fd1498Szrj   s->macro_maps_used_size = macro_maps_used_size;
196838fd1498Szrj   s->duplicated_macro_maps_locations_size =
196938fd1498Szrj     duplicated_macro_maps_locations_size;
197038fd1498Szrj   s->adhoc_table_size = (set->location_adhoc_data_map.allocated
197138fd1498Szrj 			 * sizeof (struct location_adhoc_data));
197238fd1498Szrj   s->adhoc_table_entries_used = set->location_adhoc_data_map.curr_loc;
197338fd1498Szrj }
197438fd1498Szrj 
197538fd1498Szrj 
197638fd1498Szrj /* Dump line table SET to STREAM.  If STREAM is NULL, stderr is used.
197738fd1498Szrj    NUM_ORDINARY specifies how many ordinary maps to dump.  NUM_MACRO
197838fd1498Szrj    specifies how many macro maps to dump.  */
197938fd1498Szrj 
198038fd1498Szrj void
line_table_dump(FILE * stream,struct line_maps * set,unsigned int num_ordinary,unsigned int num_macro)198138fd1498Szrj line_table_dump (FILE *stream, struct line_maps *set, unsigned int num_ordinary,
198238fd1498Szrj 		 unsigned int num_macro)
198338fd1498Szrj {
198438fd1498Szrj   unsigned int i;
198538fd1498Szrj 
198638fd1498Szrj   if (set == NULL)
198738fd1498Szrj     return;
198838fd1498Szrj 
198938fd1498Szrj   if (stream == NULL)
199038fd1498Szrj     stream = stderr;
199138fd1498Szrj 
199238fd1498Szrj   fprintf (stream, "# of ordinary maps:  %d\n", LINEMAPS_ORDINARY_USED (set));
199338fd1498Szrj   fprintf (stream, "# of macro maps:     %d\n", LINEMAPS_MACRO_USED (set));
199438fd1498Szrj   fprintf (stream, "Include stack depth: %d\n", set->depth);
199538fd1498Szrj   fprintf (stream, "Highest location:    %u\n", set->highest_location);
199638fd1498Szrj 
199738fd1498Szrj   if (num_ordinary)
199838fd1498Szrj     {
199938fd1498Szrj       fprintf (stream, "\nOrdinary line maps\n");
200038fd1498Szrj       for (i = 0; i < num_ordinary && i < LINEMAPS_ORDINARY_USED (set); i++)
200138fd1498Szrj 	linemap_dump (stream, set, i, false);
200238fd1498Szrj       fprintf (stream, "\n");
200338fd1498Szrj     }
200438fd1498Szrj 
200538fd1498Szrj   if (num_macro)
200638fd1498Szrj     {
200738fd1498Szrj       fprintf (stream, "\nMacro line maps\n");
200838fd1498Szrj       for (i = 0; i < num_macro && i < LINEMAPS_MACRO_USED (set); i++)
200938fd1498Szrj 	linemap_dump (stream, set, i, true);
201038fd1498Szrj       fprintf (stream, "\n");
201138fd1498Szrj     }
201238fd1498Szrj }
201338fd1498Szrj 
201438fd1498Szrj /* class rich_location.  */
201538fd1498Szrj 
201638fd1498Szrj /* Construct a rich_location with location LOC as its initial range.  */
201738fd1498Szrj 
rich_location(line_maps * set,source_location loc)201838fd1498Szrj rich_location::rich_location (line_maps *set, source_location loc) :
201938fd1498Szrj   m_line_table (set),
202038fd1498Szrj   m_ranges (),
202138fd1498Szrj   m_column_override (0),
202238fd1498Szrj   m_have_expanded_location (false),
202338fd1498Szrj   m_fixit_hints (),
202438fd1498Szrj   m_seen_impossible_fixit (false),
202538fd1498Szrj   m_fixits_cannot_be_auto_applied (false)
202638fd1498Szrj {
202738fd1498Szrj   add_range (loc, true);
202838fd1498Szrj }
202938fd1498Szrj 
203038fd1498Szrj /* The destructor for class rich_location.  */
203138fd1498Szrj 
~rich_location()203238fd1498Szrj rich_location::~rich_location ()
203338fd1498Szrj {
203438fd1498Szrj   for (unsigned int i = 0; i < m_fixit_hints.count (); i++)
203538fd1498Szrj     delete get_fixit_hint (i);
203638fd1498Szrj }
203738fd1498Szrj 
203838fd1498Szrj /* Get location IDX within this rich_location.  */
203938fd1498Szrj 
204038fd1498Szrj source_location
get_loc(unsigned int idx)204138fd1498Szrj rich_location::get_loc (unsigned int idx) const
204238fd1498Szrj {
204338fd1498Szrj   const location_range *locrange = get_range (idx);
204438fd1498Szrj   return locrange->m_loc;
204538fd1498Szrj }
204638fd1498Szrj 
204738fd1498Szrj /* Get range IDX within this rich_location.  */
204838fd1498Szrj 
204938fd1498Szrj const location_range *
get_range(unsigned int idx)205038fd1498Szrj rich_location::get_range (unsigned int idx) const
205138fd1498Szrj {
205238fd1498Szrj   return &m_ranges[idx];
205338fd1498Szrj }
205438fd1498Szrj 
205538fd1498Szrj /* Mutable access to range IDX within this rich_location.  */
205638fd1498Szrj 
205738fd1498Szrj location_range *
get_range(unsigned int idx)205838fd1498Szrj rich_location::get_range (unsigned int idx)
205938fd1498Szrj {
206038fd1498Szrj   return &m_ranges[idx];
206138fd1498Szrj }
206238fd1498Szrj 
206338fd1498Szrj /* Expand location IDX within this rich_location.  */
206438fd1498Szrj /* Get an expanded_location for this rich_location's primary
206538fd1498Szrj    location.  */
206638fd1498Szrj 
206738fd1498Szrj expanded_location
get_expanded_location(unsigned int idx)206838fd1498Szrj rich_location::get_expanded_location (unsigned int idx)
206938fd1498Szrj {
207038fd1498Szrj   if (idx == 0)
207138fd1498Szrj    {
207238fd1498Szrj      /* Cache the expansion of the primary location.  */
207338fd1498Szrj      if (!m_have_expanded_location)
207438fd1498Szrj        {
207538fd1498Szrj 	  m_expanded_location
207638fd1498Szrj 	    = linemap_client_expand_location_to_spelling_point
207738fd1498Szrj 		(get_loc (0), LOCATION_ASPECT_CARET);
207838fd1498Szrj 	  if (m_column_override)
207938fd1498Szrj 	    m_expanded_location.column = m_column_override;
208038fd1498Szrj 	  m_have_expanded_location = true;
208138fd1498Szrj        }
208238fd1498Szrj 
208338fd1498Szrj      return m_expanded_location;
208438fd1498Szrj    }
208538fd1498Szrj   else
208638fd1498Szrj     return linemap_client_expand_location_to_spelling_point
208738fd1498Szrj 	     (get_loc (idx), LOCATION_ASPECT_CARET);
208838fd1498Szrj }
208938fd1498Szrj 
209038fd1498Szrj /* Set the column of the primary location, with 0 meaning
209138fd1498Szrj    "don't override it".  */
209238fd1498Szrj 
209338fd1498Szrj void
override_column(int column)209438fd1498Szrj rich_location::override_column (int column)
209538fd1498Szrj {
209638fd1498Szrj   m_column_override = column;
209738fd1498Szrj   m_have_expanded_location = false;
209838fd1498Szrj }
209938fd1498Szrj 
210038fd1498Szrj /* Add the given range.  */
210138fd1498Szrj 
210238fd1498Szrj void
add_range(source_location loc,bool show_caret_p)210338fd1498Szrj rich_location::add_range (source_location loc, bool show_caret_p)
210438fd1498Szrj {
210538fd1498Szrj   location_range range;
210638fd1498Szrj   range.m_loc = loc;
210738fd1498Szrj   range.m_show_caret_p = show_caret_p;
210838fd1498Szrj   m_ranges.push (range);
210938fd1498Szrj }
211038fd1498Szrj 
211138fd1498Szrj /* Add or overwrite the location given by IDX, setting its location to LOC,
211238fd1498Szrj    and setting its "should my caret be printed" flag to SHOW_CARET_P.
211338fd1498Szrj 
211438fd1498Szrj    It must either overwrite an existing location, or add one *exactly* on
211538fd1498Szrj    the end of the array.
211638fd1498Szrj 
211738fd1498Szrj    This is primarily for use by gcc when implementing diagnostic format
211838fd1498Szrj    decoders e.g.
211938fd1498Szrj    - the "+" in the C/C++ frontends, for handling format codes like "%q+D"
212038fd1498Szrj      (which writes the source location of a tree back into location 0 of
212138fd1498Szrj      the rich_location), and
212238fd1498Szrj    - the "%C" and "%L" format codes in the Fortran frontend.  */
212338fd1498Szrj 
212438fd1498Szrj void
set_range(line_maps *,unsigned int idx,source_location loc,bool show_caret_p)212538fd1498Szrj rich_location::set_range (line_maps * /*set*/, unsigned int idx,
212638fd1498Szrj 			  source_location loc, bool show_caret_p)
212738fd1498Szrj {
212838fd1498Szrj   /* We can either overwrite an existing range, or add one exactly
212938fd1498Szrj      on the end of the array.  */
213038fd1498Szrj   linemap_assert (idx <= m_ranges.count ());
213138fd1498Szrj 
213238fd1498Szrj   if (idx == m_ranges.count ())
213338fd1498Szrj     add_range (loc,  show_caret_p);
213438fd1498Szrj   else
213538fd1498Szrj     {
213638fd1498Szrj       location_range *locrange = get_range (idx);
213738fd1498Szrj       locrange->m_loc = loc;
213838fd1498Szrj       locrange->m_show_caret_p = show_caret_p;
213938fd1498Szrj     }
214038fd1498Szrj 
214138fd1498Szrj   if (idx == 0)
214238fd1498Szrj     /* Mark any cached value here as dirty.  */
214338fd1498Szrj     m_have_expanded_location = false;
214438fd1498Szrj }
214538fd1498Szrj 
214638fd1498Szrj /* Methods for adding insertion fix-it hints.  */
214738fd1498Szrj 
214838fd1498Szrj /* Add a fixit-hint, suggesting insertion of NEW_CONTENT
214938fd1498Szrj    immediately before the primary range's start location.  */
215038fd1498Szrj 
215138fd1498Szrj void
add_fixit_insert_before(const char * new_content)215238fd1498Szrj rich_location::add_fixit_insert_before (const char *new_content)
215338fd1498Szrj {
215438fd1498Szrj   add_fixit_insert_before (get_loc (), new_content);
215538fd1498Szrj }
215638fd1498Szrj 
215738fd1498Szrj /* Add a fixit-hint, suggesting insertion of NEW_CONTENT
215838fd1498Szrj    immediately before the start of WHERE.  */
215938fd1498Szrj 
216038fd1498Szrj void
add_fixit_insert_before(source_location where,const char * new_content)216138fd1498Szrj rich_location::add_fixit_insert_before (source_location where,
216238fd1498Szrj 					const char *new_content)
216338fd1498Szrj {
216438fd1498Szrj   source_location start = get_range_from_loc (m_line_table, where).m_start;
216538fd1498Szrj   maybe_add_fixit (start, start, new_content);
216638fd1498Szrj }
216738fd1498Szrj 
216838fd1498Szrj /* Add a fixit-hint, suggesting insertion of NEW_CONTENT
216938fd1498Szrj    immediately after the primary range's end-point.  */
217038fd1498Szrj 
217138fd1498Szrj void
add_fixit_insert_after(const char * new_content)217238fd1498Szrj rich_location::add_fixit_insert_after (const char *new_content)
217338fd1498Szrj {
217438fd1498Szrj   add_fixit_insert_after (get_loc (), new_content);
217538fd1498Szrj }
217638fd1498Szrj 
217738fd1498Szrj /* Add a fixit-hint, suggesting insertion of NEW_CONTENT
217838fd1498Szrj    immediately after the end-point of WHERE.  */
217938fd1498Szrj 
218038fd1498Szrj void
add_fixit_insert_after(source_location where,const char * new_content)218138fd1498Szrj rich_location::add_fixit_insert_after (source_location where,
218238fd1498Szrj 				       const char *new_content)
218338fd1498Szrj {
218438fd1498Szrj   source_location finish = get_range_from_loc (m_line_table, where).m_finish;
218538fd1498Szrj   source_location next_loc
218638fd1498Szrj     = linemap_position_for_loc_and_offset (m_line_table, finish, 1);
218738fd1498Szrj 
218838fd1498Szrj   /* linemap_position_for_loc_and_offset can fail, if so, it returns
218938fd1498Szrj      its input value.  */
219038fd1498Szrj   if (next_loc == finish)
219138fd1498Szrj     {
219238fd1498Szrj       stop_supporting_fixits ();
219338fd1498Szrj       return;
219438fd1498Szrj     }
219538fd1498Szrj 
219638fd1498Szrj   maybe_add_fixit (next_loc, next_loc, new_content);
219738fd1498Szrj }
219838fd1498Szrj 
219938fd1498Szrj /* Methods for adding removal fix-it hints.  */
220038fd1498Szrj 
220138fd1498Szrj /* Add a fixit-hint, suggesting removal of the content covered
220238fd1498Szrj    by range 0.  */
220338fd1498Szrj 
220438fd1498Szrj void
add_fixit_remove()220538fd1498Szrj rich_location::add_fixit_remove ()
220638fd1498Szrj {
220738fd1498Szrj   add_fixit_remove (get_loc ());
220838fd1498Szrj }
220938fd1498Szrj 
221038fd1498Szrj /* Add a fixit-hint, suggesting removal of the content between
221138fd1498Szrj    the start and finish of WHERE.  */
221238fd1498Szrj 
221338fd1498Szrj void
add_fixit_remove(source_location where)221438fd1498Szrj rich_location::add_fixit_remove (source_location where)
221538fd1498Szrj {
221638fd1498Szrj   source_range range = get_range_from_loc (m_line_table, where);
221738fd1498Szrj   add_fixit_remove (range);
221838fd1498Szrj }
221938fd1498Szrj 
222038fd1498Szrj /* Add a fixit-hint, suggesting removal of the content at
222138fd1498Szrj    SRC_RANGE.  */
222238fd1498Szrj 
222338fd1498Szrj void
add_fixit_remove(source_range src_range)222438fd1498Szrj rich_location::add_fixit_remove (source_range src_range)
222538fd1498Szrj {
222638fd1498Szrj   add_fixit_replace (src_range, "");
222738fd1498Szrj }
222838fd1498Szrj 
222938fd1498Szrj /* Add a fixit-hint, suggesting replacement of the content covered
223038fd1498Szrj    by range 0 with NEW_CONTENT.  */
223138fd1498Szrj 
223238fd1498Szrj void
add_fixit_replace(const char * new_content)223338fd1498Szrj rich_location::add_fixit_replace (const char *new_content)
223438fd1498Szrj {
223538fd1498Szrj   add_fixit_replace (get_loc (), new_content);
223638fd1498Szrj }
223738fd1498Szrj 
223838fd1498Szrj /* Methods for adding "replace" fix-it hints.  */
223938fd1498Szrj 
224038fd1498Szrj /* Add a fixit-hint, suggesting replacement of the content between
224138fd1498Szrj    the start and finish of WHERE with NEW_CONTENT.  */
224238fd1498Szrj 
224338fd1498Szrj void
add_fixit_replace(source_location where,const char * new_content)224438fd1498Szrj rich_location::add_fixit_replace (source_location where,
224538fd1498Szrj 				  const char *new_content)
224638fd1498Szrj {
224738fd1498Szrj   source_range range = get_range_from_loc (m_line_table, where);
224838fd1498Szrj   add_fixit_replace (range, new_content);
224938fd1498Szrj }
225038fd1498Szrj 
225138fd1498Szrj /* Add a fixit-hint, suggesting replacement of the content at
225238fd1498Szrj    SRC_RANGE with NEW_CONTENT.  */
225338fd1498Szrj 
225438fd1498Szrj void
add_fixit_replace(source_range src_range,const char * new_content)225538fd1498Szrj rich_location::add_fixit_replace (source_range src_range,
225638fd1498Szrj 				  const char *new_content)
225738fd1498Szrj {
225838fd1498Szrj   source_location start = get_pure_location (m_line_table, src_range.m_start);
225938fd1498Szrj   source_location finish = get_pure_location (m_line_table, src_range.m_finish);
226038fd1498Szrj 
226138fd1498Szrj   /* Fix-it hints use half-closed ranges, so attempt to offset the endpoint.  */
226238fd1498Szrj   source_location next_loc
226338fd1498Szrj     = linemap_position_for_loc_and_offset (m_line_table, finish, 1);
226438fd1498Szrj   /* linemap_position_for_loc_and_offset can fail, if so, it returns
226538fd1498Szrj      its input value.  */
226638fd1498Szrj   if (next_loc == finish)
226738fd1498Szrj     {
226838fd1498Szrj       stop_supporting_fixits ();
226938fd1498Szrj       return;
227038fd1498Szrj     }
227138fd1498Szrj   finish = next_loc;
227238fd1498Szrj 
227338fd1498Szrj   maybe_add_fixit (start, finish, new_content);
227438fd1498Szrj }
227538fd1498Szrj 
227638fd1498Szrj /* Get the last fix-it hint within this rich_location, or NULL if none.  */
227738fd1498Szrj 
227838fd1498Szrj fixit_hint *
get_last_fixit_hint()227938fd1498Szrj rich_location::get_last_fixit_hint () const
228038fd1498Szrj {
228138fd1498Szrj   if (m_fixit_hints.count () > 0)
228238fd1498Szrj     return get_fixit_hint (m_fixit_hints.count () - 1);
228338fd1498Szrj   else
228438fd1498Szrj     return NULL;
228538fd1498Szrj }
228638fd1498Szrj 
228738fd1498Szrj /* If WHERE is an "awkward" location, then mark this rich_location as not
228838fd1498Szrj    supporting fixits, purging any thay were already added, and return true.
228938fd1498Szrj 
229038fd1498Szrj    Otherwise (the common case), return false.  */
229138fd1498Szrj 
229238fd1498Szrj bool
reject_impossible_fixit(source_location where)229338fd1498Szrj rich_location::reject_impossible_fixit (source_location where)
229438fd1498Szrj {
229538fd1498Szrj   /* Fix-its within a rich_location should either all be suggested, or
229638fd1498Szrj      none of them should be suggested.
229738fd1498Szrj      Once we've rejected a fixit, we reject any more, even those
229838fd1498Szrj      with reasonable locations.  */
229938fd1498Szrj   if (m_seen_impossible_fixit)
230038fd1498Szrj     return true;
230138fd1498Szrj 
230238fd1498Szrj   if (where <= LINE_MAP_MAX_LOCATION_WITH_COLS)
230338fd1498Szrj     /* WHERE is a reasonable location for a fix-it; don't reject it.  */
230438fd1498Szrj     return false;
230538fd1498Szrj 
230638fd1498Szrj   /* Otherwise we have an attempt to add a fix-it with an "awkward"
230738fd1498Szrj      location: either one that we can't obtain column information
230838fd1498Szrj      for (within an ordinary map), or one within a macro expansion.  */
230938fd1498Szrj   stop_supporting_fixits ();
231038fd1498Szrj   return true;
231138fd1498Szrj }
231238fd1498Szrj 
231338fd1498Szrj /* Mark this rich_location as not supporting fixits, purging any that were
231438fd1498Szrj    already added.  */
231538fd1498Szrj 
231638fd1498Szrj void
stop_supporting_fixits()231738fd1498Szrj rich_location::stop_supporting_fixits ()
231838fd1498Szrj {
231938fd1498Szrj   m_seen_impossible_fixit = true;
232038fd1498Szrj 
232138fd1498Szrj   /* Purge the rich_location of any fix-its that were already added. */
232238fd1498Szrj   for (unsigned int i = 0; i < m_fixit_hints.count (); i++)
232338fd1498Szrj     delete get_fixit_hint (i);
232438fd1498Szrj   m_fixit_hints.truncate (0);
232538fd1498Szrj }
232638fd1498Szrj 
232738fd1498Szrj /* Add HINT to the fix-it hints in this rich_location,
232838fd1498Szrj    consolidating into the prior fixit if possible.  */
232938fd1498Szrj 
233038fd1498Szrj void
maybe_add_fixit(source_location start,source_location next_loc,const char * new_content)233138fd1498Szrj rich_location::maybe_add_fixit (source_location start,
233238fd1498Szrj 				source_location next_loc,
233338fd1498Szrj 				const char *new_content)
233438fd1498Szrj {
233538fd1498Szrj   if (reject_impossible_fixit (start))
233638fd1498Szrj     return;
233738fd1498Szrj   if (reject_impossible_fixit (next_loc))
233838fd1498Szrj     return;
233938fd1498Szrj 
234038fd1498Szrj   /* Only allow fix-it hints that affect a single line in one file.
234138fd1498Szrj      Compare the end-points.  */
234238fd1498Szrj   expanded_location exploc_start
234338fd1498Szrj     = linemap_client_expand_location_to_spelling_point (start,
234438fd1498Szrj 							LOCATION_ASPECT_START);
234538fd1498Szrj   expanded_location exploc_next_loc
234638fd1498Szrj     = linemap_client_expand_location_to_spelling_point (next_loc,
234738fd1498Szrj 							LOCATION_ASPECT_START);
234838fd1498Szrj   /* They must be within the same file...  */
234938fd1498Szrj   if (exploc_start.file != exploc_next_loc.file)
235038fd1498Szrj     {
235138fd1498Szrj       stop_supporting_fixits ();
235238fd1498Szrj       return;
235338fd1498Szrj     }
235438fd1498Szrj   /* ...and on the same line.  */
235538fd1498Szrj   if (exploc_start.line != exploc_next_loc.line)
235638fd1498Szrj     {
235738fd1498Szrj       stop_supporting_fixits ();
235838fd1498Szrj       return;
235938fd1498Szrj     }
236038fd1498Szrj   /* The columns must be in the correct order.  This can fail if the
236138fd1498Szrj      endpoints straddle the boundary for which the linemap can represent
236238fd1498Szrj      columns (PR c/82050).  */
236338fd1498Szrj   if (exploc_start.column > exploc_next_loc.column)
236438fd1498Szrj     {
236538fd1498Szrj       stop_supporting_fixits ();
236638fd1498Szrj       return;
236738fd1498Szrj     }
236838fd1498Szrj 
236938fd1498Szrj   const char *newline = strchr (new_content, '\n');
237038fd1498Szrj   if (newline)
237138fd1498Szrj     {
237238fd1498Szrj       /* For now, we can only support insertion of whole lines
237338fd1498Szrj 	 i.e. starts at start of line, and the newline is at the end of
237438fd1498Szrj 	 the insertion point.  */
237538fd1498Szrj 
237638fd1498Szrj       /* It must be an insertion, not a replacement/deletion.  */
237738fd1498Szrj       if (start != next_loc)
237838fd1498Szrj 	{
237938fd1498Szrj 	  stop_supporting_fixits ();
238038fd1498Szrj 	  return;
238138fd1498Szrj 	}
238238fd1498Szrj 
238338fd1498Szrj       /* The insertion must be at the start of a line.  */
238438fd1498Szrj       if (exploc_start.column != 1)
238538fd1498Szrj 	{
238638fd1498Szrj 	  stop_supporting_fixits ();
238738fd1498Szrj 	  return;
238838fd1498Szrj 	}
238938fd1498Szrj 
239038fd1498Szrj       /* The newline must be at end of NEW_CONTENT.
239138fd1498Szrj 	 We could eventually split up fix-its at newlines if we wanted
239238fd1498Szrj 	 to allow more generality (e.g. to allow adding multiple lines
239338fd1498Szrj 	 with one add_fixit call.  */
239438fd1498Szrj       if (newline[1] != '\0')
239538fd1498Szrj 	{
239638fd1498Szrj 	  stop_supporting_fixits ();
239738fd1498Szrj 	  return;
239838fd1498Szrj 	}
239938fd1498Szrj     }
240038fd1498Szrj 
240138fd1498Szrj   /* Consolidate neighboring fixits.
240238fd1498Szrj      Don't consolidate into newline-insertion fixits.  */
240338fd1498Szrj   fixit_hint *prev = get_last_fixit_hint ();
240438fd1498Szrj   if (prev && !prev->ends_with_newline_p ())
240538fd1498Szrj     if (prev->maybe_append (start, next_loc, new_content))
240638fd1498Szrj       return;
240738fd1498Szrj 
240838fd1498Szrj   m_fixit_hints.push (new fixit_hint (start, next_loc, new_content));
240938fd1498Szrj }
241038fd1498Szrj 
241138fd1498Szrj /* class fixit_hint.  */
241238fd1498Szrj 
fixit_hint(source_location start,source_location next_loc,const char * new_content)241338fd1498Szrj fixit_hint::fixit_hint (source_location start,
241438fd1498Szrj 			source_location next_loc,
241538fd1498Szrj 			const char *new_content)
241638fd1498Szrj : m_start (start),
241738fd1498Szrj   m_next_loc (next_loc),
241838fd1498Szrj   m_bytes (xstrdup (new_content)),
241938fd1498Szrj   m_len (strlen (new_content))
242038fd1498Szrj {
242138fd1498Szrj }
242238fd1498Szrj 
242338fd1498Szrj /* Does this fix-it hint affect the given line?  */
242438fd1498Szrj 
242538fd1498Szrj bool
affects_line_p(const char * file,int line)242638fd1498Szrj fixit_hint::affects_line_p (const char *file, int line) const
242738fd1498Szrj {
242838fd1498Szrj   expanded_location exploc_start
242938fd1498Szrj     = linemap_client_expand_location_to_spelling_point (m_start,
243038fd1498Szrj 							LOCATION_ASPECT_START);
243138fd1498Szrj   if (file != exploc_start.file)
243238fd1498Szrj     return false;
243338fd1498Szrj   if (line < exploc_start.line)
243438fd1498Szrj       return false;
243538fd1498Szrj   expanded_location exploc_next_loc
243638fd1498Szrj     = linemap_client_expand_location_to_spelling_point (m_next_loc,
243738fd1498Szrj 							LOCATION_ASPECT_START);
243838fd1498Szrj   if (file != exploc_next_loc.file)
243938fd1498Szrj     return false;
244038fd1498Szrj   if (line > exploc_next_loc.line)
244138fd1498Szrj       return false;
244238fd1498Szrj   return true;
244338fd1498Szrj }
244438fd1498Szrj 
244538fd1498Szrj /* Method for consolidating fix-it hints, for use by
244638fd1498Szrj    rich_location::maybe_add_fixit.
244738fd1498Szrj    If possible, merge a pending fix-it hint with the given params
244838fd1498Szrj    into this one and return true.
244938fd1498Szrj    Otherwise return false.  */
245038fd1498Szrj 
245138fd1498Szrj bool
maybe_append(source_location start,source_location next_loc,const char * new_content)245238fd1498Szrj fixit_hint::maybe_append (source_location start,
245338fd1498Szrj 			  source_location next_loc,
245438fd1498Szrj 			  const char *new_content)
245538fd1498Szrj {
245638fd1498Szrj   /* For consolidation to be possible, START must be at this hint's
245738fd1498Szrj      m_next_loc.  */
245838fd1498Szrj   if (start != m_next_loc)
245938fd1498Szrj     return false;
246038fd1498Szrj 
246138fd1498Szrj   /* If so, we have neighboring replacements; merge them.  */
246238fd1498Szrj   m_next_loc = next_loc;
246338fd1498Szrj   size_t extra_len = strlen (new_content);
246438fd1498Szrj   m_bytes = (char *)xrealloc (m_bytes, m_len + extra_len + 1);
246538fd1498Szrj   memcpy (m_bytes + m_len, new_content, extra_len);
246638fd1498Szrj   m_len += extra_len;
246738fd1498Szrj   m_bytes[m_len] = '\0';
246838fd1498Szrj   return true;
246938fd1498Szrj }
247038fd1498Szrj 
247138fd1498Szrj /* Return true iff this hint's content ends with a newline.  */
247238fd1498Szrj 
247338fd1498Szrj bool
ends_with_newline_p()247438fd1498Szrj fixit_hint::ends_with_newline_p () const
247538fd1498Szrj {
247638fd1498Szrj   if (m_len == 0)
247738fd1498Szrj     return false;
247838fd1498Szrj   return m_bytes[m_len - 1] == '\n';
247938fd1498Szrj }
2480