fix-it hints can't contain newlines
authorDavid Malcolm <dmalcolm@redhat.com>
Thu, 15 Sep 2016 23:57:01 +0000 (23:57 +0000)
committerDavid Malcolm <dmalcolm@gcc.gnu.org>
Thu, 15 Sep 2016 23:57:01 +0000 (23:57 +0000)
I hope to implement newline support within fix-it hints at some point,
but currently it's not supported, and leads to misleading diagnostic
output, so for now, fail gracefully.

gcc/ChangeLog:
* diagnostic-show-locus.c
(selftest::test_fixit_insert_containing_newline): New function.
(selftest::test_fixit_replace_containing_newline): New function.
(selftest::diagnostic_show_locus_c_tests): Call the above.

libcpp/ChangeLog:
* include/line-map.h (class rich_location): Note that newlines
aren't supported in fix-it text.
* line-map.c (rich_location::add_fixit_insert_before): Reject
attempts to add fix-its containing newlines.
(rich_location::add_fixit_replace): Likewise.

From-SVN: r240169

gcc/ChangeLog
gcc/diagnostic-show-locus.c
libcpp/ChangeLog
libcpp/include/line-map.h
libcpp/line-map.c

index 63651f74fbd9543193df66fe5a8d0d7086c041bf..d103ae65fe40908e9820c9bfd47817fd5e74b097 100644 (file)
@@ -1,3 +1,10 @@
+2016-09-15  David Malcolm  <dmalcolm@redhat.com>
+
+       * diagnostic-show-locus.c
+       (selftest::test_fixit_insert_containing_newline): New function.
+       (selftest::test_fixit_replace_containing_newline): New function.
+       (selftest::diagnostic_show_locus_c_tests): Call the above.
+
 2016-09-15  Bin Cheng  <bin.cheng@arm.com>
 
        PR tree-optimization/77503
index 331eb92f9686b1c4d23a0c976a19718c7badf09c..f6bfcc9c8f33c665298bb7d84485940165145d61 100644 (file)
@@ -2160,6 +2160,87 @@ test_fixit_consolidation (const line_table_case &case_)
   }
 }
 
+/* Insertion fix-it hint: adding a "break;" on a line by itself.
+   This will fail, as newlines aren't yet supported.  */
+
+static void
+test_fixit_insert_containing_newline (const line_table_case &case_)
+{
+  /* Create a tempfile and write some text to it.
+     .........................0000000001111111.
+     .........................1234567890123456.  */
+  const char *old_content = ("    case 'a':\n" /* line 1. */
+                            "      x = a;\n"  /* line 2. */
+                            "    case 'b':\n" /* line 3. */
+                            "      x = b;\n");/* line 4. */
+
+  temp_source_file tmp (SELFTEST_LOCATION, ".c", old_content);
+  line_table_test ltt (case_);
+  linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 3);
+
+  /* Add a "break;" on a line by itself before line 3 i.e. before
+     column 1 of line 3. */
+  location_t case_start = linemap_position_for_column (line_table, 5);
+  location_t case_finish = linemap_position_for_column (line_table, 13);
+  location_t case_loc = make_location (case_start, case_start, case_finish);
+  rich_location richloc (line_table, case_loc);
+  location_t line_start = linemap_position_for_column (line_table, 1);
+  richloc.add_fixit_insert_before (line_start, "      break;\n");
+
+  /* Newlines are not yet supported within fix-it hints, so
+     the fix-it should not be displayed.  */
+  ASSERT_TRUE (richloc.seen_impossible_fixit_p ());
+
+  if (case_finish > LINE_MAP_MAX_LOCATION_WITH_COLS)
+    return;
+
+  test_diagnostic_context dc;
+  diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+  ASSERT_STREQ ("\n"
+               "     case 'b':\n"
+               "     ^~~~~~~~~\n",
+               pp_formatted_text (dc.printer));
+}
+
+/* Replacement fix-it hint containing a newline.
+   This will fail, as newlines aren't yet supported.  */
+
+static void
+test_fixit_replace_containing_newline (const line_table_case &case_)
+{
+  /* Create a tempfile and write some text to it.
+    .........................0000000001111.
+    .........................1234567890123.  */
+  const char *old_content = "foo = bar ();\n";
+
+  temp_source_file tmp (SELFTEST_LOCATION, ".c", old_content);
+  line_table_test ltt (case_);
+  linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 1);
+
+  /* Replace the " = " with "\n  = ", as if we were reformatting an
+     overly long line.  */
+  location_t start = linemap_position_for_column (line_table, 4);
+  location_t finish = linemap_position_for_column (line_table, 6);
+  location_t loc = linemap_position_for_column (line_table, 13);
+  rich_location richloc (line_table, loc);
+  source_range range = source_range::from_locations (start, finish);
+  richloc.add_fixit_replace (range, "\n =");
+
+  /* Newlines are not yet supported within fix-it hints, so
+     the fix-it should not be displayed.  */
+  ASSERT_TRUE (richloc.seen_impossible_fixit_p ());
+
+  if (finish > LINE_MAP_MAX_LOCATION_WITH_COLS)
+    return;
+
+  test_diagnostic_context dc;
+  diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+  ASSERT_STREQ ("\n"
+               " foo = bar ();\n"
+               "             ^\n",
+               pp_formatted_text (dc.printer));
+}
+
 /* Run all of the selftests within this file.  */
 
 void
