1/* Map (unsigned int) keys to (source file, line, column) triples.
2 Copyright (C) 2001-2026 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/* TRUE iff the location comes from a module import. */
771
772bool
773linemap_location_from_module_p (const line_maps *set, location_t loc)
774{
775 const line_map_ordinary *map = linemap_ordinary_map_lookup (set, loc);
776 while (map && map->reason != LC_MODULE)
777 map = linemap_included_from_linemap (set, map);
778 return !!map;
779}
780
781/* Returns TRUE if the line table set tracks token locations across
782 macro expansion, FALSE otherwise. */
783
784bool
785linemap_tracks_macro_expansion_locs_p (const line_maps *set)
786{
787 return set->info_macro.maps != nullptr;
788}
789
790/* Create a macro map. A macro map encodes source locations of tokens
791 that are part of a macro replacement-list, at a macro expansion
792 point. See the extensive comments of struct line_map and struct
793 line_map_macro, in line-map.h.
794
795 This map shall be created when the macro is expanded. The map
796 encodes the source location of the expansion point of the macro as
797 well as the "original" source location of each token that is part
798 of the macro replacement-list. If a macro is defined but never
799 expanded, it has no macro map. SET is the set of maps the macro
800 map should be part of. MACRO_NODE is the macro which the new macro
801 map should encode source locations for. EXPANSION is the location
802 of the expansion point of MACRO. For function-like macros
803 invocations, it's best to make it point to the closing parenthesis
804 of the macro, rather than the the location of the first character
805 of the macro. NUM_TOKENS is the number of tokens that are part of
806 the replacement-list of MACRO.
807
808 Note that when we run out of the integer space available for source
809 locations, this function returns NULL. In that case, callers of
810 this function cannot encode {line,column} pairs into locations of
811 macro tokens anymore. */
812
813const line_map_macro *
814linemap_enter_macro (class line_maps *set, struct cpp_hashnode *macro_node,
815 location_t expansion, unsigned int num_tokens)
816{
817 location_t start_location
818 = LINEMAPS_MACRO_LOWEST_LOCATION (set) - num_tokens;
819
820 if (start_location < LINE_MAP_MAX_LOCATION)
821 /* We ran out of macro map space. */
822 return NULL;
823
824 line_map_macro *map = linemap_check_macro (map: new_linemap (set, start_location));
825
826 map->macro = macro_node;
827 map->n_tokens = num_tokens;
828 map->macro_locations
829 = (location_t*) set->m_reallocator (nullptr,
830 2 * num_tokens * sizeof (location_t));
831 map->m_expansion = expansion;
832 memset (s: MACRO_MAP_LOCATIONS (macro_map: map), c: 0,
833 n: 2 * num_tokens * sizeof (location_t));
834
835 set->info_macro.m_cache = LINEMAPS_MACRO_USED (set) - 1;
836
837 return map;
838}
839
840/* Create and return a virtual location for a token that is part of a
841 macro expansion-list at a macro expansion point. See the comment
842 inside struct line_map_macro to see what an expansion-list exactly
843 is.
844
845 A call to this function must come after a call to
846 linemap_enter_macro.
847
848 MAP is the map into which the source location is created. TOKEN_NO
849 is the index of the token in the macro replacement-list, starting
850 at number 0.
851
852 ORIG_LOC is the location of the token outside of this macro
853 expansion. If the token comes originally from the macro
854 definition, it is the locus in the macro definition; otherwise it
855 is a location in the context of the caller of this macro expansion
856 (which is a virtual location or a source location if the caller is
857 itself a macro expansion or not).
858
859 ORIG_PARM_REPLACEMENT_LOC is the location in the macro definition,
860 either of the token itself or of a macro parameter that it
861 replaces. */
862
863location_t
864linemap_add_macro_token (const line_map_macro *map,
865 unsigned int token_no,
866 location_t orig_loc,
867 location_t orig_parm_replacement_loc)
868{
869 location_t result;
870
871 linemap_assert (linemap_macro_expansion_map_p (map));
872 linemap_assert (token_no < MACRO_MAP_NUM_MACRO_TOKENS (map));
873
874 MACRO_MAP_LOCATIONS (macro_map: map)[2 * token_no] = orig_loc;
875 MACRO_MAP_LOCATIONS (macro_map: map)[2 * token_no + 1] = orig_parm_replacement_loc;
876
877 result = MAP_START_LOCATION (map) + token_no;
878 return result;
879}
880
881/* Return a location_t for the start (i.e. column==0) of
882 (physical) line TO_LINE in the current source file (as in the
883 most recent linemap_add). MAX_COLUMN_HINT is the highest column
884 number we expect to use in this line (but it does not change
885 the highest_location). */
886
887location_t
888linemap_line_start (line_maps *set, linenum_type to_line,
889 unsigned int max_column_hint)
890{
891 line_map_ordinary *map = LINEMAPS_LAST_ORDINARY_MAP (set);
892 location_t highest = set->highest_location;
893 location_t r;
894 linenum_type last_line =
895 SOURCE_LINE (ord_map: map, loc: set->highest_line);
896 auto line_delta = (linenum_arith_t) to_line - (linenum_arith_t) last_line;
897 bool add_map = false;
898 linemap_assert (map->m_column_and_range_bits >= map->m_range_bits);
899 int effective_column_bits = map->m_column_and_range_bits - map->m_range_bits;
900
901 if (line_delta < 0
902 || (line_delta > 10
903 && line_delta * map->m_column_and_range_bits > 1000)
904 || (max_column_hint >= (1U << effective_column_bits))
905 || (max_column_hint <= 80 && effective_column_bits >= 10)
906 || (highest > LINE_MAP_MAX_LOCATION_WITH_PACKED_RANGES
907 && map->m_range_bits > 0)
908 || (highest > LINE_MAP_MAX_LOCATION_WITH_COLS
909 && (set->max_column_hint || highest >= LINE_MAP_MAX_LOCATION)))
910 add_map = true;
911 else
912 max_column_hint = set->max_column_hint;
913 if (add_map)
914 {
915 int column_bits;
916 int range_bits;
917 if (max_column_hint > LINE_MAP_MAX_COLUMN_NUMBER
918 || highest > LINE_MAP_MAX_LOCATION_WITH_COLS)
919 {
920 /* If the column number is ridiculous or we've allocated a huge
921 number of location_ts, give up on column numbers
922 (and on packed ranges). */
923 max_column_hint = 1;
924 column_bits = 0;
925 range_bits = 0;
926 if (highest >= LINE_MAP_MAX_LOCATION)
927 goto overflowed;
928 }
929 else
930 {
931 column_bits = 7;
932 if (highest <= LINE_MAP_MAX_LOCATION_WITH_PACKED_RANGES)
933 range_bits = set->default_range_bits;
934 else
935 range_bits = 0;
936 while (max_column_hint >= (1U << column_bits))
937 column_bits++;
938 max_column_hint = 1U << column_bits;
939 column_bits += range_bits;
940 }
941
942 /* Allocate the new line_map. However, if the current map only has a
943 single line we can sometimes just increase its column_bits instead. */
944 if (line_delta < 0
945 || last_line != ORDINARY_MAP_STARTING_LINE_NUMBER (ord_map: map)
946 || SOURCE_COLUMN (ord_map: map, loc: highest) >= (loc_one
947 << (column_bits - range_bits))
948 || ( /* We can't reuse the map if the line offset is sufficiently
949 large to cause overflow when computing location_t values. */
950 (to_line - ORDINARY_MAP_STARTING_LINE_NUMBER (ord_map: map))
951 >= (((uint64_t) 1)
952 << (CHAR_BIT * sizeof (linenum_type) - column_bits)))
953 || range_bits < map->m_range_bits)
954 map = linemap_check_ordinary
955 (map: const_cast <line_map *>
956 (linemap_add (set, reason: LC_RENAME,
957 sysp: ORDINARY_MAP_IN_SYSTEM_HEADER_P (ord_map: map),
958 to_file: ORDINARY_MAP_FILE_NAME (ord_map: map),
959 to_line)));
960 map->m_column_and_range_bits = column_bits;
961 map->m_range_bits = range_bits;
962 r = (MAP_START_LOCATION (map)
963 + (location_t (to_line - ORDINARY_MAP_STARTING_LINE_NUMBER (ord_map: map))
964 << column_bits));
965 }
966 else
967 r = set->highest_line + (location_t (line_delta)
968 << map->m_column_and_range_bits);
969
970 /* Locations of ordinary tokens are always lower than locations of
971 macro tokens. */
972 if (r >= LINE_MAP_MAX_LOCATION)
973 {
974 overflowed:
975 /* Remember we overflowed. */
976 set->highest_line = set->highest_location = LINE_MAP_MAX_LOCATION - 1;
977 /* No column numbers! */
978 set->max_column_hint = 1;
979 return 0;
980 }
981
982 set->highest_line = r;
983 if (r > set->highest_location)
984 set->highest_location = r;
985 set->max_column_hint = max_column_hint;
986
987 /* At this point, we expect one of:
988 (a) the normal case: a "pure" location with 0 range bits, or
989 (b) we've gone past LINE_MAP_MAX_LOCATION_WITH_COLS so can't track
990 columns anymore (or ranges), or
991 (c) we're in a region with a column hint exceeding
992 LINE_MAP_MAX_COLUMN_NUMBER, so column-tracking is off,
993 with column_bits == 0. */
994 linemap_assert (pure_location_p (set, r)
995 || r >= LINE_MAP_MAX_LOCATION_WITH_COLS
996 || map->m_column_and_range_bits == 0);
997 linemap_assert (SOURCE_LINE (map, r) == to_line);
998 return r;
999}
1000
1001/* Encode and return a location_t from a column number. The
1002 source line considered is the last source line used to call
1003 linemap_line_start, i.e, the last source line which a location was
1004 encoded from. */
1005
1006location_t
1007linemap_position_for_column (line_maps *set, unsigned int to_column)
1008{
1009 location_t r = set->highest_line;
1010
1011 linemap_assert
1012 (!linemap_macro_expansion_map_p (LINEMAPS_LAST_ORDINARY_MAP (set)));
1013
1014 if (to_column >= set->max_column_hint)
1015 {
1016 if (r > LINE_MAP_MAX_LOCATION_WITH_COLS
1017 || to_column > LINE_MAP_MAX_COLUMN_NUMBER)
1018 {
1019 /* Running low on location_ts - disable column numbers. */
1020 return r;
1021 }
1022 else
1023 {
1024 /* Otherwise, attempt to start a new line that can hold TO_COLUMN,
1025 with some space to spare. This may or may not lead to a new
1026 linemap being created. */
1027 line_map_ordinary *map = LINEMAPS_LAST_ORDINARY_MAP (set);
1028 r = linemap_line_start (set, to_line: SOURCE_LINE (ord_map: map, loc: r), max_column_hint: to_column + 50);
1029 map = LINEMAPS_LAST_ORDINARY_MAP (set);
1030 if (map->m_column_and_range_bits == 0)
1031 {
1032 /* ...then the linemap has column-tracking disabled,
1033 presumably due to exceeding either
1034 LINE_MAP_MAX_LOCATION_WITH_COLS (overall) or
1035 LINE_MAP_MAX_COLUMN_NUMBER (within this line).
1036 Return the start of the linemap, which encodes column 0, for
1037 the whole line. */
1038 return r;
1039 }
1040 }
1041 }
1042 line_map_ordinary *map = LINEMAPS_LAST_ORDINARY_MAP (set);
1043 r = r + (location_t (to_column) << map->m_range_bits);
1044 if (r >= set->highest_location)
1045 set->highest_location = r;
1046 return r;
1047}
1048
1049/* Encode and return a source location from a given line and
1050 column. */
1051
1052location_t
1053linemap_position_for_line_and_column (line_maps *set,
1054 const line_map_ordinary *ord_map,
1055 linenum_type line,
1056 unsigned column)
1057{
1058 linemap_assert (ORDINARY_MAP_STARTING_LINE_NUMBER (ord_map) <= line);
1059
1060 location_t r = MAP_START_LOCATION (map: ord_map);
1061 r += (location_t (line - ORDINARY_MAP_STARTING_LINE_NUMBER (ord_map))
1062 << ord_map->m_column_and_range_bits);
1063 if (r <= LINE_MAP_MAX_LOCATION_WITH_COLS)
1064 r += ((column & ((loc_one << ord_map->m_column_and_range_bits) - 1))
1065 << ord_map->m_range_bits);
1066 location_t upper_limit = LINEMAPS_MACRO_LOWEST_LOCATION (set);
1067 if (r >= upper_limit)
1068 r = upper_limit - 1;
1069 if (r > set->highest_location)
1070 set->highest_location = r;
1071 return r;
1072}
1073
1074/* Encode and return a location_t starting from location LOC and
1075 shifting it by COLUMN_OFFSET columns. This function does not support
1076 virtual locations. */
1077
1078location_t
1079linemap_position_for_loc_and_offset (line_maps *set,
1080 location_t loc,
1081 unsigned int column_offset)
1082{
1083 const line_map_ordinary * map = NULL;
1084
1085 if (IS_ADHOC_LOC (loc))
1086 loc = get_location_from_adhoc_loc (set, loc);
1087
1088 /* This function does not support virtual locations yet. */
1089 if (linemap_location_from_macro_expansion_p (set, loc))
1090 return loc;
1091
1092 if (column_offset == 0
1093 /* Adding an offset to a reserved location (like
1094 UNKNOWN_LOCATION for the C/C++ FEs) does not really make
1095 sense. So let's leave the location intact in that case. */
1096 || loc < RESERVED_LOCATION_COUNT)
1097 return loc;
1098
1099 /* We find the real location and shift it. */
1100 loc = linemap_resolve_location (set, loc, lrk: LRK_SPELLING_LOCATION, loc_map: &map);
1101 auto shifted_offset = location_t (column_offset) << map->m_range_bits;
1102
1103 /* The new location (loc + offset) should be higher than the first
1104 location encoded by MAP. This can fail if the line information
1105 is messed up because of line directives (see PR66415). */
1106 if (MAP_START_LOCATION (map) >= loc + shifted_offset)
1107 return loc;
1108
1109 linenum_type line = SOURCE_LINE (ord_map: map, loc);
1110 unsigned int column = SOURCE_COLUMN (ord_map: map, loc);
1111
1112 /* If MAP is not the last line map of its set, then the new location
1113 (loc + offset) should be less than the first location encoded by
1114 the next line map of the set. Otherwise, we try to encode the
1115 location in the next map. */
1116 for (; map != LINEMAPS_LAST_ORDINARY_MAP (set)
1117 && loc + shifted_offset >= MAP_START_LOCATION (map: map + 1); map++)
1118 /* If the next map is a different file, or starts in a higher line, we
1119 cannot encode the location there. */
1120 if ((map + 1)->reason != LC_RENAME
1121 || line < ORDINARY_MAP_STARTING_LINE_NUMBER (ord_map: map + 1)
1122 || 0 != strcmp (s1: LINEMAP_FILE (ord_map: map + 1), s2: LINEMAP_FILE (ord_map: map)))
1123 return loc;
1124
1125 column += column_offset;
1126
1127 /* Bail out if the column is not representable within the existing
1128 linemap. */
1129 if (column >= (1u << (map->m_column_and_range_bits - map->m_range_bits)))
1130 return loc;
1131
1132 location_t r =
1133 linemap_position_for_line_and_column (set, ord_map: map, line, column);
1134 if (linemap_assert_fails (r <= set->highest_location)
1135 || linemap_assert_fails (map == linemap_lookup (set, r)))
1136 return loc;
1137
1138 return r;
1139}
1140
1141/* Given a virtual source location yielded by a map (either an
1142 ordinary or a macro map), returns that map. */
1143
1144const struct line_map*
1145linemap_lookup (const line_maps *set, location_t line)
1146{
1147 if (IS_ADHOC_LOC (loc: line))
1148 line = get_location_from_adhoc_loc (set, loc: line);
1149 if (linemap_location_from_macro_expansion_p (set, line))
1150 return linemap_macro_map_lookup (set, line);
1151 return linemap_ordinary_map_lookup (set, line);
1152}
1153
1154/* Given a source location yielded by an ordinary map, returns that
1155 map. Since the set is built chronologically, the logical lines are
1156 monotonic increasing, and so the list is sorted and we can use a
1157 binary search. */
1158
1159static const line_map_ordinary *
1160linemap_ordinary_map_lookup (const line_maps *set, location_t line)
1161{
1162 if (IS_ADHOC_LOC (loc: line))
1163 line = get_location_from_adhoc_loc (set, loc: line);
1164
1165 if (set == NULL || line < RESERVED_LOCATION_COUNT)
1166 return NULL;
1167
1168 auto mn = set->info_ordinary.m_cache;
1169 auto mx = LINEMAPS_ORDINARY_USED (set);
1170
1171 const line_map_ordinary *cached = LINEMAPS_ORDINARY_MAP_AT (set, index: mn);
1172 /* We should get a segfault if no line_maps have been added yet. */
1173 if (line >= MAP_START_LOCATION (map: cached))
1174 {
1175 if (mn + 1 == mx || line < MAP_START_LOCATION (map: &cached[1]))
1176 return cached;
1177 }
1178 else
1179 {
1180 mx = mn;
1181 mn = 0;
1182 }
1183
1184 while (mx - mn > 1)
1185 {
1186 auto md = (mn + mx) / 2;
1187 if (MAP_START_LOCATION (map: LINEMAPS_ORDINARY_MAP_AT (set, index: md)) > line)
1188 mx = md;
1189 else
1190 mn = md;
1191 }
1192
1193 set->info_ordinary.m_cache = mn;
1194 const line_map_ordinary *result = LINEMAPS_ORDINARY_MAP_AT (set, index: mn);
1195 linemap_assert (line >= MAP_START_LOCATION (result));
1196 return result;
1197}
1198
1199/* Given a source location yielded by a macro map, returns that map.
1200 Since the set is built chronologically, the logical lines are
1201 monotonic decreasing, and so the list is sorted and we can use a
1202 binary search. */
1203
1204static const line_map_macro *
1205linemap_macro_map_lookup (const line_maps *set, location_t line)
1206{
1207 if (IS_ADHOC_LOC (loc: line))
1208 line = get_location_from_adhoc_loc (set, loc: line);
1209
1210 linemap_assert (line >= LINEMAPS_MACRO_LOWEST_LOCATION (set));
1211
1212 if (set == NULL)
1213 return NULL;
1214
1215 auto ix = linemap_lookup_macro_index (set, line);
1216 const struct line_map_macro *result = LINEMAPS_MACRO_MAP_AT (set, index: ix);
1217 linemap_assert (MAP_START_LOCATION (result) <= line);
1218
1219 return result;
1220}
1221
1222line_map_uint_t
1223linemap_lookup_macro_index (const line_maps *set, location_t line)
1224{
1225 auto mn = set->info_macro.m_cache;
1226 auto mx = LINEMAPS_MACRO_USED (set);
1227 const struct line_map_macro *cached = LINEMAPS_MACRO_MAP_AT (set, index: mn);
1228
1229 if (line >= MAP_START_LOCATION (map: cached))
1230 {
1231 if (line < (MAP_START_LOCATION (map: cached)
1232 + MACRO_MAP_NUM_MACRO_TOKENS (macro_map: cached)))
1233 return mn;
1234 mx = mn - 1;
1235 mn = 0;
1236 }
1237
1238 while (mn < mx)
1239 {
1240 auto md = (mx + mn) / 2;
1241 if (MAP_START_LOCATION (map: LINEMAPS_MACRO_MAP_AT (set, index: md)) > line)
1242 mn = md + 1;
1243 else
1244 mx = md;
1245 }
1246
1247 set->info_macro.m_cache = mx;
1248 return mx;
1249}
1250
1251/* Return TRUE if MAP encodes locations coming from a macro
1252 replacement-list at macro expansion point. */
1253
1254bool
1255linemap_macro_expansion_map_p (const struct line_map *map)
1256{
1257 return map && !MAP_ORDINARY_P (map);
1258}
1259
1260/* If LOCATION is the locus of a token in a replacement-list of a
1261 macro expansion return the location of the macro expansion point.
1262
1263 Read the comments of struct line_map and struct line_map_macro in
1264 line-map.h to understand what a macro expansion point is. */
1265
1266static location_t
1267linemap_macro_map_loc_to_exp_point (const line_map_macro *map,
1268 location_t location ATTRIBUTE_UNUSED)
1269{
1270 linemap_assert (linemap_macro_expansion_map_p (map)
1271 && location >= MAP_START_LOCATION (map));
1272
1273 /* Make sure LOCATION is correct. */
1274 linemap_assert ((location - MAP_START_LOCATION (map))
1275 < MACRO_MAP_NUM_MACRO_TOKENS (map));
1276
1277 return map->get_expansion_point_location ();
1278}
1279
1280/* LOCATION is the source location of a token that belongs to a macro
1281 replacement-list as part of the macro expansion denoted by MAP.
1282
1283 Return the location of the token at the definition point of the
1284 macro. */
1285
1286static location_t
1287linemap_macro_map_loc_to_def_point (const line_map_macro *map,
1288 location_t location)
1289{
1290 unsigned token_no;
1291
1292 linemap_assert (linemap_macro_expansion_map_p (map)
1293 && location >= MAP_START_LOCATION (map));
1294 linemap_assert (location >= RESERVED_LOCATION_COUNT);
1295
1296 token_no = location - MAP_START_LOCATION (map);
1297 linemap_assert (token_no < MACRO_MAP_NUM_MACRO_TOKENS (map));
1298
1299 location = MACRO_MAP_LOCATIONS (macro_map: map)[2 * token_no + 1];
1300
1301 return location;
1302}
1303
1304/* If LOCATION is the locus of a token that is an argument of a
1305 function-like macro M and appears in the expansion of M, return the
1306 locus of that argument in the context of the caller of M.
1307
1308 In other words, this returns the xI location presented in the
1309 comments of line_map_macro above. */
1310location_t
1311linemap_macro_map_loc_unwind_toward_spelling (const line_maps *set,
1312 const line_map_macro* map,
1313 location_t location)
1314{
1315 unsigned token_no;
1316
1317 if (IS_ADHOC_LOC (loc: location))
1318 location = get_location_from_adhoc_loc (set, loc: location);
1319
1320 linemap_assert (linemap_macro_expansion_map_p (map)
1321 && location >= MAP_START_LOCATION (map));
1322 linemap_assert (location >= RESERVED_LOCATION_COUNT);
1323 linemap_assert (!IS_ADHOC_LOC (location));
1324
1325 token_no = location - MAP_START_LOCATION (map);
1326 linemap_assert (token_no < MACRO_MAP_NUM_MACRO_TOKENS (map));
1327
1328 location = MACRO_MAP_LOCATIONS (macro_map: map)[2 * token_no];
1329
1330 return location;
1331}
1332
1333/* Return the source line number corresponding to source location
1334 LOCATION. SET is the line map set LOCATION comes from. If
1335 LOCATION is the source location of token that is part of the
1336 replacement-list of a macro expansion return the line number of the
1337 macro expansion point. */
1338
1339int
1340linemap_get_expansion_line (const line_maps *set,
1341 location_t location)
1342{
1343 const line_map_ordinary *map = NULL;
1344
1345 if (IS_ADHOC_LOC (loc: location))
1346 location = get_location_from_adhoc_loc (set, loc: location);
1347
1348 if (location < RESERVED_LOCATION_COUNT)
1349 return 0;
1350
1351 location =
1352 linemap_macro_loc_to_exp_point (set, location, &map);
1353
1354 return SOURCE_LINE (ord_map: map, loc: location);
1355}
1356
1357/* Return the path of the file corresponding to source code location
1358 LOCATION.
1359
1360 If LOCATION is the source location of token that is part of the
1361 replacement-list of a macro expansion return the file path of the
1362 macro expansion point.
1363
1364 SET is the line map set LOCATION comes from. */
1365
1366const char*
1367linemap_get_expansion_filename (const line_maps *set,
1368 location_t location)
1369{
1370 const struct line_map_ordinary *map = NULL;
1371
1372 if (IS_ADHOC_LOC (loc: location))
1373 location = get_location_from_adhoc_loc (set, loc: location);
1374
1375 if (location < RESERVED_LOCATION_COUNT)
1376 return NULL;
1377
1378 linemap_macro_loc_to_exp_point (set, location, &map);
1379
1380 return LINEMAP_FILE (ord_map: map);
1381}
1382
1383/* Return the name of the macro associated to MACRO_MAP. */
1384
1385const char*
1386linemap_map_get_macro_name (const line_map_macro *macro_map)
1387{
1388 linemap_assert (macro_map && linemap_macro_expansion_map_p (macro_map));
1389 return (const char*) NODE_NAME (MACRO_MAP_MACRO (macro_map));
1390}
1391
1392/* Return a positive value if LOCATION is the locus of a token that is
1393 located in a system header, O otherwise. It returns 1 if LOCATION
1394 is the locus of a token that is located in a system header, and 2
1395 if LOCATION is the locus of a token located in a C system header
1396 that therefore needs to be extern "C" protected in C++.
1397
1398 Note that this function returns 1 if LOCATION belongs to a token
1399 that is part of a macro replacement-list defined in a system
1400 header, but expanded in a non-system file. */
1401
1402int
1403linemap_location_in_system_header_p (const line_maps *set,
1404 location_t location)
1405{
1406 const struct line_map *map = NULL;
1407
1408 if (IS_ADHOC_LOC (loc: location))
1409 location = get_location_from_adhoc_loc (set, loc: location);
1410
1411 if (location < RESERVED_LOCATION_COUNT)
1412 return false;
1413
1414 /* Let's look at where the token for LOCATION comes from. */
1415 while (true)
1416 {
1417 map = linemap_lookup (set, line: location);
1418 if (map != NULL)
1419 {
1420 if (!linemap_macro_expansion_map_p (map))
1421 /* It's a normal token. */
1422 return LINEMAP_SYSP (ord_map: linemap_check_ordinary (map));
1423 else
1424 {
1425 const line_map_macro *macro_map = linemap_check_macro (map);
1426
1427 /* It's a token resulting from a macro expansion. */
1428 location_t loc =
1429 linemap_macro_map_loc_unwind_toward_spelling (set, map: macro_map, location);
1430 if (loc < RESERVED_LOCATION_COUNT)
1431 /* This token might come from a built-in macro. Let's
1432 look at where that macro got expanded. */
1433 location = linemap_macro_map_loc_to_exp_point (map: macro_map, location);
1434 else
1435 location = loc;
1436 }
1437 }
1438 else
1439 break;
1440 }
1441 return false;
1442}
1443
1444/* Return TRUE if LOCATION is a source code location of a token that is part of
1445 a macro expansion, FALSE otherwise. */
1446
1447bool
1448linemap_location_from_macro_expansion_p (const class line_maps *set,
1449 location_t location)
1450{
1451 if (IS_ADHOC_LOC (loc: location))
1452 location = get_location_from_adhoc_loc (set, loc: location);
1453
1454 return location >= LINEMAPS_MACRO_LOWEST_LOCATION (set);
1455}
1456
1457/* Given two virtual locations *LOC0 and *LOC1, return the first
1458 common macro map in their macro expansion histories. Return NULL
1459 if no common macro was found. *LOC0 (resp. *LOC1) is set to the
1460 virtual location of the token inside the resulting macro. */
1461
1462static const struct line_map*
1463first_map_in_common_1 (const line_maps *set,
1464 location_t *loc0,
1465 location_t *loc1)
1466{
1467 location_t l0 = *loc0, l1 = *loc1;
1468 const struct line_map *map0 = linemap_lookup (set, line: l0);
1469 if (IS_ADHOC_LOC (loc: l0))
1470 l0 = get_location_from_adhoc_loc (set, loc: l0);
1471
1472 const struct line_map *map1 = linemap_lookup (set, line: l1);
1473 if (IS_ADHOC_LOC (loc: l1))
1474 l1 = get_location_from_adhoc_loc (set, loc: l1);
1475
1476 while (linemap_macro_expansion_map_p (map: map0)
1477 && linemap_macro_expansion_map_p (map: map1)
1478 && (map0 != map1))
1479 {
1480 if (MAP_START_LOCATION (map: map0) < MAP_START_LOCATION (map: map1))
1481 {
1482 l0 = linemap_macro_map_loc_to_exp_point (map: linemap_check_macro (map: map0),
1483 location: l0);
1484 map0 = linemap_lookup (set, line: l0);
1485 }
1486 else
1487 {
1488 l1 = linemap_macro_map_loc_to_exp_point (map: linemap_check_macro (map: map1),
1489 location: l1);
1490 map1 = linemap_lookup (set, line: l1);
1491 }
1492 }
1493
1494 if (map0 == map1)
1495 {
1496 *loc0 = l0;
1497 *loc1 = l1;
1498 return map0;
1499 }
1500 return NULL;
1501}
1502
1503/* Given two virtual locations LOC0 and LOC1, return the first common
1504 macro map in their macro expansion histories. Return NULL if no
1505 common macro was found. *RES_LOC0 (resp. *RES_LOC1) is set to the
1506 virtual location of the token inside the resulting macro, upon
1507 return of a non-NULL result. */
1508
1509const struct line_map*
1510first_map_in_common (const line_maps *set,
1511 location_t loc0,
1512 location_t loc1,
1513 location_t *res_loc0,
1514 location_t *res_loc1)
1515{
1516 *res_loc0 = loc0;
1517 *res_loc1 = loc1;
1518
1519 return first_map_in_common_1 (set, loc0: res_loc0, loc1: res_loc1);
1520}
1521
1522/* Return a positive value if PRE denotes the location of a token that
1523 comes before the token of POST, 0 if PRE denotes the location of
1524 the same token as the token for POST, and a negative value
1525 otherwise. */
1526
1527int
1528linemap_compare_locations (const line_maps *set,
1529 location_t pre,
1530 location_t post)
1531{
1532 bool pre_virtual_p, post_virtual_p;
1533 location_t l0 = pre, l1 = post;
1534
1535 if (IS_ADHOC_LOC (loc: l0))
1536 l0 = get_location_from_adhoc_loc (set, loc: l0);
1537 if (IS_ADHOC_LOC (loc: l1))
1538 l1 = get_location_from_adhoc_loc (set, loc: l1);
1539
1540 if (l0 == l1)
1541 return 0;
1542
1543 if ((pre_virtual_p = linemap_location_from_macro_expansion_p (set, location: l0)))
1544 l0 = linemap_resolve_location (set, loc: l0,
1545 lrk: LRK_MACRO_EXPANSION_POINT,
1546 NULL);
1547
1548 if ((post_virtual_p = linemap_location_from_macro_expansion_p (set, location: l1)))
1549 l1 = linemap_resolve_location (set, loc: l1,
1550 lrk: LRK_MACRO_EXPANSION_POINT,
1551 NULL);
1552
1553 if (l0 == l1
1554 && pre_virtual_p
1555 && post_virtual_p)
1556 {
1557 /* So pre and post represent two tokens that are present in a
1558 same macro expansion. Let's see if the token for pre was
1559 before the token for post in that expansion. */
1560 const struct line_map *map =
1561 first_map_in_common (set, loc0: pre, loc1: post, res_loc0: &l0, res_loc1: &l1);
1562
1563 if (map == NULL)
1564 /* This should not be possible while we have column information, but if
1565 we don't, the tokens could be from separate macro expansions on the
1566 same line. */
1567 gcc_assert (l0 > LINE_MAP_MAX_LOCATION_WITH_COLS);
1568 else
1569 {
1570 unsigned i0 = l0 - MAP_START_LOCATION (map);
1571 unsigned i1 = l1 - MAP_START_LOCATION (map);
1572 return i1 - i0;
1573 }
1574 }
1575
1576 if (IS_ADHOC_LOC (loc: l0))
1577 l0 = get_location_from_adhoc_loc (set, loc: l0);
1578 if (IS_ADHOC_LOC (loc: l1))
1579 l1 = get_location_from_adhoc_loc (set, loc: l1);
1580
1581 /* This function is intended e.g. for implementing a qsort() comparator, so it
1582 needs to return really an "int" and not something larger. */
1583 const auto res = (location_diff_t)l1 - (location_diff_t)l0;
1584 return res < INT_MIN ? INT_MIN : res > INT_MAX ? INT_MAX : res;
1585}
1586
1587/* Print an include trace, for e.g. the -H option of the preprocessor. */
1588
1589static void
1590trace_include (const class line_maps *set, const line_map_ordinary *map)
1591{
1592 unsigned int i = set->depth;
1593
1594 while (--i)
1595 putc ('.', stderr);
1596
1597 fprintf (stderr, format: " %s\n", ORDINARY_MAP_FILE_NAME (ord_map: map));
1598}
1599
1600/* Return the spelling location of the token wherever it comes from,
1601 whether part of a macro definition or not.
1602
1603 This is a subroutine for linemap_resolve_location. */
1604
1605static location_t
1606linemap_macro_loc_to_spelling_point (const line_maps *set,
1607 location_t location,
1608 const line_map_ordinary **original_map)
1609{
1610 linemap_assert (set && location >= RESERVED_LOCATION_COUNT);
1611
1612 while (true)
1613 {
1614 const struct line_map *map = linemap_lookup (set, line: location);
1615 if (!map || MAP_ORDINARY_P (map))
1616 {
1617 if (original_map)
1618 *original_map = (const line_map_ordinary *)map;
1619 break;
1620 }
1621
1622 location = linemap_macro_map_loc_unwind_toward_spelling
1623 (set, map: linemap_check_macro (map), location);
1624 }
1625
1626 return location;
1627}
1628
1629/* If LOCATION is the source location of a token that belongs to a
1630 macro replacement-list -- as part of a macro expansion -- then
1631 return the location of the token at the definition point of the
1632 macro. Otherwise, return LOCATION. SET is the set of maps
1633 location come from. ORIGINAL_MAP is an output parm. If non NULL,
1634 the function sets *ORIGINAL_MAP to the ordinary (non-macro) map the
1635 returned location comes from.
1636
1637 This is a subroutine of linemap_resolve_location. */
1638
1639static location_t
1640linemap_macro_loc_to_def_point (const line_maps *set,
1641 location_t location,
1642 const line_map_ordinary **original_map)
1643{
1644 linemap_assert (set && location >= RESERVED_LOCATION_COUNT);
1645
1646 for (;;)
1647 {
1648 location_t caret_loc = location;
1649 if (IS_ADHOC_LOC (loc: caret_loc))
1650 caret_loc = get_location_from_adhoc_loc (set, loc: caret_loc);
1651
1652 const line_map *map = linemap_lookup (set, line: caret_loc);
1653 if (!map || MAP_ORDINARY_P (map))
1654 {
1655 if (original_map)
1656 *original_map = (const line_map_ordinary *)map;
1657 break;
1658 }
1659
1660 location = linemap_macro_map_loc_to_def_point
1661 (map: linemap_check_macro (map), location: caret_loc);
1662 }
1663
1664 return location;
1665}
1666
1667/* If LOCATION is the source location of a token that belongs to a
1668 macro replacement-list -- at a macro expansion point -- then return
1669 the location of the topmost expansion point of the macro. We say
1670 topmost because if we are in the context of a nested macro
1671 expansion, the function returns the source location of the first
1672 macro expansion that triggered the nested expansions.
1673
1674 Otherwise, return LOCATION. SET is the set of maps location come
1675 from. ORIGINAL_MAP is an output parm. If non NULL, the function
1676 sets *ORIGINAL_MAP to the ordinary (non-macro) map the returned
1677 location comes from.
1678
1679 This is a subroutine of linemap_resolve_location. */
1680
1681static location_t
1682linemap_macro_loc_to_exp_point (const line_maps *set,
1683 location_t location,
1684 const line_map_ordinary **original_map)
1685{
1686 struct line_map *map;
1687
1688 if (IS_ADHOC_LOC (loc: location))
1689 location = get_location_from_adhoc_loc (set, loc: location);
1690
1691 linemap_assert (set && location >= RESERVED_LOCATION_COUNT);
1692
1693 while (true)
1694 {
1695 map = const_cast <line_map *> (linemap_lookup (set, line: location));
1696 if (!linemap_macro_expansion_map_p (map))
1697 break;
1698 location = linemap_macro_map_loc_to_exp_point (map: linemap_check_macro (map),
1699 location);
1700 }
1701
1702 if (original_map)
1703 *original_map = linemap_check_ordinary (map);
1704 return location;
1705}
1706
1707/* Resolve a virtual location into either a spelling location, an
1708 expansion point location or a token argument replacement point
1709 location. Return the map that encodes the virtual location as well
1710 as the resolved location.
1711
1712 If LOC is *NOT* the location of a token resulting from the
1713 expansion of a macro, then the parameter LRK (which stands for
1714 Location Resolution Kind) is ignored and the resulting location
1715 just equals the one given in argument.
1716
1717 Now if LOC *IS* the location of a token resulting from the
1718 expansion of a macro, this is what happens.
1719
1720 * If LRK is set to LRK_MACRO_EXPANSION_POINT
1721 -------------------------------
1722
1723 The virtual location is resolved to the first macro expansion point
1724 that led to this macro expansion.
1725
1726 * If LRK is set to LRK_SPELLING_LOCATION
1727 -------------------------------------
1728
1729 The virtual location is resolved to the locus where the token has
1730 been spelled in the source. This can follow through all the macro
1731 expansions that led to the token.
1732
1733 * If LRK is set to LRK_MACRO_DEFINITION_LOCATION
1734 --------------------------------------
1735
1736 The virtual location is resolved to the locus of the token in the
1737 context of the macro definition.
1738
1739 If LOC is the locus of a token that is an argument of a
1740 function-like macro [replacing a parameter in the replacement list
1741 of the macro] the virtual location is resolved to the locus of the
1742 parameter that is replaced, in the context of the definition of the
1743 macro.
1744
1745 If LOC is the locus of a token that is not an argument of a
1746 function-like macro, then the function behaves as if LRK was set to
1747 LRK_SPELLING_LOCATION.
1748
1749 If MAP is not NULL, *MAP is set to the map encoding the
1750 returned location. Note that if the returned location wasn't originally
1751 encoded by a map, then *MAP is set to NULL. This can happen if LOC
1752 resolves to a location reserved for the client code, like
1753 UNKNOWN_LOCATION or BUILTINS_LOCATION in GCC. */
1754
1755location_t
1756linemap_resolve_location (const line_maps *set,
1757 location_t loc,
1758 enum location_resolution_kind lrk,
1759 const line_map_ordinary **map)
1760{
1761 location_t locus = loc;
1762 if (IS_ADHOC_LOC (loc))
1763 locus = get_location_from_adhoc_loc (set, loc);
1764
1765 if (locus < RESERVED_LOCATION_COUNT)
1766 {
1767 /* A reserved location wasn't encoded in a map. Let's return a
1768 NULL map here, just like what linemap_ordinary_map_lookup
1769 does. */
1770 if (map)
1771 *map = NULL;
1772 return loc;
1773 }
1774
1775 switch (lrk)
1776 {
1777 case LRK_MACRO_EXPANSION_POINT:
1778 loc = linemap_macro_loc_to_exp_point (set, location: loc, original_map: map);
1779 break;
1780 case LRK_SPELLING_LOCATION:
1781 loc = linemap_macro_loc_to_spelling_point (set, location: loc, original_map: map);
1782 break;
1783 case LRK_MACRO_DEFINITION_LOCATION:
1784 loc = linemap_macro_loc_to_def_point (set, location: loc, original_map: map);
1785 break;
1786 default:
1787 abort ();
1788 }
1789 return loc;
1790}
1791
1792/* TRUE if LOCATION is a source code location of a token that is part of the
1793 definition of a macro, FALSE otherwise. */
1794
1795bool
1796linemap_location_from_macro_definition_p (const line_maps *set,
1797 location_t loc)
1798{
1799 if (IS_ADHOC_LOC (loc))
1800 loc = get_location_from_adhoc_loc (set, loc);
1801
1802 if (!linemap_location_from_macro_expansion_p (set, location: loc))
1803 return false;
1804
1805 while (true)
1806 {
1807 const struct line_map_macro *map
1808 = linemap_check_macro (map: linemap_lookup (set, line: loc));
1809
1810 location_t s_loc
1811 = linemap_macro_map_loc_unwind_toward_spelling (set, map, location: loc);
1812 if (linemap_location_from_macro_expansion_p (set, location: s_loc))
1813 loc = s_loc;
1814 else
1815 {
1816 location_t def_loc
1817 = linemap_macro_map_loc_to_def_point (map, location: loc);
1818 return s_loc == def_loc;
1819 }
1820 }
1821}
1822
1823/*
1824 Suppose that LOC is the virtual location of a token T coming from
1825 the expansion of a macro M. This function then steps up to get the
1826 location L of the point where M got expanded. If L is a spelling
1827 location inside a macro expansion M', then this function returns
1828 the locus of the point where M' was expanded. Said otherwise, this
1829 function returns the location of T in the context that triggered
1830 the expansion of M.
1831
1832 *LOC_MAP must be set to the map of LOC. This function then sets it
1833 to the map of the returned location. */
1834
1835location_t
1836linemap_unwind_toward_expansion (const line_maps *set,
1837 location_t loc,
1838 const struct line_map **map)
1839{
1840 location_t resolved_location;
1841 const line_map_macro *macro_map = linemap_check_macro (map: *map);
1842 const struct line_map *resolved_map;
1843
1844 if (IS_ADHOC_LOC (loc))
1845 loc = get_location_from_adhoc_loc (set, loc);
1846
1847 resolved_location =
1848 linemap_macro_map_loc_unwind_toward_spelling (set, map: macro_map, location: loc);
1849 resolved_map = linemap_lookup (set, line: resolved_location);
1850
1851 if (!linemap_macro_expansion_map_p (map: resolved_map))
1852 {
1853 resolved_location = linemap_macro_map_loc_to_exp_point (map: macro_map, location: loc);
1854 resolved_map = linemap_lookup (set, line: resolved_location);
1855 }
1856
1857 *map = resolved_map;
1858 return resolved_location;
1859}
1860
1861/* If LOC is the virtual location of a token coming from the expansion
1862 of a macro M and if its spelling location is reserved (e.g, a
1863 location for a built-in token), then this function unwinds (using
1864 linemap_unwind_toward_expansion) the location until a location that
1865 is not reserved and is not in a system header is reached. In other
1866 words, this unwinds the reserved location until a location that is
1867 in real source code is reached.
1868
1869 Otherwise, if the spelling location for LOC is not reserved or if
1870 LOC doesn't come from the expansion of a macro, the function
1871 returns LOC as is and *MAP is not touched.
1872
1873 *MAP is set to the map of the returned location if the later is
1874 different from LOC. */
1875location_t
1876linemap_unwind_to_first_non_reserved_loc (const line_maps *set,
1877 location_t loc,
1878 const struct line_map **map)
1879{
1880 location_t resolved_loc;
1881 const struct line_map *map0 = NULL;
1882 const line_map_ordinary *map1 = NULL;
1883
1884 if (IS_ADHOC_LOC (loc))
1885 loc = get_location_from_adhoc_loc (set, loc);
1886
1887 map0 = linemap_lookup (set, line: loc);
1888 if (!linemap_macro_expansion_map_p (map: map0))
1889 return loc;
1890
1891 resolved_loc = linemap_resolve_location (set, loc,
1892 lrk: LRK_SPELLING_LOCATION,
1893 map: &map1);
1894
1895 if (resolved_loc >= RESERVED_LOCATION_COUNT
1896 && !LINEMAP_SYSP (ord_map: map1))
1897 return loc;
1898
1899 while (linemap_macro_expansion_map_p (map: map0)
1900 && (resolved_loc < RESERVED_LOCATION_COUNT
1901 || LINEMAP_SYSP (ord_map: map1)))
1902 {
1903 loc = linemap_unwind_toward_expansion (set, loc, map: &map0);
1904 resolved_loc = linemap_resolve_location (set, loc,
1905 lrk: LRK_SPELLING_LOCATION,
1906 map: &map1);
1907 }
1908
1909 if (map != NULL)
1910 *map = map0;
1911 return loc;
1912}
1913
1914/* Expand source code location LOC and return a user readable source
1915 code location. LOC must be a spelling (non-virtual) location. If
1916 it's a location < RESERVED_LOCATION_COUNT a zeroed expanded source
1917 location is returned. */
1918
1919expanded_location
1920linemap_expand_location (const line_maps *set,
1921 const struct line_map *map,
1922 location_t loc)
1923
1924{
1925 expanded_location xloc;
1926
1927 memset (s: &xloc, c: 0, n: sizeof (xloc));
1928 if (IS_ADHOC_LOC (loc))
1929 {
1930 xloc.data = get_data_from_adhoc_loc (set, loc);
1931 loc = get_location_from_adhoc_loc (set, loc);
1932 }
1933
1934 if (loc < RESERVED_LOCATION_COUNT)
1935 /* The location for this token wasn't generated from a line map.
1936 It was probably a location for a builtin token, chosen by some
1937 client code. Let's not try to expand the location in that
1938 case. */;
1939 else if (map == NULL)
1940 /* We shouldn't be getting a NULL map with a location that is not
1941 reserved by the client code. */
1942 abort ();
1943 else
1944 {
1945 /* MAP must be an ordinary map and LOC must be non-virtual,
1946 encoded into this map, obviously; the accessors used on MAP
1947 below ensure it is ordinary. Let's just assert the
1948 non-virtualness of LOC here. */
1949 if (linemap_location_from_macro_expansion_p (set, location: loc))
1950 abort ();
1951
1952 const line_map_ordinary *ord_map = linemap_check_ordinary (map);
1953
1954 xloc.file = LINEMAP_FILE (ord_map);
1955 xloc.line = SOURCE_LINE (ord_map, loc);
1956 xloc.column = SOURCE_COLUMN (ord_map, loc);
1957 xloc.sysp = LINEMAP_SYSP (ord_map) != 0;
1958 }
1959
1960 return xloc;
1961}
1962
1963bool
1964operator== (const expanded_location &a,
1965 const expanded_location &b)
1966{
1967 /* "file" can be null; for them to be equal they must both
1968 have either null or nonnull values, and if non-null
1969 they must compare as equal. */
1970 if ((a.file == nullptr) != (b.file == nullptr))
1971 return false;
1972 if (a.file && strcmp (s1: a.file, s2: b.file))
1973 return false;
1974
1975 if (a.line != b.line)
1976 return false;
1977 if (a.column != b.column)
1978 return false;
1979 if (a.data != b.data)
1980 return false;
1981 if (a.sysp != b.sysp)
1982 return false;
1983 return true;
1984}
1985
1986/* Dump line map at index IX in line table SET to STREAM. If STREAM
1987 is NULL, use stderr. IS_MACRO is true if the caller wants to
1988 dump a macro map, false otherwise. */
1989
1990void
1991linemap_dump (FILE *stream, const line_maps *set, line_map_uint_t ix,
1992 bool is_macro)
1993{
1994 const char *const lc_reasons_v[LC_HWM]
1995 = { "LC_ENTER", "LC_LEAVE", "LC_RENAME", "LC_RENAME_VERBATIM",
1996 "LC_ENTER_MACRO", "LC_MODULE" };
1997 const line_map *map;
1998 unsigned reason;
1999
2000 if (stream == NULL)
2001 stream = stderr;
2002
2003 if (!is_macro)
2004 {
2005 map = LINEMAPS_ORDINARY_MAP_AT (set, index: ix);
2006 reason = linemap_check_ordinary (map)->reason;
2007 }
2008 else
2009 {
2010 map = LINEMAPS_MACRO_MAP_AT (set, index: ix);
2011 reason = LC_ENTER_MACRO;
2012 }
2013
2014 fprintf (stream: stream, format: "Map #%llu [%p] - LOC: %llu - REASON: %s - SYSP: %s\n",
2015 (unsigned long long) ix,
2016 (void *) map,
2017 (unsigned long long) map->start_location,
2018 reason < LC_HWM ? lc_reasons_v[reason] : "???",
2019 ((!is_macro
2020 && ORDINARY_MAP_IN_SYSTEM_HEADER_P (ord_map: linemap_check_ordinary (map)))
2021 ? "yes" : "no"));
2022 if (!is_macro)
2023 {
2024 const line_map_ordinary *ord_map = linemap_check_ordinary (map);
2025 const line_map_ordinary *includer_map
2026 = linemap_included_from_linemap (set, map: ord_map);
2027
2028 fprintf (stream: stream, format: "File: %s:%u\n", ORDINARY_MAP_FILE_NAME (ord_map),
2029 ORDINARY_MAP_STARTING_LINE_NUMBER (ord_map));
2030 const long long from_ind
2031 = includer_map ? includer_map - set->info_ordinary.maps : -1;
2032 fprintf (stream: stream, format: "Included from: [%lld] %s\n",
2033 from_ind,
2034 includer_map ? ORDINARY_MAP_FILE_NAME (ord_map: includer_map) : "None");
2035 }
2036 else
2037 {
2038 const line_map_macro *macro_map = linemap_check_macro (map);
2039 fprintf (stream: stream, format: "Macro: %s (%u tokens)\n",
2040 linemap_map_get_macro_name (macro_map),
2041 MACRO_MAP_NUM_MACRO_TOKENS (macro_map));
2042 }
2043
2044 fprintf (stream: stream, format: "\n");
2045}
2046
2047
2048/* Dump debugging information about source location LOC into the file
2049 stream STREAM. SET is the line map set LOC comes from. */
2050
2051void
2052linemap_dump_location (const line_maps *set,
2053 location_t loc,
2054 FILE *stream)
2055{
2056 const line_map_ordinary *map;
2057 location_t location;
2058 const char *path = "", *from = "";
2059 int l = -1, c = -1, s = -1, e = -1;
2060
2061 if (IS_ADHOC_LOC (loc))
2062 loc = get_location_from_adhoc_loc (set, loc);
2063
2064 if (loc == 0)
2065 return;
2066
2067 location =
2068 linemap_resolve_location (set, loc, lrk: LRK_MACRO_DEFINITION_LOCATION, map: &map);
2069
2070 if (map == NULL)
2071 /* Only reserved locations can be tolerated in this case. */
2072 linemap_assert (location < RESERVED_LOCATION_COUNT);
2073 else
2074 {
2075 path = LINEMAP_FILE (ord_map: map);
2076 l = SOURCE_LINE (ord_map: map, loc: location);
2077 c = SOURCE_COLUMN (ord_map: map, loc: location);
2078 s = LINEMAP_SYSP (ord_map: map) != 0;
2079 e = location != loc;
2080 if (e)
2081 from = "N/A";
2082 else
2083 {
2084 const line_map_ordinary *from_map
2085 = linemap_included_from_linemap (set, map);
2086 from = from_map ? LINEMAP_FILE (ord_map: from_map) : "<NULL>";
2087 }
2088 }
2089
2090 /* P: path, L: line, C: column, S: in-system-header, M: map address,
2091 E: macro expansion?, LOC: original location, R: resolved location */
2092 fprintf (stream: stream, format: "{P:%s;F:%s;L:%d;C:%d;S:%d;M:%p;E:%d,LOC:%llu,R:%llu}",
2093 path, from, l, c, s, (void*)map, e,
2094 (unsigned long long) loc,
2095 (unsigned long long) location);
2096}
2097
2098/* Return the highest location emitted for a given file for which
2099 there is a line map in SET. FILE_NAME is the file name to
2100 consider. If the function returns TRUE, *LOC is set to the highest
2101 location emitted for that file. */
2102
2103bool
2104linemap_get_file_highest_location (const line_maps *set,
2105 const char *file_name,
2106 location_t *loc)
2107{
2108 /* If the set is empty or no ordinary map has been created then
2109 there is no file to look for ... */
2110 if (set == NULL || set->info_ordinary.used == 0)
2111 return false;
2112
2113 /* Now look for the last ordinary map created for FILE_NAME. */
2114 location_diff_t i;
2115 for (i = set->info_ordinary.used - 1; i >= 0; --i)
2116 {
2117 const char *fname = set->info_ordinary.maps[i].to_file;
2118 if (fname && !filename_cmp (s1: fname, s2: file_name))
2119 break;
2120 }
2121
2122 if (i < 0)
2123 return false;
2124
2125 /* The highest location for a given map is either the starting
2126 location of the next map minus one, or -- if the map is the
2127 latest one -- the highest location of the set. */
2128 location_t result;
2129 if ((location_t) i == set->info_ordinary.used - 1)
2130 result = set->highest_location;
2131 else
2132 result = set->info_ordinary.maps[i + 1].start_location - 1;
2133
2134 *loc = result;
2135 return true;
2136}
2137
2138/* Compute and return statistics about the memory consumption of some
2139 parts of the line table SET. */
2140
2141void
2142linemap_get_statistics (const line_maps *set,
2143 struct linemap_stats *s)
2144{
2145 long ordinary_maps_allocated_size, ordinary_maps_used_size,
2146 macro_maps_allocated_size, macro_maps_used_size,
2147 macro_maps_locations_size = 0, duplicated_macro_maps_locations_size = 0;
2148
2149 const line_map_macro *cur_map;
2150
2151 ordinary_maps_allocated_size =
2152 LINEMAPS_ORDINARY_ALLOCATED (set) * sizeof (struct line_map_ordinary);
2153
2154 ordinary_maps_used_size =
2155 LINEMAPS_ORDINARY_USED (set) * sizeof (struct line_map_ordinary);
2156
2157 macro_maps_allocated_size =
2158 LINEMAPS_MACRO_ALLOCATED (set) * sizeof (struct line_map_macro);
2159
2160 for (cur_map = set->info_macro.maps;
2161 cur_map && cur_map <= LINEMAPS_LAST_MACRO_MAP (set);
2162 ++cur_map)
2163 {
2164 unsigned i;
2165
2166 linemap_assert (linemap_macro_expansion_map_p (cur_map));
2167
2168 macro_maps_locations_size +=
2169 2 * MACRO_MAP_NUM_MACRO_TOKENS (macro_map: cur_map) * sizeof (location_t);
2170
2171 for (i = 0; i < 2 * MACRO_MAP_NUM_MACRO_TOKENS (macro_map: cur_map); i += 2)
2172 {
2173 if (MACRO_MAP_LOCATIONS (macro_map: cur_map)[i] ==
2174 MACRO_MAP_LOCATIONS (macro_map: cur_map)[i + 1])
2175 duplicated_macro_maps_locations_size +=
2176 sizeof (location_t);
2177 }
2178 }
2179
2180 macro_maps_used_size =
2181 LINEMAPS_MACRO_USED (set) * sizeof (struct line_map_macro);
2182
2183 s->num_ordinary_maps_allocated = LINEMAPS_ORDINARY_ALLOCATED (set);
2184 s->num_ordinary_maps_used = LINEMAPS_ORDINARY_USED (set);
2185 s->ordinary_maps_allocated_size = ordinary_maps_allocated_size;
2186 s->ordinary_maps_used_size = ordinary_maps_used_size;
2187 s->num_expanded_macros = num_expanded_macros_counter;
2188 s->num_macro_tokens = num_macro_tokens_counter;
2189 s->num_macro_maps_used = LINEMAPS_MACRO_USED (set);
2190 s->macro_maps_allocated_size = macro_maps_allocated_size;
2191 s->macro_maps_locations_size = macro_maps_locations_size;
2192 s->macro_maps_used_size = macro_maps_used_size;
2193 s->duplicated_macro_maps_locations_size =
2194 duplicated_macro_maps_locations_size;
2195 s->adhoc_table_size = (set->m_location_adhoc_data_map.allocated
2196 * sizeof (struct location_adhoc_data));
2197 s->adhoc_table_entries_used = set->m_location_adhoc_data_map.curr_loc;
2198}
2199
2200
2201/* Dump line table SET to STREAM. If STREAM is NULL, stderr is used.
2202 NUM_ORDINARY specifies how many ordinary maps to dump. NUM_MACRO
2203 specifies how many macro maps to dump. */
2204
2205void
2206line_table_dump (FILE *stream, const line_maps *set,
2207 line_map_uint_t num_ordinary, line_map_uint_t num_macro)
2208{
2209 line_map_uint_t i;
2210
2211 if (set == NULL)
2212 return;
2213
2214 if (stream == NULL)
2215 stream = stderr;
2216
2217 fprintf (stream: stream, format: "# of ordinary maps: %llu\n",
2218 (unsigned long long) LINEMAPS_ORDINARY_USED (set));
2219 fprintf (stream: stream, format: "# of macro maps: %llu\n",
2220 (unsigned long long) LINEMAPS_MACRO_USED (set));
2221 fprintf (stream: stream, format: "Include stack depth: %d\n", set->depth);
2222 fprintf (stream: stream, format: "Highest location: %llu\n",
2223 (unsigned long long) set->highest_location);
2224
2225 if (num_ordinary)
2226 {
2227 fprintf (stream: stream, format: "\nOrdinary line maps\n");
2228 for (i = 0; i < num_ordinary && i < LINEMAPS_ORDINARY_USED (set); i++)
2229 linemap_dump (stream, set, ix: i, is_macro: false);
2230 fprintf (stream: stream, format: "\n");
2231 }
2232
2233 if (num_macro)
2234 {
2235 fprintf (stream: stream, format: "\nMacro line maps\n");
2236 for (i = 0; i < num_macro && i < LINEMAPS_MACRO_USED (set); i++)
2237 linemap_dump (stream, set, ix: i, is_macro: true);
2238 fprintf (stream: stream, format: "\n");
2239 }
2240}
2241
2242/* class rich_location. */
2243
2244/* Construct a rich_location with location LOC as its initial range. */
2245
2246rich_location::rich_location (line_maps *set, location_t loc,
2247 const range_label *label,
2248 const char *label_highlight_color)
2249: m_line_table (set),
2250 m_ranges (),
2251 m_column_override (0),
2252 m_have_expanded_location (false),
2253 m_seen_impossible_fixit (false),
2254 m_fixits_cannot_be_auto_applied (false),
2255 m_escape_on_output (false),
2256 m_fixit_hints (),
2257 m_path (NULL)
2258{
2259 add_range (loc, range_display_kind: SHOW_RANGE_WITH_CARET, label, highlight_color: label_highlight_color);
2260}
2261
2262/* Copy ctor for rich_location.
2263 Take a deep copy of the fixit hints, which are owneed;
2264 everything else is borrowed. */
2265
2266rich_location::rich_location (const rich_location &other)
2267: m_line_table (other.m_line_table),
2268 m_ranges (other.m_ranges),
2269 m_column_override (other.m_column_override),
2270 m_have_expanded_location (other.m_have_expanded_location),
2271 m_seen_impossible_fixit (other.m_seen_impossible_fixit),
2272 m_fixits_cannot_be_auto_applied (other.m_fixits_cannot_be_auto_applied),
2273 m_escape_on_output (other.m_escape_on_output),
2274 m_expanded_location (other.m_expanded_location),
2275 m_fixit_hints (),
2276 m_path (other.m_path)
2277{
2278 for (unsigned i = 0; i < other.m_fixit_hints.count (); i++)
2279 m_fixit_hints.push (value: new fixit_hint (*other.m_fixit_hints[i]));
2280}
2281
2282/* The destructor for class rich_location. */
2283
2284rich_location::~rich_location ()
2285{
2286 for (unsigned int i = 0; i < m_fixit_hints.count (); i++)
2287 delete get_fixit_hint (idx: i);
2288}
2289
2290/* Get location IDX within this rich_location. */
2291
2292location_t
2293rich_location::get_loc (unsigned int idx) const
2294{
2295 const location_range *locrange = get_range (idx);
2296 return locrange->m_loc;
2297}
2298
2299/* Get range IDX within this rich_location. */
2300
2301const location_range *
2302rich_location::get_range (unsigned int idx) const
2303{
2304 return &m_ranges[idx];
2305}
2306
2307/* Mutable access to range IDX within this rich_location. */
2308
2309location_range *
2310rich_location::get_range (unsigned int idx)
2311{
2312 return &m_ranges[idx];
2313}
2314
2315/* Expand location IDX within this rich_location. */
2316/* Get an expanded_location for this rich_location's primary
2317 location. */
2318
2319expanded_location
2320rich_location::get_expanded_location (unsigned int idx) const
2321{
2322 if (idx == 0)
2323 {
2324 /* Cache the expansion of the primary location. */
2325 if (!m_have_expanded_location)
2326 {
2327 m_expanded_location
2328 = linemap_client_expand_location_to_spelling_point
2329 (m_line_table, get_loc (idx: 0), location_aspect::caret);
2330 if (m_column_override)
2331 m_expanded_location.column = m_column_override;
2332 m_have_expanded_location = true;
2333 }
2334
2335 return m_expanded_location;
2336 }
2337 else
2338 return linemap_client_expand_location_to_spelling_point
2339 (m_line_table, get_loc (idx), location_aspect::caret);
2340}
2341
2342/* Set the column of the primary location, with 0 meaning
2343 "don't override it". */
2344
2345void
2346rich_location::override_column (int column)
2347{
2348 m_column_override = column;
2349 m_have_expanded_location = false;
2350}
2351
2352/* Set (or clear) the highlight color of the primary location. */
2353
2354void
2355rich_location::set_highlight_color (const char *highlight_color)
2356{
2357 location_range *locrange = get_range (idx: 0);
2358 locrange->m_highlight_color = highlight_color;
2359}
2360
2361/* Add the given range. */
2362
2363void
2364rich_location::add_range (location_t loc,
2365 enum range_display_kind range_display_kind,
2366 const range_label *label,
2367 const char *label_highlight_color)
2368{
2369 location_range range;
2370 range.m_loc = loc;
2371 range.m_range_display_kind = range_display_kind;
2372 range.m_label = label;
2373 range.m_highlight_color = label_highlight_color;
2374 m_ranges.push (value: range);
2375}
2376
2377/* Add or overwrite the location given by IDX, setting its location to LOC,
2378 setting its m_range_display_kind to RANGE_DISPLAY_KIND, and setting
2379 its m_highlight_color to HIGHLIGHT_COLOR (which may be nullptr).
2380
2381 It must either overwrite an existing location, or add one *exactly* on
2382 the end of the array.
2383
2384 This is primarily for use by gcc when implementing diagnostic format
2385 decoders e.g.
2386 - the "+" in the C/C++ frontends, for handling format codes like "%q+D"
2387 (which writes the source location of a tree back into location 0 of
2388 the rich_location), and
2389 - the "%C" and "%L" format codes in the Fortran frontend. */
2390
2391void
2392rich_location::set_range (unsigned int idx, location_t loc,
2393 enum range_display_kind range_display_kind,
2394 const char *highlight_color)
2395{
2396 /* We can either overwrite an existing range, or add one exactly
2397 on the end of the array. */
2398 linemap_assert (idx <= m_ranges.count ());
2399
2400 if (idx == m_ranges.count ())
2401 add_range (loc, range_display_kind, label: nullptr, label_highlight_color: highlight_color);
2402 else
2403 {
2404 location_range *locrange = get_range (idx);
2405 locrange->m_loc = loc;
2406 locrange->m_range_display_kind = range_display_kind;
2407 locrange->m_highlight_color = highlight_color;
2408 }
2409
2410 if (idx == 0)
2411 /* Mark any cached value here as dirty. */
2412 m_have_expanded_location = false;
2413}
2414
2415/* Methods for adding insertion fix-it hints. */
2416
2417/* Add a fixit-hint, suggesting insertion of NEW_CONTENT
2418 immediately before the primary range's start location. */
2419
2420void
2421rich_location::add_fixit_insert_before (const char *new_content)
2422{
2423 add_fixit_insert_before (where: get_loc (), new_content);
2424}
2425
2426/* Add a fixit-hint, suggesting insertion of NEW_CONTENT
2427 immediately before the start of WHERE. */
2428
2429void
2430rich_location::add_fixit_insert_before (location_t where,
2431 const char *new_content)
2432{
2433 location_t start = get_range_from_loc (set: m_line_table, loc: where).m_start;
2434 maybe_add_fixit (start, next_loc: start, new_content);
2435}
2436
2437/* Add a fixit-hint, suggesting insertion of NEW_CONTENT
2438 immediately after the primary range's end-point. */
2439
2440void
2441rich_location::add_fixit_insert_after (const char *new_content)
2442{
2443 add_fixit_insert_after (where: get_loc (), new_content);
2444}
2445
2446/* Add a fixit-hint, suggesting insertion of NEW_CONTENT
2447 immediately after the end-point of WHERE. */
2448
2449void
2450rich_location::add_fixit_insert_after (location_t where,
2451 const char *new_content)
2452{
2453 location_t finish = get_range_from_loc (set: m_line_table, loc: where).m_finish;
2454 location_t next_loc
2455 = linemap_position_for_loc_and_offset (set: m_line_table, loc: finish, column_offset: 1);
2456
2457 /* linemap_position_for_loc_and_offset can fail, if so, it returns
2458 its input value. */
2459 if (next_loc == finish)
2460 {
2461 stop_supporting_fixits ();
2462 return;
2463 }
2464
2465 maybe_add_fixit (start: next_loc, next_loc, new_content);
2466}
2467
2468/* Methods for adding removal fix-it hints. */
2469
2470/* Add a fixit-hint, suggesting removal of the content covered
2471 by range 0. */
2472
2473void
2474rich_location::add_fixit_remove ()
2475{
2476 add_fixit_remove (where: get_loc ());
2477}
2478
2479/* Add a fixit-hint, suggesting removal of the content between
2480 the start and finish of WHERE. */
2481
2482void
2483rich_location::add_fixit_remove (location_t where)
2484{
2485 source_range range = get_range_from_loc (set: m_line_table, loc: where);
2486 add_fixit_remove (src_range: range);
2487}
2488
2489/* Add a fixit-hint, suggesting removal of the content at
2490 SRC_RANGE. */
2491
2492void
2493rich_location::add_fixit_remove (source_range src_range)
2494{
2495 add_fixit_replace (src_range, new_content: "");
2496}
2497
2498/* Add a fixit-hint, suggesting replacement of the content covered
2499 by range 0 with NEW_CONTENT. */
2500
2501void
2502rich_location::add_fixit_replace (const char *new_content)
2503{
2504 add_fixit_replace (where: get_loc (), new_content);
2505}
2506
2507/* Methods for adding "replace" fix-it hints. */
2508
2509/* Add a fixit-hint, suggesting replacement of the content between
2510 the start and finish of WHERE with NEW_CONTENT. */
2511
2512void
2513rich_location::add_fixit_replace (location_t where,
2514 const char *new_content)
2515{
2516 source_range range = get_range_from_loc (set: m_line_table, loc: where);
2517 add_fixit_replace (src_range: range, new_content);
2518}
2519
2520/* Add a fixit-hint, suggesting replacement of the content at
2521 SRC_RANGE with NEW_CONTENT. */
2522
2523void
2524rich_location::add_fixit_replace (source_range src_range,
2525 const char *new_content)
2526{
2527 location_t start = get_pure_location (set: m_line_table, loc: src_range.m_start);
2528 location_t finish = get_pure_location (set: m_line_table, loc: src_range.m_finish);
2529
2530 /* Fix-it hints use half-closed ranges, so attempt to offset the endpoint. */
2531 location_t next_loc
2532 = linemap_position_for_loc_and_offset (set: m_line_table, loc: finish, column_offset: 1);
2533 /* linemap_position_for_loc_and_offset can fail, if so, it returns
2534 its input value. */
2535 if (next_loc == finish)
2536 {
2537 stop_supporting_fixits ();
2538 return;
2539 }
2540 finish = next_loc;
2541
2542 maybe_add_fixit (start, next_loc: finish, new_content);
2543}
2544
2545/* Get the last fix-it hint within this rich_location, or NULL if none. */
2546
2547fixit_hint *
2548rich_location::get_last_fixit_hint () const
2549{
2550 if (m_fixit_hints.count () > 0)
2551 return get_fixit_hint (idx: m_fixit_hints.count () - 1);
2552 else
2553 return NULL;
2554}
2555
2556/* If WHERE is an "awkward" location, then mark this rich_location as not
2557 supporting fixits, purging any thay were already added, and return true.
2558
2559 Otherwise (the common case), return false. */
2560
2561bool
2562rich_location::reject_impossible_fixit (location_t where)
2563{
2564 /* Fix-its within a rich_location should either all be suggested, or
2565 none of them should be suggested.
2566 Once we've rejected a fixit, we reject any more, even those
2567 with reasonable locations. */
2568 if (m_seen_impossible_fixit)
2569 return true;
2570
2571 if (where <= LINE_MAP_MAX_LOCATION_WITH_COLS)
2572 /* WHERE is a reasonable location for a fix-it; don't reject it. */
2573 return false;
2574
2575 /* Otherwise we have an attempt to add a fix-it with an "awkward"
2576 location: either one that we can't obtain column information
2577 for (within an ordinary map), or one within a macro expansion. */
2578 stop_supporting_fixits ();
2579 return true;
2580}
2581
2582/* Mark this rich_location as not supporting fixits, purging any that were
2583 already added. */
2584
2585void
2586rich_location::stop_supporting_fixits ()
2587{
2588 m_seen_impossible_fixit = true;
2589
2590 /* Purge the rich_location of any fix-its that were already added. */
2591 for (unsigned int i = 0; i < m_fixit_hints.count (); i++)
2592 delete get_fixit_hint (idx: i);
2593 m_fixit_hints.truncate (len: 0);
2594}
2595
2596/* Add HINT to the fix-it hints in this rich_location,
2597 consolidating into the prior fixit if possible. */
2598
2599void
2600rich_location::maybe_add_fixit (location_t start,
2601 location_t next_loc,
2602 const char *new_content)
2603{
2604 if (reject_impossible_fixit (where: start))
2605 return;
2606 if (reject_impossible_fixit (where: next_loc))
2607 return;
2608
2609 /* Only allow fix-it hints that affect a single line in one file.
2610 Compare the end-points. */
2611 expanded_location exploc_start
2612 = linemap_client_expand_location_to_spelling_point (m_line_table,
2613 start,
2614 location_aspect::start);
2615 expanded_location exploc_next_loc
2616 = linemap_client_expand_location_to_spelling_point (m_line_table,
2617 next_loc,
2618 location_aspect::start);
2619 /* They must be within the same file... */
2620 if (exploc_start.file != exploc_next_loc.file)
2621 {
2622 stop_supporting_fixits ();
2623 return;
2624 }
2625 /* ...and on the same line. */
2626 if (exploc_start.line != exploc_next_loc.line)
2627 {
2628 stop_supporting_fixits ();
2629 return;
2630 }
2631 /* The columns must be in the correct order. This can fail if the
2632 endpoints straddle the boundary for which the linemap can represent
2633 columns (PR c/82050). */
2634 if (exploc_start.column > exploc_next_loc.column)
2635 {
2636 stop_supporting_fixits ();
2637 return;
2638 }
2639 /* If we have very long lines, tokens will eventually fall back to
2640 having column == 0.
2641 We can't handle fix-it hints that use such locations. */
2642 if (exploc_start.column == 0 || exploc_next_loc.column == 0)
2643 {
2644 stop_supporting_fixits ();
2645 return;
2646 }
2647
2648 const char *newline = strchr (s: new_content, c: '\n');
2649 if (newline)
2650 {
2651 /* For now, we can only support insertion of whole lines
2652 i.e. starts at start of line, and the newline is at the end of
2653 the insertion point. */
2654
2655 /* It must be an insertion, not a replacement/deletion. */
2656 if (start != next_loc)
2657 {
2658 stop_supporting_fixits ();
2659 return;
2660 }
2661
2662 /* The insertion must be at the start of a line. */
2663 if (exploc_start.column != 1)
2664 {
2665 stop_supporting_fixits ();
2666 return;
2667 }
2668
2669 /* The newline must be at end of NEW_CONTENT.
2670 We could eventually split up fix-its at newlines if we wanted
2671 to allow more generality (e.g. to allow adding multiple lines
2672 with one add_fixit call. */
2673 if (newline[1] != '\0')
2674 {
2675 stop_supporting_fixits ();
2676 return;
2677 }
2678 }
2679
2680 /* Consolidate neighboring fixits.
2681 Don't consolidate into newline-insertion fixits. */
2682 fixit_hint *prev = get_last_fixit_hint ();
2683 if (prev && !prev->ends_with_newline_p ())
2684 if (prev->maybe_append (start, next_loc, new_content))
2685 return;
2686
2687 m_fixit_hints.push (value: new fixit_hint (start, next_loc, new_content));
2688}
2689
2690/* class fixit_hint. */
2691
2692fixit_hint::fixit_hint (location_t start,
2693 location_t next_loc,
2694 const char *new_content)
2695: m_start (start),
2696 m_next_loc (next_loc),
2697 m_bytes (xstrdup (new_content)),
2698 m_len (strlen (s: new_content))
2699{
2700}
2701
2702fixit_hint::fixit_hint (const fixit_hint &other)
2703: m_start (other.m_start),
2704 m_next_loc (other.m_next_loc),
2705 m_bytes (xstrdup (other.m_bytes)),
2706 m_len (other.m_len)
2707{
2708}
2709
2710/* Does this fix-it hint affect the given line? */
2711
2712bool
2713fixit_hint::affects_line_p (const line_maps *set,
2714 const char *file,
2715 int line) const
2716{
2717 expanded_location exploc_start
2718 = linemap_client_expand_location_to_spelling_point (set,
2719 m_start,
2720 location_aspect::start);
2721 if (file != exploc_start.file)
2722 return false;
2723 if (line < exploc_start.line)
2724 return false;
2725 expanded_location exploc_next_loc
2726 = linemap_client_expand_location_to_spelling_point (set,
2727 m_next_loc,
2728 location_aspect::start);
2729 if (file != exploc_next_loc.file)
2730 return false;
2731 if (line > exploc_next_loc.line)
2732 return false;
2733 return true;
2734}
2735
2736/* Method for consolidating fix-it hints, for use by
2737 rich_location::maybe_add_fixit.
2738 If possible, merge a pending fix-it hint with the given params
2739 into this one and return true.
2740 Otherwise return false. */
2741
2742bool
2743fixit_hint::maybe_append (location_t start,
2744 location_t next_loc,
2745 const char *new_content)
2746{
2747 /* For consolidation to be possible, START must be at this hint's
2748 m_next_loc. */
2749 if (start != m_next_loc)
2750 return false;
2751
2752 /* If so, we have neighboring replacements; merge them. */
2753 m_next_loc = next_loc;
2754 size_t extra_len = strlen (s: new_content);
2755 m_bytes = (char *)xrealloc (m_bytes, m_len + extra_len + 1);
2756 memcpy (dest: m_bytes + m_len, src: new_content, n: extra_len);
2757 m_len += extra_len;
2758 m_bytes[m_len] = '\0';
2759 return true;
2760}
2761
2762/* Return true iff this hint's content ends with a newline. */
2763
2764bool
2765fixit_hint::ends_with_newline_p () const
2766{
2767 if (m_len == 0)
2768 return false;
2769 return m_bytes[m_len - 1] == '\n';
2770}
2771

source code of libcpp/line-map.cc