diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-05-02 14:43:35 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-05-02 14:43:35 +0000 |
commit | 34efdaf078b01a7387007c4e6bde6db86384c4b7 (patch) | |
tree | d503eaf41d085669d1481bb46ec038bc866fece6 /libcpp/line-map.c | |
parent | f733cf303bcdc952c92b81dd62199a40a1f555ec (diff) | |
download | gcc-tarball-master.tar.gz |
gcc-7.1.0gcc-7.1.0
Diffstat (limited to 'libcpp/line-map.c')
-rw-r--r-- | libcpp/line-map.c | 441 |
1 files changed, 372 insertions, 69 deletions
diff --git a/libcpp/line-map.c b/libcpp/line-map.c index 2e61895bb3..949489eb1a 100644 --- a/libcpp/line-map.c +++ b/libcpp/line-map.c @@ -1,5 +1,5 @@ /* Map (unsigned int) keys to (source file, line, column) triples. - Copyright (C) 2001-2016 Free Software Foundation, Inc. + Copyright (C) 2001-2017 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 @@ -31,18 +31,6 @@ along with this program; see the file COPYING3. If not see disabled). */ const unsigned int LINE_MAP_MAX_COLUMN_NUMBER = (1U << 12); -/* Do not pack ranges if locations get higher than this. - If you change this, update: - gcc.dg/plugin/location_overflow_plugin.c - gcc.dg/plugin/location-overflow-test-*.c. */ -const source_location LINE_MAP_MAX_LOCATION_WITH_PACKED_RANGES = 0x50000000; - -/* Do not track column numbers if locations get higher than this. - If you change this, update: - gcc.dg/plugin/location_overflow_plugin.c - 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 or macro map. */ const source_location LINE_MAP_MAX_SOURCE_LOCATION = 0x70000000; @@ -69,6 +57,14 @@ static source_location linemap_macro_loc_to_exp_point (struct line_maps *, extern unsigned num_expanded_macros_counter; extern unsigned num_macro_tokens_counter; +/* Destructor for class line_maps. + Ensure non-GC-managed memory is released. */ + +line_maps::~line_maps () +{ + htab_delete (location_adhoc_data_map.htab); +} + /* Hash function for location_adhoc_data hashtable. */ static hashval_t @@ -102,7 +98,7 @@ location_adhoc_data_eq (const void *l1, const void *l2) static int location_adhoc_data_update (void **slot, void *data) { - *((char **) slot) += *((long long *) data); + *((char **) slot) += *((int64_t *) data); return 1; } @@ -224,7 +220,7 @@ get_combined_adhoc_loc (struct line_maps *set, set->location_adhoc_data_map.allocated) { char *orig_data = (char *) set->location_adhoc_data_map.data; - long long offset; + int64_t offset; /* Cast away extern "C" from the type of xrealloc. */ line_map_realloc reallocator = (set->reallocator ? set->reallocator @@ -323,11 +319,26 @@ pure_location_p (line_maps *set, source_location loc) return true; } -/* Finalize the location_adhoc_data structure. */ -void -location_adhoc_data_fini (struct line_maps *set) +/* Given location LOC within SET, strip away any packed range information + or ad-hoc information. */ + +source_location +get_pure_location (line_maps *set, source_location loc) { - htab_delete (set->location_adhoc_data_map.htab); + if (IS_ADHOC_LOC (loc)) + loc + = set->location_adhoc_data_map.data[loc & MAX_SOURCE_LOCATION].locus; + + if (loc >= LINEMAPS_MACRO_LOWEST_LOCATION (set)) + return loc; + + if (loc < RESERVED_LOCATION_COUNT) + return loc; + + const line_map *map = linemap_lookup (set, loc); + const line_map_ordinary *ordmap = linemap_check_ordinary (map); + + return loc & ~((1 << ordmap->m_range_bits) - 1); } /* Initialize a line map set. */ @@ -741,7 +752,7 @@ linemap_line_start (struct line_maps *set, linenum_type to_line, 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) + || SOURCE_COLUMN (map, highest) >= (1U << (column_bits - range_bits)) || range_bits < map->m_range_bits) map = linemap_check_ordinary (const_cast <line_map *> @@ -805,8 +816,22 @@ linemap_position_for_column (struct line_maps *set, unsigned int to_column) } else { + /* Otherwise, attempt to start a new line that can hold TO_COLUMN, + with some space to spare. This may or may not lead to a new + linemap being created. */ line_map_ordinary *map = LINEMAPS_LAST_ORDINARY_MAP (set); r = linemap_line_start (set, SOURCE_LINE (map, r), to_column + 50); + map = LINEMAPS_LAST_ORDINARY_MAP (set); + if (map->m_column_and_range_bits == 0) + { + /* ...then the linemap has column-tracking disabled, + presumably due to exceeding either + LINE_MAP_MAX_LOCATION_WITH_COLS (overall) or + LINE_MAP_MAX_COLUMN_NUMBER (within this line). + Return the start of the linemap, which encodes column 0, for + the whole line. */ + return r; + } } } line_map_ordinary *map = LINEMAPS_LAST_ORDINARY_MAP (set); @@ -894,7 +919,10 @@ linemap_position_for_loc_and_offset (struct line_maps *set, } column += column_offset; - if (linemap_assert_fails (column < (1u << map->m_column_and_range_bits))) + + /* Bail out if the column is not representable within the existing + linemap. */ + if (column >= (1u << (map->m_column_and_range_bits - map->m_range_bits))) return loc; source_location r = @@ -1213,9 +1241,8 @@ linemap_location_in_system_header_p (struct line_maps *set, 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. */ +/* Return TRUE if LOCATION is a source code location of a token that is part of + a macro expansion, FALSE otherwise. */ bool linemap_location_from_macro_expansion_p (const struct line_maps *set, @@ -1560,6 +1587,37 @@ linemap_resolve_location (struct line_maps *set, return loc; } +/* TRUE if LOCATION is a source code location of a token that is part of the + definition of a macro, FALSE otherwise. */ + +bool +linemap_location_from_macro_definition_p (struct line_maps *set, + source_location loc) +{ + if (IS_ADHOC_LOC (loc)) + loc = get_location_from_adhoc_loc (set, loc); + + if (!linemap_location_from_macro_expansion_p (set, loc)) + return false; + + while (true) + { + const struct line_map_macro *map + = linemap_check_macro (linemap_lookup (set, loc)); + + source_location s_loc + = linemap_macro_map_loc_unwind_toward_spelling (set, map, loc); + if (linemap_location_from_macro_expansion_p (set, s_loc)) + loc = s_loc; + else + { + source_location def_loc + = linemap_macro_map_loc_to_def_point (map, loc); + return s_loc == def_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 @@ -1971,11 +2029,13 @@ source_range::intersects_line_p (const char *file, int line) const /* Construct a rich_location with location LOC as its initial range. */ -rich_location::rich_location (line_maps */*set*/, source_location loc) : - m_num_ranges (0), +rich_location::rich_location (line_maps *set, source_location loc) : + m_line_table (set), + m_ranges (), m_column_override (0), m_have_expanded_location (false), - m_num_fixit_hints (0) + m_fixit_hints (), + m_seen_impossible_fixit (false) { add_range (loc, true); } @@ -1984,8 +2044,8 @@ rich_location::rich_location (line_maps */*set*/, source_location loc) : rich_location::~rich_location () { - for (unsigned int i = 0; i < m_num_fixit_hints; i++) - delete m_fixit_hints[i]; + for (unsigned int i = 0; i < m_fixit_hints.count (); i++) + delete get_fixit_hint (i); } /* Get location IDX within this rich_location. */ @@ -1993,8 +2053,24 @@ rich_location::~rich_location () source_location rich_location::get_loc (unsigned int idx) const { - linemap_assert (idx < m_num_ranges); - return m_ranges[idx].m_loc; + const location_range *locrange = get_range (idx); + return locrange->m_loc; +} + +/* Get range IDX within this rich_location. */ + +const location_range * +rich_location::get_range (unsigned int idx) const +{ + return &m_ranges[idx]; +} + +/* Mutable access to range IDX within this rich_location. */ + +location_range * +rich_location::get_range (unsigned int idx) +{ + return &m_ranges[idx]; } /* Expand location IDX within this rich_location. */ @@ -2037,11 +2113,10 @@ rich_location::override_column (int column) void rich_location::add_range (source_location loc, bool show_caret_p) { - linemap_assert (m_num_ranges < MAX_RANGES); - - location_range *range = &m_ranges[m_num_ranges++]; - range->m_loc = loc; - range->m_show_caret_p = show_caret_p; + location_range range; + range.m_loc = loc; + range.m_show_caret_p = show_caret_p; + m_ranges.push (range); } /* Add or overwrite the location given by IDX, setting its location to LOC, @@ -2061,35 +2136,109 @@ void rich_location::set_range (line_maps * /*set*/, unsigned int idx, source_location loc, bool show_caret_p) { - linemap_assert (idx < MAX_RANGES); - /* We can either overwrite an existing range, or add one exactly on the end of the array. */ - linemap_assert (idx <= m_num_ranges); + linemap_assert (idx <= m_ranges.count ()); - location_range *locrange = &m_ranges[idx]; - locrange->m_loc = loc; - locrange->m_show_caret_p = show_caret_p; - - /* Are we adding a range onto the end? */ - if (idx == m_num_ranges) - m_num_ranges = idx + 1; + if (idx == m_ranges.count ()) + add_range (loc, show_caret_p); + else + { + location_range *locrange = get_range (idx); + locrange->m_loc = loc; + locrange->m_show_caret_p = show_caret_p; + } if (idx == 0) /* Mark any cached value here as dirty. */ m_have_expanded_location = false; } +/* Methods for adding insertion fix-it hints. */ + +/* Add a fixit-hint, suggesting insertion of NEW_CONTENT + immediately before the primary range's start location. */ + +void +rich_location::add_fixit_insert_before (const char *new_content) +{ + add_fixit_insert_before (get_loc (), new_content); +} + +/* Add a fixit-hint, suggesting insertion of NEW_CONTENT + immediately before the start of WHERE. */ + +void +rich_location::add_fixit_insert_before (source_location where, + const char *new_content) +{ + source_location start = get_range_from_loc (m_line_table, where).m_start; + + if (reject_impossible_fixit (start)) + return; + /* We do not yet support newlines within fix-it hints. */ + if (strchr (new_content, '\n')) + { + stop_supporting_fixits (); + return; + } + add_fixit (new fixit_insert (start, new_content)); +} + /* Add a fixit-hint, suggesting insertion of NEW_CONTENT - at WHERE. */ + immediately after the primary range's end-point. */ void -rich_location::add_fixit_insert (source_location where, - const char *new_content) +rich_location::add_fixit_insert_after (const char *new_content) { - linemap_assert (m_num_fixit_hints < MAX_FIXIT_HINTS); - m_fixit_hints[m_num_fixit_hints++] - = new fixit_insert (where, new_content); + add_fixit_insert_after (get_loc (), new_content); +} + +/* Add a fixit-hint, suggesting insertion of NEW_CONTENT + immediately after the end-point of WHERE. */ + +void +rich_location::add_fixit_insert_after (source_location where, + const char *new_content) +{ + source_location finish = get_range_from_loc (m_line_table, where).m_finish; + + if (reject_impossible_fixit (finish)) + return; + + source_location next_loc + = linemap_position_for_loc_and_offset (m_line_table, finish, 1); + + /* linemap_position_for_loc_and_offset can fail, if so, it returns + its input value. */ + if (next_loc == finish) + { + stop_supporting_fixits (); + return; + } + + add_fixit (new fixit_insert (next_loc, new_content)); +} + +/* Methods for adding removal fix-it hints. */ + +/* Add a fixit-hint, suggesting removal of the content covered + by range 0. */ + +void +rich_location::add_fixit_remove () +{ + add_fixit_remove (get_loc ()); +} + +/* Add a fixit-hint, suggesting removal of the content between + the start and finish of WHERE. */ + +void +rich_location::add_fixit_remove (source_location where) +{ + source_range range = get_range_from_loc (m_line_table, where); + add_fixit_remove (range); } /* Add a fixit-hint, suggesting removal of the content at @@ -2098,8 +2247,67 @@ rich_location::add_fixit_insert (source_location where, void rich_location::add_fixit_remove (source_range src_range) { - linemap_assert (m_num_fixit_hints < MAX_FIXIT_HINTS); - m_fixit_hints[m_num_fixit_hints++] = new fixit_remove (src_range); + add_fixit_replace (src_range, ""); +} + +/* Return true iff A is in the column directly before B, on the + same line of the same source file. */ + +static bool +column_before_p (line_maps *set, source_location a, source_location b) +{ + if (IS_ADHOC_LOC (a)) + a = get_location_from_adhoc_loc (set, a); + if (IS_ADHOC_LOC (b)) + b = get_location_from_adhoc_loc (set, b); + + /* They must both be in ordinary maps. */ + const struct line_map *linemap_a = linemap_lookup (set, a); + if (linemap_macro_expansion_map_p (linemap_a)) + return false; + const struct line_map *linemap_b = linemap_lookup (set, b); + if (linemap_macro_expansion_map_p (linemap_b)) + return false; + + /* To be on the same line, they must be in the same ordinary map. */ + if (linemap_a != linemap_b) + return false; + + linenum_type line_a + = SOURCE_LINE (linemap_check_ordinary (linemap_a), a); + linenum_type line_b + = SOURCE_LINE (linemap_check_ordinary (linemap_b), b); + if (line_a != line_b) + return false; + + linenum_type column_a + = SOURCE_COLUMN (linemap_check_ordinary (linemap_a), a); + linenum_type column_b + = SOURCE_COLUMN (linemap_check_ordinary (linemap_b), b); + + return column_b == column_a + 1; +} + +/* Add a fixit-hint, suggesting replacement of the content covered + by range 0 with NEW_CONTENT. */ + +void +rich_location::add_fixit_replace (const char *new_content) +{ + add_fixit_replace (get_loc (), new_content); +} + +/* Methods for adding "replace" fix-it hints. */ + +/* Add a fixit-hint, suggesting replacement of the content between + the start and finish of WHERE with NEW_CONTENT. */ + +void +rich_location::add_fixit_replace (source_location where, + const char *new_content) +{ + source_range range = get_range_from_loc (m_line_table, where); + add_fixit_replace (range, new_content); } /* Add a fixit-hint, suggesting replacement of the content at @@ -2109,9 +2317,87 @@ void rich_location::add_fixit_replace (source_range src_range, const char *new_content) { - linemap_assert (m_num_fixit_hints < MAX_FIXIT_HINTS); - m_fixit_hints[m_num_fixit_hints++] - = new fixit_replace (src_range, new_content); + src_range.m_start = get_pure_location (m_line_table, src_range.m_start); + src_range.m_finish = get_pure_location (m_line_table, src_range.m_finish); + + if (reject_impossible_fixit (src_range.m_start)) + return; + if (reject_impossible_fixit (src_range.m_finish)) + return; + + /* We do not yet support newlines within fix-it hints. */ + if (strchr (new_content, '\n')) + { + stop_supporting_fixits (); + return; + } + + /* Consolidate neighboring fixits. */ + fixit_hint *prev = get_last_fixit_hint (); + if (prev) + if (prev->maybe_append_replace (m_line_table, src_range, new_content)) + return; + + add_fixit (new fixit_replace (src_range, new_content)); +} + +/* Get the last fix-it hint within this rich_location, or NULL if none. */ + +fixit_hint * +rich_location::get_last_fixit_hint () const +{ + if (m_fixit_hints.count () > 0) + return get_fixit_hint (m_fixit_hints.count () - 1); + else + return NULL; +} + +/* If WHERE is an "awkward" location, then mark this rich_location as not + supporting fixits, purging any thay were already added, and return true. + + Otherwise (the common case), return false. */ + +bool +rich_location::reject_impossible_fixit (source_location where) +{ + /* Fix-its within a rich_location should either all be suggested, or + none of them should be suggested. + Once we've rejected a fixit, we reject any more, even those + with reasonable locations. */ + if (m_seen_impossible_fixit) + return true; + + if (where <= LINE_MAP_MAX_LOCATION_WITH_COLS) + /* WHERE is a reasonable location for a fix-it; don't reject it. */ + return false; + + /* Otherwise we have an attempt to add a fix-it with an "awkward" + location: either one that we can't obtain column information + for (within an ordinary map), or one within a macro expansion. */ + stop_supporting_fixits (); + return true; +} + +/* Mark this rich_location as not supporting fixits, purging any that were + already added. */ + +void +rich_location::stop_supporting_fixits () +{ + m_seen_impossible_fixit = true; + + /* Purge the rich_location of any fix-its that were already added. */ + for (unsigned int i = 0; i < m_fixit_hints.count (); i++) + delete get_fixit_hint (i); + m_fixit_hints.truncate (0); +} + +/* Add HINT to the fix-it hints in this rich_location. */ + +void +rich_location::add_fixit (fixit_hint *hint) +{ + m_fixit_hints.push (hint); } /* class fixit_insert. */ @@ -2132,7 +2418,7 @@ fixit_insert::~fixit_insert () /* Implementation of fixit_hint::affects_line_p for fixit_insert. */ bool -fixit_insert::affects_line_p (const char *file, int line) +fixit_insert::affects_line_p (const char *file, int line) const { expanded_location exploc = linemap_client_expand_location_to_spelling_point (m_where); @@ -2142,19 +2428,13 @@ fixit_insert::affects_line_p (const char *file, int line) return false; } -/* class fixit_remove. */ - -fixit_remove::fixit_remove (source_range src_range) -: m_src_range (src_range) -{ -} - -/* Implementation of fixit_hint::affects_line_p for fixit_remove. */ +/* Implementation of maybe_append_replace for fixit_insert. Reject + the attempt to consolidate fix-its. */ bool -fixit_remove::affects_line_p (const char *file, int line) +fixit_insert::maybe_append_replace (line_maps *, source_range, const char *) { - return m_src_range.intersects_line_p (file, line); + return false; } /* class fixit_replace. */ @@ -2175,7 +2455,30 @@ fixit_replace::~fixit_replace () /* Implementation of fixit_hint::affects_line_p for fixit_replace. */ bool -fixit_replace::affects_line_p (const char *file, int line) +fixit_replace::affects_line_p (const char *file, int line) const { return m_src_range.intersects_line_p (file, line); } + +/* Implementation of maybe_append_replace for fixit_replace. If + possible, merge the new replacement into this one and return true. + Otherwise return false. */ + +bool +fixit_replace::maybe_append_replace (line_maps *set, + source_range src_range, + const char *new_content) +{ + /* Does SRC_RANGE start immediately after this one finishes? */ + if (!column_before_p (set, m_src_range.m_finish, src_range.m_start)) + return false; + + /* We have neighboring replacements; merge them. */ + m_src_range.m_finish = src_range.m_finish; + size_t extra_len = strlen (new_content); + m_bytes = (char *)xrealloc (m_bytes, m_len + extra_len + 1); + memcpy (m_bytes + m_len, new_content, extra_len); + m_len += extra_len; + m_bytes[m_len] = '\0'; + return true; +} |