1 /* Data and functions related to line maps and input files.
2 Copyright (C) 2004-2014 Free Software Foundation, Inc.
4 This file is part of GCC.
6 GCC is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 3, or (at your option) any later
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3. If not see
18 <http://www.gnu.org/licenses/>. */
22 #include "coretypes.h"
27 /* This is a cache used by get_next_line to store the content of a
28 file to be searched for file lines. */
31 /* These are information used to store a line boundary. */
34 /* The line number. It starts from 1. */
37 /* The position (byte count) of the beginning of the line,
38 relative to the file data pointer. This starts at zero. */
41 /* The position (byte count) of the last byte of the line. This
42 normally points to the '\n' character, or to one byte after the
43 last byte of the file, if the file doesn't contain a '\n'
47 line_info (size_t l, size_t s, size_t e)
48 : line_num (l), start_pos (s), end_pos (e)
52 :line_num (0), start_pos (0), end_pos (0)
56 /* The number of time this file has been accessed. This is used
57 to designate which file cache to evict from the cache
61 const char *file_path;
65 /* This points to the content of the file that we've read so
69 /* The size of the DATA array above.*/
72 /* The number of bytes read from the underlying file so far. This
73 must be less (or equal) than SIZE above. */
76 /* The index of the beginning of the current line. */
77 size_t line_start_idx;
79 /* The number of the previous line read. This starts at 1. Zero
80 means we've read no line so far. */
83 /* This is the total number of lines of the current file. At the
84 moment, we try to get this information from the line map
85 subsystem. Note that this is just a hint. When using the C++
86 front-end, this hint is correct because the input file is then
87 completely tokenized before parsing starts; so the line map knows
88 the number of lines before compilation really starts. For e.g,
89 the C front-end, it can happen that we start emitting diagnostics
90 before the line map has seen the end of the file. */
93 /* This is a record of the beginning and end of the lines we've seen
94 while reading the file. This is useful to avoid walking the data
95 from the beginning when we are asked to read a line that is
96 before LINE_START_IDX above. Note that the maximum size of this
97 record is fcache_line_record_size, so that the memory consumption
98 doesn't explode. We thus scale total_lines down to
99 fcache_line_record_size. */
100 vec<line_info, va_heap> line_record;
106 /* Current position in real source file. */
108 location_t input_location;
110 struct line_maps *line_table;
112 static vec<location_t> discriminator_location_locations;
113 static vec<int> discriminator_location_discriminators;
114 static location_t next_discriminator_location = UNKNOWN_LOCATION;
115 static location_t min_discriminator_location = UNKNOWN_LOCATION;
117 static fcache *fcache_tab;
118 static const size_t fcache_tab_size = 16;
119 static const size_t fcache_buffer_size = 4 * 1024;
120 static const size_t fcache_line_record_size = 100;
122 /* Expand the source location LOC into a human readable location. If
123 LOC resolves to a builtin location, the file name of the readable
124 location is set to the string "<built-in>". If EXPANSION_POINT_P is
125 TRUE and LOC is virtual, then it is resolved to the expansion
126 point of the involved macro. Otherwise, it is resolved to the
127 spelling location of the token.
129 When resolving to the spelling location of the token, if the
130 resulting location is for a built-in location (that is, it has no
131 associated line/column) in the context of a macro expansion, the
132 returned location is the first one (while unwinding the macro
133 location towards its expansion point) that is in real source
136 static expanded_location
137 expand_location_1 (source_location loc,
138 bool expansion_point_p)
140 expanded_location xloc;
141 const struct line_map *map;
142 enum location_resolution_kind lrk = LRK_MACRO_EXPANSION_POINT;
145 if (IS_ADHOC_LOC (loc))
147 block = LOCATION_BLOCK (loc);
148 loc = LOCATION_LOCUS (loc);
151 /* If LOC describes a location with a discriminator, extract the
152 discriminator and map it to the real location. */
153 if (min_discriminator_location != UNKNOWN_LOCATION
154 && loc >= min_discriminator_location
155 && loc < next_discriminator_location)
156 loc = map_discriminator_location (loc);
158 memset (&xloc, 0, sizeof (xloc));
160 if (loc >= RESERVED_LOCATION_COUNT)
162 if (!expansion_point_p)
164 /* We want to resolve LOC to its spelling location.
166 But if that spelling location is a reserved location that
167 appears in the context of a macro expansion (like for a
168 location for a built-in token), let's consider the first
169 location (toward the expansion point) that is not reserved;
170 that is, the first location that is in real source code. */
171 loc = linemap_unwind_to_first_non_reserved_loc (line_table,
173 lrk = LRK_SPELLING_LOCATION;
175 loc = linemap_resolve_location (line_table, loc,
177 xloc = linemap_expand_location (line_table, map, loc);
181 if (loc <= BUILTINS_LOCATION)
182 xloc.file = loc == UNKNOWN_LOCATION ? NULL : _("<built-in>");
187 /* Initialize the set of cache used for files accessed by caret
191 diagnostic_file_cache_init (void)
193 if (fcache_tab == NULL)
194 fcache_tab = new fcache[fcache_tab_size];
197 /* Free the ressources used by the set of cache used for files accessed
198 by caret diagnostic. */
201 diagnostic_file_cache_fini (void)
205 delete [] (fcache_tab);
210 /* Return the total lines number that have been read so far by the
211 line map (in the preprocessor) so far. For languages like C++ that
212 entirely preprocess the input file before starting to parse, this
213 equals the actual number of lines of the file. */
216 total_lines_num (const char *file_path)
219 source_location l = 0;
220 if (linemap_get_file_highest_location (line_table, file_path, &l))
222 gcc_assert (l >= RESERVED_LOCATION_COUNT);
223 expanded_location xloc = expand_location (l);
229 /* Lookup the cache used for the content of a given file accessed by
230 caret diagnostic. Return the found cached file, or NULL if no
231 cached file was found. */
234 lookup_file_in_cache_tab (const char *file_path)
236 if (file_path == NULL)
239 diagnostic_file_cache_init ();
241 /* This will contain the found cached file. */
243 for (unsigned i = 0; i < fcache_tab_size; ++i)
245 fcache *c = &fcache_tab[i];
246 if (c->file_path && !strcmp (c->file_path, file_path))
259 /* Return the file cache that has been less used, recently, or the
260 first empty one. If HIGHEST_USE_COUNT is non-null,
261 *HIGHEST_USE_COUNT is set to the highest use count of the entries
262 in the cache table. */
265 evicted_cache_tab_entry (unsigned *highest_use_count)
267 diagnostic_file_cache_init ();
269 fcache *to_evict = &fcache_tab[0];
270 unsigned huc = to_evict->use_count;
271 for (unsigned i = 1; i < fcache_tab_size; ++i)
273 fcache *c = &fcache_tab[i];
274 bool c_is_empty = (c->file_path == NULL);
276 if (c->use_count < to_evict->use_count
277 || (to_evict->file_path && c_is_empty))
278 /* We evict C because it's either an entry with a lower use
279 count or one that is empty. */
282 if (huc < c->use_count)
286 /* We've reached the end of the cache; subsequent elements are
291 if (highest_use_count)
292 *highest_use_count = huc;
297 /* Create the cache used for the content of a given file to be
298 accessed by caret diagnostic. This cache is added to an array of
299 cache and can be retrieved by lookup_file_in_cache_tab. This
300 function returns the created cache. Note that only the last
301 fcache_tab_size files are cached. */
304 add_file_to_cache_tab (const char *file_path)
307 FILE *fp = fopen (file_path, "r");
311 unsigned highest_use_count = 0;
312 fcache *r = evicted_cache_tab_entry (&highest_use_count);
313 r->file_path = file_path;
318 r->line_start_idx = 0;
320 r->line_record.truncate (0);
321 /* Ensure that this cache entry doesn't get evicted next time
322 add_file_to_cache_tab is called. */
323 r->use_count = ++highest_use_count;
324 r->total_lines = total_lines_num (file_path);
329 /* Lookup the cache used for the content of a given file accessed by
330 caret diagnostic. If no cached file was found, create a new cache
331 for this file, add it to the array of cached file and return
335 lookup_or_add_file_to_cache_tab (const char *file_path)
337 fcache *r = lookup_file_in_cache_tab (file_path);
339 r = add_file_to_cache_tab (file_path);
343 /* Default constructor for a cache of file used by caret
347 : use_count (0), file_path (NULL), fp (NULL), data (0),
348 size (0), nb_read (0), line_start_idx (0), line_num (0),
351 line_record.create (0);
354 /* Destructor for a cache of file used by caret diagnostic. */
368 line_record.release ();
371 /* Returns TRUE iff the cache would need to be filled with data coming
372 from the file. That is, either the cache is empty or full or the
373 current line is empty. Note that if the cache is full, it would
374 need to be extended and filled again. */
377 needs_read (fcache *c)
379 return (c->nb_read == 0
380 || c->nb_read == c->size
381 || (c->line_start_idx >= c->nb_read - 1));
384 /* Return TRUE iff the cache is full and thus needs to be
388 needs_grow (fcache *c)
390 return c->nb_read == c->size;
393 /* Grow the cache if it needs to be extended. */
396 maybe_grow (fcache *c)
401 size_t size = c->size == 0 ? fcache_buffer_size : c->size * 2;
402 c->data = XRESIZEVEC (char, c->data, size + 1);
406 /* Read more data into the cache. Extends the cache if need be.
407 Returns TRUE iff new data could be read. */
410 read_data (fcache *c)
412 if (feof (c->fp) || ferror (c->fp))
417 char * from = c->data + c->nb_read;
418 size_t to_read = c->size - c->nb_read;
419 size_t nb_read = fread (from, 1, to_read, c->fp);
424 c->nb_read += nb_read;
428 /* Read new data iff the cache needs to be filled with more data
429 coming from the file FP. Return TRUE iff the cache was filled with
433 maybe_read_data (fcache *c)
437 return read_data (c);
440 /* Read a new line from file FP, using C as a cache for the data
441 coming from the file. Upon successful completion, *LINE is set to
442 the beginning of the line found. Space for that line has been
443 allocated in the cache thus *LINE has the same life time as C.
444 *LINE_LEN is set to the length of the line. Note that the line
445 does not contain any terminal delimiter. This function returns
446 true if some data was read or process from the cache, false
447 otherwise. Note that subsequent calls to get_next_line return the
448 next lines of the file and might overwrite the content of
452 get_next_line (fcache *c, char **line, ssize_t *line_len)
454 /* Fill the cache with data to process. */
457 size_t remaining_size = c->nb_read - c->line_start_idx;
458 if (remaining_size == 0)
459 /* There is no more data to process. */
462 char *line_start = c->data + c->line_start_idx;
464 char *next_line_start = NULL;
466 char *line_end = (char *) memchr (line_start, '\n', remaining_size);
467 if (line_end == NULL)
469 /* We haven't found the end-of-line delimiter in the cache.
470 Fill the cache with more data from the file and look for the
472 while (maybe_read_data (c))
474 line_start = c->data + c->line_start_idx;
475 remaining_size = c->nb_read - c->line_start_idx;
476 line_end = (char *) memchr (line_start, '\n', remaining_size);
477 if (line_end != NULL)
479 next_line_start = line_end + 1;
483 if (line_end == NULL)
484 /* We've loadded all the file into the cache and still no
485 '\n'. Let's say the line ends up at one byte passed the
486 end of the file. This is to stay consistent with the case
487 of when the line ends up with a '\n' and line_end points to
488 that terminal '\n'. That consistency is useful below in
489 the len calculation. */
490 line_end = c->data + c->nb_read ;
493 next_line_start = line_end + 1;
498 /* At this point, we've found the end of the of line. It either
499 points to the '\n' or to one byte after the last byte of the
501 gcc_assert (line_end != NULL);
503 len = line_end - line_start;
505 if (c->line_start_idx < c->nb_read)
510 /* Before we update our line record, make sure the hint about the
511 total number of lines of the file is correct. If it's not, then
512 we give up recording line boundaries from now on. */
513 bool update_line_record = true;
514 if (c->line_num > c->total_lines)
515 update_line_record = false;
517 /* Now update our line record so that re-reading lines from the
518 before c->line_start_idx is faster. */
519 if (update_line_record
520 && c->line_record.length () < fcache_line_record_size)
522 /* If the file lines fits in the line record, we just record all
524 if (c->total_lines <= fcache_line_record_size
525 && c->line_num > c->line_record.length ())
526 c->line_record.safe_push (fcache::line_info (c->line_num,
528 line_end - c->data));
529 else if (c->total_lines > fcache_line_record_size)
531 /* ... otherwise, we just scale total_lines down to
532 (fcache_line_record_size lines. */
533 size_t n = (c->line_num * fcache_line_record_size) / c->total_lines;
534 if (c->line_record.length () == 0
535 || n >= c->line_record.length ())
536 c->line_record.safe_push (fcache::line_info (c->line_num,
538 line_end - c->data));
542 /* Update c->line_start_idx so that it points to the next line to be
545 c->line_start_idx = next_line_start - c->data;
547 /* We didn't find any terminal '\n'. Let's consider that the end
548 of line is the end of the data in the cache. The next
549 invocation of get_next_line will either read more data from the
550 underlying file or return false early because we've reached the
552 c->line_start_idx = c->nb_read;
559 /* Reads the next line from FILE into *LINE. If *LINE is too small
560 (or NULL) it is allocated (or extended) to have enough space to
561 containe the line. *LINE_LENGTH must contain the size of the
562 initial*LINE buffer. It's then updated by this function to the
563 actual length of the returned line. Note that the returned line
564 can contain several zero bytes. Also note that the returned string
565 is allocated in static storage that is going to be re-used by
566 subsequent invocations of read_line. */
569 read_next_line (fcache *cache, char ** line, ssize_t *line_len)
574 if (!get_next_line (cache, &l, &len))
578 *line = XNEWVEC (char, len);
581 *line = XRESIZEVEC (char, *line, len);
583 memcpy (*line, l, len);
589 /* Consume the next bytes coming from the cache (or from its
590 underlying file if there are remaining unread bytes in the file)
591 until we reach the next end-of-line (or end-of-file). There is no
592 copying from the cache involved. Return TRUE upon successful
596 goto_next_line (fcache *cache)
601 return get_next_line (cache, &l, &len);
604 /* Read an arbitrary line number LINE_NUM from the file cached in C.
605 The line is copied into *LINE. *LINE_LEN must have been set to the
606 length of *LINE. If *LINE is too small (or NULL) it's extended (or
607 allocated) and *LINE_LEN is adjusted accordingly. *LINE ends up
608 with a terminal zero byte and can contain additional zero bytes.
609 This function returns bool if a line was read. */
612 read_line_num (fcache *c, size_t line_num,
613 char ** line, ssize_t *line_len)
615 gcc_assert (line_num > 0);
617 if (line_num <= c->line_num)
619 /* We've been asked to read lines that are before c->line_num.
620 So lets use our line record (if it's not empty) to try to
621 avoid re-reading the file from the beginning again. */
623 if (c->line_record.is_empty ())
625 c->line_start_idx = 0;
630 fcache::line_info *i = NULL;
631 if (c->total_lines <= fcache_line_record_size)
633 /* In languages where the input file is not totally
634 preprocessed up front, the c->total_lines hint
635 can be smaller than the number of lines of the
636 file. In that case, only the first
637 c->total_lines have been recorded.
639 Otherwise, the first c->total_lines we've read have
640 their start/end recorded here. */
641 i = (line_num <= c->total_lines)
642 ? &c->line_record[line_num - 1]
643 : &c->line_record[c->total_lines - 1];
644 gcc_assert (i->line_num <= line_num);
648 /* So the file had more lines than our line record
649 size. Thus the number of lines we've recorded has
650 been scaled down to fcache_line_reacord_size. Let's
651 pick the start/end of the recorded line that is
652 closest to line_num. */
653 size_t n = (line_num <= c->total_lines)
654 ? line_num * fcache_line_record_size / c->total_lines
655 : c ->line_record.length () - 1;
656 if (n < c->line_record.length ())
658 i = &c->line_record[n];
659 gcc_assert (i->line_num <= line_num);
663 if (i && i->line_num == line_num)
665 /* We have the start/end of the line. Let's just copy
666 it again and we are done. */
667 ssize_t len = i->end_pos - i->start_pos + 1;
669 *line = XRESIZEVEC (char, *line, len);
670 memmove (*line, c->data + i->start_pos, len);
671 (*line)[len - 1] = '\0';
678 c->line_start_idx = i->start_pos;
679 c->line_num = i->line_num - 1;
683 c->line_start_idx = 0;
689 /* Let's walk from line c->line_num up to line_num - 1, without
691 while (c->line_num < line_num - 1)
692 if (!goto_next_line (c))
695 /* The line we want is the next one. Let's read and copy it back to
697 return read_next_line (c, line, line_len);
700 /* Return the physical source line that corresponds to xloc in a
701 buffer that is statically allocated. The newline is replaced by
702 the null character. Note that the line can contain several null
703 characters, so LINE_LEN, if non-null, points to the actual length
707 location_get_source_line (expanded_location xloc,
716 fcache *c = lookup_or_add_file_to_cache_tab (xloc.file);
720 bool read = read_line_num (c, xloc.line, &buffer, &len);
722 if (read && line_len)
725 return read ? buffer : NULL;
728 /* Expand the source location LOC into a human readable location. If
729 LOC is virtual, it resolves to the expansion point of the involved
730 macro. If LOC resolves to a builtin location, the file name of the
731 readable location is set to the string "<built-in>". */
734 expand_location (source_location loc)
736 return expand_location_1 (loc, /*expansion_point_p=*/true);
739 /* Expand the source location LOC into a human readable location. If
740 LOC is virtual, it resolves to the expansion location of the
741 relevant macro. If LOC resolves to a builtin location, the file
742 name of the readable location is set to the string
746 expand_location_to_spelling_point (source_location loc)
748 return expand_location_1 (loc, /*expansion_piont_p=*/false);
751 /* If LOCATION is in a system header and if it's a virtual location for
752 a token coming from the expansion of a macro M, unwind it to the
753 location of the expansion point of M. Otherwise, just return
756 This is used for instance when we want to emit diagnostics about a
757 token that is located in a macro that is itself defined in a system
758 header -- e.g for the NULL macro. In that case, if LOCATION is
759 passed to diagnostics emitting functions like warning_at as is, no
760 diagnostic won't be emitted. */
763 expansion_point_location_if_in_system_header (source_location location)
765 if (in_system_header_at (location))
766 location = linemap_resolve_location (line_table, location,
767 LRK_MACRO_EXPANSION_POINT,
773 #define ONE_M (ONE_K * ONE_K)
775 /* Display a number as an integer multiple of either:
776 - 1024, if said integer is >= to 10 K (in base 2)
777 - 1024 * 1024, if said integer is >= 10 M in (base 2)
779 #define SCALE(x) ((unsigned long) ((x) < 10 * ONE_K \
781 : ((x) < 10 * ONE_M \
785 /* For a given integer, display either:
786 - the character 'k', if the number is higher than 10 K (in base 2)
787 but strictly lower than 10 M (in base 2)
788 - the character 'M' if the number is higher than 10 M (in base2)
789 - the charcter ' ' if the number is strictly lower than 10 K */
790 #define STAT_LABEL(x) ((x) < 10 * ONE_K ? ' ' : ((x) < 10 * ONE_M ? 'k' : 'M'))
792 /* Display an integer amount as multiple of 1K or 1M (in base 2).
793 Display the correct unit (either k, M, or ' ') after the amout, as
795 #define FORMAT_AMOUNT(size) SCALE (size), STAT_LABEL (size)
797 /* Dump statistics to stderr about the memory usage of the line_table
798 set of line maps. This also displays some statistics about macro
802 dump_line_table_statistics (void)
804 struct linemap_stats s;
805 long total_used_map_size,
807 total_allocated_map_size;
809 memset (&s, 0, sizeof (s));
811 linemap_get_statistics (line_table, &s);
813 macro_maps_size = s.macro_maps_used_size
814 + s.macro_maps_locations_size;
816 total_allocated_map_size = s.ordinary_maps_allocated_size
817 + s.macro_maps_allocated_size
818 + s.macro_maps_locations_size;
820 total_used_map_size = s.ordinary_maps_used_size
821 + s.macro_maps_used_size
822 + s.macro_maps_locations_size;
824 fprintf (stderr, "Number of expanded macros: %5ld\n",
825 s.num_expanded_macros);
826 if (s.num_expanded_macros != 0)
827 fprintf (stderr, "Average number of tokens per macro expansion: %5ld\n",
828 s.num_macro_tokens / s.num_expanded_macros);
830 "\nLine Table allocations during the "
831 "compilation process\n");
832 fprintf (stderr, "Number of ordinary maps used: %5ld%c\n",
833 SCALE (s.num_ordinary_maps_used),
834 STAT_LABEL (s.num_ordinary_maps_used));
835 fprintf (stderr, "Ordinary map used size: %5ld%c\n",
836 SCALE (s.ordinary_maps_used_size),
837 STAT_LABEL (s.ordinary_maps_used_size));
838 fprintf (stderr, "Number of ordinary maps allocated: %5ld%c\n",
839 SCALE (s.num_ordinary_maps_allocated),
840 STAT_LABEL (s.num_ordinary_maps_allocated));
841 fprintf (stderr, "Ordinary maps allocated size: %5ld%c\n",
842 SCALE (s.ordinary_maps_allocated_size),
843 STAT_LABEL (s.ordinary_maps_allocated_size));
844 fprintf (stderr, "Number of macro maps used: %5ld%c\n",
845 SCALE (s.num_macro_maps_used),
846 STAT_LABEL (s.num_macro_maps_used));
847 fprintf (stderr, "Macro maps used size: %5ld%c\n",
848 SCALE (s.macro_maps_used_size),
849 STAT_LABEL (s.macro_maps_used_size));
850 fprintf (stderr, "Macro maps locations size: %5ld%c\n",
851 SCALE (s.macro_maps_locations_size),
852 STAT_LABEL (s.macro_maps_locations_size));
853 fprintf (stderr, "Macro maps size: %5ld%c\n",
854 SCALE (macro_maps_size),
855 STAT_LABEL (macro_maps_size));
856 fprintf (stderr, "Duplicated maps locations size: %5ld%c\n",
857 SCALE (s.duplicated_macro_maps_locations_size),
858 STAT_LABEL (s.duplicated_macro_maps_locations_size));
859 fprintf (stderr, "Total allocated maps size: %5ld%c\n",
860 SCALE (total_allocated_map_size),
861 STAT_LABEL (total_allocated_map_size));
862 fprintf (stderr, "Total used maps size: %5ld%c\n",
863 SCALE (total_used_map_size),
864 STAT_LABEL (total_used_map_size));
865 fprintf (stderr, "\n");
868 /* Associate the DISCRIMINATOR with LOCUS, and return a new locus.
869 We associate discriminators with a locus by allocating location_t
870 values beyond those assigned by libcpp. Each new value is mapped
871 directly to a real location_t value, and separately to the
875 location_with_discriminator (location_t locus, int discriminator)
877 tree block = LOCATION_BLOCK (locus);
880 locus = map_discriminator_location (locus);
882 if (locus == UNKNOWN_LOCATION)
883 return block ? COMBINE_LOCATION_DATA (line_table, locus, block)
886 if (min_discriminator_location == UNKNOWN_LOCATION)
888 min_discriminator_location = line_table->highest_location + 1;
889 next_discriminator_location = min_discriminator_location;
892 /* Traverse the last few discriminator_locations to see if we can reuse
894 for (i = next_discriminator_location - min_discriminator_location - 1;
895 (i >= 0 && LOCATION_LINE (discriminator_location_locations[i]) ==
896 LOCATION_LINE (locus)
897 && discriminator_location_discriminators[i] == discriminator);
899 if (discriminator_location_locations[i] == locus)
901 ? COMBINE_LOCATION_DATA (line_table, min_discriminator_location + i,
903 : min_discriminator_location + i);
905 discriminator_location_locations.safe_push(locus);
906 discriminator_location_discriminators.safe_push(discriminator);
909 ? COMBINE_LOCATION_DATA (line_table, next_discriminator_location, block)
910 : next_discriminator_location);
912 next_discriminator_location++;
916 /* Return TRUE if LOCUS represents a location with a discriminator. */
919 has_discriminator (location_t locus)
921 locus = LOCATION_LOCUS (locus);
922 return (min_discriminator_location != UNKNOWN_LOCATION
923 && locus >= min_discriminator_location
924 && locus < next_discriminator_location);
927 /* Return the real location_t value for LOCUS. */
930 map_discriminator_location (location_t locus)
932 locus = LOCATION_LOCUS (locus);
933 if (! has_discriminator (locus))
935 return (location_t) discriminator_location_locations[locus - min_discriminator_location];
938 /* Return the discriminator for LOCUS. */
941 get_discriminator_from_locus (location_t locus)
943 locus = LOCATION_LOCUS (locus);
944 if (! has_discriminator (locus))
946 return discriminator_location_discriminators[locus - min_discriminator_location];