LC_LEAVE,
LC_RENAME,
LC_RENAME_VERBATIM,
- LC_ENTER_MACRO
+ LC_ENTER_MACRO,
/* FIXME: add support for stringize and paste. */
+ LC_HWM /* High Water Mark. */
};
/* The typedef "source_location" is a key within the location database,
| Beyond this point, ordinary linemaps have 0 bits per column:
| each increment of the value corresponds to a new source line.
|
- 0x70000000 | LINE_MAP_MAX_SOURCE_LOCATION
+ 0x70000000 | LINE_MAP_MAX_LOCATION
| Beyond the point, we give up on ordinary maps; attempts to
| create locations in them lead to UNKNOWN_LOCATION (0).
|
gcc.dg/plugin/location-overflow-test-*.c. */
const source_location LINE_MAP_MAX_LOCATION_WITH_COLS = 0x60000000;
+/* Highest possible source location encoded within an ordinary map. */
+const source_location LINE_MAP_MAX_LOCATION = 0x70000000;
+
/* A range of source locations.
Ranges are closed:
location of the expansion point of PLUS. That location is mapped in
the map that is active right before the location of the invocation
of PLUS. */
-struct GTY((tag ("0"), desc ("%h.reason == LC_ENTER_MACRO ? 2 : 1"))) line_map {
+
+/* This contains GTY mark-up to support precompiled headers.
+ line_map is an abstract class, only derived objects exist. */
+struct GTY((tag ("0"), desc ("MAP_ORDINARY_P (&%h) ? 1 : 2"))) line_map {
source_location start_location;
- /* The reason for creation of this line map. */
- ENUM_BITFIELD (lc_reason) reason : CHAR_BIT;
+ /* Size and alignment is (usually) 4 bytes. */
};
/* An ordinary line map encodes physical source locations. Those
The highest possible source location is MAX_SOURCE_LOCATION. */
struct GTY((tag ("1"))) line_map_ordinary : public line_map {
- const char *to_file;
- linenum_type to_line;
+ /* Base class is 4 bytes. */
- /* An index into the set that gives the line mapping at whose end
- the current one was included. File(s) at the bottom of the
- include stack have this set to -1. */
- int included_from;
+ /* 4 bytes of integers, each 1 byte for easy extraction/insertion. */
+
+ /* The reason for creation of this line map. */
+ ENUM_BITFIELD (lc_reason) reason : 8;
/* SYSP is one for a system header, two for a C system header file
that therefore needs to be extern "C" protected in C++, and zero
| | (e.g. 7) | (e.g. 5) |
+-------------------------+-----------------------+-------------------+ */
unsigned int m_range_bits : 8;
+
+ /* Pointer alignment boundary on both 32 and 64-bit systems. */
+
+ const char *to_file;
+ linenum_type to_line;
+
+ /* An index into the set that gives the line mapping at whose end
+ the current one was included. File(s) at the bottom of the
+ include stack have this set to -1. */
+ int included_from;
+
+ /* Size is 20 or 24 bytes, no padding */
};
/* This is the highest possible source location encoded within an
The offset from START_LOCATION is used to index into
MACRO_LOCATIONS; this holds the original location of the token. */
struct GTY((tag ("2"))) line_map_macro : public line_map {
- /* The cpp macro which expansion gave birth to this macro map. */
- struct cpp_hashnode * GTY ((nested_ptr (union tree_node,
- "%h ? CPP_HASHNODE (GCC_IDENT_TO_HT_IDENT (%h)) : NULL",
- "%h ? HT_IDENT_TO_GCC_IDENT (HT_NODE (%h)) : NULL")))
- macro;
+ /* Base is 4 bytes. */
/* The number of tokens inside the replacement-list of MACRO. */
unsigned int n_tokens;
+ /* Pointer alignment boundary. */
+
+ /* The cpp macro whose expansion gave birth to this macro map. */
+ struct cpp_hashnode *
+ GTY ((nested_ptr (union tree_node,
+ "%h ? CPP_HASHNODE (GCC_IDENT_TO_HT_IDENT (%h)) : NULL",
+ "%h ? HT_IDENT_TO_GCC_IDENT (HT_NODE (%h)) : NULL")))
+ macro;
+
/* This array of location is actually an array of pairs of
locations. The elements inside it thus look like:
could have been either a macro or an ordinary map, depending on
if we are in a nested expansion context not. */
source_location expansion;
+
+ /* Size is 20 or 32 (4 bytes padding on 64-bit). */
};
#if CHECKING_P && (GCC_VERSION >= 2007)
#define linemap_assert_fails(EXPR) (! (EXPR))
#endif
+/* Categorize line map kinds. */
+
+inline bool
+MAP_ORDINARY_P (const line_map *map)
+{
+ return map->start_location < LINE_MAP_MAX_LOCATION;
+}
+
/* Return TRUE if MAP encodes locations coming from a macro
replacement-list at macro expansion point. */
bool
inline line_map_ordinary *
linemap_check_ordinary (struct line_map *map)
{
- linemap_assert (!linemap_macro_expansion_map_p (map));
+ linemap_assert (MAP_ORDINARY_P (map));
return (line_map_ordinary *)map;
}
inline const line_map_ordinary *
linemap_check_ordinary (const struct line_map *map)
{
- linemap_assert (!linemap_macro_expansion_map_p (map));
+ linemap_assert (MAP_ORDINARY_P (map));
return (const line_map_ordinary *)map;
}
inline line_map_macro *linemap_check_macro (line_map *map)
{
- linemap_assert (linemap_macro_expansion_map_p (map));
+ linemap_assert (!MAP_ORDINARY_P (map));
return (line_map_macro *)map;
}
inline const line_map_macro *
linemap_check_macro (const line_map *map)
{
- linemap_assert (linemap_macro_expansion_map_p (map));
+ linemap_assert (!MAP_ORDINARY_P (map));
return (const line_map_macro *)map;
}
#include "internal.h"
#include "hashtab.h"
-/* Highest possible source location encoded within an ordinary or
- macro map. */
-const source_location LINE_MAP_MAX_SOURCE_LOCATION = 0x70000000;
-
static void trace_include (const struct line_maps *, const line_map_ordinary *);
static const line_map_ordinary * linemap_ordinary_map_lookup (struct line_maps *,
source_location);
macro maps are allocated in different memory location. */
static struct line_map *
-new_linemap (struct line_maps *set,
- enum lc_reason reason)
+new_linemap (struct line_maps *set, source_location start_location)
{
- /* 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;
+ bool macro_map_p = start_location >= LINE_MAP_MAX_LOCATION;
if (LINEMAPS_USED (set, macro_map_p) == LINEMAPS_ALLOCATED (set, macro_map_p))
{
result = &set->info_ordinary.maps[LINEMAPS_USED (set, macro_map_p)];
}
+ result->start_location = start_location;
+
LINEMAPS_USED (set, macro_map_p)++;
- result->reason = reason;
return result;
}
else
start_location = set->highest_location + 1;
- linemap_assert (!(LINEMAPS_ORDINARY_USED (set)
- && (start_location
- < MAP_START_LOCATION (LINEMAPS_LAST_ORDINARY_MAP (set)))));
+ 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 (reason != LC_ENTER_MACRO);
- line_map_ordinary *map = linemap_check_ordinary (new_linemap (set, reason));
+ line_map_ordinary *map
+ = linemap_check_ordinary (new_linemap (set, start_location));
+ map->reason = reason;
if (to_file && *to_file == '\0' && reason != LC_RENAME_VERBATIM)
to_file = "<stdin>";
}
map->sysp = sysp;
- map->start_location = start_location;
map->to_file = to_file;
map->to_line = to_line;
LINEMAPS_ORDINARY_CACHE (set) = LINEMAPS_ORDINARY_USED (set) - 1;
start_location = LINEMAPS_MACRO_LOWEST_LOCATION (set) - num_tokens;
- if (start_location <= set->highest_line
- || start_location > LINEMAPS_MACRO_LOWEST_LOCATION (set))
+ if (start_location < LINE_MAP_MAX_LOCATION)
/* We ran out of macro map space. */
return NULL;
- map = linemap_check_macro (new_linemap (set, LC_ENTER_MACRO));
+ map = linemap_check_macro (new_linemap (set, start_location));
- map->start_location = start_location;
map->macro = macro_node;
map->n_tokens = num_tokens;
map->macro_locations
|| (highest > LINE_MAP_MAX_LOCATION_WITH_PACKED_RANGES
&& map->m_range_bits > 0)
|| (highest > LINE_MAP_MAX_LOCATION_WITH_COLS
- && (set->max_column_hint || highest >= LINE_MAP_MAX_SOURCE_LOCATION)))
+ && (set->max_column_hint || highest >= LINE_MAP_MAX_LOCATION)))
add_map = true;
else
max_column_hint = set->max_column_hint;
max_column_hint = 0;
column_bits = 0;
range_bits = 0;
- if (highest > LINE_MAP_MAX_SOURCE_LOCATION)
+ if (highest >= LINE_MAP_MAX_LOCATION)
return 0;
}
else
/* Locations of ordinary tokens are always lower than locations of
macro tokens. */
- if (r >= LINEMAPS_MACRO_LOWEST_LOCATION (set))
+ if (r >= LINE_MAP_MAX_LOCATION)
return 0;
set->highest_line = r;
bool
linemap_macro_expansion_map_p (const struct line_map *map)
{
- if (!map)
- return false;
- return (map->reason == LC_ENTER_MACRO);
+ return map && !MAP_ORDINARY_P (map);
}
/* If LOCATION is the locus of a token in a replacement-list of a
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);
+ return location >= LINE_MAP_MAX_LOCATION;
}
/* Given two virtual locations *LOC0 and *LOC1, return the first
source_location location,
const line_map_ordinary **original_map)
{
- struct line_map *map;
linemap_assert (set && location >= RESERVED_LOCATION_COUNT);
while (true)
{
- map = const_cast <line_map *> (linemap_lookup (set, location));
- if (!linemap_macro_expansion_map_p (map))
- break;
+ const struct line_map *map = linemap_lookup (set, location);
+ if (!map || MAP_ORDINARY_P (map))
+ {
+ if (original_map)
+ *original_map = (const line_map_ordinary *)map;
+ break;
+ }
- location
- = linemap_macro_map_loc_unwind_toward_spelling
- (set, linemap_check_macro (map),
- location);
+ location = linemap_macro_map_loc_unwind_toward_spelling
+ (set, linemap_check_macro (map), location);
}
- if (original_map)
- *original_map = linemap_check_ordinary (map);
return location;
}
source_location location,
const line_map_ordinary **original_map)
{
- struct line_map *map;
-
linemap_assert (set && location >= RESERVED_LOCATION_COUNT);
- while (true)
+ for (;;)
{
- source_location caret_loc;
- if (IS_ADHOC_LOC (location))
- caret_loc = get_location_from_adhoc_loc (set, location);
- else
- caret_loc = location;
+ source_location caret_loc = location;
+ if (IS_ADHOC_LOC (caret_loc))
+ caret_loc = get_location_from_adhoc_loc (set, caret_loc);
- map = const_cast <line_map *> (linemap_lookup (set, caret_loc));
- if (!linemap_macro_expansion_map_p (map))
- break;
+ const line_map *map = linemap_lookup (set, caret_loc);
+ if (!map || MAP_ORDINARY_P (map))
+ {
+ if (original_map)
+ *original_map = (const line_map_ordinary *)map;
+ break;
+ }
- location =
- linemap_macro_map_loc_to_def_point (linemap_check_macro (map),
- caret_loc);
+ location = linemap_macro_map_loc_to_def_point
+ (linemap_check_macro (map), caret_loc);
}
- if (original_map)
- *original_map = linemap_check_ordinary (map);
return location;
}
void
linemap_dump (FILE *stream, struct line_maps *set, unsigned ix, bool is_macro)
{
- const char *lc_reasons_v[LC_ENTER_MACRO + 1]
+ const char *const lc_reasons_v[LC_HWM]
= { "LC_ENTER", "LC_LEAVE", "LC_RENAME", "LC_RENAME_VERBATIM",
"LC_ENTER_MACRO" };
- const char *reason;
const line_map *map;
+ unsigned reason;
if (stream == NULL)
stream = stderr;
if (!is_macro)
- map = LINEMAPS_ORDINARY_MAP_AT (set, ix);
+ {
+ map = LINEMAPS_ORDINARY_MAP_AT (set, ix);
+ reason = linemap_check_ordinary (map)->reason;
+ }
else
- map = LINEMAPS_MACRO_MAP_AT (set, ix);
-
- reason = (map->reason <= LC_ENTER_MACRO) ? lc_reasons_v[map->reason] : "???";
+ {
+ map = LINEMAPS_MACRO_MAP_AT (set, ix);
+ reason = LC_ENTER_MACRO;
+ }
fprintf (stream, "Map #%u [%p] - LOC: %u - REASON: %s - SYSP: %s\n",
- ix, (void *) map, map->start_location, reason,
+ ix, (void *) map, map->start_location,
+ reason < LC_HWM ? lc_reasons_v[reason] : "???",
((!is_macro
&& ORDINARY_MAP_IN_SYSTEM_HEADER_P (linemap_check_ordinary (map)))
? "yes" : "no"));