From 31316208638e76c2273a82864d32457a9cb9806d Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Thu, 15 Sep 2016 23:57:01 +0000 Subject: [PATCH] fix-it hints can't contain newlines 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 | 7 ++++ gcc/diagnostic-show-locus.c | 83 +++++++++++++++++++++++++++++++++++++ libcpp/ChangeLog | 8 ++++ libcpp/include/line-map.h | 2 + libcpp/line-map.c | 13 ++++++ 5 files changed, 113 insertions(+) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 63651f74fbd..d103ae65fe4 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2016-09-15 David Malcolm + + * 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 PR tree-optimization/77503 diff --git a/gcc/diagnostic-show-locus.c b/gcc/diagnostic-show-locus.c index 331eb92f968..f6bfcc9c8f3 100644 --- a/gcc/diagnostic-show-locus.c +++ b/gcc/diagnostic-show-locus.c @@ -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 diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog index 95e12a9ba6b..b2b36037463 100644 --- a/libcpp/ChangeLog +++ b/libcpp/ChangeLog @@ -1,3 +1,11 @@ +2016-09-15 David Malcolm + + * 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 * include/line-map.h (class rich_location): Add description of diff --git a/libcpp/include/line-map.h b/libcpp/include/line-map.h index 939bfcc5712..747609d4393 100644 --- a/libcpp/include/line-map.h +++ b/libcpp/include/line-map.h @@ -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. diff --git a/libcpp/line-map.c b/libcpp/line-map.c index 742af0a07bb..07e3acb78a5 100644 --- a/libcpp/line-map.c +++ b/libcpp/line-map.c @@ -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) -- 2.30.2