summaryrefslogtreecommitdiff
path: root/libcpp/line-map.c
diff options
context:
space:
mode:
authordmalcolm <dmalcolm@138bc75d-0d04-0410-961f-82ee72b054a4>2015-11-20 20:08:47 +0000
committerdmalcolm <dmalcolm@138bc75d-0d04-0410-961f-82ee72b054a4>2015-11-20 20:08:47 +0000
commit734caf844448fdbacd488ee19b96e20c751fe063 (patch)
treef65f921f35a1b100513886cbde83b0f1b31e72d9 /libcpp/line-map.c
parent219e09fcec6667d6af390f8a361927bdc069d720 (diff)
downloadgcc-734caf844448fdbacd488ee19b96e20c751fe063.tar.gz
PR 62314: add ability to add fixit-hints to a diagnostic
This is the combination of two patches: [PATCH 01/02] PR/62314: add ability to add fixit-hints [PATCH 02/02] C FE: add fix-it hint for . vs -> gcc/ChangeLog: PR 62314 * diagnostic-show-locus.c (colorizer::set_fixit_hint): New. (class layout): Update comment (layout::print_any_fixits): New method. (layout::move_to_column): New method. (diagnostic_show_locus): Add call to layout.print_any_fixits. gcc/c/ChangeLog: PR 62314 * c-typeck.c (should_suggest_deref_p): New function. (build_component_ref): Special-case POINTER_TYPE when generating a "not a structure of union" error message, and suggest a "->" rather than a ".", providing a fix-it hint. gcc/testsuite/ChangeLog: PR 62314 * gcc.dg/fixits.c: New file. * gcc.dg/plugin/diagnostic-test-show-locus-ascii-bw.c (test_fixit_insert): New. (test_fixit_remove): New. (test_fixit_replace): New. * gcc.dg/plugin/diagnostic-test-show-locus-ascii-color.c (test_fixit_insert): New. (test_fixit_remove): New. (test_fixit_replace): New. * gcc.dg/plugin/diagnostic_plugin_test_show_locus.c (test_show_locus): Add tests of rendering fixit hints. libcpp/ChangeLog: PR 62314 * include/line-map.h (source_range::intersects_line_p): New method. (rich_location::~rich_location): New. (rich_location::add_fixit_insert): New method. (rich_location::add_fixit_remove): New method. (rich_location::add_fixit_replace): New method. (rich_location::get_num_fixit_hints): New accessor. (rich_location::get_fixit_hint): New accessor. (rich_location::MAX_FIXIT_HINTS): New constant. (rich_location::m_num_fixit_hints): New field. (rich_location::m_fixit_hints): New field. (class fixit_hint): New class. (class fixit_insert): New class. (class fixit_remove): New class. (class fixit_replace): New class. * line-map.c (source_range::intersects_line_p): New method. (rich_location::rich_location): Add initialization of m_num_fixit_hints to both ctors. (rich_location::~rich_location): New. (rich_location::add_fixit_insert): New method. (rich_location::add_fixit_remove): New method. (rich_location::add_fixit_replace): New method. (fixit_insert::fixit_insert): New. (fixit_insert::~fixit_insert): New. (fixit_insert::affects_line_p): New. (fixit_remove::fixit_remove): New. (fixit_remove::affects_line_p): New. (fixit_replace::fixit_replace): New. (fixit_replace::~fixit_replace): New. (fixit_replace::affects_line_p): New. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@230674 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libcpp/line-map.c')
-rw-r--r--libcpp/line-map.c136
1 files changed, 134 insertions, 2 deletions
diff --git a/libcpp/line-map.c b/libcpp/line-map.c
index c5aa4223b1b..42843038e3b 100644
--- a/libcpp/line-map.c
+++ b/libcpp/line-map.c
@@ -1947,6 +1947,28 @@ 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. */
@@ -1954,7 +1976,8 @@ line_table_dump (FILE *stream, struct line_maps *set, unsigned int num_ordinary,
rich_location::rich_location (line_maps *set, source_location loc) :
m_loc (loc),
m_num_ranges (0),
- m_have_expanded_location (false)
+ m_have_expanded_location (false),
+ m_num_fixit_hints (0)
{
/* Set up the 0th range, extracting any range from LOC. */
source_range src_range = get_range_from_loc (set, loc);
@@ -1968,12 +1991,21 @@ rich_location::rich_location (line_maps *set, source_location loc) :
rich_location::rich_location (source_range src_range)
: m_loc (src_range.m_start),
m_num_ranges (0),
- m_have_expanded_location (false)
+ m_have_expanded_location (false),
+ m_num_fixit_hints (0)
{
/* Set up the 0th range: */
add_range (src_range, true);
}
+/* The destructor for class rich_location. */
+
+rich_location::~rich_location ()
+{
+ for (unsigned int i = 0; i < m_num_fixit_hints; i++)
+ delete m_fixit_hints[i];
+}
+
/* Get an expanded_location for this rich_location's primary
location. */
@@ -2077,3 +2109,103 @@ rich_location::set_range (unsigned int idx, source_range src_range,
m_have_expanded_location = false;
}
}
+
+/* Add a fixit-hint, suggesting insertion of NEW_CONTENT
+ at WHERE. */
+
+void
+rich_location::add_fixit_insert (source_location where,
+ 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 a fixit-hint, suggesting removal of the content at
+ SRC_RANGE. */
+
+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 a fixit-hint, suggesting replacement of the content at
+ SRC_RANGE with NEW_CONTENT. */
+
+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);
+}
+
+/* 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. */
+
+bool
+fixit_insert::affects_line_p (const char *file, int line)
+{
+ expanded_location exploc
+ = linemap_client_expand_location_to_spelling_point (m_where);
+ if (file == exploc.file)
+ if (line == exploc.line)
+ return true;
+ 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. */
+
+bool
+fixit_remove::affects_line_p (const char *file, int line)
+{
+ return m_src_range.intersects_line_p (file, line);
+}
+
+/* class fixit_replace. */
+
+fixit_replace::fixit_replace (source_range src_range,
+ const char *new_content)
+: m_src_range (src_range),
+ 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. */
+
+bool
+fixit_replace::affects_line_p (const char *file, int line)
+{
+ return m_src_range.intersects_line_p (file, line);
+}