This patch adds the ability to add "fix-it hints" to a rich_location,
which will be displayed when the corresponding diagnostic is printed.
It does not actually add any fix-it hints (that comes in a later
patch), but it adds test coverage of the machinery and printing,
by using the existing diagnostic_plugin_test_show_locus to inject
some meaningless fixit hints, and to verify the output.
gcc/ChangeLog:
PR/62314
* diagnostic-show-locus.c (colorizer::set_fixit_hint): New.
(layout::move_to_column): New method.
(layout::print_line): Print any fixit hints affecting the line.
For now, add nasty linker kludge for the sake of
diagnostic_plugin_test_show_locus.
gcc/testsuite/ChangeLog:
PR/62314
* 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-test-show-locus-utf-8-bw.c
(test_fixit_insert): New.
(test_fixit_remove): New.
(test_fixit_replace): New.
* gcc.dg/plugin/diagnostic-test-show-locus-utf-8-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::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): Delete the fixit hints.
(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.
---
gcc/diagnostic-show-locus.c | 111 +++++++++++++++++-
.../plugin/diagnostic-test-show-locus-ascii-bw.c | 43 +++++++
.../diagnostic-test-show-locus-ascii-color.c | 43 +++++++
.../plugin/diagnostic-test-show-locus-utf-8-bw.c | 43 +++++++
.../diagnostic-test-show-locus-utf-8-color.c | 43 +++++++
.../plugin/diagnostic_plugin_test_show_locus.c | 35 ++++++
libcpp/include/line-map.h | 93 +++++++++++++++
libcpp/line-map.c | 130 ++++++++++++++++++++-
8 files changed, 538 insertions(+), 3 deletions(-)
diff --git a/gcc/diagnostic-show-locus.c b/gcc/diagnostic-show-locus.c
index 9216c4c..0f58f6c 100644
--- a/gcc/diagnostic-show-locus.c
+++ b/gcc/diagnostic-show-locus.c
@@ -271,6 +271,7 @@ class colorizer
void set_range (int range_idx) { set_state (range_idx); }
void set_normal_text () { set_state (STATE_NORMAL_TEXT); }
+ void set_fixit_hint () { set_state (0); }
private:
void set_state (int state);
@@ -353,6 +354,9 @@ class layout
void
print_any_margin (int line, int column, enum print_line_kind kind);
+ void
+ move_to_column (int *column, int dest_column);
+
private:
diagnostic_context *m_context;
pretty_printer *m_pp;
@@ -635,7 +639,10 @@ layout::layout (diagnostic_context * context,
describing the ranges.
Both lines (1) and (2) may contain a right-most margin containing a
- vertical bar and a caption, describing a range. */
+ vertical bar and a caption, describing a range.
+
+ In addition, if there are fixit hints affecting this source line,
+ there will be one or more further lines printed, showing them. */
void
layout::print_line (int row)
@@ -749,6 +756,87 @@ layout::print_line (int row)
}
print_any_margin (row, x_bound, PRINT_LINE_KIND_ANNOTATION);
pp_newline (m_pp);
+
+ /* Step 3: if there are any fixit hints on this source line, print them.
+ They are printed in order, attempting to combine them onto lines, but
+ starting new lines if necessary. */
+ column = 0;
+
+ for (unsigned int i = 0; i < m_richloc->get_num_fixit_hints (); i++)
+ {
+ fixit_hint *hint = m_richloc->get_fixit_hint (i);
+ if (hint->affects_line_p (m_exploc.file, row))
+ {
+ /* For now we assume each fixit hint can only touch one line. */
+ switch (hint->get_kind ())
+ {
+ case fixit_hint::INSERT:
+ {
+ fixit_insert *insert = static_cast <fixit_insert *> (hint);
+ /* This assumes the insertion just affects one line. */
+ int start_column
+ = LOCATION_COLUMN (insert->get_location ());
+ move_to_column (&column, start_column);
+ m_colorizer.set_fixit_hint ();
+ pp_string (m_pp, insert->get_string ());
+ m_colorizer.set_normal_text ();
+ column += insert->get_length ();
+ }
+ break;
+
+ case fixit_hint::REMOVE:
+ {
+ fixit_remove *remove = static_cast <fixit_remove *> (hint);
+ /* This assumes the removal just affects one line. */
+ source_range src_range = remove->get_range ();
+ int start_column = LOCATION_COLUMN (src_range.m_start);
+ int finish_column = LOCATION_COLUMN (src_range.m_finish);
+ move_to_column (&column, start_column);
+ for (int column = start_column; column <= finish_column;
column++)
+ {
+ m_colorizer.set_fixit_hint ();
+ pp_character (m_pp, '-');
+ m_colorizer.set_normal_text ();
+ }
+ }
+ break;
+
+ case fixit_hint::REPLACE:
+ {
+ fixit_replace *replace = static_cast <fixit_replace *> (hint);
+ int start_column
+ = LOCATION_COLUMN (replace->get_range ().m_start);
+ move_to_column (&column, start_column);
+ m_colorizer.set_fixit_hint ();
+ pp_string (m_pp, replace->get_string ());
+ m_colorizer.set_normal_text ();
+ column += replace->get_length ();
+ }
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+ }
+ }
+
+ /* Nasty workaround to convince the linker to add
+ rich_location::add_fixit_insert
+ rich_location::add_fixit_remove
+ rich_location::add_fixit_replace
+ to cc1 for use by diagnostic_plugin_test_show_locus,
+ before anything in cc1 is using them.
+
+ This conditional should never hold, but hopefully the compiler can't
+ figure that out. */
+ if (0 == strcmp ("grotesque linking kludge", g_line_art.default_caret))
+ {
+ m_richloc->add_fixit_insert (UNKNOWN_LOCATION, "");
+ m_richloc->add_fixit_remove
+ (source_range::from_location (UNKNOWN_LOCATION));
+ m_richloc->add_fixit_replace
+ (source_range::from_location (UNKNOWN_LOCATION), "");
+ }
}
/* Given a line of source code, get the per_range_info for the first range
@@ -825,6 +913,27 @@ layout::print_any_margin (int line, int column, enum
print_line_kind kind)
pp_string (m_pp, g_line_art.rmargin_vbar);
}
+/* Given *COLUMN as an x-coordinate, print spaces to position
+ successive output at DEST_COLUMN, printing a newline if necessary,
+ and updating *COLUMN. */
+
+void
+layout::move_to_column (int *column, int dest_column)
+{
+ /* Start a new line if we need to. */
+ if (*column > dest_column)
+ {
+ pp_newline (m_pp);
+ *column = 0;
+ }
+
+ while (*column < dest_column)
+ {
+ pp_space (m_pp);
+ (*column)++;
+ }
+}
+
} /* End of anonymous namespace. */
/* For debugging layout issues in diagnostic_show_locus and friends,
diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-ascii-bw.c
b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-ascii-bw.c
index 8ffe2e0..8aef89d 100644
--- a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-ascii-bw.c
+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-ascii-bw.c
@@ -112,3 +112,46 @@ void test6 (void)
{ dg-end-multiline-output "" } */
#endif
}
+
+/* Unit test for rendering of insertion fixit hints
+ (example taken from PR 62316). */
+
+void test_fixit_insert (void)
+{
+#if 0
+ int a[2][2] = { 0, 1 , 2, 3 }; /* { dg-warning "insertion hints" } */
+/* { dg-begin-multiline-output "" }
+ int a[2][2] = { 0, 1 , 2, 3 };
+ ^~~~
+ { }
+ { dg-end-multiline-output "" } */
+#endif
+}
+
+/* Unit test for rendering of "remove" fixit hints. */
+
+void test_fixit_remove (void)
+{
+#if 0
+ int a;; /* { dg-warning "example of a removal hint" } */
+/* { dg-begin-multiline-output "" }
+ int a;;
+ ^
+ -
+ { dg-end-multiline-output "" } */
+#endif
+}
+
+/* Unit test for rendering of "replace" fixit hints. */
+
+void test_fixit_replace (void)
+{
+#if 0
+ gtk_widget_showall (dlg); /* { dg-warning "example of a replacement hint" }
*/
+/* { dg-begin-multiline-output "" }
+ gtk_widget_showall (dlg);
+ ^~~~~~~~~~~~~~~~~~
+ gtk_widget_show_all
+ { dg-end-multiline-output "" } */
+#endif
+}
diff --git
a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-ascii-color.c
b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-ascii-color.c
index dba851d..f261e2a 100644
--- a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-ascii-color.c
+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-ascii-color.c
@@ -33,3 +33,46 @@ void test2 (void)
{ dg-end-multiline-output "" } */
#endif
}
+
+/* Unit test for rendering of insertion fixit hints
+ (example taken from PR 62316). */
+
+void test_fixit_insert (void)
+{
+#if 0
+ int a[2][2] = { 0, 1 , 2, 3 }; /* { dg-warning "insertion hints" } */
+/* { dg-begin-multiline-output "" }
+ int a[2][2] = { [01;35m[K0, 1[m[K , 2, 3 };
+ [01;35m[K^~~~
+ {[m[K [01;35m[K}[m[K
+ { dg-end-multiline-output "" } */
+#endif
+}
+
+/* Unit test for rendering of "remove" fixit hints. */
+
+void test_fixit_remove (void)
+{
+#if 0
+ int a;; /* { dg-warning "example of a removal hint" } */
+/* { dg-begin-multiline-output "" }
+ int a;[01;35m[K;[m[K
+ [01;35m[K^
+ -[m[K
+ { dg-end-multiline-output "" } */
+#endif
+}
+
+/* Unit test for rendering of "replace" fixit hints. */
+
+void test_fixit_replace (void)
+{
+#if 0
+ gtk_widget_showall (dlg); /* { dg-warning "example of a replacement hint" }
*/
+/* { dg-begin-multiline-output "" }
+ [01;35m[Kgtk_widget_showall[m[K (dlg);
+ [01;35m[K^~~~~~~~~~~~~~~~~~
+ gtk_widget_show_all[m[K
+ { dg-end-multiline-output "" } */
+#endif
+}
diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-utf-8-bw.c
b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-utf-8-bw.c
index 5fc8395..0e869fb 100644
--- a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-utf-8-bw.c
+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-utf-8-bw.c
@@ -56,3 +56,46 @@ void test6 (void)
{ dg-end-multiline-output "" } */
#endif
}
+
+/* Unit test for rendering of insertion fixit hints
+ (example taken from PR 62316). */
+
+void test_fixit_insert (void)
+{
+#if 0
+ int a[2][2] = { 0, 1 , 2, 3 }; /* { dg-warning "insertion hints" } */
+/* { dg-begin-multiline-output "" }
+ int a[2][2] = { 0, 1 , 2, 3 };
+ ▲───
+ { }
+ { dg-end-multiline-output "" } */
+#endif
+}
+
+/* Unit test for rendering of "remove" fixit hints. */
+
+void test_fixit_remove (void)
+{
+#if 0
+ int a;; /* { dg-warning "example of a removal hint" } */
+/* { dg-begin-multiline-output "" }
+ int a;;
+ ▲
+ -
+ { dg-end-multiline-output "" } */
+#endif
+}
+
+/* Unit test for rendering of "replace" fixit hints. */
+
+void test_fixit_replace (void)
+{
+#if 0
+ gtk_widget_showall (dlg); /* { dg-warning "example of a replacement hint" }
*/
+/* { dg-begin-multiline-output "" }
+ gtk_widget_showall (dlg);
+ ▲─────────────────
+ gtk_widget_show_all
+ { dg-end-multiline-output "" } */
+#endif
+}
diff --git
a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-utf-8-color.c
b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-utf-8-color.c
index a8f4bc3..df861f6 100644
--- a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-utf-8-color.c
+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-utf-8-color.c
@@ -60,3 +60,46 @@ void test6 (void)
{ dg-end-multiline-output "" } */
#endif
}
+
+/* Unit test for rendering of insertion fixit hints
+ (example taken from PR 62316). */
+
+void test_fixit_insert (void)
+{
+#if 0
+ int a[2][2] = { 0, 1 , 2, 3 }; /* { dg-warning "insertion hints" } */
+/* { dg-begin-multiline-output "" }
+ int a[2][2] = { [01;35m[K0, 1[m[K , 2, 3 };
+ [01;35m[K▲───
+ {[m[K [01;35m[K}[m[K
+ { dg-end-multiline-output "" } */
+#endif
+}
+
+/* Unit test for rendering of "remove" fixit hints. */
+
+void test_fixit_remove (void)
+{
+#if 0
+ int a;; /* { dg-warning "example of a removal hint" } */
+/* { dg-begin-multiline-output "" }
+ int a;[01;35m[K;[m[K
+ [01;35m[K▲
+ -[m[K
+ { dg-end-multiline-output "" } */
+#endif
+}
+
+/* Unit test for rendering of "replace" fixit hints. */
+
+void test_fixit_replace (void)
+{
+#if 0
+ gtk_widget_showall (dlg); /* { dg-warning "example of a replacement hint" }
*/
+/* { dg-begin-multiline-output "" }
+ [01;35m[Kgtk_widget_showall[m[K (dlg);
+ [01;35m[K▲─────────────────
+ gtk_widget_show_all[m[K
+ { dg-end-multiline-output "" } */
+#endif
+}
diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_show_locus.c
b/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_show_locus.c
index f724ef4..0162caa 100644
--- a/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_show_locus.c
+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_show_locus.c
@@ -306,6 +306,41 @@ test_show_locus (function *fun)
gcc_rich_location richloc (src_range);
warning_at_rich_loc (&richloc, 0, "test 6");
}
+
+ /* Tests of rendering fixit hints. */
+ if (0 == strcmp (fnname, "test_fixit_insert"))
+ {
+ const int line = fnstart_line + 2;
+ source_range src_range;
+ src_range.m_start = get_loc (line, 19);
+ src_range.m_finish = get_loc (line, 22);
+ gcc_rich_location richloc (src_range);
+ richloc.add_fixit_insert (src_range.m_start, "{");
+ richloc.add_fixit_insert (src_range.m_finish + 1, "}");
+ warning_at_rich_loc (&richloc, 0, "example of insertion hints");
+ }
+
+ if (0 == strcmp (fnname, "test_fixit_remove"))
+ {
+ const int line = fnstart_line + 2;
+ source_range src_range;
+ src_range.m_start = get_loc (line, 8);
+ src_range.m_finish = get_loc (line, 8);
+ gcc_rich_location richloc (src_range);
+ richloc.add_fixit_remove (src_range);
+ warning_at_rich_loc (&richloc, 0, "example of a removal hint");
+ }
+
+ if (0 == strcmp (fnname, "test_fixit_replace"))
+ {
+ const int line = fnstart_line + 2;
+ source_range src_range;
+ src_range.m_start = get_loc (line, 2);
+ src_range.m_finish = get_loc (line, 19);
+ gcc_rich_location richloc (src_range);
+ richloc.add_fixit_replace (src_range, "gtk_widget_show_all");
+ warning_at_rich_loc (&richloc, 0, "example of a replacement hint");
+ }
}
unsigned int
diff --git a/libcpp/include/line-map.h b/libcpp/include/line-map.h
index 53ba68b..2861b42 100644
--- a/libcpp/include/line-map.h
+++ b/libcpp/include/line-map.h
@@ -145,6 +145,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. */
@@ -1097,6 +1100,11 @@ enum buffer_ownership
BUFFER_OWNERSHIP_BORROWED /* Make a copy. */
};
+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 a "primary location", along with zero or more
additional ranges.
@@ -1195,8 +1203,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:
friend class range_iter;
@@ -1208,8 +1232,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;
+};
+
+
inline
rich_location::range_iter::range_iter (rich_location *richloc) :
m_richloc (richloc),
diff --git a/libcpp/line-map.c b/libcpp/line-map.c
index 79d8eee..fec57fc 100644
--- a/libcpp/line-map.c
+++ b/libcpp/line-map.c
@@ -1747,6 +1747,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. */
@@ -1754,7 +1776,8 @@ line_table_dump (FILE *stream, struct line_maps *set,
unsigned int num_ordinary,
rich_location::rich_location (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: */
add_range (loc, loc, true);
@@ -1766,7 +1789,8 @@ rich_location::rich_location (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);
@@ -1778,6 +1802,8 @@ rich_location::~rich_location ()
{
for (unsigned int i = 0; i < m_num_ranges; i++)
free (m_ranges[i].m_caption);
+ for (unsigned int i = 0; i < m_num_fixit_hints; i++)
+ delete m_fixit_hints[i];
}
/* Get the first line of the rich_location, either that of
@@ -1954,3 +1980,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);
+}
--
1.8.5.3