source_range src_range = get_range_from_loc (line_table, range_c_b_d);
ASSERT_EQ (loc_b, src_range.m_start);
ASSERT_EQ (loc_d, src_range.m_finish);
+
+ /* Verify raw line map usage. The map should have the requested properties,
+ irrespective of limits like LINE_MAP_MAX_LOCATION_WITH_COLS. */
+ for (int sysp = 0; sysp != 3; ++sysp)
+ {
+ constexpr int column_bits = 8, range_bits = 7;
+ const int line = 1 + sysp;
+ const auto map = linemap_add_raw_map (line_table, LC_RENAME,
+ line_table->highest_location + 1,
+ sysp, column_bits + range_bits,
+ range_bits, "foo2.c", line, 1);
+ ASSERT_NE (map, nullptr);
+ ASSERT_EQ (map->reason, LC_RENAME);
+ ASSERT_EQ (map->m_column_and_range_bits, column_bits + range_bits);
+ ASSERT_EQ (map->m_range_bits, range_bits);
+ const line_map_uint_t col = 200 + sysp;
+ const location_t loc = MAP_START_LOCATION (map) + (col << range_bits);
+ ASSERT_GT (loc, line_table->highest_line);
+ ASSERT_LT (loc, line_table->highest_location);
+ ASSERT_EQ (in_system_header_at (loc), sysp);
+ assert_loceq ("foo2.c", line, col, loc);
+ }
}
/* Verify various properties of UNKNOWN_LOCATION. */
/* Allocate a raw block of line maps, zero initialized. */
extern line_map *line_map_new_raw (line_maps *, bool, line_map_uint_t);
+/* Return the location_t at which a new line map with RANGE_BITS range bits
+ would begin, if it needs to begin at least at START_LOC. */
+inline location_t
+linemap_next_start_location (location_t start_loc, int range_bits)
+{
+ const auto mask = (location_t (1) << range_bits) - 1;
+ return (start_loc + mask) & ~mask;
+}
+
/* Add a mapping of logical source line to physical source file and
line number. This function creates an "ordinary map", which is a
map that records locations of tokens that are not part of macro
(class line_maps *, enum lc_reason, unsigned int sysp,
const char *to_file, linenum_type to_line);
+/* Create a map with exactly the requested parameters. Not intended for general
+ use, but useful for applications that need to work with linemap internals
+ directly. NUM_LINES is the number of lines this map should be able to hold;
+ this just ensures that set->highest_location is set properly so that the next
+ added map will leave sufficient room for NUM_LINES lines in this map. */
+extern line_map_ordinary *
+linemap_add_raw_map (line_maps *set, lc_reason reason, location_t start_loc,
+ unsigned int sysp, int column_and_range_bits,
+ int range_bits, const char *to_file, linenum_type to_line,
+ line_map_uint_t num_lines);
+
/* 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
/* Given a logical source location, returns the map which the
corresponding (source file, line, column) triplet can be deduced
- from. 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. If no line map have been allocated yet, this
- function returns NULL. */
+ from. Since the start_location of each map is monotonic increasing,
+ this can be done with binary search. */
extern const line_map *linemap_lookup
(const line_maps *, location_t);
unsigned range_bits = 0;
if (start_location < LINE_MAP_MAX_LOCATION_WITH_COLS)
range_bits = set->default_range_bits;
- start_location += (loc_one << range_bits) - 1;
- start_location &= ~((loc_one << range_bits) - 1);
-
+ start_location = linemap_next_start_location (start_location, range_bits);
linemap_assert (!LINEMAPS_ORDINARY_USED (set)
|| (start_location
>= MAP_START_LOCATION (LINEMAPS_LAST_ORDINARY_MAP (set))));
return map;
}
+/* Create a map with exactly the requested parameters. Not intended for general
+ use, but useful for applications that need to work with linemap internals
+ directly. NUM_LINES is the number of lines this map should be able to hold;
+ this just ensures that set->highest_location is set properly so that the next
+ added map will leave sufficient room for NUM_LINES lines in this map. */
+
+line_map_ordinary *
+linemap_add_raw_map (line_maps *set, lc_reason reason, location_t start_loc,
+ unsigned int sysp, int column_and_range_bits,
+ int range_bits, const char *to_file, linenum_type to_line,
+ line_map_uint_t num_lines)
+{
+ start_loc = linemap_next_start_location (start_loc, range_bits);
+ gcc_assert (start_loc > set->highest_location);
+ location_t last_loc = start_loc + (loc_one << column_and_range_bits) - 1;
+ if (num_lines > 1)
+ last_loc += (num_lines - 1) << column_and_range_bits;
+ if (last_loc >= LINE_MAP_MAX_LOCATION)
+ return nullptr;
+ const auto map = linemap_check_ordinary (new_linemap (set, start_loc));
+ map->reason = reason;
+ map->sysp = sysp;
+ map->m_column_and_range_bits = column_and_range_bits;
+ map->m_range_bits = range_bits;
+ map->to_file = to_file;
+ map->to_line = to_line;
+ set->info_ordinary.m_cache = LINEMAPS_ORDINARY_USED (set) - 1;
+ set->highest_location = last_loc;
+ set->highest_line
+ = start_loc + ((last_loc - start_loc)
+ & (line_map_uint_t (-1) << column_and_range_bits));
+ set->max_column_hint = 1U << (column_and_range_bits - range_bits);
+ return map;
+}
+
/* Create a location for a module NAME imported at FROM. */
location_t
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. */
+/* Given a source location yielded by an ordinary map, returns that map. Since
+ the start_location of each map is larger than the prior one, this can be done
+ with binary search. Note that the line maps are not necessarily sorted by
+ file name or by line number, although they often are, at least in a local
+ region, since things like #line directives, multiple includes, or
+ manipulations outside the normal usage during parsing can all affect the
+ sorting. But they are always sorted by start_location. */
static const line_map_ordinary *
linemap_ordinary_map_lookup (const line_maps *set, location_t line)