diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 7db3d032079..1a985a3d69a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,29 @@ +2016-06-22 David Malcolm + + * common.opt (fdiagnostics-parseable-fixits): New option. + * diagnostic.c: Include "selftest.h". + (print_escaped_string): New function. + (print_parseable_fixits): New function. + (diagnostic_report_diagnostic): Call print_parseable_fixits. + (selftest::assert_print_escaped_string): New function. + (ASSERT_PRINT_ESCAPED_STRING_STREQ): New macro. + (selftest::test_print_escaped_string): New function. + (selftest::test_print_parseable_fixits_none): New function. + (selftest::test_print_parseable_fixits_insert): New function. + (selftest::test_print_parseable_fixits_remove): New function. + (selftest::test_print_parseable_fixits_replace): New function. + (selftest::diagnostic_c_tests): New function. + * diagnostic.h (struct diagnostic_context): Add field + "parseable_fixits_p". + * doc/invoke.texi (Diagnostic Message Formatting Options): Add + -fdiagnostics-parseable-fixits. + (-fdiagnostics-parseable-fixits): New option. + * opts.c (common_handle_option): Handle + -fdiagnostics-parseable-fixits. + * selftest-run-tests.c (selftest::run_tests): Call + selftest::diagnostic_c_tests. + * selftest.h (selftest::diagnostic_c_tests): New prototype. + 2016-06-22 Ilya Enkovich PR middle-end/71488 diff --git a/gcc/common.opt b/gcc/common.opt index f0d71966cdf..5d90385eaea 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -1185,6 +1185,10 @@ Enum(diagnostic_color_rule) String(always) Value(DIAGNOSTICS_COLOR_YES) EnumValue Enum(diagnostic_color_rule) String(auto) Value(DIAGNOSTICS_COLOR_AUTO) +fdiagnostics-parseable-fixits +Common Var(flag_diagnostics_parseable_fixits) +Print fixit hints in machine-readable form. + fdiagnostics-show-option Common Var(flag_diagnostics_show_option) Init(1) Amend appropriate diagnostic messages with the command line option that controls them. diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c index 8467aaa377d..d39afff6622 100644 --- a/gcc/diagnostic.c +++ b/gcc/diagnostic.c @@ -31,6 +31,7 @@ along with GCC; see the file COPYING3. If not see #include "backtrace.h" #include "diagnostic.h" #include "diagnostic-color.h" +#include "selftest.h" #ifdef HAVE_TERMIOS_H # include @@ -667,6 +668,112 @@ diagnostic_pop_diagnostics (diagnostic_context *context, location_t where) context->n_classification_history ++; } +/* Helper function for print_parseable_fixits. Print TEXT to PP, obeying the + escaping rules for -fdiagnostics-parseable-fixits. */ + +static void +print_escaped_string (pretty_printer *pp, const char *text) +{ + gcc_assert (pp); + gcc_assert (text); + + pp_character (pp, '"'); + for (const char *ch = text; *ch; ch++) + { + switch (*ch) + { + case '\\': + /* Escape backslash as two backslashes. */ + pp_string (pp, "\\\\"); + break; + case '\t': + /* Escape tab as "\t". */ + pp_string (pp, "\\t"); + break; + case '\n': + /* Escape newline as "\n". */ + pp_string (pp, "\\n"); + break; + case '"': + /* Escape doublequotes as \". */ + pp_string (pp, "\\\""); + break; + default: + if (ISPRINT (*ch)) + pp_character (pp, *ch); + else + /* Use octal for non-printable chars. */ + { + unsigned char c = (*ch & 0xff); + pp_printf (pp, "\\%o%o%o", (c / 64), (c / 8) & 007, c & 007); + } + break; + } + } + pp_character (pp, '"'); +} + +/* Implementation of -fdiagnostics-parseable-fixits. Print a + machine-parseable version of all fixits in RICHLOC to PP. */ + +static void +print_parseable_fixits (pretty_printer *pp, rich_location *richloc) +{ + gcc_assert (pp); + gcc_assert (richloc); + + for (unsigned i = 0; i < richloc->get_num_fixit_hints (); i++) + { + const fixit_hint *hint = richloc->get_fixit_hint (i); + source_location start_loc = hint->get_start_loc (); + expanded_location start_exploc = expand_location (start_loc); + pp_string (pp, "fix-it:"); + print_escaped_string (pp, start_exploc.file); + source_location end_loc; + + /* For compatibility with clang, print as a half-open range. */ + if (hint->maybe_get_end_loc (&end_loc)) + { + expanded_location end_exploc = expand_location (end_loc); + pp_printf (pp, ":{%i:%i-%i:%i}:", + start_exploc.line, start_exploc.column, + end_exploc.line, end_exploc.column + 1); + } + else + { + pp_printf (pp, ":{%i:%i-%i:%i}:", + start_exploc.line, start_exploc.column, + start_exploc.line, start_exploc.column); + } + switch (hint->get_kind ()) + { + case fixit_hint::INSERT: + { + const fixit_insert *insert + = static_cast (hint); + print_escaped_string (pp, insert->get_string ()); + } + break; + + case fixit_hint::REMOVE: + print_escaped_string (pp, ""); + break; + + case fixit_hint::REPLACE: + { + const fixit_replace *replace + = static_cast (hint); + print_escaped_string (pp, replace->get_string ()); + } + break; + + default: + gcc_unreachable (); + } + pp_newline (pp); + } +} + /* Report a diagnostic message (an error or a warning) as specified by DC. This function is *the* subroutine in terms of which front-ends should implement their specific diagnostic handling modules. The @@ -828,6 +935,11 @@ diagnostic_report_diagnostic (diagnostic_context *context, (*diagnostic_starter (context)) (context, diagnostic); pp_output_formatted_text (context->printer); (*diagnostic_finalizer (context)) (context, diagnostic); + if (context->parseable_fixits_p) + { + print_parseable_fixits (context->printer, diagnostic->richloc); + pp_flush (context->printer); + } diagnostic_action_after_output (context, diagnostic->kind); diagnostic->message.format_spec = saved_format_spec; diagnostic->x_data = NULL; @@ -1290,3 +1402,149 @@ real_abort (void) { abort (); } + +#if CHECKING_P + +namespace selftest { + +/* Helper function for test_print_escaped_string. */ + +static void +assert_print_escaped_string (const location &loc, const char *expected_output, + const char *input) +{ + pretty_printer pp; + print_escaped_string (&pp, input); + ASSERT_STREQ_AT (loc, expected_output, pp_formatted_text (&pp)); +} + +#define ASSERT_PRINT_ESCAPED_STRING_STREQ(EXPECTED_OUTPUT, INPUT) \ + assert_print_escaped_string (SELFTEST_LOCATION, EXPECTED_OUTPUT, INPUT) + +/* Tests of print_escaped_string. */ + +static void +test_print_escaped_string () +{ + /* Empty string. */ + ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"\"", ""); + + /* Non-empty string. */ + ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"hello world\"", "hello world"); + + /* Various things that need to be escaped: */ + /* Backslash. */ + ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\\\after\"", + "before\\after"); + /* Tab. */ + ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\tafter\"", + "before\tafter"); + /* Newline. */ + ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\nafter\"", + "before\nafter"); + /* Double quote. */ + ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\\"after\"", + "before\"after"); + + /* Non-printable characters: BEL: '\a': 0x07 */ + ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\007after\"", + "before\aafter"); + /* Non-printable characters: vertical tab: '\v': 0x0b */ + ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\013after\"", + "before\vafter"); +} + +/* Tests of print_parseable_fixits. */ + +/* Verify that print_parseable_fixits emits the empty string if there + are no fixits. */ + +static void +test_print_parseable_fixits_none () +{ + pretty_printer pp; + rich_location richloc (line_table, UNKNOWN_LOCATION); + + print_parseable_fixits (&pp, &richloc); + ASSERT_STREQ ("", pp_formatted_text (&pp)); +} + +/* Verify that print_parseable_fixits does the right thing if there + is an insertion fixit hint. */ + +static void +test_print_parseable_fixits_insert () +{ + pretty_printer pp; + rich_location richloc (line_table, UNKNOWN_LOCATION); + + linemap_add (line_table, LC_ENTER, false, "test.c", 0); + linemap_line_start (line_table, 5, 100); + linemap_add (line_table, LC_LEAVE, false, NULL, 0); + location_t where = linemap_position_for_column (line_table, 10); + richloc.add_fixit_insert (where, "added content"); + + print_parseable_fixits (&pp, &richloc); + ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:10}:\"added content\"\n", + pp_formatted_text (&pp)); +} + +/* Verify that print_parseable_fixits does the right thing if there + is an removal fixit hint. */ + +static void +test_print_parseable_fixits_remove () +{ + pretty_printer pp; + rich_location richloc (line_table, UNKNOWN_LOCATION); + + linemap_add (line_table, LC_ENTER, false, "test.c", 0); + linemap_line_start (line_table, 5, 100); + linemap_add (line_table, LC_LEAVE, false, NULL, 0); + source_range where; + where.m_start = linemap_position_for_column (line_table, 10); + where.m_finish = linemap_position_for_column (line_table, 20); + richloc.add_fixit_remove (where); + + print_parseable_fixits (&pp, &richloc); + ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:21}:\"\"\n", + pp_formatted_text (&pp)); +} + +/* Verify that print_parseable_fixits does the right thing if there + is an replacement fixit hint. */ + +static void +test_print_parseable_fixits_replace () +{ + pretty_printer pp; + rich_location richloc (line_table, UNKNOWN_LOCATION); + + linemap_add (line_table, LC_ENTER, false, "test.c", 0); + linemap_line_start (line_table, 5, 100); + linemap_add (line_table, LC_LEAVE, false, NULL, 0); + source_range where; + where.m_start = linemap_position_for_column (line_table, 10); + where.m_finish = linemap_position_for_column (line_table, 20); + richloc.add_fixit_replace (where, "replacement"); + + print_parseable_fixits (&pp, &richloc); + ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:21}:\"replacement\"\n", + pp_formatted_text (&pp)); +} + +/* Run all of the selftests within this file. */ + +void +diagnostic_c_tests () +{ + test_print_escaped_string (); + test_print_parseable_fixits_none (); + test_print_parseable_fixits_insert (); + test_print_parseable_fixits_remove (); + test_print_parseable_fixits_replace (); +} + +} // namespace selftest + +#endif /* #if CHECKING_P */ diff --git a/gcc/diagnostic.h b/gcc/diagnostic.h index 58d77df61c5..afce2850882 100644 --- a/gcc/diagnostic.h +++ b/gcc/diagnostic.h @@ -205,6 +205,10 @@ struct diagnostic_context /* Usable by plugins; if true, print a debugging ruler above the source output. */ bool show_ruler_p; + + /* If true, print fixits in machine-parseable form after the + rest of the diagnostic. */ + bool parseable_fixits_p; }; static inline void diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index fdb65f025a1..2c87c53d3d1 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -246,7 +246,8 @@ Objective-C and Objective-C++ Dialects}. @gccoptlist{-fmessage-length=@var{n} @gol -fdiagnostics-show-location=@r{[}once@r{|}every-line@r{]} @gol -fdiagnostics-color=@r{[}auto@r{|}never@r{|}always@r{]} @gol --fno-diagnostics-show-option -fno-diagnostics-show-caret} +-fno-diagnostics-show-option -fno-diagnostics-show-caret @gol +-fdiagnostics-parseable-fixits} @item Warning Options @xref{Warning Options,,Options to Request or Suppress Warnings}. @@ -3389,6 +3390,37 @@ the @option{-fmessage-length=n} option is given. When the output is done to the terminal, the width is limited to the width given by the @env{COLUMNS} environment variable or, if not set, to the terminal width. +@item -fdiagnostics-parseable-fixits +@opindex fdiagnostics-parseable-fixits +Emit fix-it hints in a machine-parseable format, suitable for consumption +by IDEs. For each fix-it, a line will be printed after the relevant +diagnostic, starting with the string ``fix-it:''. For example: + +@smallexample +fix-it:"test.c":@{45:3-45:21@}:"gtk_widget_show_all" +@end smallexample + +The location is expressed as a half-open range, expressed as a count of +bytes, starting at byte 1 for the initial column. In the above example, +bytes 3 through 20 of line 45 of ``test.c'' are to be replaced with the +given string: + +@smallexample +00000000011111111112222222222 +12345678901234567890123456789 + gtk_widget_showall (dlg); + ^^^^^^^^^^^^^^^^^^ + gtk_widget_show_all +@end smallexample + +The filename and replacement string escape backslash as ``\\", tab as ``\t'', +newline as ``\n'', double quotes as ``\"'', non-printable characters as octal +(e.g. vertical tab as ``\013''). + +An empty replacement string indicates that the given range is to be removed. +An empty range (e.g. ``45:3-45:3'') indicates that the string is to +be inserted at the given position. + @end table @node Warning Options diff --git a/gcc/opts.c b/gcc/opts.c index e80331f4bf5..74062106895 100644 --- a/gcc/opts.c +++ b/gcc/opts.c @@ -1871,6 +1871,10 @@ common_handle_option (struct gcc_options *opts, diagnostic_color_init (dc, value); break; + case OPT_fdiagnostics_parseable_fixits: + dc->parseable_fixits_p = value; + break; + case OPT_fdiagnostics_show_option: dc->show_option_requested = value; break; diff --git a/gcc/selftest-run-tests.c b/gcc/selftest-run-tests.c index d4a9c0b26b8..bddf0b2d9a9 100644 --- a/gcc/selftest-run-tests.c +++ b/gcc/selftest-run-tests.c @@ -59,6 +59,7 @@ selftest::run_tests () /* Higher-level tests, or for components that other selftests don't rely on. */ diagnostic_show_locus_c_tests (); + diagnostic_c_tests (); fold_const_c_tests (); spellcheck_c_tests (); spellcheck_tree_c_tests (); diff --git a/gcc/selftest.h b/gcc/selftest.h index 2bc7316c990..c6becdd01df 100644 --- a/gcc/selftest.h +++ b/gcc/selftest.h @@ -72,6 +72,7 @@ extern void assert_streq (const location &loc, /* Declarations for specific families of tests (by source file), in alphabetical order. */ extern void bitmap_c_tests (); +extern void diagnostic_c_tests (); extern void diagnostic_show_locus_c_tests (); extern void et_forest_c_tests (); extern void fold_const_c_tests (); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 93aad44974d..8cac69489d6 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,17 @@ +2016-06-22 David Malcolm + + * gcc.dg/plugin/diagnostic-test-show-locus-parseable-fixits.c: New + file. + * gcc.dg/plugin/plugin.exp (plugin_test_list): Add + diagnostic-test-show-locus-parseable-fixits.c to sources for + diagnostic_plugin_test_show_locus.c. + * lib/gcc-defs.exp (freeform_regexps): New global. + (dg-regexp): New function. + (handle-dg-regexps): New function. + * lib/gcc-dg.exp (cleanup-after-saved-dg-test): Reset + freeform_regexps to the empty list. + * lib/prune.exp (prune_gcc_output): Call handle-dg-regexps. + 2016-06-22 Ilya Enkovich PR middle-end/71488 diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-parseable-fixits.c b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-parseable-fixits.c new file mode 100644 index 00000000000..1490c981e45 --- /dev/null +++ b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-parseable-fixits.c @@ -0,0 +1,41 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdiagnostics-parseable-fixits" } */ + +/* This is a collection of unittests for diagnostic_show_locus; + see the overview in diagnostic_plugin_test_show_locus.c. + + In particular, note the discussion of why we need a very long line here: +01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 + and that we can't use macros in this file. */ + +/* 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-regexp "fix-it:.*\\{17:20-17:20\\}:.*" } */ +/* { dg-regexp "fix-it:.*\\{17:24-17:24\\}:.*" } */ +#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-regexp "fix-it:.*\\{28:9-28:10\\}:.*" } */ +#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-regexp "fix-it:.*\\{38:3-38:21\\}:.*" } */ +#endif +} diff --git a/gcc/testsuite/gcc.dg/plugin/plugin.exp b/gcc/testsuite/gcc.dg/plugin/plugin.exp index be2ac8dcfcb..f039c8de35f 100644 --- a/gcc/testsuite/gcc.dg/plugin/plugin.exp +++ b/gcc/testsuite/gcc.dg/plugin/plugin.exp @@ -65,7 +65,8 @@ set plugin_test_list [list \ { wide-int_plugin.c wide-int-test-1.c } \ { diagnostic_plugin_test_show_locus.c \ diagnostic-test-show-locus-bw.c \ - diagnostic-test-show-locus-color.c } \ + diagnostic-test-show-locus-color.c \ + diagnostic-test-show-locus-parseable-fixits.c } \ { diagnostic_plugin_test_tree_expression_range.c \ diagnostic-test-expressions-1.c } \ { diagnostic_plugin_show_trees.c \ diff --git a/gcc/testsuite/lib/gcc-defs.exp b/gcc/testsuite/lib/gcc-defs.exp index 0210af8e838..1186e5ba1a3 100644 --- a/gcc/testsuite/lib/gcc-defs.exp +++ b/gcc/testsuite/lib/gcc-defs.exp @@ -352,3 +352,54 @@ proc gcc-set-multilib-library-path { compiler } { return $libpath } + +# A list of all uses of dg-regexp, each entry of the form: +# line-number regexp +# This is cleared at the end of each test by gcc-dg.exp's wrapper for dg-test. +set freeform_regexps [] + +# Directive for looking for a regexp, without any line numbers or other +# prefixes. + +proc dg-regexp { args } { + verbose "dg-regexp: args: $args" 2 + + global freeform_regexps + lappend freeform_regexps $args +} + +# Hook to be called by prune.exp's prune_gcc_output to +# look for the expected dg-regexp expressions, pruning them, +# reporting PASS for those that are found, and FAIL for +# those that weren't found. +# +# It returns a pruned version of its output. + +proc handle-dg-regexps { text } { + global freeform_regexps + global testname_with_flags + + foreach entry $freeform_regexps { + verbose " entry: $entry" 3 + + set linenum [lindex $entry 0] + set rexp [lindex $entry 1] + + # Escape newlines in $rexp so that we can print them in + # pass/fail results. + set escaped_regex [string map {"\n" "\\n"} $rexp] + verbose "escaped_regex: ${escaped_regex}" 4 + + set title "$testname_with_flags dg-regexp $linenum" + + # Use "regsub" to attempt to prune the pattern from $text + if {[regsub -line $rexp $text "" text]} { + # Success; the multiline pattern was pruned. + pass "$title was found: \"$escaped_regex\"" + } else { + fail "$title not found: \"$escaped_regex\"" + } + } + + return $text +} diff --git a/gcc/testsuite/lib/gcc-dg.exp b/gcc/testsuite/lib/gcc-dg.exp index 70391407c01..b7f0ff7838a 100644 --- a/gcc/testsuite/lib/gcc-dg.exp +++ b/gcc/testsuite/lib/gcc-dg.exp @@ -899,6 +899,7 @@ if { [info procs saved-dg-test] == [list] } { global saved_compiler_env_var global keep_saved_temps_suffixes global multiline_expected_outputs + global freeform_regexps set additional_files "" set additional_sources "" @@ -924,6 +925,7 @@ if { [info procs saved-dg-test] == [list] } { unset testname_with_flags } set multiline_expected_outputs [] + set freeform_regexps [] } proc dg-test { args } { diff --git a/gcc/testsuite/lib/prune.exp b/gcc/testsuite/lib/prune.exp index ab6f3697ff8..d3ff4930276 100644 --- a/gcc/testsuite/lib/prune.exp +++ b/gcc/testsuite/lib/prune.exp @@ -73,6 +73,9 @@ proc prune_gcc_output { text } { # Call into multiline.exp to handle any multiline output directives. set text [handle-multiline-outputs $text] + # Handle any freeform regexps. + set text [handle-dg-regexps $text] + #send_user "After:$text\n" return $text diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog index c32b15725f8..65bfe2612e2 100644 --- a/libcpp/ChangeLog +++ b/libcpp/ChangeLog @@ -1,3 +1,21 @@ +2016-06-22 David Malcolm + + * include/line-map.h (fixit_hint::get_start_loc): New pure virtual + function. + (fixit_hint::maybe_get_end_loc): Likewise. + (fixit_insert::get_start_loc): New function, implementing + fixit_hint::get_start_loc. + (fixit_insert::maybe_get_end_loc): New function, implementing + fixit_hint::maybe_get_end_loc. + (fixit_remove::get_start_loc): New function, implementing + fixit_hint::get_start_loc. + (fixit_remove::maybe_get_end_loc): New function, implementing + fixit_hint::maybe_get_end_loc. + (fixit_replace::get_start_loc): New function, implementing + fixit_hint::get_start_loc. + (fixit_replace::maybe_get_end_loc): New function, implementing + fixit_hint::maybe_get_end_loc. + 2016-06-21 John David Anglin * line-map.c (location_adhoc_data_update): Use int64_t instead of diff --git a/libcpp/include/line-map.h b/libcpp/include/line-map.h index 292abce3ec9..416419c59d9 100644 --- a/libcpp/include/line-map.h +++ b/libcpp/include/line-map.h @@ -1418,6 +1418,8 @@ public: virtual enum kind get_kind () const = 0; virtual bool affects_line_p (const char *file, int line) = 0; + virtual source_location get_start_loc () const = 0; + virtual bool maybe_get_end_loc (source_location *out) const = 0; }; class fixit_insert : public fixit_hint @@ -1428,6 +1430,8 @@ class fixit_insert : public fixit_hint ~fixit_insert (); enum kind get_kind () const { return INSERT; } bool affects_line_p (const char *file, int line); + source_location get_start_loc () const { return m_where; } + bool maybe_get_end_loc (source_location *) const { return false; } source_location get_location () const { return m_where; } const char *get_string () const { return m_bytes; } @@ -1447,6 +1451,12 @@ class fixit_remove : public fixit_hint enum kind get_kind () const { return REMOVE; } bool affects_line_p (const char *file, int line); + source_location get_start_loc () const { return m_src_range.m_start; } + bool maybe_get_end_loc (source_location *out) const + { + *out = m_src_range.m_finish; + return true; + } source_range get_range () const { return m_src_range; } @@ -1463,6 +1473,12 @@ class fixit_replace : public fixit_hint enum kind get_kind () const { return REPLACE; } bool affects_line_p (const char *file, int line); + source_location get_start_loc () const { return m_src_range.m_start; } + bool maybe_get_end_loc (source_location *out) const + { + *out = m_src_range.m_finish; + return true; + } source_range get_range () const { return m_src_range; } const char *get_string () const { return m_bytes; }