[gcc r11-7461] diagnostics: fix ICE on fix-it hints on very long lines [PR99323]
David Malcolm
dmalcolm@gcc.gnu.org
Tue Mar 2 20:47:24 GMT 2021
https://gcc.gnu.org/g:41fbacdd10305654b1d10f887fa3f4677f9b8f34
commit r11-7461-g41fbacdd10305654b1d10f887fa3f4677f9b8f34
Author: David Malcolm <dmalcolm@redhat.com>
Date: Tue Mar 2 15:46:06 2021 -0500
diagnostics: fix ICE on fix-it hints on very long lines [PR99323]
PR c/99323 describes an ICE due to a failed assertion deep inside the
fix-it printing machinery, where the fix-it hints on one line have not
been properly sorted in layout's constructor.
The underlying issue occurs when multiple fix-it hints affect a line
wider that LINE_MAP_MAX_COLUMN_NUMBER, where the location_t values for
characters after that threshold fall back to having column zero.
It's not meaningful to try to handle fix-it hints without column
information, so this patch rejects them as they are added to the
rich_location, falling back to the "no fix-it hints on this diagnostic"
case, fixing the crash.
gcc/ChangeLog:
PR c/99323
* diagnostic-show-locus.c
(selftest::test_one_liner_many_fixits_2): Fix accidental usage of
column 0.
gcc/testsuite/ChangeLog:
PR c/99323
* gcc.dg/pr99323-1.c: New test.
* gcc.dg/pr99323-2.c: New test.
libcpp/ChangeLog:
PR c/99323
* line-map.c (rich_location::maybe_add_fixit): Reject fix-it hints
at column 0.
Diff:
---
gcc/diagnostic-show-locus.c | 4 ++--
gcc/testsuite/gcc.dg/pr99323-1.c | 17 +++++++++++++++++
gcc/testsuite/gcc.dg/pr99323-2.c | 11 +++++++++++
libcpp/line-map.c | 8 ++++++++
4 files changed, 38 insertions(+), 2 deletions(-)
diff --git a/gcc/diagnostic-show-locus.c b/gcc/diagnostic-show-locus.c
index 458830aa2a9..4111cd66544 100644
--- a/gcc/diagnostic-show-locus.c
+++ b/gcc/diagnostic-show-locus.c
@@ -3288,14 +3288,14 @@ test_one_liner_many_fixits_2 ()
rich_location richloc (line_table, equals);
for (int i = 0; i < 19; i++)
{
- location_t loc = linemap_position_for_column (line_table, i * 2);
+ location_t loc = linemap_position_for_column (line_table, (i * 2) + 1);
richloc.add_fixit_insert_before (loc, "a");
}
ASSERT_EQ (19, richloc.get_num_fixit_hints ());
diagnostic_show_locus (&dc, &richloc, DK_ERROR);
ASSERT_STREQ (" foo = bar.field;\n"
" ^\n"
- "a a a a a a a a a a a a a a a a a a a\n",
+ " a a a a a a a a a a a a a a a a a a a\n",
pp_formatted_text (dc.printer));
}
diff --git a/gcc/testsuite/gcc.dg/pr99323-1.c b/gcc/testsuite/gcc.dg/pr99323-1.c
new file mode 100644
index 00000000000..6fe14002e59
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr99323-1.c
@@ -0,0 +1,17 @@
+/* Verify that fix-it printing doesn't ICE when there are multiple
+ fix-it hints on a very long line after LINE_MAP_MAX_COLUMN_NUMBER. */
+
+/* { dg-options "-Wall -no-integrated-cpp -fdiagnostics-show-caret" } */
+/* { dg-allow-blank-lines-in-output 1 } */
+/* { dg-prune-output ".*" } */
+
+typedef struct {
+} REFERENCE;
+#define LIM2() LIM1()
+#define LIM3() LIM2() LIM2() LIM2() LIM2() LIM2() LIM2()
+#define LIM4() \
+ LIM3() LIM3() LIM3() LIM3() LIM3() LIM3() LIM3() LIM3() LIM3() LIM3()
+#define LIM5() \
+ LIM4() LIM4() LIM4() LIM4() LIM4() LIM4() LIM4() LIM4() LIM4() LIM4()
+#define LIM1() DEF(),
+REFERENCE references[] = {LIM5()};
diff --git a/gcc/testsuite/gcc.dg/pr99323-2.c b/gcc/testsuite/gcc.dg/pr99323-2.c
new file mode 100644
index 00000000000..d4075b61525
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr99323-2.c
@@ -0,0 +1,11 @@
+/* Verify that fix-it printing doesn't ICE when there are multiple
+ fix-it hints on a very long line after LINE_MAP_MAX_COLUMN_NUMBER. */
+
+/* { dg-options "-Wall -fdiagnostics-show-caret" } */
+/* { dg-allow-blank-lines-in-output 1 } */
+/* { dg-prune-output ".*" } */
+
+typedef struct {
+} REFERENCE;
+
+REFERENCE references[] = {DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(), DEF(),}
diff --git a/libcpp/line-map.c b/libcpp/line-map.c
index ccabd51c62f..a003af8533c 100644
--- a/libcpp/line-map.c
+++ b/libcpp/line-map.c
@@ -2431,6 +2431,14 @@ rich_location::maybe_add_fixit (location_t start,
stop_supporting_fixits ();
return;
}
+ /* If we have very long lines, tokens will eventually fall back to
+ having column == 0.
+ We can't handle fix-it hints that use such locations. */
+ if (exploc_start.column == 0 || exploc_next_loc.column == 0)
+ {
+ stop_supporting_fixits ();
+ return;
+ }
const char *newline = strchr (new_content, '\n');
if (newline)
More information about the Gcc-cvs
mailing list