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