diff options
author | David Malcolm <dmalcolm@redhat.com> | 2015-11-20 20:08:47 +0000 |
---|---|---|
committer | David Malcolm <dmalcolm@gcc.gnu.org> | 2015-11-20 20:08:47 +0000 |
commit | a87a86e1e97610650fb4305edc76a8f4a399a46e (patch) | |
tree | f65f921f35a1b100513886cbde83b0f1b31e72d9 /libcpp | |
parent | 48a78aee68fe0d88f01fcdef61782b4f8008f651 (diff) | |
download | gcc-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/ChangeLog | 34 | ||||
-rw-r--r-- | libcpp/include/line-map.h | 96 | ||||
-rw-r--r-- | libcpp/line-map.c | 136 |
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); +} |