1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699 |
- /* Map logical line numbers to (source file, line number) pairs.
- Copyright (C) 2001-2015 Free Software Foundation, Inc.
- This program is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 3, or (at your option) any
- later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING3. If not see
- <http://www.gnu.org/licenses/>.
- In other words, you are welcome to use, share and improve this program.
- You are forbidden to forbid anyone else to use, share and improve
- what you give them. Help stamp out software-hoarding! */
- #include "config.h"
- #include "system.h"
- #include "line-map.h"
- #include "cpplib.h"
- #include "internal.h"
- #include "hashtab.h"
- static void trace_include (const struct line_maps *, const struct line_map *);
- static const struct line_map * linemap_ordinary_map_lookup (struct line_maps *,
- source_location);
- static const struct line_map* linemap_macro_map_lookup (struct line_maps *,
- source_location);
- static source_location linemap_macro_map_loc_to_def_point
- (const struct line_map*, source_location);
- static source_location linemap_macro_map_loc_unwind_toward_spelling
- (const struct line_map*, source_location);
- static source_location linemap_macro_map_loc_to_exp_point
- (const struct line_map*, source_location);
- static source_location linemap_macro_loc_to_spelling_point
- (struct line_maps *, source_location, const struct line_map **);
- static source_location linemap_macro_loc_to_def_point (struct line_maps *,
- source_location,
- const struct line_map **);
- static source_location linemap_macro_loc_to_exp_point (struct line_maps *,
- source_location,
- const struct line_map **);
- /* Counters defined in macro.c. */
- extern unsigned num_expanded_macros_counter;
- extern unsigned num_macro_tokens_counter;
- /* Hash function for location_adhoc_data hashtable. */
- static hashval_t
- location_adhoc_data_hash (const void *l)
- {
- const struct location_adhoc_data *lb =
- (const struct location_adhoc_data *) l;
- return (hashval_t) lb->locus + (size_t) lb->data;
- }
- /* Compare function for location_adhoc_data hashtable. */
- static int
- location_adhoc_data_eq (const void *l1, const void *l2)
- {
- const struct location_adhoc_data *lb1 =
- (const struct location_adhoc_data *) l1;
- const struct location_adhoc_data *lb2 =
- (const struct location_adhoc_data *) l2;
- return lb1->locus == lb2->locus && lb1->data == lb2->data;
- }
- /* Update the hashtable when location_adhoc_data is reallocated. */
- static int
- location_adhoc_data_update (void **slot, void *data)
- {
- *((char **) slot) += *((long long *) data);
- return 1;
- }
- /* Rebuild the hash table from the location adhoc data. */
- void
- rebuild_location_adhoc_htab (struct line_maps *set)
- {
- unsigned i;
- set->location_adhoc_data_map.htab =
- htab_create (100, location_adhoc_data_hash, location_adhoc_data_eq, NULL);
- for (i = 0; i < set->location_adhoc_data_map.curr_loc; i++)
- htab_find_slot (set->location_adhoc_data_map.htab,
- set->location_adhoc_data_map.data + i, INSERT);
- }
- /* Combine LOCUS and DATA to a combined adhoc loc. */
- source_location
- get_combined_adhoc_loc (struct line_maps *set,
- source_location locus, void *data)
- {
- struct location_adhoc_data lb;
- struct location_adhoc_data **slot;
- linemap_assert (data);
- if (IS_ADHOC_LOC (locus))
- locus
- = set->location_adhoc_data_map.data[locus & MAX_SOURCE_LOCATION].locus;
- if (locus == 0 && data == NULL)
- return 0;
- lb.locus = locus;
- lb.data = data;
- slot = (struct location_adhoc_data **)
- htab_find_slot (set->location_adhoc_data_map.htab, &lb, INSERT);
- if (*slot == NULL)
- {
- if (set->location_adhoc_data_map.curr_loc >=
- set->location_adhoc_data_map.allocated)
- {
- char *orig_data = (char *) set->location_adhoc_data_map.data;
- long long offset;
- /* Cast away extern "C" from the type of xrealloc. */
- line_map_realloc reallocator = (set->reallocator
- ? set->reallocator
- : (line_map_realloc) xrealloc);
- if (set->location_adhoc_data_map.allocated == 0)
- set->location_adhoc_data_map.allocated = 128;
- else
- set->location_adhoc_data_map.allocated *= 2;
- set->location_adhoc_data_map.data = (struct location_adhoc_data *)
- reallocator (set->location_adhoc_data_map.data,
- set->location_adhoc_data_map.allocated
- * sizeof (struct location_adhoc_data));
- offset = (char *) (set->location_adhoc_data_map.data) - orig_data;
- if (set->location_adhoc_data_map.allocated > 128)
- htab_traverse (set->location_adhoc_data_map.htab,
- location_adhoc_data_update, &offset);
- }
- *slot = set->location_adhoc_data_map.data
- + set->location_adhoc_data_map.curr_loc;
- set->location_adhoc_data_map.data[set->location_adhoc_data_map.curr_loc++]
- = lb;
- }
- return ((*slot) - set->location_adhoc_data_map.data) | 0x80000000;
- }
- /* Return the data for the adhoc loc. */
- void *
- get_data_from_adhoc_loc (struct line_maps *set, source_location loc)
- {
- linemap_assert (IS_ADHOC_LOC (loc));
- return set->location_adhoc_data_map.data[loc & MAX_SOURCE_LOCATION].data;
- }
- /* Return the location for the adhoc loc. */
- source_location
- get_location_from_adhoc_loc (struct line_maps *set, source_location loc)
- {
- linemap_assert (IS_ADHOC_LOC (loc));
- return set->location_adhoc_data_map.data[loc & MAX_SOURCE_LOCATION].locus;
- }
- /* Finalize the location_adhoc_data structure. */
- void
- location_adhoc_data_fini (struct line_maps *set)
- {
- htab_delete (set->location_adhoc_data_map.htab);
- }
- /* Initialize a line map set. */
- void
- linemap_init (struct line_maps *set,
- source_location builtin_location)
- {
- memset (set, 0, sizeof (struct line_maps));
- set->highest_location = RESERVED_LOCATION_COUNT - 1;
- set->highest_line = RESERVED_LOCATION_COUNT - 1;
- set->location_adhoc_data_map.htab =
- htab_create (100, location_adhoc_data_hash, location_adhoc_data_eq, NULL);
- set->builtin_location = builtin_location;
- }
- /* Check for and warn about line_maps entered but not exited. */
- void
- linemap_check_files_exited (struct line_maps *set)
- {
- struct line_map *map;
- /* Depending upon whether we are handling preprocessed input or
- not, this can be a user error or an ICE. */
- for (map = LINEMAPS_LAST_ORDINARY_MAP (set);
- ! MAIN_FILE_P (map);
- map = INCLUDED_FROM (set, map))
- fprintf (stderr, "line-map.c: file \"%s\" entered but not left\n",
- ORDINARY_MAP_FILE_NAME (map));
- }
- /* Create a new line map in the line map set SET, and return it.
- REASON is the reason of creating the map. It determines the type
- of map created (ordinary or macro map). Note that ordinary maps and
- macro maps are allocated in different memory location. */
- static struct line_map *
- new_linemap (struct line_maps *set,
- enum lc_reason reason)
- {
- /* Depending on this variable, a macro map would be allocated in a
- different memory location than an ordinary map. */
- bool macro_map_p = (reason == LC_ENTER_MACRO);
- struct line_map *result;
- if (LINEMAPS_USED (set, macro_map_p) == LINEMAPS_ALLOCATED (set, macro_map_p))
- {
- /* We ran out of allocated line maps. Let's allocate more. */
- unsigned alloc_size;
- /* Cast away extern "C" from the type of xrealloc. */
- line_map_realloc reallocator = (set->reallocator
- ? set->reallocator
- : (line_map_realloc) xrealloc);
- line_map_round_alloc_size_func round_alloc_size =
- set->round_alloc_size;
- /* We are going to execute some dance to try to reduce the
- overhead of the memory allocator, in case we are using the
- ggc-page.c one.
-
- The actual size of memory we are going to get back from the
- allocator is the smallest power of 2 that is greater than the
- size we requested. So let's consider that size then. */
- alloc_size =
- (2 * LINEMAPS_ALLOCATED (set, macro_map_p) + 256)
- * sizeof (struct line_map);
- /* Get the actual size of memory that is going to be allocated
- by the allocator. */
- alloc_size = round_alloc_size (alloc_size);
- /* Now alloc_size contains the exact memory size we would get if
- we have asked for the initial alloc_size amount of memory.
- Let's get back to the number of macro map that amounts
- to. */
- LINEMAPS_ALLOCATED (set, macro_map_p) =
- alloc_size / (sizeof (struct line_map));
- /* And now let's really do the re-allocation. */
- LINEMAPS_MAPS (set, macro_map_p) =
- (struct line_map *) (*reallocator)
- (LINEMAPS_MAPS (set, macro_map_p),
- (LINEMAPS_ALLOCATED (set, macro_map_p)
- * sizeof (struct line_map)));
- result =
- &LINEMAPS_MAPS (set, macro_map_p)[LINEMAPS_USED (set, macro_map_p)];
- memset (result, 0,
- ((LINEMAPS_ALLOCATED (set, macro_map_p)
- - LINEMAPS_USED (set, macro_map_p))
- * sizeof (struct line_map)));
- }
- else
- result =
- &LINEMAPS_MAPS (set, macro_map_p)[LINEMAPS_USED (set, macro_map_p)];
- LINEMAPS_USED (set, macro_map_p)++;
- result->reason = reason;
- return result;
- }
- /* Add a mapping of logical source line to physical source file and
- line number.
- The text pointed to by TO_FILE must have a lifetime
- at least as long as the final call to lookup_line (). An empty
- TO_FILE means standard input. If reason is LC_LEAVE, and
- TO_FILE is NULL, then TO_FILE, TO_LINE and SYSP are given their
- natural values considering the file we are returning to.
- FROM_LINE should be monotonic increasing across calls to this
- function. A call to this function can relocate the previous set of
- maps, so any stored line_map pointers should not be used. */
- 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)
- {
- struct line_map *map;
- source_location start_location = set->highest_location + 1;
- linemap_assert (!(LINEMAPS_ORDINARY_USED (set)
- && (start_location
- < MAP_START_LOCATION (LINEMAPS_LAST_ORDINARY_MAP (set)))));
- /* When we enter the file for the first time reason cannot be
- LC_RENAME. */
- linemap_assert (!(set->depth == 0 && reason == LC_RENAME));
- /* If we are leaving the main file, return a NULL map. */
- if (reason == LC_LEAVE
- && MAIN_FILE_P (LINEMAPS_LAST_ORDINARY_MAP (set))
- && to_file == NULL)
- {
- set->depth--;
- return NULL;
- }
- map = new_linemap (set, reason);
- if (to_file && *to_file == '\0' && reason != LC_RENAME_VERBATIM)
- to_file = "<stdin>";
- if (reason == LC_RENAME_VERBATIM)
- reason = LC_RENAME;
- if (reason == LC_LEAVE)
- {
- /* When we are just leaving an "included" file, and jump to the next
- location inside the "includer" right after the #include
- "included", this variable points the map in use right before the
- #include "included", inside the same "includer" file. */
- struct line_map *from;
- bool error;
- if (MAIN_FILE_P (map - 1))
- {
- /* So this _should_ mean we are leaving the main file --
- effectively ending the compilation unit. But to_file not
- being NULL means the caller thinks we are leaving to
- another file. This is an erroneous behaviour but we'll
- try to recover from it. Let's pretend we are not leaving
- the main file. */
- error = true;
- reason = LC_RENAME;
- from = map - 1;
- }
- else
- {
- /* (MAP - 1) points to the map we are leaving. The
- map from which (MAP - 1) got included should be the map
- that comes right before MAP in the same file. */
- from = INCLUDED_FROM (set, map - 1);
- error = to_file && filename_cmp (ORDINARY_MAP_FILE_NAME (from),
- to_file);
- }
- /* Depending upon whether we are handling preprocessed input or
- not, this can be a user error or an ICE. */
- if (error)
- fprintf (stderr, "line-map.c: file \"%s\" left but not entered\n",
- to_file);
- /* A TO_FILE of NULL is special - we use the natural values. */
- if (error || to_file == NULL)
- {
- to_file = ORDINARY_MAP_FILE_NAME (from);
- to_line = SOURCE_LINE (from, from[1].start_location);
- sysp = ORDINARY_MAP_IN_SYSTEM_HEADER_P (from);
- }
- }
- linemap_assert (reason != LC_ENTER_MACRO);
- ORDINARY_MAP_IN_SYSTEM_HEADER_P (map) = sysp;
- MAP_START_LOCATION (map) = start_location;
- ORDINARY_MAP_FILE_NAME (map) = to_file;
- ORDINARY_MAP_STARTING_LINE_NUMBER (map) = to_line;
- LINEMAPS_ORDINARY_CACHE (set) = LINEMAPS_ORDINARY_USED (set) - 1;
- ORDINARY_MAP_NUMBER_OF_COLUMN_BITS (map) = 0;
- set->highest_location = start_location;
- set->highest_line = start_location;
- set->max_column_hint = 0;
- if (reason == LC_ENTER)
- {
- ORDINARY_MAP_INCLUDER_FILE_INDEX (map) =
- set->depth == 0 ? -1 : (int) (LINEMAPS_ORDINARY_USED (set) - 2);
- set->depth++;
- if (set->trace_includes)
- trace_include (set, map);
- }
- else if (reason == LC_RENAME)
- ORDINARY_MAP_INCLUDER_FILE_INDEX (map) =
- ORDINARY_MAP_INCLUDER_FILE_INDEX (&map[-1]);
- else if (reason == LC_LEAVE)
- {
- set->depth--;
- ORDINARY_MAP_INCLUDER_FILE_INDEX (map) =
- ORDINARY_MAP_INCLUDER_FILE_INDEX (INCLUDED_FROM (set, map - 1));
- }
- return map;
- }
- /* Returns TRUE if the line table set tracks token locations across
- macro expansion, FALSE otherwise. */
- bool
- linemap_tracks_macro_expansion_locs_p (struct line_maps *set)
- {
- return LINEMAPS_MACRO_MAPS (set) != NULL;
- }
- /* Create a macro map. A macro map encodes source locations of tokens
- that are part of a macro replacement-list, at a macro expansion
- point. See the extensive comments of struct line_map and struct
- line_map_macro, in line-map.h.
- This map shall be created when the macro is expanded. The map
- encodes the source location of the expansion point of the macro as
- well as the "original" source location of each token that is part
- of the macro replacement-list. If a macro is defined but never
- expanded, it has no macro map. SET is the set of maps the macro
- map should be part of. MACRO_NODE is the macro which the new macro
- map should encode source locations for. EXPANSION is the location
- of the expansion point of MACRO. For function-like macros
- invocations, it's best to make it point to the closing parenthesis
- of the macro, rather than the the location of the first character
- of the macro. NUM_TOKENS is the number of tokens that are part of
- the replacement-list of MACRO.
- Note that when we run out of the integer space available for source
- locations, this function returns NULL. In that case, callers of
- this function cannot encode {line,column} pairs into locations of
- macro tokens anymore. */
- const struct line_map *
- linemap_enter_macro (struct line_maps *set, struct cpp_hashnode *macro_node,
- source_location expansion, unsigned int num_tokens)
- {
- struct line_map *map;
- source_location start_location;
- /* Cast away extern "C" from the type of xrealloc. */
- line_map_realloc reallocator = (set->reallocator
- ? set->reallocator
- : (line_map_realloc) xrealloc);
- start_location = LINEMAPS_MACRO_LOWEST_LOCATION (set) - num_tokens;
- if (start_location <= set->highest_line
- || start_location > LINEMAPS_MACRO_LOWEST_LOCATION (set))
- /* We ran out of macro map space. */
- return NULL;
- map = new_linemap (set, LC_ENTER_MACRO);
- MAP_START_LOCATION (map) = start_location;
- MACRO_MAP_MACRO (map) = macro_node;
- MACRO_MAP_NUM_MACRO_TOKENS (map) = num_tokens;
- MACRO_MAP_LOCATIONS (map)
- = (source_location*) reallocator (NULL,
- 2 * num_tokens
- * sizeof (source_location));
- MACRO_MAP_EXPANSION_POINT_LOCATION (map) = expansion;
- memset (MACRO_MAP_LOCATIONS (map), 0,
- num_tokens * sizeof (source_location));
- LINEMAPS_MACRO_CACHE (set) = LINEMAPS_MACRO_USED (set) - 1;
- return map;
- }
- /* Create and return a virtual location for a token that is part of a
- macro expansion-list at a macro expansion point. See the comment
- inside struct line_map_macro to see what an expansion-list exactly
- is.
- A call to this function must come after a call to
- linemap_enter_macro.
- MAP is the map into which the source location is created. TOKEN_NO
- is the index of the token in the macro replacement-list, starting
- at number 0.
- ORIG_LOC is the location of the token outside of this macro
- expansion. If the token comes originally from the macro
- definition, it is the locus in the macro definition; otherwise it
- is a location in the context of the caller of this macro expansion
- (which is a virtual location or a source location if the caller is
- itself a macro expansion or not).
- ORIG_PARM_REPLACEMENT_LOC is the location in the macro definition,
- either of the token itself or of a macro parameter that it
- replaces. */
- source_location
- linemap_add_macro_token (const struct line_map *map,
- unsigned int token_no,
- source_location orig_loc,
- source_location orig_parm_replacement_loc)
- {
- source_location result;
- linemap_assert (linemap_macro_expansion_map_p (map));
- linemap_assert (token_no < MACRO_MAP_NUM_MACRO_TOKENS (map));
- MACRO_MAP_LOCATIONS (map)[2 * token_no] = orig_loc;
- MACRO_MAP_LOCATIONS (map)[2 * token_no + 1] = orig_parm_replacement_loc;
- result = MAP_START_LOCATION (map) + token_no;
- return result;
- }
- /* Return a source_location for the start (i.e. column==0) of
- (physical) line TO_LINE in the current source file (as in the
- most recent linemap_add). MAX_COLUMN_HINT is the highest column
- number we expect to use in this line (but it does not change
- the highest_location). */
- source_location
- linemap_line_start (struct line_maps *set, linenum_type to_line,
- unsigned int max_column_hint)
- {
- struct line_map *map = LINEMAPS_LAST_ORDINARY_MAP (set);
- source_location highest = set->highest_location;
- source_location r;
- linenum_type last_line =
- SOURCE_LINE (map, set->highest_line);
- int line_delta = to_line - last_line;
- bool add_map = false;
- if (line_delta < 0
- || (line_delta > 10
- && line_delta * ORDINARY_MAP_NUMBER_OF_COLUMN_BITS (map) > 1000)
- || (max_column_hint >= (1U << ORDINARY_MAP_NUMBER_OF_COLUMN_BITS (map)))
- || (max_column_hint <= 80
- && ORDINARY_MAP_NUMBER_OF_COLUMN_BITS (map) >= 10)
- || (highest > 0x60000000
- && (set->max_column_hint || highest > 0x70000000)))
- add_map = true;
- else
- max_column_hint = set->max_column_hint;
- if (add_map)
- {
- int column_bits;
- if (max_column_hint > 100000 || highest > 0x60000000)
- {
- /* If the column number is ridiculous or we've allocated a huge
- number of source_locations, give up on column numbers. */
- max_column_hint = 0;
- if (highest > 0x70000000)
- return 0;
- column_bits = 0;
- }
- else
- {
- column_bits = 7;
- while (max_column_hint >= (1U << column_bits))
- column_bits++;
- max_column_hint = 1U << column_bits;
- }
- /* Allocate the new line_map. However, if the current map only has a
- single line we can sometimes just increase its column_bits instead. */
- if (line_delta < 0
- || last_line != ORDINARY_MAP_STARTING_LINE_NUMBER (map)
- || SOURCE_COLUMN (map, highest) >= (1U << column_bits))
- map = (struct line_map *) linemap_add (set, LC_RENAME,
- ORDINARY_MAP_IN_SYSTEM_HEADER_P
- (map),
- ORDINARY_MAP_FILE_NAME (map),
- to_line);
- ORDINARY_MAP_NUMBER_OF_COLUMN_BITS (map) = column_bits;
- r = (MAP_START_LOCATION (map)
- + ((to_line - ORDINARY_MAP_STARTING_LINE_NUMBER (map))
- << column_bits));
- }
- else
- r = highest - SOURCE_COLUMN (map, highest)
- + (line_delta << ORDINARY_MAP_NUMBER_OF_COLUMN_BITS (map));
- /* Locations of ordinary tokens are always lower than locations of
- macro tokens. */
- if (r >= LINEMAPS_MACRO_LOWEST_LOCATION (set))
- return 0;
- set->highest_line = r;
- if (r > set->highest_location)
- set->highest_location = r;
- set->max_column_hint = max_column_hint;
- return r;
- }
- /* Encode and return a source_location from a column number. The
- source line considered is the last source line used to call
- linemap_line_start, i.e, the last source line which a location was
- encoded from. */
- source_location
- linemap_position_for_column (struct line_maps *set, unsigned int to_column)
- {
- source_location r = set->highest_line;
- linemap_assert
- (!linemap_macro_expansion_map_p (LINEMAPS_LAST_ORDINARY_MAP (set)));
- if (to_column >= set->max_column_hint)
- {
- if (r >= 0xC000000 || to_column > 100000)
- {
- /* Running low on source_locations - disable column numbers. */
- return r;
- }
- else
- {
- struct line_map *map = LINEMAPS_LAST_ORDINARY_MAP (set);
- r = linemap_line_start (set, SOURCE_LINE (map, r), to_column + 50);
- }
- }
- r = r + to_column;
- if (r >= set->highest_location)
- set->highest_location = r;
- return r;
- }
- /* Encode and return a source location from a given line and
- column. */
- source_location
- linemap_position_for_line_and_column (const struct line_map *map,
- linenum_type line,
- unsigned column)
- {
- linemap_assert (ORDINARY_MAP_STARTING_LINE_NUMBER (map) <= line);
- return (MAP_START_LOCATION (map)
- + ((line - ORDINARY_MAP_STARTING_LINE_NUMBER (map))
- << ORDINARY_MAP_NUMBER_OF_COLUMN_BITS (map))
- + (column & ((1 << ORDINARY_MAP_NUMBER_OF_COLUMN_BITS (map)) - 1)));
- }
- /* Encode and return a source_location starting from location LOC and
- shifting it by OFFSET columns. This function does not support
- virtual locations. */
- source_location
- linemap_position_for_loc_and_offset (struct line_maps *set,
- source_location loc,
- unsigned int offset)
- {
- const struct line_map * map = NULL;
- /* This function does not support virtual locations yet. */
- if (linemap_assert_fails
- (!linemap_location_from_macro_expansion_p (set, loc)))
- return loc;
- if (offset == 0
- /* Adding an offset to a reserved location (like
- UNKNOWN_LOCATION for the C/C++ FEs) does not really make
- sense. So let's leave the location intact in that case. */
- || loc < RESERVED_LOCATION_COUNT)
- return loc;
- /* We find the real location and shift it. */
- loc = linemap_resolve_location (set, loc, LRK_SPELLING_LOCATION, &map);
- /* The new location (loc + offset) should be higher than the first
- location encoded by MAP. */
- if (linemap_assert_fails (MAP_START_LOCATION (map) < loc + offset))
- return loc;
- /* If MAP is not the last line map of its set, then the new location
- (loc + offset) should be less than the first location encoded by
- the next line map of the set. */
- if (map != LINEMAPS_LAST_ORDINARY_MAP (set))
- if (linemap_assert_fails (loc + offset < MAP_START_LOCATION (&map[1])))
- return loc;
- offset += SOURCE_COLUMN (map, loc);
- if (linemap_assert_fails (offset < (1u << map->d.ordinary.column_bits)))
- return loc;
- source_location r =
- linemap_position_for_line_and_column (map,
- SOURCE_LINE (map, loc),
- offset);
- if (linemap_assert_fails (r <= set->highest_location)
- || linemap_assert_fails (map == linemap_lookup (set, r)))
- return loc;
- return r;
- }
- /* Given a virtual source location yielded by a map (either an
- ordinary or a macro map), returns that map. */
- const struct line_map*
- linemap_lookup (struct line_maps *set, source_location line)
- {
- if (IS_ADHOC_LOC (line))
- line = set->location_adhoc_data_map.data[line & MAX_SOURCE_LOCATION].locus;
- if (linemap_location_from_macro_expansion_p (set, line))
- return linemap_macro_map_lookup (set, line);
- return linemap_ordinary_map_lookup (set, line);
- }
- /* Given a source location yielded by an ordinary map, returns that
- map. Since the set is built chronologically, the logical lines are
- monotonic increasing, and so the list is sorted and we can use a
- binary search. */
- static const struct line_map *
- linemap_ordinary_map_lookup (struct line_maps *set, source_location line)
- {
- unsigned int md, mn, mx;
- const struct line_map *cached, *result;
- if (IS_ADHOC_LOC (line))
- line = set->location_adhoc_data_map.data[line & MAX_SOURCE_LOCATION].locus;
- if (set == NULL || line < RESERVED_LOCATION_COUNT)
- return NULL;
- mn = LINEMAPS_ORDINARY_CACHE (set);
- mx = LINEMAPS_ORDINARY_USED (set);
-
- cached = LINEMAPS_ORDINARY_MAP_AT (set, mn);
- /* We should get a segfault if no line_maps have been added yet. */
- if (line >= MAP_START_LOCATION (cached))
- {
- if (mn + 1 == mx || line < MAP_START_LOCATION (&cached[1]))
- return cached;
- }
- else
- {
- mx = mn;
- mn = 0;
- }
- while (mx - mn > 1)
- {
- md = (mn + mx) / 2;
- if (MAP_START_LOCATION (LINEMAPS_ORDINARY_MAP_AT (set, md)) > line)
- mx = md;
- else
- mn = md;
- }
- LINEMAPS_ORDINARY_CACHE (set) = mn;
- result = LINEMAPS_ORDINARY_MAP_AT (set, mn);
- linemap_assert (line >= MAP_START_LOCATION (result));
- return result;
- }
- /* Given a source location yielded by a macro map, returns that map.
- Since the set is built chronologically, the logical lines are
- monotonic decreasing, and so the list is sorted and we can use a
- binary search. */
- static const struct line_map*
- linemap_macro_map_lookup (struct line_maps *set, source_location line)
- {
- unsigned int md, mn, mx;
- const struct line_map *cached, *result;
- if (IS_ADHOC_LOC (line))
- line = set->location_adhoc_data_map.data[line & MAX_SOURCE_LOCATION].locus;
- linemap_assert (line >= LINEMAPS_MACRO_LOWEST_LOCATION (set));
- if (set == NULL)
- return NULL;
- mn = LINEMAPS_MACRO_CACHE (set);
- mx = LINEMAPS_MACRO_USED (set);
- cached = LINEMAPS_MACRO_MAP_AT (set, mn);
-
- if (line >= MAP_START_LOCATION (cached))
- {
- if (mn == 0 || line < MAP_START_LOCATION (&cached[-1]))
- return cached;
- mx = mn - 1;
- mn = 0;
- }
- while (mn < mx)
- {
- md = (mx + mn) / 2;
- if (MAP_START_LOCATION (LINEMAPS_MACRO_MAP_AT (set, md)) > line)
- mn = md + 1;
- else
- mx = md;
- }
- LINEMAPS_MACRO_CACHE (set) = mx;
- result = LINEMAPS_MACRO_MAP_AT (set, LINEMAPS_MACRO_CACHE (set));
- linemap_assert (MAP_START_LOCATION (result) <= line);
- return result;
- }
- /* Return TRUE if MAP encodes locations coming from a macro
- replacement-list at macro expansion point. */
- bool
- linemap_macro_expansion_map_p (const struct line_map *map)
- {
- if (!map)
- return false;
- return (map->reason == LC_ENTER_MACRO);
- }
- /* If LOCATION is the locus of a token in a replacement-list of a
- macro expansion return the location of the macro expansion point.
- Read the comments of struct line_map and struct line_map_macro in
- line-map.h to understand what a macro expansion point is. */
- static source_location
- linemap_macro_map_loc_to_exp_point (const struct line_map *map,
- source_location location ATTRIBUTE_UNUSED)
- {
- linemap_assert (linemap_macro_expansion_map_p (map)
- && location >= MAP_START_LOCATION (map));
- /* Make sure LOCATION is correct. */
- linemap_assert ((location - MAP_START_LOCATION (map))
- < MACRO_MAP_NUM_MACRO_TOKENS (map));
- return MACRO_MAP_EXPANSION_POINT_LOCATION (map);
- }
- /* LOCATION is the source location of a token that belongs to a macro
- replacement-list as part of the macro expansion denoted by MAP.
- Return the location of the token at the definition point of the
- macro. */
- static source_location
- linemap_macro_map_loc_to_def_point (const struct line_map *map,
- source_location location)
- {
- unsigned token_no;
- linemap_assert (linemap_macro_expansion_map_p (map)
- && location >= MAP_START_LOCATION (map));
- linemap_assert (location >= RESERVED_LOCATION_COUNT);
- token_no = location - MAP_START_LOCATION (map);
- linemap_assert (token_no < MACRO_MAP_NUM_MACRO_TOKENS (map));
- location = MACRO_MAP_LOCATIONS (map)[2 * token_no + 1];
- return location;
- }
- /* If LOCATION is the locus of a token that is an argument of a
- function-like macro M and appears in the expansion of M, return the
- locus of that argument in the context of the caller of M.
- In other words, this returns the xI location presented in the
- comments of line_map_macro above. */
- source_location
- linemap_macro_map_loc_unwind_toward_spelling (const struct line_map* map,
- source_location location)
- {
- unsigned token_no;
- linemap_assert (linemap_macro_expansion_map_p (map)
- && location >= MAP_START_LOCATION (map));
- linemap_assert (location >= RESERVED_LOCATION_COUNT);
- token_no = location - MAP_START_LOCATION (map);
- linemap_assert (token_no < MACRO_MAP_NUM_MACRO_TOKENS (map));
- location = MACRO_MAP_LOCATIONS (map)[2 * token_no];
-
- return location;
- }
- /* Return the source line number corresponding to source location
- LOCATION. SET is the line map set LOCATION comes from. If
- LOCATION is the source location of token that is part of the
- replacement-list of a macro expansion return the line number of the
- macro expansion point. */
- int
- linemap_get_expansion_line (struct line_maps *set,
- source_location location)
- {
- const struct line_map *map = NULL;
- if (IS_ADHOC_LOC (location))
- location = set->location_adhoc_data_map.data[location
- & MAX_SOURCE_LOCATION].locus;
- if (location < RESERVED_LOCATION_COUNT)
- return 0;
- location =
- linemap_macro_loc_to_exp_point (set, location, &map);
- return SOURCE_LINE (map, location);
- }
- /* Return the path of the file corresponding to source code location
- LOCATION.
- If LOCATION is the source location of token that is part of the
- replacement-list of a macro expansion return the file path of the
- macro expansion point.
- SET is the line map set LOCATION comes from. */
- const char*
- linemap_get_expansion_filename (struct line_maps *set,
- source_location location)
- {
- const struct line_map *map = NULL;
- if (IS_ADHOC_LOC (location))
- location = set->location_adhoc_data_map.data[location
- & MAX_SOURCE_LOCATION].locus;
- if (location < RESERVED_LOCATION_COUNT)
- return NULL;
- location =
- linemap_macro_loc_to_exp_point (set, location, &map);
- return LINEMAP_FILE (map);
- }
- /* Return the name of the macro associated to MACRO_MAP. */
- const char*
- linemap_map_get_macro_name (const struct line_map* macro_map)
- {
- linemap_assert (macro_map && linemap_macro_expansion_map_p (macro_map));
- return (const char*) NODE_NAME (MACRO_MAP_MACRO (macro_map));
- }
- /* Return a positive value if LOCATION is the locus of a token that is
- located in a system header, O otherwise. It returns 1 if LOCATION
- is the locus of a token that is located in a system header, and 2
- if LOCATION is the locus of a token located in a C system header
- that therefore needs to be extern "C" protected in C++.
- Note that this function returns 1 if LOCATION belongs to a token
- that is part of a macro replacement-list defined in a system
- header, but expanded in a non-system file. */
- int
- linemap_location_in_system_header_p (struct line_maps *set,
- source_location location)
- {
- const struct line_map *map = NULL;
- if (IS_ADHOC_LOC (location))
- location = set->location_adhoc_data_map.data[location
- & MAX_SOURCE_LOCATION].locus;
- if (location < RESERVED_LOCATION_COUNT)
- return false;
- /* Let's look at where the token for LOCATION comes from. */
- while (true)
- {
- map = linemap_lookup (set, location);
- if (map != NULL)
- {
- if (!linemap_macro_expansion_map_p (map))
- /* It's a normal token. */
- return LINEMAP_SYSP (map);
- else
- {
- /* It's a token resulting from a macro expansion. */
- source_location loc =
- linemap_macro_map_loc_unwind_toward_spelling (map, location);
- if (loc < RESERVED_LOCATION_COUNT)
- /* This token might come from a built-in macro. Let's
- look at where that macro got expanded. */
- location = linemap_macro_map_loc_to_exp_point (map, location);
- else
- location = loc;
- }
- }
- else
- break;
- }
- return false;
- }
- /* Return TRUE if LOCATION is a source code location of a token coming
- from a macro replacement-list at a macro expansion point, FALSE
- otherwise. */
- bool
- linemap_location_from_macro_expansion_p (const struct line_maps *set,
- source_location location)
- {
- if (IS_ADHOC_LOC (location))
- location = set->location_adhoc_data_map.data[location
- & MAX_SOURCE_LOCATION].locus;
- linemap_assert (location <= MAX_SOURCE_LOCATION
- && (set->highest_location
- < LINEMAPS_MACRO_LOWEST_LOCATION (set)));
- if (set == NULL)
- return false;
- return (location > set->highest_location);
- }
- /* Given two virtual locations *LOC0 and *LOC1, return the first
- common macro map in their macro expansion histories. Return NULL
- if no common macro was found. *LOC0 (resp. *LOC1) is set to the
- virtual location of the token inside the resulting macro. */
- static const struct line_map*
- first_map_in_common_1 (struct line_maps *set,
- source_location *loc0,
- source_location *loc1)
- {
- source_location l0 = *loc0, l1 = *loc1;
- const struct line_map *map0 = linemap_lookup (set, l0),
- *map1 = linemap_lookup (set, l1);
- while (linemap_macro_expansion_map_p (map0)
- && linemap_macro_expansion_map_p (map1)
- && (map0 != map1))
- {
- if (MAP_START_LOCATION (map0) < MAP_START_LOCATION (map1))
- {
- l0 = linemap_macro_map_loc_to_exp_point (map0, l0);
- map0 = linemap_lookup (set, l0);
- }
- else
- {
- l1 = linemap_macro_map_loc_to_exp_point (map1, l1);
- map1 = linemap_lookup (set, l1);
- }
- }
- if (map0 == map1)
- {
- *loc0 = l0;
- *loc1 = l1;
- return map0;
- }
- return NULL;
- }
- /* Given two virtual locations LOC0 and LOC1, return the first common
- macro map in their macro expansion histories. Return NULL if no
- common macro was found. *RES_LOC0 (resp. *RES_LOC1) is set to the
- virtual location of the token inside the resulting macro, upon
- return of a non-NULL result. */
- 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)
- {
- *res_loc0 = loc0;
- *res_loc1 = loc1;
- return first_map_in_common_1 (set, res_loc0, res_loc1);
- }
- /* Return a positive value if PRE denotes the location of a token that
- comes before the token of POST, 0 if PRE denotes the location of
- the same token as the token for POST, and a negative value
- otherwise. */
- int
- linemap_compare_locations (struct line_maps *set,
- source_location pre,
- source_location post)
- {
- bool pre_virtual_p, post_virtual_p;
- source_location l0 = pre, l1 = post;
- if (IS_ADHOC_LOC (l0))
- l0 = set->location_adhoc_data_map.data[l0 & MAX_SOURCE_LOCATION].locus;
- if (IS_ADHOC_LOC (l1))
- l1 = set->location_adhoc_data_map.data[l1 & MAX_SOURCE_LOCATION].locus;
- if (l0 == l1)
- return 0;
- if ((pre_virtual_p = linemap_location_from_macro_expansion_p (set, l0)))
- l0 = linemap_resolve_location (set, l0,
- LRK_MACRO_EXPANSION_POINT,
- NULL);
- if ((post_virtual_p = linemap_location_from_macro_expansion_p (set, l1)))
- l1 = linemap_resolve_location (set, l1,
- LRK_MACRO_EXPANSION_POINT,
- NULL);
- if (l0 == l1
- && pre_virtual_p
- && post_virtual_p)
- {
- /* So pre and post represent two tokens that are present in a
- same macro expansion. Let's see if the token for pre was
- before the token for post in that expansion. */
- unsigned i0, i1;
- const struct line_map *map =
- first_map_in_common (set, pre, post, &l0, &l1);
- if (map == NULL)
- /* This should not be possible. */
- abort ();
- i0 = l0 - MAP_START_LOCATION (map);
- i1 = l1 - MAP_START_LOCATION (map);
- return i1 - i0;
- }
- return l1 - l0;
- }
- /* Print an include trace, for e.g. the -H option of the preprocessor. */
- static void
- trace_include (const struct line_maps *set, const struct line_map *map)
- {
- unsigned int i = set->depth;
- while (--i)
- putc ('.', stderr);
- fprintf (stderr, " %s\n", ORDINARY_MAP_FILE_NAME (map));
- }
- /* Return the spelling location of the token wherever it comes from,
- whether part of a macro definition or not.
- This is a subroutine for linemap_resolve_location. */
- static source_location
- linemap_macro_loc_to_spelling_point (struct line_maps *set,
- source_location location,
- const struct line_map **original_map)
- {
- struct line_map *map;
- if (IS_ADHOC_LOC (location))
- location = set->location_adhoc_data_map.data[location
- & MAX_SOURCE_LOCATION].locus;
- linemap_assert (set && location >= RESERVED_LOCATION_COUNT);
- while (true)
- {
- map = (struct line_map*) linemap_lookup (set, location);
- if (!linemap_macro_expansion_map_p (map))
- break;
- location =
- linemap_macro_map_loc_unwind_toward_spelling (map, location);
- }
- if (original_map)
- *original_map = map;
- return location;
- }
- /* If LOCATION is the source location of a token that belongs to a
- macro replacement-list -- as part of a macro expansion -- then
- return the location of the token at the definition point of the
- macro. Otherwise, return LOCATION. SET is the set of maps
- location come from. ORIGINAL_MAP is an output parm. If non NULL,
- the function sets *ORIGINAL_MAP to the ordinary (non-macro) map the
- returned location comes from.
- This is a subroutine of linemap_resolve_location. */
- static source_location
- linemap_macro_loc_to_def_point (struct line_maps *set,
- source_location location,
- const struct line_map **original_map)
- {
- struct line_map *map;
- if (IS_ADHOC_LOC (location))
- location = set->location_adhoc_data_map.data[location
- & MAX_SOURCE_LOCATION].locus;
- linemap_assert (set && location >= RESERVED_LOCATION_COUNT);
- while (true)
- {
- map = (struct line_map*) linemap_lookup (set, location);
- if (!linemap_macro_expansion_map_p (map))
- break;
- location =
- linemap_macro_map_loc_to_def_point (map, location);
- }
- if (original_map)
- *original_map = map;
- return location;
- }
- /* If LOCATION is the source location of a token that belongs to a
- macro replacement-list -- at a macro expansion point -- then return
- the location of the topmost expansion point of the macro. We say
- topmost because if we are in the context of a nested macro
- expansion, the function returns the source location of the first
- macro expansion that triggered the nested expansions.
- Otherwise, return LOCATION. SET is the set of maps location come
- from. ORIGINAL_MAP is an output parm. If non NULL, the function
- sets *ORIGINAL_MAP to the ordinary (non-macro) map the returned
- location comes from.
- This is a subroutine of linemap_resolve_location. */
- static source_location
- linemap_macro_loc_to_exp_point (struct line_maps *set,
- source_location location,
- const struct line_map **original_map)
- {
- struct line_map *map;
- if (IS_ADHOC_LOC (location))
- location = set->location_adhoc_data_map.data[location
- & MAX_SOURCE_LOCATION].locus;
- linemap_assert (set && location >= RESERVED_LOCATION_COUNT);
- while (true)
- {
- map = (struct line_map*) linemap_lookup (set, location);
- if (!linemap_macro_expansion_map_p (map))
- break;
- location = linemap_macro_map_loc_to_exp_point (map, location);
- }
- if (original_map)
- *original_map = map;
- return location;
- }
- /* Resolve a virtual location into either a spelling location, an
- expansion point location or a token argument replacement point
- location. Return the map that encodes the virtual location as well
- as the resolved location.
- If LOC is *NOT* the location of a token resulting from the
- expansion of a macro, then the parameter LRK (which stands for
- Location Resolution Kind) is ignored and the resulting location
- just equals the one given in argument.
- Now if LOC *IS* the location of a token resulting from the
- expansion of a macro, this is what happens.
- * If LRK is set to LRK_MACRO_EXPANSION_POINT
- -------------------------------
- The virtual location is resolved to the first macro expansion point
- that led to this macro expansion.
- * If LRK is set to LRK_SPELLING_LOCATION
- -------------------------------------
- The virtual location is resolved to the locus where the token has
- been spelled in the source. This can follow through all the macro
- expansions that led to the token.
- * If LRK is set to LRK_MACRO_DEFINITION_LOCATION
- --------------------------------------
- The virtual location is resolved to the locus of the token in the
- context of the macro definition.
- If LOC is the locus of a token that is an argument of a
- function-like macro [replacing a parameter in the replacement list
- of the macro] the virtual location is resolved to the locus of the
- parameter that is replaced, in the context of the definition of the
- macro.
- If LOC is the locus of a token that is not an argument of a
- function-like macro, then the function behaves as if LRK was set to
- LRK_SPELLING_LOCATION.
- If MAP is not NULL, *MAP is set to the map encoding the
- returned location. Note that if the returned location wasn't originally
- encoded by a map, then *MAP is set to NULL. This can happen if LOC
- resolves to a location reserved for the client code, like
- UNKNOWN_LOCATION or BUILTINS_LOCATION in GCC. */
- source_location
- linemap_resolve_location (struct line_maps *set,
- source_location loc,
- enum location_resolution_kind lrk,
- const struct line_map **map)
- {
- if (IS_ADHOC_LOC (loc))
- loc = set->location_adhoc_data_map.data[loc & MAX_SOURCE_LOCATION].locus;
- if (loc < RESERVED_LOCATION_COUNT)
- {
- /* A reserved location wasn't encoded in a map. Let's return a
- NULL map here, just like what linemap_ordinary_map_lookup
- does. */
- if (map)
- *map = NULL;
- return loc;
- }
- switch (lrk)
- {
- case LRK_MACRO_EXPANSION_POINT:
- loc = linemap_macro_loc_to_exp_point (set, loc, map);
- break;
- case LRK_SPELLING_LOCATION:
- loc = linemap_macro_loc_to_spelling_point (set, loc, map);
- break;
- case LRK_MACRO_DEFINITION_LOCATION:
- loc = linemap_macro_loc_to_def_point (set, loc, map);
- break;
- default:
- abort ();
- }
- return loc;
- }
- /*
- Suppose that LOC is the virtual location of a token T coming from
- the expansion of a macro M. This function then steps up to get the
- location L of the point where M got expanded. If L is a spelling
- location inside a macro expansion M', then this function returns
- the locus of the point where M' was expanded. Said otherwise, this
- function returns the location of T in the context that triggered
- the expansion of M.
- *LOC_MAP must be set to the map of LOC. This function then sets it
- to the map of the returned location. */
- source_location
- linemap_unwind_toward_expansion (struct line_maps *set,
- source_location loc,
- const struct line_map **map)
- {
- source_location resolved_location;
- const struct line_map *resolved_map;
- if (IS_ADHOC_LOC (loc))
- loc = set->location_adhoc_data_map.data[loc & MAX_SOURCE_LOCATION].locus;
- resolved_location =
- linemap_macro_map_loc_unwind_toward_spelling (*map, loc);
- resolved_map = linemap_lookup (set, resolved_location);
- if (!linemap_macro_expansion_map_p (resolved_map))
- {
- resolved_location = linemap_macro_map_loc_to_exp_point (*map, loc);
- resolved_map = linemap_lookup (set, resolved_location);
- }
- *map = resolved_map;
- return resolved_location;
- }
- /* If LOC is the virtual location of a token coming from the expansion
- of a macro M and if its spelling location is reserved (e.g, a
- location for a built-in token), then this function unwinds (using
- linemap_unwind_toward_expansion) the location until a location that
- is not reserved and is not in a system header is reached. In other
- words, this unwinds the reserved location until a location that is
- in real source code is reached.
- Otherwise, if the spelling location for LOC is not reserved or if
- LOC doesn't come from the expansion of a macro, the function
- returns LOC as is and *MAP is not touched.
- *MAP is set to the map of the returned location if the later is
- different from LOC. */
- source_location
- linemap_unwind_to_first_non_reserved_loc (struct line_maps *set,
- source_location loc,
- const struct line_map **map)
- {
- source_location resolved_loc;
- const struct line_map *map0 = NULL, *map1 = NULL;
- if (IS_ADHOC_LOC (loc))
- loc = set->location_adhoc_data_map.data[loc & MAX_SOURCE_LOCATION].locus;
- map0 = linemap_lookup (set, loc);
- if (!linemap_macro_expansion_map_p (map0))
- return loc;
- resolved_loc = linemap_resolve_location (set, loc,
- LRK_SPELLING_LOCATION,
- &map1);
- if (resolved_loc >= RESERVED_LOCATION_COUNT
- && !LINEMAP_SYSP (map1))
- return loc;
- while (linemap_macro_expansion_map_p (map0)
- && (resolved_loc < RESERVED_LOCATION_COUNT
- || LINEMAP_SYSP (map1)))
- {
- loc = linemap_unwind_toward_expansion (set, loc, &map0);
- resolved_loc = linemap_resolve_location (set, loc,
- LRK_SPELLING_LOCATION,
- &map1);
- }
- if (map != NULL)
- *map = map0;
- return loc;
- }
- /* Expand source code location LOC and return a user readable source
- code location. LOC must be a spelling (non-virtual) location. If
- it's a location < RESERVED_LOCATION_COUNT a zeroed expanded source
- location is returned. */
- expanded_location
- linemap_expand_location (struct line_maps *set,
- const struct line_map *map,
- source_location loc)
- {
- expanded_location xloc;
- memset (&xloc, 0, sizeof (xloc));
- if (IS_ADHOC_LOC (loc))
- {
- loc = set->location_adhoc_data_map.data[loc & MAX_SOURCE_LOCATION].locus;
- xloc.data
- = set->location_adhoc_data_map.data[loc & MAX_SOURCE_LOCATION].data;
- }
- if (loc < RESERVED_LOCATION_COUNT)
- /* The location for this token wasn't generated from a line map.
- It was probably a location for a builtin token, chosen by some
- client code. Let's not try to expand the location in that
- case. */;
- else if (map == NULL)
- /* We shouldn't be getting a NULL map with a location that is not
- reserved by the client code. */
- abort ();
- else
- {
- /* MAP must be an ordinary map and LOC must be non-virtual,
- encoded into this map, obviously; the accessors used on MAP
- below ensure it is ordinary. Let's just assert the
- non-virtualness of LOC here. */
- if (linemap_location_from_macro_expansion_p (set, loc))
- abort ();
- xloc.file = LINEMAP_FILE (map);
- xloc.line = SOURCE_LINE (map, loc);
- xloc.column = SOURCE_COLUMN (map, loc);
- xloc.sysp = LINEMAP_SYSP (map) != 0;
- }
- return xloc;
- }
- /* Dump line map at index IX in line table SET to STREAM. If STREAM
- is NULL, use stderr. IS_MACRO is true if the caller wants to
- dump a macro map, false otherwise. */
- void
- linemap_dump (FILE *stream, struct line_maps *set, unsigned ix, bool is_macro)
- {
- const char *lc_reasons_v[LC_ENTER_MACRO + 1]
- = { "LC_ENTER", "LC_LEAVE", "LC_RENAME", "LC_RENAME_VERBATIM",
- "LC_ENTER_MACRO" };
- const char *reason;
- struct line_map *map;
- if (stream == NULL)
- stream = stderr;
- if (!is_macro)
- map = LINEMAPS_ORDINARY_MAP_AT (set, ix);
- else
- map = LINEMAPS_MACRO_MAP_AT (set, ix);
- reason = (map->reason <= LC_ENTER_MACRO) ? lc_reasons_v[map->reason] : "???";
- fprintf (stream, "Map #%u [%p] - LOC: %u - REASON: %s - SYSP: %s\n",
- ix, (void *) map, map->start_location, reason,
- (!is_macro && ORDINARY_MAP_IN_SYSTEM_HEADER_P (map)) ? "yes" : "no");
- if (!is_macro)
- {
- unsigned includer_ix;
- struct line_map *includer_map;
- includer_ix = ORDINARY_MAP_INCLUDER_FILE_INDEX (map);
- includer_map = includer_ix < LINEMAPS_ORDINARY_USED (set)
- ? LINEMAPS_ORDINARY_MAP_AT (set, includer_ix)
- : NULL;
- fprintf (stream, "File: %s:%d\n", ORDINARY_MAP_FILE_NAME (map),
- ORDINARY_MAP_STARTING_LINE_NUMBER (map));
- fprintf (stream, "Included from: [%d] %s\n", includer_ix,
- includer_map ? ORDINARY_MAP_FILE_NAME (includer_map) : "None");
- }
- else
- fprintf (stream, "Macro: %s (%u tokens)\n",
- linemap_map_get_macro_name (map),
- MACRO_MAP_NUM_MACRO_TOKENS (map));
- fprintf (stream, "\n");
- }
- /* Dump debugging information about source location LOC into the file
- stream STREAM. SET is the line map set LOC comes from. */
- void
- linemap_dump_location (struct line_maps *set,
- source_location loc,
- FILE *stream)
- {
- const struct line_map *map;
- source_location location;
- const char *path = "", *from = "";
- int l = -1, c = -1, s = -1, e = -1;
- if (IS_ADHOC_LOC (loc))
- loc = set->location_adhoc_data_map.data[loc & MAX_SOURCE_LOCATION].locus;
- if (loc == 0)
- return;
- location =
- linemap_resolve_location (set, loc, LRK_MACRO_DEFINITION_LOCATION, &map);
- if (map == NULL)
- /* Only reserved locations can be tolerated in this case. */
- linemap_assert (location < RESERVED_LOCATION_COUNT);
- else
- {
- path = LINEMAP_FILE (map);
- l = SOURCE_LINE (map, location);
- c = SOURCE_COLUMN (map, location);
- s = LINEMAP_SYSP (map) != 0;
- e = location != loc;
- if (e)
- from = "N/A";
- else
- from = (INCLUDED_FROM (set, map))
- ? LINEMAP_FILE (INCLUDED_FROM (set, map))
- : "<NULL>";
- }
- /* P: path, L: line, C: column, S: in-system-header, M: map address,
- E: macro expansion?, LOC: original location, R: resolved location */
- fprintf (stream, "{P:%s;F:%s;L:%d;C:%d;S:%d;M:%p;E:%d,LOC:%d,R:%d}",
- path, from, l, c, s, (void*)map, e, loc, location);
- }
- /* Return the highest location emitted for a given file for which
- there is a line map in SET. FILE_NAME is the file name to
- consider. If the function returns TRUE, *LOC is set to the highest
- location emitted for that file. */
- bool
- linemap_get_file_highest_location (struct line_maps *set,
- const char *file_name,
- source_location *loc)
- {
- /* If the set is empty or no ordinary map has been created then
- there is no file to look for ... */
- if (set == NULL || set->info_ordinary.used == 0)
- return false;
- /* Now look for the last ordinary map created for FILE_NAME. */
- int i;
- for (i = set->info_ordinary.used - 1; i >= 0; --i)
- {
- const char *fname = set->info_ordinary.maps[i].d.ordinary.to_file;
- if (fname && !filename_cmp (fname, file_name))
- break;
- }
- if (i < 0)
- return false;
- /* The highest location for a given map is either the starting
- location of the next map minus one, or -- if the map is the
- latest one -- the highest location of the set. */
- source_location result;
- if (i == (int) set->info_ordinary.used - 1)
- result = set->highest_location;
- else
- result = set->info_ordinary.maps[i + 1].start_location - 1;
- *loc = result;
- return true;
- }
- /* Compute and return statistics about the memory consumption of some
- parts of the line table SET. */
- void
- linemap_get_statistics (struct line_maps *set,
- struct linemap_stats *s)
- {
- long ordinary_maps_allocated_size, ordinary_maps_used_size,
- macro_maps_allocated_size, macro_maps_used_size,
- macro_maps_locations_size = 0, duplicated_macro_maps_locations_size = 0;
- struct line_map *cur_map;
- ordinary_maps_allocated_size =
- LINEMAPS_ORDINARY_ALLOCATED (set) * sizeof (struct line_map);
- ordinary_maps_used_size =
- LINEMAPS_ORDINARY_USED (set) * sizeof (struct line_map);
- macro_maps_allocated_size =
- LINEMAPS_MACRO_ALLOCATED (set) * sizeof (struct line_map);
- for (cur_map = LINEMAPS_MACRO_MAPS (set);
- cur_map && cur_map <= LINEMAPS_LAST_MACRO_MAP (set);
- ++cur_map)
- {
- unsigned i;
- linemap_assert (linemap_macro_expansion_map_p (cur_map));
- macro_maps_locations_size +=
- 2 * MACRO_MAP_NUM_MACRO_TOKENS (cur_map) * sizeof (source_location);
- for (i = 0; i < 2 * MACRO_MAP_NUM_MACRO_TOKENS (cur_map); i += 2)
- {
- if (MACRO_MAP_LOCATIONS (cur_map)[i] ==
- MACRO_MAP_LOCATIONS (cur_map)[i + 1])
- duplicated_macro_maps_locations_size +=
- sizeof (source_location);
- }
- }
- macro_maps_used_size =
- LINEMAPS_MACRO_USED (set) * sizeof (struct line_map);
- s->num_ordinary_maps_allocated = LINEMAPS_ORDINARY_ALLOCATED (set);
- s->num_ordinary_maps_used = LINEMAPS_ORDINARY_USED (set);
- s->ordinary_maps_allocated_size = ordinary_maps_allocated_size;
- s->ordinary_maps_used_size = ordinary_maps_used_size;
- s->num_expanded_macros = num_expanded_macros_counter;
- s->num_macro_tokens = num_macro_tokens_counter;
- s->num_macro_maps_used = LINEMAPS_MACRO_USED (set);
- s->macro_maps_allocated_size = macro_maps_allocated_size;
- s->macro_maps_locations_size = macro_maps_locations_size;
- s->macro_maps_used_size = macro_maps_used_size;
- s->duplicated_macro_maps_locations_size =
- duplicated_macro_maps_locations_size;
- }
- /* Dump line table SET to STREAM. If STREAM is NULL, stderr is used.
- NUM_ORDINARY specifies how many ordinary maps to dump. NUM_MACRO
- specifies how many macro maps to dump. */
- void
- line_table_dump (FILE *stream, struct line_maps *set, unsigned int num_ordinary,
- unsigned int num_macro)
- {
- unsigned int i;
- if (set == NULL)
- return;
- if (stream == NULL)
- stream = stderr;
- fprintf (stream, "# of ordinary maps: %d\n", LINEMAPS_ORDINARY_USED (set));
- fprintf (stream, "# of macro maps: %d\n", LINEMAPS_MACRO_USED (set));
- fprintf (stream, "Include stack depth: %d\n", set->depth);
- fprintf (stream, "Highest location: %u\n", set->highest_location);
- if (num_ordinary)
- {
- fprintf (stream, "\nOrdinary line maps\n");
- for (i = 0; i < num_ordinary && i < LINEMAPS_ORDINARY_USED (set); i++)
- linemap_dump (stream, set, i, false);
- fprintf (stream, "\n");
- }
- if (num_macro)
- {
- fprintf (stream, "\nMacro line maps\n");
- for (i = 0; i < num_macro && i < LINEMAPS_MACRO_USED (set); i++)
- linemap_dump (stream, set, i, true);
- fprintf (stream, "\n");
- }
- }
|