@@ -2176,6 +2257,8 @@ diagnostic_show_locus_c_tests ()
   for_each_line_table_case (test_diagnostic_show_locus_one_liner);
   for_each_line_table_case (test_diagnostic_show_locus_fixit_lines);
   for_each_line_table_case (test_fixit_consolidation);
+  for_each_line_table_case (test_fixit_insert_containing_newline);
+  for_each_line_table_case (test_fixit_replace_containing_newline);
 }
 
 } // namespace selftest
index 95e12a9ba6b5439d91b0fefd16d9d7ad67dc428a..b2b36037463b0458231faa4fd25e9f96d39d8bc9 100644 (file)
@@ -1,3 +1,11 @@
+2016-09-15  David Malcolm  <dmalcolm@redhat.com>
+
+       * include/line-map.h (class rich_location): Note that newlines
+       aren't supported in fix-it text.
+       * line-map.c (rich_location::add_fixit_insert_before): Reject
+       attempts to add fix-its containing newlines.
+       (rich_location::add_fixit_replace): Likewise.
+
 2016-09-13  David Malcolm  <dmalcolm@redhat.com>
 
        * include/line-map.h (class rich_location): Add description of
index 939bfcc5712532636dceb150e6703ec230290c54..747609d4393d6860500816dd0cd627477097631a 100644 (file)
@@ -1551,6 +1551,8 @@ class fixit_hint;
 
    Attempts to add a fix-it hint within a macro expansion will fail.
 
+   We do not yet support newlines in fix-it text; attempts to do so will fail.
+
    The rich_location API handles these failures gracefully, so that
    diagnostics can attempt to add fix-it hints without each needing
    extensive checking.
index 742af0a07bbd39f055687e60df0ac752ad80f30c..07e3acb78a5fba04ef23df2e9de7276fe7c01956 100644 (file)
@@ -2128,6 +2128,12 @@ rich_location::add_fixit_insert_before (source_location where,
 
   if (reject_impossible_fixit (start))
     return;
+  /* We do not yet support newlines within fix-it hints.  */
+  if (strchr (new_content, '\n'))
+    {
+      stop_supporting_fixits ();
+      return;
+    }
   add_fixit (new fixit_insert (start, new_content));
 }
 
@@ -2271,6 +2277,13 @@ rich_location::add_fixit_replace (source_range src_range,
   if (reject_impossible_fixit (src_range.m_finish))
     return;
 
+  /* We do not yet support newlines within fix-it hints.  */
+  if (strchr (new_content, '\n'))
+    {
+      stop_supporting_fixits ();
+      return;
+    }
+
   /* Consolidate neighboring fixits.  */
   fixit_hint *prev = get_last_fixit_hint ();
   if (prev)