@@ -1494,6 +1494,8 @@ layout::print_source_line (linenum_type row, const char *line, int line_bytes,
int last_non_ws = 0;
for (int col_byte = 1 + x_offset_bytes; col_byte <= line_bytes; col_byte++)
{
+ char c = *line;
+
/* Assuming colorization is enabled for the caret and underline
characters, we may also colorize the associated characters
within the source line.
@@ -1505,8 +1507,13 @@ layout::print_source_line (linenum_type row, const char *line, int line_bytes,
For frontends that only generate carets, we don't colorize the
characters above them, since this would look strange (e.g.
- colorizing just the first character in a token). */
- if (m_colorize_source_p)
+ colorizing just the first character in a token).
+
+ We need to avoid inserting color codes ahead of UTF-8 continuation
+ bytes to avoid corrupting the output, in case the location range
+ points only to the first byte of a multibyte sequence. */
+
+ if (m_colorize_source_p && (((unsigned int) c) & 0xC0) != 0x80)
{
bool in_range_p;
point_state state;
@@ -1519,7 +1526,6 @@ layout::print_source_line (linenum_type row, const char *line, int line_bytes,
else
m_colorizer.set_normal_text ();
}
- char c = *line;
if (c == '\0' || c == '\t' || c == '\r')
c = ' ';
if (c != ' ')
@@ -3854,6 +3860,27 @@ test_one_liner_labels_utf8 ()
}
}
+/* Make sure that colorization codes don't interrupt a multibyte
+ sequence, which would corrupt it. */
+static void
+test_one_liner_colorized_utf8 ()
+{
+ test_diagnostic_context dc;
+ dc.colorize_source_p = true;
+ diagnostic_color_init (&dc, DIAGNOSTICS_COLOR_YES);
+ const location_t pi = linemap_position_for_column (line_table, 12);
+ rich_location richloc (line_table, pi);
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+
+ /* In order to avoid having the test depend on exactly how the colorization
+ was effected, just confirm there are two pi characters in the output. */
+ const char *result = pp_formatted_text (dc.printer);
+ const char *null_term = result + strlen (result);
+ const char *first_pi = strstr (result, "\xcf\x80");
+ ASSERT_TRUE (first_pi && first_pi <= null_term - 2);
+ ASSERT_STR_CONTAINS (first_pi + 2, "\xcf\x80");
+}
+
/* Run the various one-liner tests. */
static void
@@ -3900,6 +3927,7 @@ test_diagnostic_show_locus_one_liner_utf8 (const line_table_case &case_)
test_one_liner_many_fixits_1_utf8 ();
test_one_liner_many_fixits_2_utf8 ();
test_one_liner_labels_utf8 ();
+ test_one_liner_colorized_utf8 ();
}
/* Verify that gcc_rich_location::add_location_if_nearby works. */