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] = { 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-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] = { 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_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

Reply via email to