+/* 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. */
+ linemap_assert (!linemap_location_from_macro_expansion_p (set, 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. */
+ linemap_assert (MAP_START_LOCATION (map) < loc + offset);
+
+ /* 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))
+ linemap_assert (loc + offset < MAP_START_LOCATION (&map[1]));
+
+ offset += SOURCE_COLUMN (map, loc);
+ linemap_assert (offset < (1u << map->d.ordinary.column_bits));
+
+ source_location r =
+ linemap_position_for_line_and_column (map,
+ SOURCE_LINE (map, loc),
+ offset);
+ linemap_assert (map == linemap_lookup (set, r));
+ return r;
+}
+