aboutsummaryrefslogtreecommitdiff
path: root/libcpp
diff options
context:
space:
mode:
authorDavid Malcolm <dmalcolm@redhat.com>2015-11-20 20:08:47 +0000
committerDavid Malcolm <dmalcolm@gcc.gnu.org>2015-11-20 20:08:47 +0000
commita87a86e1e97610650fb4305edc76a8f4a399a46e (patch)
treef65f921f35a1b100513886cbde83b0f1b31e72d9 /libcpp
parent48a78aee68fe0d88f01fcdef61782b4f8008f651 (diff)
downloadgcc-a87a86e1e97610650fb4305edc76a8f4a399a46e.zip
gcc-a87a86e1e97610650fb4305edc76a8f4a399a46e.tar.gz
gcc-a87a86e1e97610650fb4305edc76a8f4a399a46e.tar.bz2
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. From-SVN: r230674
Diffstat (limited to 'libcpp')
-rw-r--r--libcpp/ChangeLog34
-rw-r--r--libcpp/include/line-map.h96
-rw-r--r--libcpp/line-map.c136
3 files changed, 264 insertions, 2 deletions
diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog
index ce294ae88..78a0d7c 100644
--- a/libcpp/ChangeLog
+++ b/libcpp/ChangeLog
@@ -1,3 +1,37 @@
+2015-11-20 David Malcolm <dmalcolm@redhat.com>
+
+ 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.
+
2015-11-19 Jakub Jelinek <jakub@redhat.com>
PR preprocessor/60736
diff --git a/libcpp/include/line-map.h b/libcpp/include/line-map.h
index e7608f1..4f440fa 100644
--- a/libcpp/include/line-map.h
+++ b/libcpp/include/line-map.h
@@ -299,6 +299,9 @@ struct GTY(()) source_range
result.m_finish = loc;
return result;
}
+
+ /* Is there any part of this range on the given line? */
+ bool intersects_line_p (const char *file, int line) const;
};
/* Memory allocation function typedef. Works like xrealloc. */
@@ -1267,6 +1270,11 @@ struct location_range
expanded_location m_caret;
};
+class fixit_hint;
+ class fixit_insert;
+ class fixit_remove;
+ class fixit_replace;
+
/* A "rich" source code location, for use when printing diagnostics.
A rich_location has one or more ranges, each optionally with
a caret. Typically the zeroth range has a caret; other ranges
@@ -1349,6 +1357,9 @@ class rich_location
/* Constructing from a source_range. */
rich_location (source_range src_range);
+ /* Destructor. */
+ ~rich_location ();
+
/* Accessors. */
source_location get_loc () const { return m_loc; }
@@ -1381,8 +1392,24 @@ class rich_location
void
override_column (int column);
+ /* Fix-it hints. */
+ void
+ add_fixit_insert (source_location where,
+ const char *new_content);
+
+ void
+ add_fixit_remove (source_range src_range);
+
+ void
+ add_fixit_replace (source_range src_range,
+ const char *new_content);
+
+ unsigned int get_num_fixit_hints () const { return m_num_fixit_hints; }
+ fixit_hint *get_fixit_hint (int idx) const { return m_fixit_hints[idx]; }
+
public:
static const int MAX_RANGES = 3;
+ static const int MAX_FIXIT_HINTS = 2;
protected:
source_location m_loc;
@@ -1392,8 +1419,77 @@ protected:
bool m_have_expanded_location;
expanded_location m_expanded_location;
+
+ unsigned int m_num_fixit_hints;
+ fixit_hint *m_fixit_hints[MAX_FIXIT_HINTS];
+};
+
+class fixit_hint
+{
+public:
+ enum kind {INSERT, REMOVE, REPLACE};
+
+ virtual ~fixit_hint () {}
+
+ virtual enum kind get_kind () const = 0;
+ virtual bool affects_line_p (const char *file, int line) = 0;
+};
+
+class fixit_insert : public fixit_hint
+{
+ public:
+ fixit_insert (source_location where,
+ const char *new_content);
+ ~fixit_insert ();
+ enum kind get_kind () const { return INSERT; }
+ bool affects_line_p (const char *file, int line);
+
+ source_location get_location () const { return m_where; }
+ const char *get_string () const { return m_bytes; }
+ size_t get_length () const { return m_len; }
+
+ private:
+ source_location m_where;
+ char *m_bytes;
+ size_t m_len;
+};
+
+class fixit_remove : public fixit_hint
+{
+ public:
+ fixit_remove (source_range src_range);
+ ~fixit_remove () {}
+
+ enum kind get_kind () const { return REMOVE; }
+ bool affects_line_p (const char *file, int line);
+
+ source_range get_range () const { return m_src_range; }
+
+ private:
+ source_range m_src_range;
};
+class fixit_replace : public fixit_hint
+{
+ public:
+ fixit_replace (source_range src_range,
+ const char *new_content);
+ ~fixit_replace ();
+
+ enum kind get_kind () const { return REPLACE; }
+ bool affects_line_p (const char *file, int line);
+
+ source_range get_range () const { return m_src_range; }
+ const char *get_string () const { return m_bytes; }
+ size_t get_length () const { return m_len; }
+
+ private:
+ source_range m_src_range;
+ char *m_bytes;
+ size_t m_len;
+};
+
+
/* This is enum is used by the function linemap_resolve_location
below. The meaning of the values is explained in the comment of
that function. */
diff --git a/libcpp/line-map.c b/libcpp/line-map.c
index c5aa422..4284303 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);
+}