1 /* Map (unsigned int) keys to (source file, line, column) triples.
2    Copyright (C) 2001-2021 Free Software Foundation, Inc.
3 
4 This program is free software; you can redistribute it and/or modify it
5 under the terms of the GNU General Public License as published by the
6 Free Software Foundation; either version 3, or (at your option) any
7 later version.
8 
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 GNU General Public License for more details.
13 
14 You should have received a copy of the GNU General Public License
15 along with this program; see the file COPYING3.  If not see
16 <http://www.gnu.org/licenses/>.
17 
18  In other words, you are welcome to use, share and improve this program.
19  You are forbidden to forbid anyone else to use, share and improve
20  what you give them.   Help stamp out software-hoarding!  */
21 
22 #include "config.h"
23 #include "system.h"
24 #include "line-map.h"
25 #include "cpplib.h"
26 #include "internal.h"
27 #include "hashtab.h"
28 
29 static void trace_include (const line_maps *, const line_map_ordinary *);
30 static const line_map_ordinary * linemap_ordinary_map_lookup (const line_maps *,
31 							      location_t);
32 static const line_map_macro* linemap_macro_map_lookup (const line_maps *,
33 						       location_t);
34 static location_t linemap_macro_map_loc_to_def_point
35 (const line_map_macro *, location_t);
36 static location_t linemap_macro_map_loc_to_exp_point
37 (const line_map_macro *, location_t);
38 static location_t linemap_macro_loc_to_spelling_point
39 (line_maps *, location_t, const line_map_ordinary **);
40 static location_t linemap_macro_loc_to_def_point (line_maps *,
41 						  location_t,
42 						  const line_map_ordinary **);
43 static location_t linemap_macro_loc_to_exp_point (line_maps *,
44 						  location_t,
45 						  const line_map_ordinary **);
46 
47 /* Counters defined in macro.c.  */
48 extern unsigned num_expanded_macros_counter;
49 extern unsigned num_macro_tokens_counter;
50 
51 /* Destructor for class line_maps.
52    Ensure non-GC-managed memory is released.  */
53 
~line_maps()54 line_maps::~line_maps ()
55 {
56   if (location_adhoc_data_map.htab)
57     htab_delete (location_adhoc_data_map.htab);
58 }
59 
60 /* Hash function for location_adhoc_data hashtable.  */
61 
62 static hashval_t
location_adhoc_data_hash(const void * l)63 location_adhoc_data_hash (const void *l)
64 {
65   const struct location_adhoc_data *lb =
66       (const struct location_adhoc_data *) l;
67   return ((hashval_t) lb->locus
68 	  + (hashval_t) lb->src_range.m_start
69 	  + (hashval_t) lb->src_range.m_finish
70 	  + (size_t) lb->data);
71 }
72 
73 /* Compare function for location_adhoc_data hashtable.  */
74 
75 static int
location_adhoc_data_eq(const void * l1,const void * l2)76 location_adhoc_data_eq (const void *l1, const void *l2)
77 {
78   const struct location_adhoc_data *lb1 =
79       (const struct location_adhoc_data *) l1;
80   const struct location_adhoc_data *lb2 =
81       (const struct location_adhoc_data *) l2;
82   return (lb1->locus == lb2->locus
83 	  && lb1->src_range.m_start == lb2->src_range.m_start
84 	  && lb1->src_range.m_finish == lb2->src_range.m_finish
85 	  && lb1->data == lb2->data);
86 }
87 
88 /* Update the hashtable when location_adhoc_data is reallocated.  */
89 
90 static int
location_adhoc_data_update(void ** slot,void * data)91 location_adhoc_data_update (void **slot, void *data)
92 {
93   *((char **) slot)
94     = (char *) ((uintptr_t) *((char **) slot) + *((ptrdiff_t *) data));
95   return 1;
96 }
97 
98 /* Rebuild the hash table from the location adhoc data.  */
99 
100 void
rebuild_location_adhoc_htab(line_maps * set)101 rebuild_location_adhoc_htab (line_maps *set)
102 {
103   unsigned i;
104   set->location_adhoc_data_map.htab =
105       htab_create (100, location_adhoc_data_hash, location_adhoc_data_eq, NULL);
106   for (i = 0; i < set->location_adhoc_data_map.curr_loc; i++)
107     htab_find_slot (set->location_adhoc_data_map.htab,
108 		    set->location_adhoc_data_map.data + i, INSERT);
109 }
110 
111 /* Helper function for get_combined_adhoc_loc.
112    Can the given LOCUS + SRC_RANGE and DATA pointer be stored compactly
113    within a location_t, without needing to use an ad-hoc location.  */
114 
115 static bool
can_be_stored_compactly_p(line_maps * set,location_t locus,source_range src_range,void * data)116 can_be_stored_compactly_p (line_maps *set,
117 			   location_t locus,
118 			   source_range src_range,
119 			   void *data)
120 {
121   /* If there's an ad-hoc pointer, we can't store it directly in the
122      location_t, we need the lookaside.  */
123   if (data)
124     return false;
125 
126   /* We only store ranges that begin at the locus and that are sufficiently
127      "sane".  */
128   if (src_range.m_start != locus)
129     return false;
130 
131   if (src_range.m_finish < src_range.m_start)
132     return false;
133 
134   if (src_range.m_start < RESERVED_LOCATION_COUNT)
135     return false;
136 
137   if (locus >= LINE_MAP_MAX_LOCATION_WITH_PACKED_RANGES)
138     return false;
139 
140   /* All 3 locations must be within ordinary maps, typically, the same
141      ordinary map.  */
142   location_t lowest_macro_loc = LINEMAPS_MACRO_LOWEST_LOCATION (set);
143   if (locus >= lowest_macro_loc)
144     return false;
145   if (src_range.m_start >= lowest_macro_loc)
146     return false;
147   if (src_range.m_finish >= lowest_macro_loc)
148     return false;
149 
150   /* Passed all tests.  */
151   return true;
152 }
153 
154 /* Combine LOCUS and DATA to a combined adhoc loc.  */
155 
156 location_t
get_combined_adhoc_loc(line_maps * set,location_t locus,source_range src_range,void * data)157 get_combined_adhoc_loc (line_maps *set,
158 			location_t locus,
159 			source_range src_range,
160 			void *data)
161 {
162   struct location_adhoc_data lb;
163   struct location_adhoc_data **slot;
164 
165   if (IS_ADHOC_LOC (locus))
166     locus = get_location_from_adhoc_loc (set, locus);
167   if (locus == 0 && data == NULL)
168     return 0;
169 
170   /* Any ordinary locations ought to be "pure" at this point: no
171      compressed ranges.  */
172   linemap_assert (locus < RESERVED_LOCATION_COUNT
173 		  || locus >= LINE_MAP_MAX_LOCATION_WITH_PACKED_RANGES
174 		  || locus >= LINEMAPS_MACRO_LOWEST_LOCATION (set)
175 		  || pure_location_p (set, locus));
176 
177   /* Consider short-range optimization.  */
178   if (can_be_stored_compactly_p (set, locus, src_range, data))
179     {
180       /* The low bits ought to be clear.  */
181       linemap_assert (pure_location_p (set, locus));
182       const line_map *map = linemap_lookup (set, locus);
183       const line_map_ordinary *ordmap = linemap_check_ordinary (map);
184       unsigned int int_diff = src_range.m_finish - src_range.m_start;
185       unsigned int col_diff = (int_diff >> ordmap->m_range_bits);
186       if (col_diff < (1U << ordmap->m_range_bits))
187 	{
188 	  location_t packed = locus | col_diff;
189 	  set->num_optimized_ranges++;
190 	  return packed;
191 	}
192     }
193 
194   /* We can also compactly store locations
195      when locus == start == finish (and data is NULL).  */
196   if (locus == src_range.m_start
197       && locus == src_range.m_finish
198       && !data)
199     return locus;
200 
201   if (!data)
202     set->num_unoptimized_ranges++;
203 
204   lb.locus = locus;
205   lb.src_range = src_range;
206   lb.data = data;
207   slot = (struct location_adhoc_data **)
208       htab_find_slot (set->location_adhoc_data_map.htab, &lb, INSERT);
209   if (*slot == NULL)
210     {
211       if (set->location_adhoc_data_map.curr_loc >=
212 	  set->location_adhoc_data_map.allocated)
213 	{
214 	  char *orig_data = (char *) set->location_adhoc_data_map.data;
215 	  ptrdiff_t offset;
216 	  /* Cast away extern "C" from the type of xrealloc.  */
217 	  line_map_realloc reallocator = (set->reallocator
218 					  ? set->reallocator
219 					  : (line_map_realloc) xrealloc);
220 
221 	  if (set->location_adhoc_data_map.allocated == 0)
222 	    set->location_adhoc_data_map.allocated = 128;
223 	  else
224 	    set->location_adhoc_data_map.allocated *= 2;
225 	  set->location_adhoc_data_map.data = (struct location_adhoc_data *)
226 	      reallocator (set->location_adhoc_data_map.data,
227 			   set->location_adhoc_data_map.allocated
228 			   * sizeof (struct location_adhoc_data));
229 	  offset = (char *) (set->location_adhoc_data_map.data) - orig_data;
230 	  if (set->location_adhoc_data_map.allocated > 128)
231 	    htab_traverse (set->location_adhoc_data_map.htab,
232 			   location_adhoc_data_update, &offset);
233 	}
234       *slot = set->location_adhoc_data_map.data
235 	      + set->location_adhoc_data_map.curr_loc;
236       set->location_adhoc_data_map.data[set->location_adhoc_data_map.curr_loc++]
237 	= lb;
238     }
239   return ((*slot) - set->location_adhoc_data_map.data) | 0x80000000;
240 }
241 
242 /* Return the data for the adhoc loc.  */
243 
244 void *
get_data_from_adhoc_loc(const class line_maps * set,location_t loc)245 get_data_from_adhoc_loc (const class line_maps *set, location_t loc)
246 {
247   linemap_assert (IS_ADHOC_LOC (loc));
248   return set->location_adhoc_data_map.data[loc & MAX_LOCATION_T].data;
249 }
250 
251 /* Return the location for the adhoc loc.  */
252 
253 location_t
get_location_from_adhoc_loc(const class line_maps * set,location_t loc)254 get_location_from_adhoc_loc (const class line_maps *set, location_t loc)
255 {
256   linemap_assert (IS_ADHOC_LOC (loc));
257   return set->location_adhoc_data_map.data[loc & MAX_LOCATION_T].locus;
258 }
259 
260 /* Return the source_range for adhoc location LOC.  */
261 
262 static source_range
get_range_from_adhoc_loc(const class line_maps * set,location_t loc)263 get_range_from_adhoc_loc (const class line_maps *set, location_t loc)
264 {
265   linemap_assert (IS_ADHOC_LOC (loc));
266   return set->location_adhoc_data_map.data[loc & MAX_LOCATION_T].src_range;
267 }
268 
269 /* Get the source_range of location LOC, either from the ad-hoc
270    lookaside table, or embedded inside LOC itself.  */
271 
272 source_range
get_range_from_loc(line_maps * set,location_t loc)273 get_range_from_loc (line_maps *set,
274 		    location_t loc)
275 {
276   if (IS_ADHOC_LOC (loc))
277     return get_range_from_adhoc_loc (set, loc);
278 
279   /* For ordinary maps, extract packed range.  */
280   if (loc >= RESERVED_LOCATION_COUNT
281       && loc < LINEMAPS_MACRO_LOWEST_LOCATION (set)
282       && loc <= LINE_MAP_MAX_LOCATION_WITH_PACKED_RANGES)
283     {
284       const line_map *map = linemap_lookup (set, loc);
285       const line_map_ordinary *ordmap = linemap_check_ordinary (map);
286       source_range result;
287       int offset = loc & ((1 << ordmap->m_range_bits) - 1);
288       result.m_start = loc - offset;
289       result.m_finish = result.m_start + (offset << ordmap->m_range_bits);
290       return result;
291     }
292 
293   return source_range::from_location (loc);
294 }
295 
296 /* Get whether location LOC is a "pure" location, or
297    whether it is an ad-hoc location, or embeds range information.  */
298 
299 bool
pure_location_p(line_maps * set,location_t loc)300 pure_location_p (line_maps *set, location_t loc)
301 {
302   if (IS_ADHOC_LOC (loc))
303     return false;
304 
305   const line_map *map = linemap_lookup (set, loc);
306   if (map == NULL)
307     return true;
308   const line_map_ordinary *ordmap = linemap_check_ordinary (map);
309 
310   if (loc & ((1U << ordmap->m_range_bits) - 1))
311     return false;
312 
313   return true;
314 }
315 
316 /* Given location LOC within SET, strip away any packed range information
317    or ad-hoc information.  */
318 
319 location_t
get_pure_location(line_maps * set,location_t loc)320 get_pure_location (line_maps *set, location_t loc)
321 {
322   if (IS_ADHOC_LOC (loc))
323     loc = get_location_from_adhoc_loc (set, loc);
324 
325   if (loc >= LINEMAPS_MACRO_LOWEST_LOCATION (set))
326     return loc;
327 
328   if (loc < RESERVED_LOCATION_COUNT)
329     return loc;
330 
331   const line_map *map = linemap_lookup (set, loc);
332   const line_map_ordinary *ordmap = linemap_check_ordinary (map);
333 
334   return loc & ~((1 << ordmap->m_range_bits) - 1);
335 }
336 
337 /* Initialize a line map set.  */
338 
339 void
linemap_init(line_maps * set,location_t builtin_location)340 linemap_init (line_maps *set,
341 	      location_t builtin_location)
342 {
343 #if __GNUC__ == 4 && __GNUC_MINOR__ == 2 && !defined (__clang__)
344   /* PR33916, needed to fix PR82939.  */
345   memset (set, 0, sizeof (line_maps));
346 #else
347   new (set) line_maps();
348 #endif
349   /* Set default reallocator (used for initial alloc too).  */
350   set->reallocator = xrealloc;
351   set->highest_location = RESERVED_LOCATION_COUNT - 1;
352   set->highest_line = RESERVED_LOCATION_COUNT - 1;
353   set->location_adhoc_data_map.htab =
354       htab_create (100, location_adhoc_data_hash, location_adhoc_data_eq, NULL);
355   set->builtin_location = builtin_location;
356 }
357 
358 /* Return the ordinary line map from whence MAP was included.  Returns
359    NULL if MAP was not an include.  */
360 
361 const line_map_ordinary *
linemap_included_from_linemap(line_maps * set,const line_map_ordinary * map)362 linemap_included_from_linemap (line_maps *set, const line_map_ordinary *map)
363 {
364   return linemap_ordinary_map_lookup (set, linemap_included_from (map));
365 }
366 
367 /* Check for and warn about line_maps entered but not exited.  */
368 
369 void
linemap_check_files_exited(line_maps * set)370 linemap_check_files_exited (line_maps *set)
371 {
372   /* Depending upon whether we are handling preprocessed input or
373      not, this can be a user error or an ICE.  */
374   for (const line_map_ordinary *map = LINEMAPS_LAST_ORDINARY_MAP (set);
375        ! MAIN_FILE_P (map);
376        map = linemap_included_from_linemap (set, map))
377     fprintf (stderr, "line-map.c: file \"%s\" entered but not left\n",
378 	     ORDINARY_MAP_FILE_NAME (map));
379 }
380 
381 /* Create NUM zero-initialized maps of type MACRO_P.  */
382 
383 line_map *
line_map_new_raw(line_maps * set,bool macro_p,unsigned num)384 line_map_new_raw (line_maps *set, bool macro_p, unsigned num)
385 {
386   unsigned num_maps_allocated = LINEMAPS_ALLOCATED (set, macro_p);
387   unsigned num_maps_used = LINEMAPS_USED (set, macro_p);
388 
389   if (num > num_maps_allocated - num_maps_used)
390     {
391       /* We need more space!  */
392       if (!num_maps_allocated)
393 	num_maps_allocated = 128;
394       if (num_maps_allocated < num_maps_used + num)
395 	num_maps_allocated = num_maps_used + num;
396       num_maps_allocated *= 2;
397 
398       size_t size_of_a_map;
399       void *buffer;
400       if (macro_p)
401 	{
402 	  size_of_a_map = sizeof (line_map_macro);
403 	  buffer = set->info_macro.maps;
404 	}
405       else
406 	{
407 	  size_of_a_map = sizeof (line_map_ordinary);
408 	  buffer = set->info_ordinary.maps;
409 	}
410 
411       /* We are going to execute some dance to try to reduce the
412 	 overhead of the memory allocator, in case we are using the
413 	 ggc-page.c one.
414 
415 	 The actual size of memory we are going to get back from the
416 	 allocator may well be larger than what we ask for.  Use this
417 	 hook to find what that size is.  */
418       size_t alloc_size
419 	= set->round_alloc_size (num_maps_allocated * size_of_a_map);
420 
421       /* Now alloc_size contains the exact memory size we would get if
422 	 we have asked for the initial alloc_size amount of memory.
423 	 Let's get back to the number of map that amounts to.  */
424       unsigned num_maps = alloc_size / size_of_a_map;
425       buffer = set->reallocator (buffer, num_maps * size_of_a_map);
426       memset ((char *)buffer + num_maps_used * size_of_a_map, 0,
427 	      (num_maps - num_maps_used) * size_of_a_map);
428       if (macro_p)
429 	set->info_macro.maps = (line_map_macro *)buffer;
430       else
431 	set->info_ordinary.maps = (line_map_ordinary *)buffer;
432       LINEMAPS_ALLOCATED (set, macro_p) = num_maps;
433     }
434 
435   line_map *result = (macro_p ? (line_map *)&set->info_macro.maps[num_maps_used]
436 		      : (line_map *)&set->info_ordinary.maps[num_maps_used]);
437   LINEMAPS_USED (set, macro_p) += num;
438 
439   return result;
440 }
441 
442 /* Create a new line map in the line map set SET, and return it.
443    REASON is the reason of creating the map. It determines the type
444    of map created (ordinary or macro map). Note that ordinary maps and
445    macro maps are allocated in different memory location.  */
446 
447 static struct line_map *
new_linemap(line_maps * set,location_t start_location)448 new_linemap (line_maps *set, location_t start_location)
449 {
450   line_map *result = line_map_new_raw (set,
451 				       start_location >= LINE_MAP_MAX_LOCATION,
452 				       1);
453 
454   result->start_location = start_location;
455 
456   return result;
457 }
458 
459 /* Return the location of the last source line within an ordinary
460    map.  */
461 inline location_t
LAST_SOURCE_LINE_LOCATION(const line_map_ordinary * map)462 LAST_SOURCE_LINE_LOCATION (const line_map_ordinary *map)
463 {
464   return (((map[1].start_location - 1
465 	    - map->start_location)
466 	   & ~((1 << map->m_column_and_range_bits) - 1))
467 	  + map->start_location);
468 }
469 
470 /* Add a mapping of logical source line to physical source file and
471    line number.
472 
473    The text pointed to by TO_FILE must have a lifetime
474    at least as long as the final call to lookup_line ().  An empty
475    TO_FILE means standard input.  If reason is LC_LEAVE, and
476    TO_FILE is NULL, then TO_FILE, TO_LINE and SYSP are given their
477    natural values considering the file we are returning to.
478 
479    FROM_LINE should be monotonic increasing across calls to this
480    function.  A call to this function can relocate the previous set of
481    maps, so any stored line_map pointers should not be used.  */
482 
483 const struct line_map *
linemap_add(line_maps * set,enum lc_reason reason,unsigned int sysp,const char * to_file,linenum_type to_line)484 linemap_add (line_maps *set, enum lc_reason reason,
485 	     unsigned int sysp, const char *to_file, linenum_type to_line)
486 {
487   /* Generate a start_location above the current highest_location.
488      If possible, make the low range bits be zero.  */
489   location_t start_location = set->highest_location + 1;
490   unsigned range_bits = 0;
491   if (start_location < LINE_MAP_MAX_LOCATION_WITH_COLS)
492     range_bits = set->default_range_bits;
493   start_location += (1 << range_bits) - 1;
494   start_location &=  ~((1 << range_bits) - 1);
495 
496   linemap_assert (!LINEMAPS_ORDINARY_USED (set)
497 		  || (start_location
498 		      >= MAP_START_LOCATION (LINEMAPS_LAST_ORDINARY_MAP (set))));
499 
500   /* When we enter the file for the first time reason cannot be
501      LC_RENAME.  */
502   linemap_assert (!(set->depth == 0 && reason == LC_RENAME));
503 
504   /* If we are leaving the main file, return a NULL map.  */
505   if (reason == LC_LEAVE
506       && MAIN_FILE_P (LINEMAPS_LAST_ORDINARY_MAP (set))
507       && to_file == NULL)
508     {
509       set->depth--;
510       return NULL;
511     }
512 
513   linemap_assert (reason != LC_ENTER_MACRO);
514 
515   if (start_location >= LINE_MAP_MAX_LOCATION)
516     /* We ran out of line map space.   */
517     start_location = 0;
518 
519   line_map_ordinary *map
520     = linemap_check_ordinary (new_linemap (set, start_location));
521   map->reason = reason;
522 
523   if (to_file && *to_file == '\0' && reason != LC_RENAME_VERBATIM)
524     to_file = "<stdin>";
525 
526   if (reason == LC_RENAME_VERBATIM)
527     reason = LC_RENAME;
528 
529   const line_map_ordinary *from = NULL;
530   if (reason == LC_LEAVE)
531     {
532       /* When we are just leaving an "included" file, and jump to the next
533 	 location inside the "includer" right after the #include
534 	 "included", this variable points the map in use right before the
535 	 #include "included", inside the same "includer" file.  */
536 
537       linemap_assert (!MAIN_FILE_P (map - 1));
538       /* (MAP - 1) points to the map we are leaving. The
539 	 map from which (MAP - 1) got included should be the map
540 	 that comes right before MAP in the same file.  */
541       from = linemap_included_from_linemap (set, map - 1);
542 
543       /* A TO_FILE of NULL is special - we use the natural values.  */
544       if (to_file == NULL)
545 	{
546 	  to_file = ORDINARY_MAP_FILE_NAME (from);
547 	  to_line = SOURCE_LINE (from, from[1].start_location);
548 	  sysp = ORDINARY_MAP_IN_SYSTEM_HEADER_P (from);
549 	}
550       else
551 	linemap_assert (filename_cmp (ORDINARY_MAP_FILE_NAME (from),
552 				      to_file) == 0);
553     }
554 
555   map->sysp = sysp;
556   map->to_file = to_file;
557   map->to_line = to_line;
558   LINEMAPS_ORDINARY_CACHE (set) = LINEMAPS_ORDINARY_USED (set) - 1;
559   /* Do not store range_bits here.  That's readjusted in
560      linemap_line_start.  */
561   map->m_range_bits = map->m_column_and_range_bits = 0;
562   set->highest_location = start_location;
563   set->highest_line = start_location;
564   set->max_column_hint = 0;
565 
566   /* This assertion is placed after set->highest_location has
567      been updated, since the latter affects
568      linemap_location_from_macro_expansion_p, which ultimately affects
569      pure_location_p.  */
570   linemap_assert (pure_location_p (set, start_location));
571 
572   if (reason == LC_ENTER)
573     {
574       if (set->depth == 0)
575 	map->included_from = 0;
576       else
577 	/* The location of the end of the just-closed map.  */
578 	map->included_from
579 	  = (((map[0].start_location - 1 - map[-1].start_location)
580 	      & ~((1 << map[-1].m_column_and_range_bits) - 1))
581 	     + map[-1].start_location);
582       set->depth++;
583       if (set->trace_includes)
584 	trace_include (set, map);
585     }
586   else if (reason == LC_RENAME)
587     map->included_from = linemap_included_from (&map[-1]);
588   else if (reason == LC_LEAVE)
589     {
590       set->depth--;
591       map->included_from = linemap_included_from (from);
592     }
593 
594   return map;
595 }
596 
597 /* Create a location for a module NAME imported at FROM.  */
598 
599 location_t
linemap_module_loc(line_maps * set,location_t from,const char * name)600 linemap_module_loc (line_maps *set, location_t from, const char *name)
601 {
602   const line_map_ordinary *map
603     = linemap_check_ordinary (linemap_add (set, LC_MODULE, false, name, 0));
604   const_cast <line_map_ordinary *> (map)->included_from = from;
605 
606   location_t loc = linemap_line_start (set, 0, 0);
607 
608   return loc;
609 }
610 
611 /* The linemap containing LOC is being reparented to be
612    imported/included from ADOPTOR.  This can happen when an
613    indirectly imported module is then directly imported, or when
614    partitions are involved.  */
615 
616 void
linemap_module_reparent(line_maps * set,location_t loc,location_t adoptor)617 linemap_module_reparent (line_maps *set, location_t loc, location_t adoptor)
618 {
619   const line_map_ordinary *map = linemap_ordinary_map_lookup (set, loc);
620   const_cast<line_map_ordinary *> (map)->included_from = adoptor;
621 }
622 
623 /* A linemap at LWM-1 was interrupted to insert module locations & imports.
624    Append a new map, continuing the interrupted one.  Return the start location
625    of the new map, or 0 if failed (because we ran out of locations.  */
626 
627 unsigned
linemap_module_restore(line_maps * set,unsigned lwm)628 linemap_module_restore (line_maps *set, unsigned lwm)
629 {
630   linemap_assert (lwm);
631 
632   const line_map_ordinary *pre_map
633     = linemap_check_ordinary (LINEMAPS_MAP_AT (set, false, lwm - 1));
634   unsigned src_line = SOURCE_LINE (pre_map, LAST_SOURCE_LINE_LOCATION (pre_map));
635   location_t inc_at = pre_map->included_from;
636   if (const line_map_ordinary *post_map
637       = (linemap_check_ordinary
638 	 (linemap_add (set, LC_RENAME_VERBATIM,
639 		       ORDINARY_MAP_IN_SYSTEM_HEADER_P (pre_map),
640 		       ORDINARY_MAP_FILE_NAME (pre_map), src_line))))
641     {
642       /* linemap_add will think we were included from the same as the preceeding
643 	 map.  */
644       const_cast <line_map_ordinary *> (post_map)->included_from = inc_at;
645 
646       return post_map->start_location;
647     }
648 
649   return 0;
650 }
651 
652 /* Returns TRUE if the line table set tracks token locations across
653    macro expansion, FALSE otherwise.  */
654 
655 bool
linemap_tracks_macro_expansion_locs_p(line_maps * set)656 linemap_tracks_macro_expansion_locs_p (line_maps *set)
657 {
658   return LINEMAPS_MACRO_MAPS (set) != NULL;
659 }
660 
661 /* Create a macro map.  A macro map encodes source locations of tokens
662    that are part of a macro replacement-list, at a macro expansion
663    point.  See the extensive comments of struct line_map and struct
664    line_map_macro, in line-map.h.
665 
666    This map shall be created when the macro is expanded.  The map
667    encodes the source location of the expansion point of the macro as
668    well as the "original" source location of each token that is part
669    of the macro replacement-list.  If a macro is defined but never
670    expanded, it has no macro map.  SET is the set of maps the macro
671    map should be part of.  MACRO_NODE is the macro which the new macro
672    map should encode source locations for.  EXPANSION is the location
673    of the expansion point of MACRO. For function-like macros
674    invocations, it's best to make it point to the closing parenthesis
675    of the macro, rather than the the location of the first character
676    of the macro.  NUM_TOKENS is the number of tokens that are part of
677    the replacement-list of MACRO.
678 
679    Note that when we run out of the integer space available for source
680    locations, this function returns NULL.  In that case, callers of
681    this function cannot encode {line,column} pairs into locations of
682    macro tokens anymore.  */
683 
684 const line_map_macro *
linemap_enter_macro(class line_maps * set,struct cpp_hashnode * macro_node,location_t expansion,unsigned int num_tokens)685 linemap_enter_macro (class line_maps *set, struct cpp_hashnode *macro_node,
686 		     location_t expansion, unsigned int num_tokens)
687 {
688   location_t start_location
689     = LINEMAPS_MACRO_LOWEST_LOCATION (set) - num_tokens;
690 
691   if (start_location < LINE_MAP_MAX_LOCATION)
692     /* We ran out of macro map space.   */
693     return NULL;
694 
695   line_map_macro *map = linemap_check_macro (new_linemap (set, start_location));
696 
697   map->macro = macro_node;
698   map->n_tokens = num_tokens;
699   map->macro_locations
700     = (location_t*) set->reallocator (NULL,
701 					   2 * num_tokens
702 					   * sizeof (location_t));
703   map->expansion = expansion;
704   memset (MACRO_MAP_LOCATIONS (map), 0,
705 	  2 * num_tokens * sizeof (location_t));
706 
707   LINEMAPS_MACRO_CACHE (set) = LINEMAPS_MACRO_USED (set) - 1;
708 
709   return map;
710 }
711 
712 /* Create and return a virtual location for a token that is part of a
713    macro expansion-list at a macro expansion point.  See the comment
714    inside struct line_map_macro to see what an expansion-list exactly
715    is.
716 
717    A call to this function must come after a call to
718    linemap_enter_macro.
719 
720    MAP is the map into which the source location is created.  TOKEN_NO
721    is the index of the token in the macro replacement-list, starting
722    at number 0.
723 
724    ORIG_LOC is the location of the token outside of this macro
725    expansion.  If the token comes originally from the macro
726    definition, it is the locus in the macro definition; otherwise it
727    is a location in the context of the caller of this macro expansion
728    (which is a virtual location or a source location if the caller is
729    itself a macro expansion or not).
730 
731    ORIG_PARM_REPLACEMENT_LOC is the location in the macro definition,
732    either of the token itself or of a macro parameter that it
733    replaces.  */
734 
735 location_t
linemap_add_macro_token(const line_map_macro * map,unsigned int token_no,location_t orig_loc,location_t orig_parm_replacement_loc)736 linemap_add_macro_token (const line_map_macro *map,
737 			 unsigned int token_no,
738 			 location_t orig_loc,
739 			 location_t orig_parm_replacement_loc)
740 {
741   location_t result;
742 
743   linemap_assert (linemap_macro_expansion_map_p (map));
744   linemap_assert (token_no < MACRO_MAP_NUM_MACRO_TOKENS (map));
745 
746   MACRO_MAP_LOCATIONS (map)[2 * token_no] = orig_loc;
747   MACRO_MAP_LOCATIONS (map)[2 * token_no + 1] = orig_parm_replacement_loc;
748 
749   result = MAP_START_LOCATION (map) + token_no;
750   return result;
751 }
752 
753 /* Return a location_t for the start (i.e. column==0) of
754    (physical) line TO_LINE in the current source file (as in the
755    most recent linemap_add).   MAX_COLUMN_HINT is the highest column
756    number we expect to use in this line (but it does not change
757    the highest_location).  */
758 
759 location_t
linemap_line_start(line_maps * set,linenum_type to_line,unsigned int max_column_hint)760 linemap_line_start (line_maps *set, linenum_type to_line,
761 		    unsigned int max_column_hint)
762 {
763   line_map_ordinary *map = LINEMAPS_LAST_ORDINARY_MAP (set);
764   location_t highest = set->highest_location;
765   location_t r;
766   linenum_type last_line =
767     SOURCE_LINE (map, set->highest_line);
768   int line_delta = to_line - last_line;
769   bool add_map = false;
770   linemap_assert (map->m_column_and_range_bits >= map->m_range_bits);
771   int effective_column_bits = map->m_column_and_range_bits - map->m_range_bits;
772 
773   if (line_delta < 0
774       || (line_delta > 10
775 	  && line_delta * map->m_column_and_range_bits > 1000)
776       || (max_column_hint >= (1U << effective_column_bits))
777       || (max_column_hint <= 80 && effective_column_bits >= 10)
778       || (highest > LINE_MAP_MAX_LOCATION_WITH_PACKED_RANGES
779 	  && map->m_range_bits > 0)
780       || (highest > LINE_MAP_MAX_LOCATION_WITH_COLS
781 	  && (set->max_column_hint || highest >= LINE_MAP_MAX_LOCATION)))
782     add_map = true;
783   else
784     max_column_hint = set->max_column_hint;
785   if (add_map)
786     {
787       int column_bits;
788       int range_bits;
789       if (max_column_hint > LINE_MAP_MAX_COLUMN_NUMBER
790 	  || highest > LINE_MAP_MAX_LOCATION_WITH_COLS)
791 	{
792 	  /* If the column number is ridiculous or we've allocated a huge
793 	     number of location_ts, give up on column numbers
794 	     (and on packed ranges).  */
795 	  max_column_hint = 1;
796 	  column_bits = 0;
797 	  range_bits = 0;
798 	  if (highest >= LINE_MAP_MAX_LOCATION)
799 	    goto overflowed;
800 	}
801       else
802 	{
803 	  column_bits = 7;
804 	  if (highest <= LINE_MAP_MAX_LOCATION_WITH_PACKED_RANGES)
805 	    range_bits = set->default_range_bits;
806 	  else
807 	    range_bits = 0;
808 	  while (max_column_hint >= (1U << column_bits))
809 	    column_bits++;
810 	  max_column_hint = 1U << column_bits;
811 	  column_bits += range_bits;
812 	}
813 
814       /* Allocate the new line_map.  However, if the current map only has a
815 	 single line we can sometimes just increase its column_bits instead. */
816       if (line_delta < 0
817 	  || last_line != ORDINARY_MAP_STARTING_LINE_NUMBER (map)
818 	  || SOURCE_COLUMN (map, highest) >= (1U << (column_bits - range_bits))
819 	  || ( /* We can't reuse the map if the line offset is sufficiently
820 		  large to cause overflow when computing location_t values.  */
821 	      (to_line - ORDINARY_MAP_STARTING_LINE_NUMBER (map))
822 	      >= (((uint64_t) 1)
823 		  << (CHAR_BIT * sizeof (linenum_type) - column_bits)))
824 	  || range_bits < map->m_range_bits)
825 	map = linemap_check_ordinary
826 	        (const_cast <line_map *>
827 		  (linemap_add (set, LC_RENAME,
828 				ORDINARY_MAP_IN_SYSTEM_HEADER_P (map),
829 				ORDINARY_MAP_FILE_NAME (map),
830 				to_line)));
831       map->m_column_and_range_bits = column_bits;
832       map->m_range_bits = range_bits;
833       r = (MAP_START_LOCATION (map)
834 	   + ((to_line - ORDINARY_MAP_STARTING_LINE_NUMBER (map))
835 	      << column_bits));
836     }
837   else
838     r = set->highest_line + (line_delta << map->m_column_and_range_bits);
839 
840   /* Locations of ordinary tokens are always lower than locations of
841      macro tokens.  */
842   if (r >= LINE_MAP_MAX_LOCATION)
843     {
844     overflowed:
845       /* Remember we overflowed.  */
846       set->highest_line = set->highest_location = LINE_MAP_MAX_LOCATION - 1;
847       /* No column numbers!  */
848       set->max_column_hint = 1;
849       return 0;
850     }
851 
852   set->highest_line = r;
853   if (r > set->highest_location)
854     set->highest_location = r;
855   set->max_column_hint = max_column_hint;
856 
857   /* At this point, we expect one of:
858      (a) the normal case: a "pure" location with 0 range bits, or
859      (b) we've gone past LINE_MAP_MAX_LOCATION_WITH_COLS so can't track
860         columns anymore (or ranges), or
861      (c) we're in a region with a column hint exceeding
862         LINE_MAP_MAX_COLUMN_NUMBER, so column-tracking is off,
863 	with column_bits == 0.  */
864   linemap_assert (pure_location_p (set, r)
865 		  || r >= LINE_MAP_MAX_LOCATION_WITH_COLS
866 		  || map->m_column_and_range_bits == 0);
867   linemap_assert (SOURCE_LINE (map, r) == to_line);
868   return r;
869 }
870 
871 /* Encode and return a location_t from a column number. The
872    source line considered is the last source line used to call
873    linemap_line_start, i.e, the last source line which a location was
874    encoded from.  */
875 
876 location_t
linemap_position_for_column(line_maps * set,unsigned int to_column)877 linemap_position_for_column (line_maps *set, unsigned int to_column)
878 {
879   location_t r = set->highest_line;
880 
881   linemap_assert
882     (!linemap_macro_expansion_map_p (LINEMAPS_LAST_ORDINARY_MAP (set)));
883 
884   if (to_column >= set->max_column_hint)
885     {
886       if (r > LINE_MAP_MAX_LOCATION_WITH_COLS
887 	  || to_column > LINE_MAP_MAX_COLUMN_NUMBER)
888 	{
889 	  /* Running low on location_ts - disable column numbers.  */
890 	  return r;
891 	}
892       else
893 	{
894 	  /* Otherwise, attempt to start a new line that can hold TO_COLUMN,
895 	     with some space to spare.  This may or may not lead to a new
896 	     linemap being created.  */
897 	  line_map_ordinary *map = LINEMAPS_LAST_ORDINARY_MAP (set);
898 	  r = linemap_line_start (set, SOURCE_LINE (map, r), to_column + 50);
899 	  map = LINEMAPS_LAST_ORDINARY_MAP (set);
900 	  if (map->m_column_and_range_bits == 0)
901 	    {
902 	      /* ...then the linemap has column-tracking disabled,
903 		 presumably due to exceeding either
904 		 LINE_MAP_MAX_LOCATION_WITH_COLS (overall) or
905 		 LINE_MAP_MAX_COLUMN_NUMBER (within this line).
906 		 Return the start of the linemap, which encodes column 0, for
907 		 the whole line.  */
908 	      return r;
909 	    }
910 	}
911     }
912   line_map_ordinary *map = LINEMAPS_LAST_ORDINARY_MAP (set);
913   r = r + (to_column << map->m_range_bits);
914   if (r >= set->highest_location)
915     set->highest_location = r;
916   return r;
917 }
918 
919 /* Encode and return a source location from a given line and
920    column.  */
921 
922 location_t
linemap_position_for_line_and_column(line_maps * set,const line_map_ordinary * ord_map,linenum_type line,unsigned column)923 linemap_position_for_line_and_column (line_maps *set,
924 				      const line_map_ordinary *ord_map,
925 				      linenum_type line,
926 				      unsigned column)
927 {
928   linemap_assert (ORDINARY_MAP_STARTING_LINE_NUMBER (ord_map) <= line);
929 
930   location_t r = MAP_START_LOCATION (ord_map);
931   r += ((line - ORDINARY_MAP_STARTING_LINE_NUMBER (ord_map))
932 	<< ord_map->m_column_and_range_bits);
933   if (r <= LINE_MAP_MAX_LOCATION_WITH_COLS)
934     r += ((column & ((1 << ord_map->m_column_and_range_bits) - 1))
935 	  << ord_map->m_range_bits);
936   location_t upper_limit = LINEMAPS_MACRO_LOWEST_LOCATION (set);
937   if (r >= upper_limit)
938     r = upper_limit - 1;
939   if (r > set->highest_location)
940     set->highest_location = r;
941   return r;
942 }
943 
944 /* Encode and return a location_t starting from location LOC and
945    shifting it by COLUMN_OFFSET columns.  This function does not support
946    virtual locations.  */
947 
948 location_t
linemap_position_for_loc_and_offset(line_maps * set,location_t loc,unsigned int column_offset)949 linemap_position_for_loc_and_offset (line_maps *set,
950 				     location_t loc,
951 				     unsigned int column_offset)
952 {
953   const line_map_ordinary * map = NULL;
954 
955   if (IS_ADHOC_LOC (loc))
956     loc = get_location_from_adhoc_loc (set, loc);
957 
958   /* This function does not support virtual locations yet.  */
959   if (linemap_location_from_macro_expansion_p (set, loc))
960     return loc;
961 
962   if (column_offset == 0
963       /* Adding an offset to a reserved location (like
964 	 UNKNOWN_LOCATION for the C/C++ FEs) does not really make
965 	 sense.  So let's leave the location intact in that case.  */
966       || loc < RESERVED_LOCATION_COUNT)
967     return loc;
968 
969   /* We find the real location and shift it.  */
970   loc = linemap_resolve_location (set, loc, LRK_SPELLING_LOCATION, &map);
971   /* The new location (loc + offset) should be higher than the first
972      location encoded by MAP.  This can fail if the line information
973      is messed up because of line directives (see PR66415).  */
974   if (MAP_START_LOCATION (map) >= loc + (column_offset << map->m_range_bits))
975     return loc;
976 
977   linenum_type line = SOURCE_LINE (map, loc);
978   unsigned int column = SOURCE_COLUMN (map, loc);
979 
980   /* If MAP is not the last line map of its set, then the new location
981      (loc + offset) should be less than the first location encoded by
982      the next line map of the set.  Otherwise, we try to encode the
983      location in the next map.  */
984   for (; map != LINEMAPS_LAST_ORDINARY_MAP (set)
985 	 && (loc + (column_offset << map->m_range_bits)
986 	     >= MAP_START_LOCATION (map + 1)); map++)
987     /* If the next map is a different file, or starts in a higher line, we
988        cannot encode the location there.  */
989     if ((map + 1)->reason != LC_RENAME
990 	|| line < ORDINARY_MAP_STARTING_LINE_NUMBER (map + 1)
991 	|| 0 != strcmp (LINEMAP_FILE (map + 1), LINEMAP_FILE (map)))
992       return loc;
993 
994   column += column_offset;
995 
996   /* Bail out if the column is not representable within the existing
997      linemap.  */
998   if (column >= (1u << (map->m_column_and_range_bits - map->m_range_bits)))
999     return loc;
1000 
1001   location_t r =
1002     linemap_position_for_line_and_column (set, map, line, column);
1003   if (linemap_assert_fails (r <= set->highest_location)
1004       || linemap_assert_fails (map == linemap_lookup (set, r)))
1005     return loc;
1006 
1007   return r;
1008 }
1009 
1010 /* Given a virtual source location yielded by a map (either an
1011    ordinary or a macro map), returns that map.  */
1012 
1013 const struct line_map*
linemap_lookup(const line_maps * set,location_t line)1014 linemap_lookup (const line_maps *set, location_t line)
1015 {
1016   if (IS_ADHOC_LOC (line))
1017     line = get_location_from_adhoc_loc (set, line);
1018   if (linemap_location_from_macro_expansion_p (set, line))
1019     return linemap_macro_map_lookup (set, line);
1020   return linemap_ordinary_map_lookup (set, line);
1021 }
1022 
1023 /* Given a source location yielded by an ordinary map, returns that
1024    map.  Since the set is built chronologically, the logical lines are
1025    monotonic increasing, and so the list is sorted and we can use a
1026    binary search.  */
1027 
1028 static const line_map_ordinary *
linemap_ordinary_map_lookup(const line_maps * set,location_t line)1029 linemap_ordinary_map_lookup (const line_maps *set, location_t line)
1030 {
1031   if (IS_ADHOC_LOC (line))
1032     line = get_location_from_adhoc_loc (set, line);
1033 
1034   if (set ==  NULL || line < RESERVED_LOCATION_COUNT)
1035     return NULL;
1036 
1037   unsigned mn = LINEMAPS_ORDINARY_CACHE (set);
1038   unsigned mx = LINEMAPS_ORDINARY_USED (set);
1039 
1040   const line_map_ordinary *cached = LINEMAPS_ORDINARY_MAP_AT (set, mn);
1041   /* We should get a segfault if no line_maps have been added yet.  */
1042   if (line >= MAP_START_LOCATION (cached))
1043     {
1044       if (mn + 1 == mx || line < MAP_START_LOCATION (&cached[1]))
1045 	return cached;
1046     }
1047   else
1048     {
1049       mx = mn;
1050       mn = 0;
1051     }
1052 
1053   while (mx - mn > 1)
1054     {
1055       unsigned md = (mn + mx) / 2;
1056       if (MAP_START_LOCATION (LINEMAPS_ORDINARY_MAP_AT (set, md)) > line)
1057 	mx = md;
1058       else
1059 	mn = md;
1060     }
1061 
1062   LINEMAPS_ORDINARY_CACHE (set) = mn;
1063   const line_map_ordinary *result = LINEMAPS_ORDINARY_MAP_AT (set, mn);
1064   linemap_assert (line >= MAP_START_LOCATION (result));
1065   return result;
1066 }
1067 
1068 /* Given a source location yielded by a macro map, returns that map.
1069    Since the set is built chronologically, the logical lines are
1070    monotonic decreasing, and so the list is sorted and we can use a
1071    binary search.  */
1072 
1073 static const line_map_macro *
linemap_macro_map_lookup(const line_maps * set,location_t line)1074 linemap_macro_map_lookup (const line_maps *set, location_t line)
1075 {
1076   if (IS_ADHOC_LOC (line))
1077     line = get_location_from_adhoc_loc (set, line);
1078 
1079   linemap_assert (line >= LINEMAPS_MACRO_LOWEST_LOCATION (set));
1080 
1081   if (set == NULL)
1082     return NULL;
1083 
1084   unsigned ix = linemap_lookup_macro_index (set, line);
1085   const struct line_map_macro *result = LINEMAPS_MACRO_MAP_AT (set, ix);
1086   linemap_assert (MAP_START_LOCATION (result) <= line);
1087 
1088   return result;
1089 }
1090 
1091 unsigned
linemap_lookup_macro_index(const line_maps * set,location_t line)1092 linemap_lookup_macro_index (const line_maps *set, location_t line)
1093 {
1094   unsigned mn = LINEMAPS_MACRO_CACHE (set);
1095   unsigned mx = LINEMAPS_MACRO_USED (set);
1096   const struct line_map_macro *cached = LINEMAPS_MACRO_MAP_AT (set, mn);
1097 
1098   if (line >= MAP_START_LOCATION (cached))
1099     {
1100       if (line < (MAP_START_LOCATION (cached)
1101 		  + MACRO_MAP_NUM_MACRO_TOKENS (cached)))
1102 	return mn;
1103       mx = mn - 1;
1104       mn = 0;
1105     }
1106 
1107   while (mn < mx)
1108     {
1109       unsigned md = (mx + mn) / 2;
1110       if (MAP_START_LOCATION (LINEMAPS_MACRO_MAP_AT (set, md)) > line)
1111 	mn = md + 1;
1112       else
1113 	mx = md;
1114     }
1115 
1116   LINEMAPS_MACRO_CACHE (set) = mx;
1117   return mx;
1118 }
1119 
1120 /* Return TRUE if MAP encodes locations coming from a macro
1121    replacement-list at macro expansion point.  */
1122 
1123 bool
linemap_macro_expansion_map_p(const struct line_map * map)1124 linemap_macro_expansion_map_p (const struct line_map *map)
1125 {
1126   return map && !MAP_ORDINARY_P (map);
1127 }
1128 
1129 /* If LOCATION is the locus of a token in a replacement-list of a
1130    macro expansion return the location of the macro expansion point.
1131 
1132    Read the comments of struct line_map and struct line_map_macro in
1133    line-map.h to understand what a macro expansion point is.  */
1134 
1135 static location_t
linemap_macro_map_loc_to_exp_point(const line_map_macro * map,location_t location ATTRIBUTE_UNUSED)1136 linemap_macro_map_loc_to_exp_point (const line_map_macro *map,
1137 				    location_t location ATTRIBUTE_UNUSED)
1138 {
1139   linemap_assert (linemap_macro_expansion_map_p (map)
1140 		  && location >= MAP_START_LOCATION (map));
1141 
1142   /* Make sure LOCATION is correct.  */
1143   linemap_assert ((location - MAP_START_LOCATION (map))
1144 		  <  MACRO_MAP_NUM_MACRO_TOKENS (map));
1145 
1146   return MACRO_MAP_EXPANSION_POINT_LOCATION (map);
1147 }
1148 
1149 /* LOCATION is the source location of a token that belongs to a macro
1150    replacement-list as part of the macro expansion denoted by MAP.
1151 
1152    Return the location of the token at the definition point of the
1153    macro.  */
1154 
1155 static location_t
linemap_macro_map_loc_to_def_point(const line_map_macro * map,location_t location)1156 linemap_macro_map_loc_to_def_point (const line_map_macro *map,
1157 				    location_t location)
1158 {
1159   unsigned token_no;
1160 
1161   linemap_assert (linemap_macro_expansion_map_p (map)
1162 		  && location >= MAP_START_LOCATION (map));
1163   linemap_assert (location >= RESERVED_LOCATION_COUNT);
1164 
1165   token_no = location - MAP_START_LOCATION (map);
1166   linemap_assert (token_no < MACRO_MAP_NUM_MACRO_TOKENS (map));
1167 
1168   location = MACRO_MAP_LOCATIONS (map)[2 * token_no + 1];
1169 
1170   return location;
1171 }
1172 
1173 /* If LOCATION is the locus of a token that is an argument of a
1174    function-like macro M and appears in the expansion of M, return the
1175    locus of that argument in the context of the caller of M.
1176 
1177    In other words, this returns the xI location presented in the
1178    comments of line_map_macro above.  */
1179 location_t
linemap_macro_map_loc_unwind_toward_spelling(line_maps * set,const line_map_macro * map,location_t location)1180 linemap_macro_map_loc_unwind_toward_spelling (line_maps *set,
1181 					      const line_map_macro* map,
1182 					      location_t location)
1183 {
1184   unsigned token_no;
1185 
1186   if (IS_ADHOC_LOC (location))
1187     location = get_location_from_adhoc_loc (set, location);
1188 
1189   linemap_assert (linemap_macro_expansion_map_p (map)
1190 		  && location >= MAP_START_LOCATION (map));
1191   linemap_assert (location >= RESERVED_LOCATION_COUNT);
1192   linemap_assert (!IS_ADHOC_LOC (location));
1193 
1194   token_no = location - MAP_START_LOCATION (map);
1195   linemap_assert (token_no < MACRO_MAP_NUM_MACRO_TOKENS (map));
1196 
1197   location = MACRO_MAP_LOCATIONS (map)[2 * token_no];
1198 
1199   return location;
1200 }
1201 
1202 /* Return the source line number corresponding to source location
1203    LOCATION.  SET is the line map set LOCATION comes from.  If
1204    LOCATION is the source location of token that is part of the
1205    replacement-list of a macro expansion return the line number of the
1206    macro expansion point.  */
1207 
1208 int
linemap_get_expansion_line(line_maps * set,location_t location)1209 linemap_get_expansion_line (line_maps *set,
1210 			    location_t location)
1211 {
1212   const line_map_ordinary *map = NULL;
1213 
1214   if (IS_ADHOC_LOC (location))
1215     location = get_location_from_adhoc_loc (set, location);
1216 
1217   if (location < RESERVED_LOCATION_COUNT)
1218     return 0;
1219 
1220   location =
1221     linemap_macro_loc_to_exp_point (set, location, &map);
1222 
1223   return SOURCE_LINE (map, location);
1224 }
1225 
1226 /* Return the path of the file corresponding to source code location
1227    LOCATION.
1228 
1229    If LOCATION is the source location of token that is part of the
1230    replacement-list of a macro expansion return the file path of the
1231    macro expansion point.
1232 
1233    SET is the line map set LOCATION comes from.  */
1234 
1235 const char*
linemap_get_expansion_filename(line_maps * set,location_t location)1236 linemap_get_expansion_filename (line_maps *set,
1237 				location_t location)
1238 {
1239   const struct line_map_ordinary *map = NULL;
1240 
1241   if (IS_ADHOC_LOC (location))
1242     location = get_location_from_adhoc_loc (set, location);
1243 
1244   if (location < RESERVED_LOCATION_COUNT)
1245     return NULL;
1246 
1247   linemap_macro_loc_to_exp_point (set, location, &map);
1248 
1249   return LINEMAP_FILE (map);
1250 }
1251 
1252 /* Return the name of the macro associated to MACRO_MAP.  */
1253 
1254 const char*
linemap_map_get_macro_name(const line_map_macro * macro_map)1255 linemap_map_get_macro_name (const line_map_macro *macro_map)
1256 {
1257   linemap_assert (macro_map && linemap_macro_expansion_map_p (macro_map));
1258   return (const char*) NODE_NAME (MACRO_MAP_MACRO (macro_map));
1259 }
1260 
1261 /* Return a positive value if LOCATION is the locus of a token that is
1262    located in a system header, O otherwise. It returns 1 if LOCATION
1263    is the locus of a token that is located in a system header, and 2
1264    if LOCATION is the locus of a token located in a C system header
1265    that therefore needs to be extern "C" protected in C++.
1266 
1267    Note that this function returns 1 if LOCATION belongs to a token
1268    that is part of a macro replacement-list defined in a system
1269    header, but expanded in a non-system file.  */
1270 
1271 int
linemap_location_in_system_header_p(line_maps * set,location_t location)1272 linemap_location_in_system_header_p (line_maps *set,
1273 				     location_t location)
1274 {
1275   const struct line_map *map = NULL;
1276 
1277   if (IS_ADHOC_LOC (location))
1278     location = get_location_from_adhoc_loc (set, location);
1279 
1280   if (location < RESERVED_LOCATION_COUNT)
1281     return false;
1282 
1283   /* Let's look at where the token for LOCATION comes from.  */
1284   while (true)
1285     {
1286       map = linemap_lookup (set, location);
1287       if (map != NULL)
1288 	{
1289 	  if (!linemap_macro_expansion_map_p (map))
1290 	    /* It's a normal token.  */
1291 	    return LINEMAP_SYSP (linemap_check_ordinary (map));
1292 	  else
1293 	    {
1294 	      const line_map_macro *macro_map = linemap_check_macro (map);
1295 
1296 	      /* It's a token resulting from a macro expansion.  */
1297 	      location_t loc =
1298 		linemap_macro_map_loc_unwind_toward_spelling (set, macro_map, location);
1299 	      if (loc < RESERVED_LOCATION_COUNT)
1300 		/* This token might come from a built-in macro.  Let's
1301 		   look at where that macro got expanded.  */
1302 		location = linemap_macro_map_loc_to_exp_point (macro_map, location);
1303 	      else
1304 		location = loc;
1305 	    }
1306 	}
1307       else
1308 	break;
1309     }
1310   return false;
1311 }
1312 
1313 /* Return TRUE if LOCATION is a source code location of a token that is part of
1314    a macro expansion, FALSE otherwise.  */
1315 
1316 bool
linemap_location_from_macro_expansion_p(const class line_maps * set,location_t location)1317 linemap_location_from_macro_expansion_p (const class line_maps *set,
1318 					 location_t location)
1319 {
1320   if (IS_ADHOC_LOC (location))
1321     location = get_location_from_adhoc_loc (set, location);
1322 
1323   return location >= LINEMAPS_MACRO_LOWEST_LOCATION (set);
1324 }
1325 
1326 /* Given two virtual locations *LOC0 and *LOC1, return the first
1327    common macro map in their macro expansion histories.  Return NULL
1328    if no common macro was found.  *LOC0 (resp. *LOC1) is set to the
1329    virtual location of the token inside the resulting macro.  */
1330 
1331 static const struct line_map*
first_map_in_common_1(line_maps * set,location_t * loc0,location_t * loc1)1332 first_map_in_common_1 (line_maps *set,
1333 		       location_t *loc0,
1334 		       location_t *loc1)
1335 {
1336   location_t l0 = *loc0, l1 = *loc1;
1337   const struct line_map *map0 = linemap_lookup (set, l0);
1338   if (IS_ADHOC_LOC (l0))
1339     l0 = get_location_from_adhoc_loc (set, l0);
1340 
1341   const struct line_map *map1 = linemap_lookup (set, l1);
1342   if (IS_ADHOC_LOC (l1))
1343     l1 = get_location_from_adhoc_loc (set, l1);
1344 
1345   while (linemap_macro_expansion_map_p (map0)
1346 	 && linemap_macro_expansion_map_p (map1)
1347 	 && (map0 != map1))
1348     {
1349       if (MAP_START_LOCATION (map0) < MAP_START_LOCATION (map1))
1350 	{
1351 	  l0 = linemap_macro_map_loc_to_exp_point (linemap_check_macro (map0),
1352 						   l0);
1353 	  map0 = linemap_lookup (set, l0);
1354 	}
1355       else
1356 	{
1357 	  l1 = linemap_macro_map_loc_to_exp_point (linemap_check_macro (map1),
1358 						   l1);
1359 	  map1 = linemap_lookup (set, l1);
1360 	}
1361     }
1362 
1363   if (map0 == map1)
1364     {
1365       *loc0 = l0;
1366       *loc1 = l1;
1367       return map0;
1368     }
1369   return NULL;
1370 }
1371 
1372 /* Given two virtual locations LOC0 and LOC1, return the first common
1373    macro map in their macro expansion histories.  Return NULL if no
1374    common macro was found.  *RES_LOC0 (resp. *RES_LOC1) is set to the
1375    virtual location of the token inside the resulting macro, upon
1376    return of a non-NULL result.  */
1377 
1378 const struct line_map*
first_map_in_common(line_maps * set,location_t loc0,location_t loc1,location_t * res_loc0,location_t * res_loc1)1379 first_map_in_common (line_maps *set,
1380 		     location_t loc0,
1381 		     location_t loc1,
1382 		     location_t  *res_loc0,
1383 		     location_t  *res_loc1)
1384 {
1385   *res_loc0 = loc0;
1386   *res_loc1 = loc1;
1387 
1388   return first_map_in_common_1 (set, res_loc0, res_loc1);
1389 }
1390 
1391 /* Return a positive value if PRE denotes the location of a token that
1392    comes before the token of POST, 0 if PRE denotes the location of
1393    the same token as the token for POST, and a negative value
1394    otherwise.  */
1395 
1396 int
linemap_compare_locations(line_maps * set,location_t pre,location_t post)1397 linemap_compare_locations (line_maps *set,
1398 			   location_t  pre,
1399 			   location_t post)
1400 {
1401   bool pre_virtual_p, post_virtual_p;
1402   location_t l0 = pre, l1 = post;
1403 
1404   if (IS_ADHOC_LOC (l0))
1405     l0 = get_location_from_adhoc_loc (set, l0);
1406   if (IS_ADHOC_LOC (l1))
1407     l1 = get_location_from_adhoc_loc (set, l1);
1408 
1409   if (l0 == l1)
1410     return 0;
1411 
1412   if ((pre_virtual_p = linemap_location_from_macro_expansion_p (set, l0)))
1413     l0 = linemap_resolve_location (set, l0,
1414 				   LRK_MACRO_EXPANSION_POINT,
1415 				   NULL);
1416 
1417   if ((post_virtual_p = linemap_location_from_macro_expansion_p (set, l1)))
1418     l1 = linemap_resolve_location (set, l1,
1419 				   LRK_MACRO_EXPANSION_POINT,
1420 				   NULL);
1421 
1422   if (l0 == l1
1423       && pre_virtual_p
1424       && post_virtual_p)
1425     {
1426       /* So pre and post represent two tokens that are present in a
1427 	 same macro expansion.  Let's see if the token for pre was
1428 	 before the token for post in that expansion.  */
1429       const struct line_map *map =
1430 	first_map_in_common (set, pre, post, &l0, &l1);
1431 
1432       if (map == NULL)
1433 	/* This should not be possible while we have column information, but if
1434 	   we don't, the tokens could be from separate macro expansions on the
1435 	   same line.  */
1436 	gcc_assert (l0 > LINE_MAP_MAX_LOCATION_WITH_COLS);
1437       else
1438 	{
1439 	  unsigned i0 = l0 - MAP_START_LOCATION (map);
1440 	  unsigned i1 = l1 - MAP_START_LOCATION (map);
1441 	  return i1 - i0;
1442 	}
1443     }
1444 
1445   if (IS_ADHOC_LOC (l0))
1446     l0 = get_location_from_adhoc_loc (set, l0);
1447   if (IS_ADHOC_LOC (l1))
1448     l1 = get_location_from_adhoc_loc (set, l1);
1449 
1450   return l1 - l0;
1451 }
1452 
1453 /* Print an include trace, for e.g. the -H option of the preprocessor.  */
1454 
1455 static void
trace_include(const class line_maps * set,const line_map_ordinary * map)1456 trace_include (const class line_maps *set, const line_map_ordinary *map)
1457 {
1458   unsigned int i = set->depth;
1459 
1460   while (--i)
1461     putc ('.', stderr);
1462 
1463   fprintf (stderr, " %s\n", ORDINARY_MAP_FILE_NAME (map));
1464 }
1465 
1466 /* Return the spelling location of the token wherever it comes from,
1467    whether part of a macro definition or not.
1468 
1469    This is a subroutine for linemap_resolve_location.  */
1470 
1471 static location_t
linemap_macro_loc_to_spelling_point(line_maps * set,location_t location,const line_map_ordinary ** original_map)1472 linemap_macro_loc_to_spelling_point (line_maps *set,
1473 				     location_t location,
1474 				     const line_map_ordinary **original_map)
1475 {
1476   linemap_assert (set && location >= RESERVED_LOCATION_COUNT);
1477 
1478   while (true)
1479     {
1480       const struct line_map *map = linemap_lookup (set, location);
1481       if (!map || MAP_ORDINARY_P (map))
1482 	{
1483 	  if (original_map)
1484 	    *original_map = (const line_map_ordinary *)map;
1485 	  break;
1486 	}
1487 
1488       location = linemap_macro_map_loc_unwind_toward_spelling
1489 	(set, linemap_check_macro (map), location);
1490     }
1491 
1492   return location;
1493 }
1494 
1495 /* If LOCATION is the source location of a token that belongs to a
1496    macro replacement-list -- as part of a macro expansion -- then
1497    return the location of the token at the definition point of the
1498    macro.  Otherwise, return LOCATION.  SET is the set of maps
1499    location come from.  ORIGINAL_MAP is an output parm. If non NULL,
1500    the function sets *ORIGINAL_MAP to the ordinary (non-macro) map the
1501    returned location comes from.
1502 
1503    This is a subroutine of linemap_resolve_location.  */
1504 
1505 static location_t
linemap_macro_loc_to_def_point(line_maps * set,location_t location,const line_map_ordinary ** original_map)1506 linemap_macro_loc_to_def_point (line_maps *set,
1507 				location_t location,
1508 				const line_map_ordinary **original_map)
1509 {
1510   linemap_assert (set && location >= RESERVED_LOCATION_COUNT);
1511 
1512   for (;;)
1513     {
1514       location_t caret_loc = location;
1515       if (IS_ADHOC_LOC (caret_loc))
1516 	caret_loc = get_location_from_adhoc_loc (set, caret_loc);
1517 
1518       const line_map *map = linemap_lookup (set, caret_loc);
1519       if (!map || MAP_ORDINARY_P (map))
1520 	{
1521 	  if (original_map)
1522 	    *original_map = (const line_map_ordinary *)map;
1523 	  break;
1524 	}
1525 
1526       location = linemap_macro_map_loc_to_def_point
1527 	(linemap_check_macro (map), caret_loc);
1528     }
1529 
1530   return location;
1531 }
1532 
1533 /* If LOCATION is the source location of a token that belongs to a
1534    macro replacement-list -- at a macro expansion point -- then return
1535    the location of the topmost expansion point of the macro.  We say
1536    topmost because if we are in the context of a nested macro
1537    expansion, the function returns the source location of the first
1538    macro expansion that triggered the nested expansions.
1539 
1540    Otherwise, return LOCATION.  SET is the set of maps location come
1541    from.  ORIGINAL_MAP is an output parm. If non NULL, the function
1542    sets *ORIGINAL_MAP to the ordinary (non-macro) map the returned
1543    location comes from.
1544 
1545    This is a subroutine of linemap_resolve_location.  */
1546 
1547 static location_t
linemap_macro_loc_to_exp_point(line_maps * set,location_t location,const line_map_ordinary ** original_map)1548 linemap_macro_loc_to_exp_point (line_maps *set,
1549 				location_t location,
1550 				const line_map_ordinary **original_map)
1551 {
1552   struct line_map *map;
1553 
1554   if (IS_ADHOC_LOC (location))
1555     location = get_location_from_adhoc_loc (set, location);
1556 
1557   linemap_assert (set && location >= RESERVED_LOCATION_COUNT);
1558 
1559   while (true)
1560     {
1561       map = const_cast <line_map *> (linemap_lookup (set, location));
1562       if (!linemap_macro_expansion_map_p (map))
1563 	break;
1564       location = linemap_macro_map_loc_to_exp_point (linemap_check_macro (map),
1565 						     location);
1566     }
1567 
1568   if (original_map)
1569     *original_map = linemap_check_ordinary (map);
1570   return location;
1571 }
1572 
1573 /* Resolve a virtual location into either a spelling location, an
1574    expansion point location or a token argument replacement point
1575    location.  Return the map that encodes the virtual location as well
1576    as the resolved location.
1577 
1578    If LOC is *NOT* the location of a token resulting from the
1579    expansion of a macro, then the parameter LRK (which stands for
1580    Location Resolution Kind) is ignored and the resulting location
1581    just equals the one given in argument.
1582 
1583    Now if LOC *IS* the location of a token resulting from the
1584    expansion of a macro, this is what happens.
1585 
1586    * If LRK is set to LRK_MACRO_EXPANSION_POINT
1587    -------------------------------
1588 
1589    The virtual location is resolved to the first macro expansion point
1590    that led to this macro expansion.
1591 
1592    * If LRK is set to LRK_SPELLING_LOCATION
1593    -------------------------------------
1594 
1595    The virtual location is resolved to the locus where the token has
1596    been spelled in the source.   This can follow through all the macro
1597    expansions that led to the token.
1598 
1599    * If LRK is set to LRK_MACRO_DEFINITION_LOCATION
1600    --------------------------------------
1601 
1602    The virtual location is resolved to the locus of the token in the
1603    context of the macro definition.
1604 
1605    If LOC is the locus of a token that is an argument of a
1606    function-like macro [replacing a parameter in the replacement list
1607    of the macro] the virtual location is resolved to the locus of the
1608    parameter that is replaced, in the context of the definition of the
1609    macro.
1610 
1611    If LOC is the locus of a token that is not an argument of a
1612    function-like macro, then the function behaves as if LRK was set to
1613    LRK_SPELLING_LOCATION.
1614 
1615    If MAP is not NULL, *MAP is set to the map encoding the
1616    returned location.  Note that if the returned location wasn't originally
1617    encoded by a map, then *MAP is set to NULL.  This can happen if LOC
1618    resolves to a location reserved for the client code, like
1619    UNKNOWN_LOCATION or BUILTINS_LOCATION in GCC.  */
1620 
1621 location_t
linemap_resolve_location(line_maps * set,location_t loc,enum location_resolution_kind lrk,const line_map_ordinary ** map)1622 linemap_resolve_location (line_maps *set,
1623 			  location_t loc,
1624 			  enum location_resolution_kind lrk,
1625 			  const line_map_ordinary **map)
1626 {
1627   location_t locus = loc;
1628   if (IS_ADHOC_LOC (loc))
1629     locus = get_location_from_adhoc_loc (set, loc);
1630 
1631   if (locus < RESERVED_LOCATION_COUNT)
1632     {
1633       /* A reserved location wasn't encoded in a map.  Let's return a
1634 	 NULL map here, just like what linemap_ordinary_map_lookup
1635 	 does.  */
1636       if (map)
1637 	*map = NULL;
1638       return loc;
1639     }
1640 
1641   switch (lrk)
1642     {
1643     case LRK_MACRO_EXPANSION_POINT:
1644       loc = linemap_macro_loc_to_exp_point (set, loc, map);
1645       break;
1646     case LRK_SPELLING_LOCATION:
1647       loc = linemap_macro_loc_to_spelling_point (set, loc, map);
1648       break;
1649     case LRK_MACRO_DEFINITION_LOCATION:
1650       loc = linemap_macro_loc_to_def_point (set, loc, map);
1651       break;
1652     default:
1653       abort ();
1654     }
1655   return loc;
1656 }
1657 
1658 /* TRUE if LOCATION is a source code location of a token that is part of the
1659    definition of a macro, FALSE otherwise.  */
1660 
1661 bool
linemap_location_from_macro_definition_p(line_maps * set,location_t loc)1662 linemap_location_from_macro_definition_p (line_maps *set,
1663 					  location_t loc)
1664 {
1665   if (IS_ADHOC_LOC (loc))
1666     loc = get_location_from_adhoc_loc (set, loc);
1667 
1668   if (!linemap_location_from_macro_expansion_p (set, loc))
1669     return false;
1670 
1671   while (true)
1672     {
1673       const struct line_map_macro *map
1674 	= linemap_check_macro (linemap_lookup (set, loc));
1675 
1676       location_t s_loc
1677 	= linemap_macro_map_loc_unwind_toward_spelling (set, map, loc);
1678       if (linemap_location_from_macro_expansion_p (set, s_loc))
1679 	loc = s_loc;
1680       else
1681 	{
1682 	  location_t def_loc
1683 	    = linemap_macro_map_loc_to_def_point (map, loc);
1684 	  return s_loc == def_loc;
1685 	}
1686     }
1687 }
1688 
1689 /*
1690    Suppose that LOC is the virtual location of a token T coming from
1691    the expansion of a macro M.  This function then steps up to get the
1692    location L of the point where M got expanded.  If L is a spelling
1693    location inside a macro expansion M', then this function returns
1694    the locus of the point where M' was expanded.  Said otherwise, this
1695    function returns the location of T in the context that triggered
1696    the expansion of M.
1697 
1698    *LOC_MAP must be set to the map of LOC.  This function then sets it
1699    to the map of the returned location.  */
1700 
1701 location_t
linemap_unwind_toward_expansion(line_maps * set,location_t loc,const struct line_map ** map)1702 linemap_unwind_toward_expansion (line_maps *set,
1703 				 location_t loc,
1704 				 const struct line_map **map)
1705 {
1706   location_t resolved_location;
1707   const line_map_macro *macro_map = linemap_check_macro (*map);
1708   const struct line_map *resolved_map;
1709 
1710   if (IS_ADHOC_LOC (loc))
1711     loc = get_location_from_adhoc_loc (set, loc);
1712 
1713   resolved_location =
1714     linemap_macro_map_loc_unwind_toward_spelling (set, macro_map, loc);
1715   resolved_map = linemap_lookup (set, resolved_location);
1716 
1717   if (!linemap_macro_expansion_map_p (resolved_map))
1718     {
1719       resolved_location = linemap_macro_map_loc_to_exp_point (macro_map, loc);
1720       resolved_map = linemap_lookup (set, resolved_location);
1721     }
1722 
1723   *map = resolved_map;
1724   return resolved_location;
1725 }
1726 
1727 /* If LOC is the virtual location of a token coming from the expansion
1728    of a macro M and if its spelling location is reserved (e.g, a
1729    location for a built-in token), then this function unwinds (using
1730    linemap_unwind_toward_expansion) the location until a location that
1731    is not reserved and is not in a system header is reached.  In other
1732    words, this unwinds the reserved location until a location that is
1733    in real source code is reached.
1734 
1735    Otherwise, if the spelling location for LOC is not reserved or if
1736    LOC doesn't come from the expansion of a macro, the function
1737    returns LOC as is and *MAP is not touched.
1738 
1739    *MAP is set to the map of the returned location if the later is
1740    different from LOC.  */
1741 location_t
linemap_unwind_to_first_non_reserved_loc(line_maps * set,location_t loc,const struct line_map ** map)1742 linemap_unwind_to_first_non_reserved_loc (line_maps *set,
1743 					  location_t loc,
1744 					  const struct line_map **map)
1745 {
1746   location_t resolved_loc;
1747   const struct line_map *map0 = NULL;
1748   const line_map_ordinary *map1 = NULL;
1749 
1750   if (IS_ADHOC_LOC (loc))
1751     loc = get_location_from_adhoc_loc (set, loc);
1752 
1753   map0 = linemap_lookup (set, loc);
1754   if (!linemap_macro_expansion_map_p (map0))
1755     return loc;
1756 
1757   resolved_loc = linemap_resolve_location (set, loc,
1758 					   LRK_SPELLING_LOCATION,
1759 					   &map1);
1760 
1761   if (resolved_loc >= RESERVED_LOCATION_COUNT
1762       && !LINEMAP_SYSP (map1))
1763     return loc;
1764 
1765   while (linemap_macro_expansion_map_p (map0)
1766 	 && (resolved_loc < RESERVED_LOCATION_COUNT
1767 	     || LINEMAP_SYSP (map1)))
1768     {
1769       loc = linemap_unwind_toward_expansion (set, loc, &map0);
1770       resolved_loc = linemap_resolve_location (set, loc,
1771 					       LRK_SPELLING_LOCATION,
1772 					       &map1);
1773     }
1774 
1775   if (map != NULL)
1776     *map = map0;
1777   return loc;
1778 }
1779 
1780 /* Expand source code location LOC and return a user readable source
1781    code location.  LOC must be a spelling (non-virtual) location.  If
1782    it's a location < RESERVED_LOCATION_COUNT a zeroed expanded source
1783    location is returned.  */
1784 
1785 expanded_location
linemap_expand_location(line_maps * set,const struct line_map * map,location_t loc)1786 linemap_expand_location (line_maps *set,
1787 			 const struct line_map *map,
1788 			 location_t loc)
1789 
1790 {
1791   expanded_location xloc;
1792 
1793   memset (&xloc, 0, sizeof (xloc));
1794   if (IS_ADHOC_LOC (loc))
1795     {
1796       xloc.data = get_data_from_adhoc_loc (set, loc);
1797       loc = get_location_from_adhoc_loc (set, loc);
1798     }
1799 
1800   if (loc < RESERVED_LOCATION_COUNT)
1801     /* The location for this token wasn't generated from a line map.
1802        It was probably a location for a builtin token, chosen by some
1803        client code.  Let's not try to expand the location in that
1804        case.  */;
1805   else if (map == NULL)
1806     /* We shouldn't be getting a NULL map with a location that is not
1807        reserved by the client code.  */
1808     abort ();
1809   else
1810     {
1811       /* MAP must be an ordinary map and LOC must be non-virtual,
1812 	 encoded into this map, obviously; the accessors used on MAP
1813 	 below ensure it is ordinary.  Let's just assert the
1814 	 non-virtualness of LOC here.  */
1815       if (linemap_location_from_macro_expansion_p (set, loc))
1816 	abort ();
1817 
1818       const line_map_ordinary *ord_map = linemap_check_ordinary (map);
1819 
1820       xloc.file = LINEMAP_FILE (ord_map);
1821       xloc.line = SOURCE_LINE (ord_map, loc);
1822       xloc.column = SOURCE_COLUMN (ord_map, loc);
1823       xloc.sysp = LINEMAP_SYSP (ord_map) != 0;
1824     }
1825 
1826   return xloc;
1827 }
1828 
1829 
1830 /* Dump line map at index IX in line table SET to STREAM.  If STREAM
1831    is NULL, use stderr.  IS_MACRO is true if the caller wants to
1832    dump a macro map, false otherwise.  */
1833 
1834 void
linemap_dump(FILE * stream,class line_maps * set,unsigned ix,bool is_macro)1835 linemap_dump (FILE *stream, class line_maps *set, unsigned ix, bool is_macro)
1836 {
1837   const char *const lc_reasons_v[LC_HWM]
1838       = { "LC_ENTER", "LC_LEAVE", "LC_RENAME", "LC_RENAME_VERBATIM",
1839 	  "LC_ENTER_MACRO", "LC_MODULE" };
1840   const line_map *map;
1841   unsigned reason;
1842 
1843   if (stream == NULL)
1844     stream = stderr;
1845 
1846   if (!is_macro)
1847     {
1848       map = LINEMAPS_ORDINARY_MAP_AT (set, ix);
1849       reason = linemap_check_ordinary (map)->reason;
1850     }
1851   else
1852     {
1853       map = LINEMAPS_MACRO_MAP_AT (set, ix);
1854       reason = LC_ENTER_MACRO;
1855     }
1856 
1857   fprintf (stream, "Map #%u [%p] - LOC: %u - REASON: %s - SYSP: %s\n",
1858 	   ix, (void *) map, map->start_location,
1859 	   reason < LC_HWM ? lc_reasons_v[reason] : "???",
1860 	   ((!is_macro
1861 	     && ORDINARY_MAP_IN_SYSTEM_HEADER_P (linemap_check_ordinary (map)))
1862 	    ? "yes" : "no"));
1863   if (!is_macro)
1864     {
1865       const line_map_ordinary *ord_map = linemap_check_ordinary (map);
1866       const line_map_ordinary *includer_map
1867 	= linemap_included_from_linemap (set, ord_map);
1868 
1869       fprintf (stream, "File: %s:%d\n", ORDINARY_MAP_FILE_NAME (ord_map),
1870 	       ORDINARY_MAP_STARTING_LINE_NUMBER (ord_map));
1871       fprintf (stream, "Included from: [%d] %s\n",
1872 	       includer_map ? int (includer_map - set->info_ordinary.maps) : -1,
1873 	       includer_map ? ORDINARY_MAP_FILE_NAME (includer_map) : "None");
1874     }
1875   else
1876     {
1877       const line_map_macro *macro_map = linemap_check_macro (map);
1878       fprintf (stream, "Macro: %s (%u tokens)\n",
1879 	       linemap_map_get_macro_name (macro_map),
1880 	       MACRO_MAP_NUM_MACRO_TOKENS (macro_map));
1881     }
1882 
1883   fprintf (stream, "\n");
1884 }
1885 
1886 
1887 /* Dump debugging information about source location LOC into the file
1888    stream STREAM. SET is the line map set LOC comes from.  */
1889 
1890 void
linemap_dump_location(line_maps * set,location_t loc,FILE * stream)1891 linemap_dump_location (line_maps *set,
1892 		       location_t loc,
1893 		       FILE *stream)
1894 {
1895   const line_map_ordinary *map;
1896   location_t location;
1897   const char *path = "", *from = "";
1898   int l = -1, c = -1, s = -1, e = -1;
1899 
1900   if (IS_ADHOC_LOC (loc))
1901     loc = get_location_from_adhoc_loc (set, loc);
1902 
1903   if (loc == 0)
1904     return;
1905 
1906   location =
1907     linemap_resolve_location (set, loc, LRK_MACRO_DEFINITION_LOCATION, &map);
1908 
1909   if (map == NULL)
1910     /* Only reserved locations can be tolerated in this case.  */
1911     linemap_assert (location < RESERVED_LOCATION_COUNT);
1912   else
1913     {
1914       path = LINEMAP_FILE (map);
1915       l = SOURCE_LINE (map, location);
1916       c = SOURCE_COLUMN (map, location);
1917       s = LINEMAP_SYSP (map) != 0;
1918       e = location != loc;
1919       if (e)
1920 	from = "N/A";
1921       else
1922 	{
1923 	  const line_map_ordinary *from_map
1924 	    = linemap_included_from_linemap (set, map);
1925 	  from = from_map ? LINEMAP_FILE (from_map) : "<NULL>";
1926 	}
1927     }
1928 
1929   /* P: path, L: line, C: column, S: in-system-header, M: map address,
1930      E: macro expansion?, LOC: original location, R: resolved location   */
1931   fprintf (stream, "{P:%s;F:%s;L:%d;C:%d;S:%d;M:%p;E:%d,LOC:%d,R:%d}",
1932 	   path, from, l, c, s, (void*)map, e, loc, location);
1933 }
1934 
1935 /* Return the highest location emitted for a given file for which
1936    there is a line map in SET.  FILE_NAME is the file name to
1937    consider.  If the function returns TRUE, *LOC is set to the highest
1938    location emitted for that file.  */
1939 
1940 bool
linemap_get_file_highest_location(line_maps * set,const char * file_name,location_t * loc)1941 linemap_get_file_highest_location (line_maps *set,
1942 				   const char *file_name,
1943 				   location_t *loc)
1944 {
1945   /* If the set is empty or no ordinary map has been created then
1946      there is no file to look for ...  */
1947   if (set == NULL || set->info_ordinary.used == 0)
1948     return false;
1949 
1950   /* Now look for the last ordinary map created for FILE_NAME.  */
1951   int i;
1952   for (i = set->info_ordinary.used - 1; i >= 0; --i)
1953     {
1954       const char *fname = set->info_ordinary.maps[i].to_file;
1955       if (fname && !filename_cmp (fname, file_name))
1956 	break;
1957     }
1958 
1959   if (i < 0)
1960     return false;
1961 
1962   /* The highest location for a given map is either the starting
1963      location of the next map minus one, or -- if the map is the
1964      latest one -- the highest location of the set.  */
1965   location_t result;
1966   if (i == (int) set->info_ordinary.used - 1)
1967     result = set->highest_location;
1968   else
1969     result = set->info_ordinary.maps[i + 1].start_location - 1;
1970 
1971   *loc = result;
1972   return true;
1973 }
1974 
1975 /* Compute and return statistics about the memory consumption of some
1976    parts of the line table SET.  */
1977 
1978 void
linemap_get_statistics(line_maps * set,struct linemap_stats * s)1979 linemap_get_statistics (line_maps *set,
1980 			struct linemap_stats *s)
1981 {
1982   long ordinary_maps_allocated_size, ordinary_maps_used_size,
1983     macro_maps_allocated_size, macro_maps_used_size,
1984     macro_maps_locations_size = 0, duplicated_macro_maps_locations_size = 0;
1985 
1986   const line_map_macro *cur_map;
1987 
1988   ordinary_maps_allocated_size =
1989     LINEMAPS_ORDINARY_ALLOCATED (set) * sizeof (struct line_map_ordinary);
1990 
1991   ordinary_maps_used_size =
1992     LINEMAPS_ORDINARY_USED (set) * sizeof (struct line_map_ordinary);
1993 
1994   macro_maps_allocated_size =
1995     LINEMAPS_MACRO_ALLOCATED (set) * sizeof (struct line_map_macro);
1996 
1997   for (cur_map = LINEMAPS_MACRO_MAPS (set);
1998        cur_map && cur_map <= LINEMAPS_LAST_MACRO_MAP (set);
1999        ++cur_map)
2000     {
2001       unsigned i;
2002 
2003       linemap_assert (linemap_macro_expansion_map_p (cur_map));
2004 
2005       macro_maps_locations_size +=
2006 	2 * MACRO_MAP_NUM_MACRO_TOKENS (cur_map) * sizeof (location_t);
2007 
2008       for (i = 0; i < 2 * MACRO_MAP_NUM_MACRO_TOKENS (cur_map); i += 2)
2009 	{
2010 	  if (MACRO_MAP_LOCATIONS (cur_map)[i] ==
2011 	      MACRO_MAP_LOCATIONS (cur_map)[i + 1])
2012 	    duplicated_macro_maps_locations_size +=
2013 	      sizeof (location_t);
2014 	}
2015     }
2016 
2017   macro_maps_used_size =
2018     LINEMAPS_MACRO_USED (set) * sizeof (struct line_map_macro);
2019 
2020   s->num_ordinary_maps_allocated = LINEMAPS_ORDINARY_ALLOCATED (set);
2021   s->num_ordinary_maps_used = LINEMAPS_ORDINARY_USED (set);
2022   s->ordinary_maps_allocated_size = ordinary_maps_allocated_size;
2023   s->ordinary_maps_used_size = ordinary_maps_used_size;
2024   s->num_expanded_macros = num_expanded_macros_counter;
2025   s->num_macro_tokens = num_macro_tokens_counter;
2026   s->num_macro_maps_used = LINEMAPS_MACRO_USED (set);
2027   s->macro_maps_allocated_size = macro_maps_allocated_size;
2028   s->macro_maps_locations_size = macro_maps_locations_size;
2029   s->macro_maps_used_size = macro_maps_used_size;
2030   s->duplicated_macro_maps_locations_size =
2031     duplicated_macro_maps_locations_size;
2032   s->adhoc_table_size = (set->location_adhoc_data_map.allocated
2033 			 * sizeof (struct location_adhoc_data));
2034   s->adhoc_table_entries_used = set->location_adhoc_data_map.curr_loc;
2035 }
2036 
2037 
2038 /* Dump line table SET to STREAM.  If STREAM is NULL, stderr is used.
2039    NUM_ORDINARY specifies how many ordinary maps to dump.  NUM_MACRO
2040    specifies how many macro maps to dump.  */
2041 
2042 void
line_table_dump(FILE * stream,class line_maps * set,unsigned int num_ordinary,unsigned int num_macro)2043 line_table_dump (FILE *stream, class line_maps *set, unsigned int num_ordinary,
2044 		 unsigned int num_macro)
2045 {
2046   unsigned int i;
2047 
2048   if (set == NULL)
2049     return;
2050 
2051   if (stream == NULL)
2052     stream = stderr;
2053 
2054   fprintf (stream, "# of ordinary maps:  %d\n", LINEMAPS_ORDINARY_USED (set));
2055   fprintf (stream, "# of macro maps:     %d\n", LINEMAPS_MACRO_USED (set));
2056   fprintf (stream, "Include stack depth: %d\n", set->depth);
2057   fprintf (stream, "Highest location:    %u\n", set->highest_location);
2058 
2059   if (num_ordinary)
2060     {
2061       fprintf (stream, "\nOrdinary line maps\n");
2062       for (i = 0; i < num_ordinary && i < LINEMAPS_ORDINARY_USED (set); i++)
2063 	linemap_dump (stream, set, i, false);
2064       fprintf (stream, "\n");
2065     }
2066 
2067   if (num_macro)
2068     {
2069       fprintf (stream, "\nMacro line maps\n");
2070       for (i = 0; i < num_macro && i < LINEMAPS_MACRO_USED (set); i++)
2071 	linemap_dump (stream, set, i, true);
2072       fprintf (stream, "\n");
2073     }
2074 }
2075 
2076 /* class rich_location.  */
2077 
2078 /* Construct a rich_location with location LOC as its initial range.  */
2079 
rich_location(line_maps * set,location_t loc,const range_label * label)2080 rich_location::rich_location (line_maps *set, location_t loc,
2081 			      const range_label *label) :
2082   m_line_table (set),
2083   m_ranges (),
2084   m_column_override (0),
2085   m_have_expanded_location (false),
2086   m_fixit_hints (),
2087   m_seen_impossible_fixit (false),
2088   m_fixits_cannot_be_auto_applied (false),
2089   m_path (NULL)
2090 {
2091   add_range (loc, SHOW_RANGE_WITH_CARET, label);
2092 }
2093 
2094 /* The destructor for class rich_location.  */
2095 
~rich_location()2096 rich_location::~rich_location ()
2097 {
2098   for (unsigned int i = 0; i < m_fixit_hints.count (); i++)
2099     delete get_fixit_hint (i);
2100 }
2101 
2102 /* Get location IDX within this rich_location.  */
2103 
2104 location_t
get_loc(unsigned int idx)2105 rich_location::get_loc (unsigned int idx) const
2106 {
2107   const location_range *locrange = get_range (idx);
2108   return locrange->m_loc;
2109 }
2110 
2111 /* Get range IDX within this rich_location.  */
2112 
2113 const location_range *
get_range(unsigned int idx)2114 rich_location::get_range (unsigned int idx) const
2115 {
2116   return &m_ranges[idx];
2117 }
2118 
2119 /* Mutable access to range IDX within this rich_location.  */
2120 
2121 location_range *
get_range(unsigned int idx)2122 rich_location::get_range (unsigned int idx)
2123 {
2124   return &m_ranges[idx];
2125 }
2126 
2127 /* Expand location IDX within this rich_location.  */
2128 /* Get an expanded_location for this rich_location's primary
2129    location.  */
2130 
2131 expanded_location
get_expanded_location(unsigned int idx)2132 rich_location::get_expanded_location (unsigned int idx)
2133 {
2134   if (idx == 0)
2135    {
2136      /* Cache the expansion of the primary location.  */
2137      if (!m_have_expanded_location)
2138        {
2139 	  m_expanded_location
2140 	    = linemap_client_expand_location_to_spelling_point
2141 		(get_loc (0), LOCATION_ASPECT_CARET);
2142 	  if (m_column_override)
2143 	    m_expanded_location.column = m_column_override;
2144 	  m_have_expanded_location = true;
2145        }
2146 
2147      return m_expanded_location;
2148    }
2149   else
2150     return linemap_client_expand_location_to_spelling_point
2151 	     (get_loc (idx), LOCATION_ASPECT_CARET);
2152 }
2153 
2154 /* Set the column of the primary location, with 0 meaning
2155    "don't override it".  */
2156 
2157 void
override_column(int column)2158 rich_location::override_column (int column)
2159 {
2160   m_column_override = column;
2161   m_have_expanded_location = false;
2162 }
2163 
2164 /* Add the given range.  */
2165 
2166 void
add_range(location_t loc,enum range_display_kind range_display_kind,const range_label * label)2167 rich_location::add_range (location_t loc,
2168 			  enum range_display_kind range_display_kind,
2169 			  const range_label *label)
2170 {
2171   location_range range;
2172   range.m_loc = loc;
2173   range.m_range_display_kind = range_display_kind;
2174   range.m_label = label;
2175   m_ranges.push (range);
2176 }
2177 
2178 /* Add or overwrite the location given by IDX, setting its location to LOC,
2179    and setting its m_range_display_kind to RANGE_DISPLAY_KIND.
2180 
2181    It must either overwrite an existing location, or add one *exactly* on
2182    the end of the array.
2183 
2184    This is primarily for use by gcc when implementing diagnostic format
2185    decoders e.g.
2186    - the "+" in the C/C++ frontends, for handling format codes like "%q+D"
2187      (which writes the source location of a tree back into location 0 of
2188      the rich_location), and
2189    - the "%C" and "%L" format codes in the Fortran frontend.  */
2190 
2191 void
set_range(unsigned int idx,location_t loc,enum range_display_kind range_display_kind)2192 rich_location::set_range (unsigned int idx, location_t loc,
2193 			  enum range_display_kind range_display_kind)
2194 {
2195   /* We can either overwrite an existing range, or add one exactly
2196      on the end of the array.  */
2197   linemap_assert (idx <= m_ranges.count ());
2198 
2199   if (idx == m_ranges.count ())
2200     add_range (loc, range_display_kind);
2201   else
2202     {
2203       location_range *locrange = get_range (idx);
2204       locrange->m_loc = loc;
2205       locrange->m_range_display_kind = range_display_kind;
2206     }
2207 
2208   if (idx == 0)
2209     /* Mark any cached value here as dirty.  */
2210     m_have_expanded_location = false;
2211 }
2212 
2213 /* Methods for adding insertion fix-it hints.  */
2214 
2215 /* Add a fixit-hint, suggesting insertion of NEW_CONTENT
2216    immediately before the primary range's start location.  */
2217 
2218 void
add_fixit_insert_before(const char * new_content)2219 rich_location::add_fixit_insert_before (const char *new_content)
2220 {
2221   add_fixit_insert_before (get_loc (), new_content);
2222 }
2223 
2224 /* Add a fixit-hint, suggesting insertion of NEW_CONTENT
2225    immediately before the start of WHERE.  */
2226 
2227 void
add_fixit_insert_before(location_t where,const char * new_content)2228 rich_location::add_fixit_insert_before (location_t where,
2229 					const char *new_content)
2230 {
2231   location_t start = get_range_from_loc (m_line_table, where).m_start;
2232   maybe_add_fixit (start, start, new_content);
2233 }
2234 
2235 /* Add a fixit-hint, suggesting insertion of NEW_CONTENT
2236    immediately after the primary range's end-point.  */
2237 
2238 void
add_fixit_insert_after(const char * new_content)2239 rich_location::add_fixit_insert_after (const char *new_content)
2240 {
2241   add_fixit_insert_after (get_loc (), new_content);
2242 }
2243 
2244 /* Add a fixit-hint, suggesting insertion of NEW_CONTENT
2245    immediately after the end-point of WHERE.  */
2246 
2247 void
add_fixit_insert_after(location_t where,const char * new_content)2248 rich_location::add_fixit_insert_after (location_t where,
2249 				       const char *new_content)
2250 {
2251   location_t finish = get_range_from_loc (m_line_table, where).m_finish;
2252   location_t next_loc
2253     = linemap_position_for_loc_and_offset (m_line_table, finish, 1);
2254 
2255   /* linemap_position_for_loc_and_offset can fail, if so, it returns
2256      its input value.  */
2257   if (next_loc == finish)
2258     {
2259       stop_supporting_fixits ();
2260       return;
2261     }
2262 
2263   maybe_add_fixit (next_loc, next_loc, new_content);
2264 }
2265 
2266 /* Methods for adding removal fix-it hints.  */
2267 
2268 /* Add a fixit-hint, suggesting removal of the content covered
2269    by range 0.  */
2270 
2271 void
add_fixit_remove()2272 rich_location::add_fixit_remove ()
2273 {
2274   add_fixit_remove (get_loc ());
2275 }
2276 
2277 /* Add a fixit-hint, suggesting removal of the content between
2278    the start and finish of WHERE.  */
2279 
2280 void
add_fixit_remove(location_t where)2281 rich_location::add_fixit_remove (location_t where)
2282 {
2283   source_range range = get_range_from_loc (m_line_table, where);
2284   add_fixit_remove (range);
2285 }
2286 
2287 /* Add a fixit-hint, suggesting removal of the content at
2288    SRC_RANGE.  */
2289 
2290 void
add_fixit_remove(source_range src_range)2291 rich_location::add_fixit_remove (source_range src_range)
2292 {
2293   add_fixit_replace (src_range, "");
2294 }
2295 
2296 /* Add a fixit-hint, suggesting replacement of the content covered
2297    by range 0 with NEW_CONTENT.  */
2298 
2299 void
add_fixit_replace(const char * new_content)2300 rich_location::add_fixit_replace (const char *new_content)
2301 {
2302   add_fixit_replace (get_loc (), new_content);
2303 }
2304 
2305 /* Methods for adding "replace" fix-it hints.  */
2306 
2307 /* Add a fixit-hint, suggesting replacement of the content between
2308    the start and finish of WHERE with NEW_CONTENT.  */
2309 
2310 void
add_fixit_replace(location_t where,const char * new_content)2311 rich_location::add_fixit_replace (location_t where,
2312 				  const char *new_content)
2313 {
2314   source_range range = get_range_from_loc (m_line_table, where);
2315   add_fixit_replace (range, new_content);
2316 }
2317 
2318 /* Add a fixit-hint, suggesting replacement of the content at
2319    SRC_RANGE with NEW_CONTENT.  */
2320 
2321 void
add_fixit_replace(source_range src_range,const char * new_content)2322 rich_location::add_fixit_replace (source_range src_range,
2323 				  const char *new_content)
2324 {
2325   location_t start = get_pure_location (m_line_table, src_range.m_start);
2326   location_t finish = get_pure_location (m_line_table, src_range.m_finish);
2327 
2328   /* Fix-it hints use half-closed ranges, so attempt to offset the endpoint.  */
2329   location_t next_loc
2330     = linemap_position_for_loc_and_offset (m_line_table, finish, 1);
2331   /* linemap_position_for_loc_and_offset can fail, if so, it returns
2332      its input value.  */
2333   if (next_loc == finish)
2334     {
2335       stop_supporting_fixits ();
2336       return;
2337     }
2338   finish = next_loc;
2339 
2340   maybe_add_fixit (start, finish, new_content);
2341 }
2342 
2343 /* Get the last fix-it hint within this rich_location, or NULL if none.  */
2344 
2345 fixit_hint *
get_last_fixit_hint()2346 rich_location::get_last_fixit_hint () const
2347 {
2348   if (m_fixit_hints.count () > 0)
2349     return get_fixit_hint (m_fixit_hints.count () - 1);
2350   else
2351     return NULL;
2352 }
2353 
2354 /* If WHERE is an "awkward" location, then mark this rich_location as not
2355    supporting fixits, purging any thay were already added, and return true.
2356 
2357    Otherwise (the common case), return false.  */
2358 
2359 bool
reject_impossible_fixit(location_t where)2360 rich_location::reject_impossible_fixit (location_t where)
2361 {
2362   /* Fix-its within a rich_location should either all be suggested, or
2363      none of them should be suggested.
2364      Once we've rejected a fixit, we reject any more, even those
2365      with reasonable locations.  */
2366   if (m_seen_impossible_fixit)
2367     return true;
2368 
2369   if (where <= LINE_MAP_MAX_LOCATION_WITH_COLS)
2370     /* WHERE is a reasonable location for a fix-it; don't reject it.  */
2371     return false;
2372 
2373   /* Otherwise we have an attempt to add a fix-it with an "awkward"
2374      location: either one that we can't obtain column information
2375      for (within an ordinary map), or one within a macro expansion.  */
2376   stop_supporting_fixits ();
2377   return true;
2378 }
2379 
2380 /* Mark this rich_location as not supporting fixits, purging any that were
2381    already added.  */
2382 
2383 void
stop_supporting_fixits()2384 rich_location::stop_supporting_fixits ()
2385 {
2386   m_seen_impossible_fixit = true;
2387 
2388   /* Purge the rich_location of any fix-its that were already added. */
2389   for (unsigned int i = 0; i < m_fixit_hints.count (); i++)
2390     delete get_fixit_hint (i);
2391   m_fixit_hints.truncate (0);
2392 }
2393 
2394 /* Add HINT to the fix-it hints in this rich_location,
2395    consolidating into the prior fixit if possible.  */
2396 
2397 void
maybe_add_fixit(location_t start,location_t next_loc,const char * new_content)2398 rich_location::maybe_add_fixit (location_t start,
2399 				location_t next_loc,
2400 				const char *new_content)
2401 {
2402   if (reject_impossible_fixit (start))
2403     return;
2404   if (reject_impossible_fixit (next_loc))
2405     return;
2406 
2407   /* Only allow fix-it hints that affect a single line in one file.
2408      Compare the end-points.  */
2409   expanded_location exploc_start
2410     = linemap_client_expand_location_to_spelling_point (start,
2411 							LOCATION_ASPECT_START);
2412   expanded_location exploc_next_loc
2413     = linemap_client_expand_location_to_spelling_point (next_loc,
2414 							LOCATION_ASPECT_START);
2415   /* They must be within the same file...  */
2416   if (exploc_start.file != exploc_next_loc.file)
2417     {
2418       stop_supporting_fixits ();
2419       return;
2420     }
2421   /* ...and on the same line.  */
2422   if (exploc_start.line != exploc_next_loc.line)
2423     {
2424       stop_supporting_fixits ();
2425       return;
2426     }
2427   /* The columns must be in the correct order.  This can fail if the
2428      endpoints straddle the boundary for which the linemap can represent
2429      columns (PR c/82050).  */
2430   if (exploc_start.column > exploc_next_loc.column)
2431     {
2432       stop_supporting_fixits ();
2433       return;
2434     }
2435   /* If we have very long lines, tokens will eventually fall back to
2436      having column == 0.
2437      We can't handle fix-it hints that use such locations.  */
2438   if (exploc_start.column == 0 || exploc_next_loc.column == 0)
2439     {
2440       stop_supporting_fixits ();
2441       return;
2442     }
2443 
2444   const char *newline = strchr (new_content, '\n');
2445   if (newline)
2446     {
2447       /* For now, we can only support insertion of whole lines
2448 	 i.e. starts at start of line, and the newline is at the end of
2449 	 the insertion point.  */
2450 
2451       /* It must be an insertion, not a replacement/deletion.  */
2452       if (start != next_loc)
2453 	{
2454 	  stop_supporting_fixits ();
2455 	  return;
2456 	}
2457 
2458       /* The insertion must be at the start of a line.  */
2459       if (exploc_start.column != 1)
2460 	{
2461 	  stop_supporting_fixits ();
2462 	  return;
2463 	}
2464 
2465       /* The newline must be at end of NEW_CONTENT.
2466 	 We could eventually split up fix-its at newlines if we wanted
2467 	 to allow more generality (e.g. to allow adding multiple lines
2468 	 with one add_fixit call.  */
2469       if (newline[1] != '\0')
2470 	{
2471 	  stop_supporting_fixits ();
2472 	  return;
2473 	}
2474     }
2475 
2476   /* Consolidate neighboring fixits.
2477      Don't consolidate into newline-insertion fixits.  */
2478   fixit_hint *prev = get_last_fixit_hint ();
2479   if (prev && !prev->ends_with_newline_p ())
2480     if (prev->maybe_append (start, next_loc, new_content))
2481       return;
2482 
2483   m_fixit_hints.push (new fixit_hint (start, next_loc, new_content));
2484 }
2485 
2486 /* class fixit_hint.  */
2487 
fixit_hint(location_t start,location_t next_loc,const char * new_content)2488 fixit_hint::fixit_hint (location_t start,
2489 			location_t next_loc,
2490 			const char *new_content)
2491 : m_start (start),
2492   m_next_loc (next_loc),
2493   m_bytes (xstrdup (new_content)),
2494   m_len (strlen (new_content))
2495 {
2496 }
2497 
2498 /* Does this fix-it hint affect the given line?  */
2499 
2500 bool
affects_line_p(const char * file,int line)2501 fixit_hint::affects_line_p (const char *file, int line) const
2502 {
2503   expanded_location exploc_start
2504     = linemap_client_expand_location_to_spelling_point (m_start,
2505 							LOCATION_ASPECT_START);
2506   if (file != exploc_start.file)
2507     return false;
2508   if (line < exploc_start.line)
2509       return false;
2510   expanded_location exploc_next_loc
2511     = linemap_client_expand_location_to_spelling_point (m_next_loc,
2512 							LOCATION_ASPECT_START);
2513   if (file != exploc_next_loc.file)
2514     return false;
2515   if (line > exploc_next_loc.line)
2516       return false;
2517   return true;
2518 }
2519 
2520 /* Method for consolidating fix-it hints, for use by
2521    rich_location::maybe_add_fixit.
2522    If possible, merge a pending fix-it hint with the given params
2523    into this one and return true.
2524    Otherwise return false.  */
2525 
2526 bool
maybe_append(location_t start,location_t next_loc,const char * new_content)2527 fixit_hint::maybe_append (location_t start,
2528 			  location_t next_loc,
2529 			  const char *new_content)
2530 {
2531   /* For consolidation to be possible, START must be at this hint's
2532      m_next_loc.  */
2533   if (start != m_next_loc)
2534     return false;
2535 
2536   /* If so, we have neighboring replacements; merge them.  */
2537   m_next_loc = next_loc;
2538   size_t extra_len = strlen (new_content);
2539   m_bytes = (char *)xrealloc (m_bytes, m_len + extra_len + 1);
2540   memcpy (m_bytes + m_len, new_content, extra_len);
2541   m_len += extra_len;
2542   m_bytes[m_len] = '\0';
2543   return true;
2544 }
2545 
2546 /* Return true iff this hint's content ends with a newline.  */
2547 
2548 bool
ends_with_newline_p()2549 fixit_hint::ends_with_newline_p () const
2550 {
2551   if (m_len == 0)
2552     return false;
2553   return m_bytes[m_len - 1] == '\n';
2554 }
2555