+2018-04-30 David Malcolm <dmalcolm@redhat.com>
+
+ PR c++/85523
+ * gcc-rich-location.c (blank_line_before_p): New function.
+ (use_new_line): New function.
+ (gcc_rich_location::add_fixit_insert_formatted): New function.
+ * gcc-rich-location.h
+ (gcc_rich_location::add_fixit_insert_formatted): New function.
+
2018-04-30 David Malcolm <dmalcolm@redhat.com>
* selftest.c (assert_streq): Rename "expected" and "actual" to
add_fixit_replace (misspelled_token_loc, IDENTIFIER_POINTER (hint_id));
}
+
+/* Return true if there is nothing on LOC's line before LOC. */
+
+static bool
+blank_line_before_p (location_t loc)
+{
+ expanded_location exploc = expand_location (loc);
+ char_span line = location_get_source_line (exploc.file, exploc.line);
+ if (!line)
+ return false;
+ if (line.length () < (size_t)exploc.column)
+ return false;
+ /* Columns are 1-based. */
+ for (int column = 1; column < exploc.column; ++column)
+ if (!ISSPACE (line[column - 1]))
+ return false;
+ return true;
+}
+
+/* Subroutine of gcc_rich_location::add_fixit_insert_formatted.
+ Return true if we should add the content on its own line,
+ false otherwise.
+ If true is returned then *OUT_START_OF_LINE is written to. */
+
+static bool
+use_new_line (location_t insertion_point, location_t indent,
+ location_t *out_start_of_line)
+{
+ if (indent == UNKNOWN_LOCATION)
+ return false;
+ const line_map *indent_map = linemap_lookup (line_table, indent);
+ if (linemap_macro_expansion_map_p (indent_map))
+ return false;
+
+ if (!blank_line_before_p (insertion_point))
+ return false;
+
+ /* Locate the start of the line containing INSERTION_POINT. */
+ const line_map *insertion_point_map
+ = linemap_lookup (line_table, insertion_point);
+ if (linemap_macro_expansion_map_p (insertion_point_map))
+ return false;
+ const line_map_ordinary *ordmap
+ = linemap_check_ordinary (insertion_point_map);
+ expanded_location exploc_insertion_point = expand_location (insertion_point);
+ location_t start_of_line
+ = linemap_position_for_line_and_column (line_table, ordmap,
+ exploc_insertion_point.line, 1);
+ *out_start_of_line = start_of_line;
+ return true;
+}
+
+/* Add a fix-it hint suggesting the insertion of CONTENT before
+ INSERTION_POINT.
+
+ Attempt to handle formatting: if INSERTION_POINT is the first thing on
+ its line, and INDENT is sufficiently sane, then add CONTENT on its own
+ line, using the indentation of INDENT.
+ Otherwise, add CONTENT directly before INSERTION_POINT.
+
+ For example, adding "CONTENT;" with the closing brace as the insertion
+ point and "INDENT;" as the indentation point:
+
+ if ()
+ {
+ INDENT;
+ }
+
+ would lead to:
+
+ if ()
+ {
+ INDENT;
+ CONTENT;
+ }
+
+ but adding it to:
+
+ if () {INDENT;}
+
+ would lead to:
+
+ if () {INDENT;CONTENT;}
+*/
+
+void
+gcc_rich_location::add_fixit_insert_formatted (const char *content,
+ location_t insertion_point,
+ location_t indent)
+{
+ location_t start_of_line;
+ if (use_new_line (insertion_point, indent, &start_of_line))
+ {
+ /* Add CONTENT on its own line, using the indentation of INDENT. */
+
+ /* Generate an insertion string, indenting by the amount INDENT
+ was indented. */
+ int indent_column = LOCATION_COLUMN (get_start (indent));
+ pretty_printer tmp_pp;
+ pretty_printer *pp = &tmp_pp;
+ /* Columns are 1-based. */
+ for (int column = 1; column < indent_column; ++column)
+ pp_space (pp);
+ pp_string (pp, content);
+ pp_newline (pp);
+
+ add_fixit_insert_before (start_of_line, pp_formatted_text (pp));
+ }
+ else
+ add_fixit_insert_before (insertion_point, content);
+}
Implemented in diagnostic-show-locus.c. */
bool add_location_if_nearby (location_t loc);
+
+ /* Add a fix-it hint suggesting the insertion of CONTENT before
+ INSERTION_POINT.
+
+ Attempt to handle formatting: if INSERTION_POINT is the first thing on
+ its line, and INDENT is sufficiently sane, then add CONTENT on its own
+ line, using the indentation of INDENT.
+ Otherwise, add CONTENT directly before INSERTION_POINT.
+
+ For example, adding "CONTENT;" with the closing brace as the insertion
+ point and using "INDENT;" for indentation:
+
+ if ()
+ {
+ INDENT;
+ }
+
+ would lead to:
+
+ if ()
+ {
+ INDENT;
+ CONTENT;
+ }
+
+ but adding it to:
+
+ if () {INDENT;}
+
+ would lead to:
+
+ if () {INDENT;CONTENT;}
+ */
+ void add_fixit_insert_formatted (const char *content,
+ location_t insertion_point,
+ location_t indent);
};
#endif /* GCC_RICH_LOCATION_H */
+2018-04-30 David Malcolm <dmalcolm@redhat.com>
+
+ PR c++/85523
+ * gcc.dg/plugin/diagnostic-test-show-locus-generate-patch.c
+ (test_add_fixit_insert_formatted_single_line): New function.
+ (test_add_fixit_insert_formatted_multiline): New function.
+ Extend expected output of generated patch to include fix-it hints
+ for these.
+ * gcc.dg/plugin/diagnostic_plugin_test_show_locus.c: Include
+ "gcc-rich-location.h". Add test coverage for
+ gcc_rich_location::add_fixit_insert_formatted.
+
2018-04-30 David Malcolm <dmalcolm@redhat.com>
* gcc.dg/plugin/diagnostic_plugin_test_show_locus.c
#endif
}
+/* Unit tests for add_fixit_insert_formatted. */
+
+void test_add_fixit_insert_formatted_single_line (void)
+{
+ {}
+}
+
+void test_add_fixit_insert_formatted_multiline (void)
+{
+ if (1)
+ {
+ }
+}
+
+
/* Verify the output from -fdiagnostics-generate-patch.
We expect a header, containing the filename. This is the absolute path,
so we can only capture it via regexps. */
case 'b':
x = b;
}
+@@ -68,7 +69,7 @@
+
+ void test_add_fixit_insert_formatted_single_line (void)
+ {
+- {}
++ {INSERTED-CONTENT}
+ }
+
+ void test_add_fixit_insert_formatted_multiline (void)
+@@ -76,6 +77,7 @@
+ if (1)
+ {
+ }
++ INSERTED-CONTENT
+ }
+
+
{ dg-end-multiline-output "" } */
#include "diagnostic.h"
#include "context.h"
#include "print-tree.h"
+#include "gcc-rich-location.h"
int plugin_is_GPL_compatible;
}
}
+ /* Tests of gcc_rich_location::add_fixit_insert_formatted. */
+
+ if (0 == strcmp (fnname, "test_add_fixit_insert_formatted_single_line"))
+ {
+ const int line = fnstart_line + 1;
+ location_t insertion_point = get_loc (line, 3);
+ location_t indent = get_loc (line, 2);
+ gcc_rich_location richloc (insertion_point);
+ richloc.add_fixit_insert_formatted ("INSERTED-CONTENT",
+ insertion_point, indent);
+ inform (&richloc, "single-line insertion");
+ }
+
+ if (0 == strcmp (fnname, "test_add_fixit_insert_formatted_multiline"))
+ {
+ location_t insertion_point = fun->function_end_locus;
+ location_t indent = get_loc (fnstart_line + 1, 2);
+ gcc_rich_location richloc (insertion_point);
+ richloc.add_fixit_insert_formatted ("INSERTED-CONTENT",
+ insertion_point, indent);
+ inform (&richloc, "multiline insertion");
+ }
+
/* Example of two carets where both carets appear to have an off-by-one
error appearing one column early.
Seen with gfortran.dg/associate_5.f03.