aboutsummaryrefslogtreecommitdiff
path: root/libcpp/line-map.c
diff options
context:
space:
mode:
authorDavid Malcolm <dmalcolm@redhat.com>2017-05-01 19:15:36 +0000
committerDavid Malcolm <dmalcolm@gcc.gnu.org>2017-05-01 19:15:36 +0000
commit338035aa194405df94875cebb389d593cf9ef00a (patch)
treeec2f1379d4ea93aebee73e038601a72813231176 /libcpp/line-map.c
parent4d82d0bc4350ce18a5fb64049d24e98dee1235f9 (diff)
downloadgcc-338035aa194405df94875cebb389d593cf9ef00a.zip
gcc-338035aa194405df94875cebb389d593cf9ef00a.tar.gz
gcc-338035aa194405df94875cebb389d593cf9ef00a.tar.bz2
Eliminate fixit_hint class hierarchy
The original implementation of fix-it hints (r230674) had an abstract base class "fixit_hint" and three subclasses, representing each of insertions, replacements, and deletions. Having multiple classes for fix-it hints was a nuisance, as it required per-class logic everywhere that the hints were handled. In r239632 I eliminated the deletion subclass in favor of replacement with the empty string (two subclasses are easier than three). This patch eliminates the class hierarchy altogether by implementing insertion in terms of replacement, by representing replacements via a half-open interval (so that for an insertion, start == next location, and we're effectively replacing an empty range at the insertion point with the new string). This greatly simplifies the code for handling fix-it hints; for example it allows removal of a parallel class hierarchy of line_event within edit-context.c. It also improves consolidation of hints: we can now consolidate insertions at the same location, affecting a couple of tests (selftest::test_one_liner_many_fixits and gcc.dg/Wmissing-braces-fixits.c). gcc/ChangeLog: * diagnostic-show-locus.c (layout::get_expanded_location): Rewrite to use new fixit_hint representation, using the "replace" logic. (get_line_span_for_fixit_hint): Likewise. (layout::print_any_fixits): Likewise. (selftest::test_one_liner_many_fixits): Rename to... (selftest::test_one_liner_many_fixits_1): ...this, and update comment and expected output to reflect that the multiple fix-it hints are now consolidated into one insertion. (selftest::test_one_liner_many_fixits_2): New test. (selftest::test_diagnostic_show_locus_one_liner): Update for above. (selftest::test_fixit_consolidation): Update for fix-it API change. * diagnostic.c (print_parseable_fixits): Likewise. * edit-context.c (edited_line::m_line_events): Convert from auto_vec <line_event *> to auto_vec <line_event>. (class line_event): Convert from abstract base class to a concrete class, taking over the role of replace_event. (class insert_event): Delete. (class replace_event): Rename to class line_event. Convert to half-open range. (edit_context::add_fixits): Reimplement. (edit_context::apply_insert): Delete. (edit_context::apply_replace): Rename to... (edit_context::apply_fixit): ...this. Convert to half-open range. (edited_file::apply_insert): Delete. (edited_file::apply_replace): Rename to... (edited_file::apply_fixit): ...this. (edited_line::~edited_line): Drop deletion of events. (edited_line::apply_insert): Delete. (edited_line::apply_replace): Rename to... (edited_line::apply_fixit): ...this. Convert to half-open range. Update for change to type of m_line_events. * edit-context.h (edit_context::apply_insert): Delete. (edit_context::apply_replace): Rename to... (edit_context::apply_fixit): ...this. gcc/testsuite/ChangeLog: * gcc.dg/Wmissing-braces-fixits.c: Update expected output to reflect insertion fix-it hints at the same location now being consolidated. libcpp/ChangeLog: * include/line-map.h (source_range::intersects_line_p): Delete. (rich_location::add_fixit): Delete. (rich_location::maybe_add_fixit): New method. (class fixit_hint): Reimplement in terms of... (class fixit_replace): ...this. (class fixit_insert): Delete. * line-map.c (linemap_position_for_loc_and_offset): Drop overzealous linemap_assert_fails. (source_range::intersects_line_p): Rename to... (fixit_hint::affects_line_p): New function. (rich_location::add_fixit_insert_before): Reimplement in terms of maybe_add_fixit, moving validation there. (rich_location::add_fixit_insert_after): Likewise. (column_before_p): Delete. (rich_location::add_fixit_replace): Reimplement in terms of maybe_add_fixit, moving validation there. Convert closed input range to half-open range. (rich_location::add_fixit): Delete. (rich_location::maybe_add_fixit): New function. (fixit_insert::fixit_insert): Delete. (fixit_insert::~fixit_insert): Delete. (fixit_insert::affects_line_p): Delete. (fixit_insert::maybe_append_replace): Delete. (fixit_replace::fixit_replace): Rename to... (fixit_hint::fixit_hint): ...this, rewriting as necessary. (fixit_replace::~fixit_replace): Delete. (fixit_replace::affects_line_p): Delete. (fixit_replace::maybe_append_replace): Rename to... (fixit_hint::maybe_append): ...this, rewriting as necessary. From-SVN: r247445
Diffstat (limited to 'libcpp/line-map.c')
-rw-r--r--libcpp/line-map.c218
1 files changed, 67 insertions, 151 deletions
diff --git a/libcpp/line-map.c b/libcpp/line-map.c
index 949489e..176e58d 100644
--- a/libcpp/line-map.c
+++ b/libcpp/line-map.c
@@ -881,8 +881,7 @@ linemap_position_for_loc_and_offset (struct line_maps *set,
loc = set->location_adhoc_data_map.data[loc & MAX_SOURCE_LOCATION].locus;
/* This function does not support virtual locations yet. */
- if (linemap_assert_fails
- (!linemap_location_from_macro_expansion_p (set, loc)))
+ if (linemap_location_from_macro_expansion_p (set, loc))
return loc;
if (column_offset == 0
@@ -2003,28 +2002,6 @@ line_table_dump (FILE *stream, struct line_maps *set, unsigned int num_ordinary,
}
}
-/* struct source_range. */
-
-/* Is there any part of this range on the given line? */
-
-bool
-source_range::intersects_line_p (const char *file, int line) const
-{
- expanded_location exploc_start
- = linemap_client_expand_location_to_spelling_point (m_start);
- if (file != exploc_start.file)
- return false;
- if (line < exploc_start.line)
- return false;
- expanded_location exploc_finish
- = linemap_client_expand_location_to_spelling_point (m_finish);
- if (file != exploc_finish.file)
- return false;
- if (line > exploc_finish.line)
- return false;
- return true;
-}
-
/* class rich_location. */
/* Construct a rich_location with location LOC as its initial range. */
@@ -2173,16 +2150,7 @@ 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));
+ maybe_add_fixit (start, start, new_content);
}
/* Add a fixit-hint, suggesting insertion of NEW_CONTENT
@@ -2202,10 +2170,6 @@ 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);
@@ -2217,7 +2181,7 @@ rich_location::add_fixit_insert_after (source_location where,
return;
}
- add_fixit (new fixit_insert (next_loc, new_content));
+ maybe_add_fixit (next_loc, next_loc, new_content);
}
/* Methods for adding removal fix-it hints. */
@@ -2250,44 +2214,6 @@ rich_location::add_fixit_remove (source_range 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. */
@@ -2317,28 +2243,22 @@ void
rich_location::add_fixit_replace (source_range src_range,
const char *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;
+ source_location start = get_pure_location (m_line_table, src_range.m_start);
+ source_location finish = get_pure_location (m_line_table, src_range.m_finish);
- /* We do not yet support newlines within fix-it hints. */
- if (strchr (new_content, '\n'))
+ /* Fix-it hints use half-closed ranges, so attempt to offset the endpoint. */
+ 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;
}
+ finish = next_loc;
- /* 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));
+ maybe_add_fixit (start, finish, new_content);
}
/* Get the last fix-it hint within this rich_location, or NULL if none. */
@@ -2392,89 +2312,85 @@ rich_location::stop_supporting_fixits ()
m_fixit_hints.truncate (0);
}
-/* Add HINT to the fix-it hints in this rich_location. */
+/* Add HINT to the fix-it hints in this rich_location,
+ consolidating into the prior fixit if possible. */
void
-rich_location::add_fixit (fixit_hint *hint)
+rich_location::maybe_add_fixit (source_location start,
+ source_location next_loc,
+ const char *new_content)
{
- m_fixit_hints.push (hint);
-}
-
-/* class fixit_insert. */
-
-fixit_insert::fixit_insert (source_location where,
- const char *new_content)
-: m_where (where),
- m_bytes (xstrdup (new_content)),
- m_len (strlen (new_content))
-{
-}
-
-fixit_insert::~fixit_insert ()
-{
- free (m_bytes);
-}
-
-/* Implementation of fixit_hint::affects_line_p for fixit_insert. */
+ if (reject_impossible_fixit (start))
+ return;
+ if (reject_impossible_fixit (next_loc))
+ return;
-bool
-fixit_insert::affects_line_p (const char *file, int line) const
-{
- expanded_location exploc
- = linemap_client_expand_location_to_spelling_point (m_where);
- if (file == exploc.file)
- if (line == exploc.line)
- return true;
- return false;
-}
+ /* We do not yet support newlines within fix-it hints. */
+ if (strchr (new_content, '\n'))
+ {
+ stop_supporting_fixits ();
+ return;
+ }
-/* Implementation of maybe_append_replace for fixit_insert. Reject
- the attempt to consolidate fix-its. */
+ /* Consolidate neighboring fixits. */
+ fixit_hint *prev = get_last_fixit_hint ();
+ if (prev)
+ if (prev->maybe_append (start, next_loc, new_content))
+ return;
-bool
-fixit_insert::maybe_append_replace (line_maps *, source_range, const char *)
-{
- return false;
+ m_fixit_hints.push (new fixit_hint (start, next_loc, new_content));
}
-/* class fixit_replace. */
+/* class fixit_hint. */
-fixit_replace::fixit_replace (source_range src_range,
- const char *new_content)
-: m_src_range (src_range),
+fixit_hint::fixit_hint (source_location start,
+ source_location next_loc,
+ const char *new_content)
+: m_start (start),
+ m_next_loc (next_loc),
m_bytes (xstrdup (new_content)),
m_len (strlen (new_content))
{
}
-fixit_replace::~fixit_replace ()
-{
- free (m_bytes);
-}
-
-/* Implementation of fixit_hint::affects_line_p for fixit_replace. */
+/* Does this fix-it hint affect the given line? */
bool
-fixit_replace::affects_line_p (const char *file, int line) const
+fixit_hint::affects_line_p (const char *file, int line) const
{
- return m_src_range.intersects_line_p (file, line);
+ expanded_location exploc_start
+ = linemap_client_expand_location_to_spelling_point (m_start);
+ if (file != exploc_start.file)
+ return false;
+ if (line < exploc_start.line)
+ return false;
+ expanded_location exploc_next_loc
+ = linemap_client_expand_location_to_spelling_point (m_next_loc);
+ if (file != exploc_next_loc.file)
+ return false;
+ if (line > exploc_next_loc.line)
+ return false;
+ return true;
}
-/* Implementation of maybe_append_replace for fixit_replace. If
- possible, merge the new replacement into this one and return true.
+/* Method for consolidating fix-it hints, for use by
+ rich_location::maybe_add_fixit.
+ If possible, merge a pending fix-it hint with the given params
+ 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)
+fixit_hint::maybe_append (source_location start,
+ source_location next_loc,
+ 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))
+ /* For consolidation to be possible, START must be at this hint's
+ m_next_loc. */
+ if (start != m_next_loc)
return false;
- /* We have neighboring replacements; merge them. */
- m_src_range.m_finish = src_range.m_finish;
+ /* If so, we have neighboring replacements; merge them. */
+ m_next_loc = next_loc;
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);