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

Provided by KDAB

Privacy Policy
Update your C++ knowledge – Modern C++11/14/17 Training
Find out more

source code of libcpp/line-map.cc