From 7a90645fe6440d109f879249d4c075ca3024244d Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Thu, 8 Oct 2015 11:30:03 -0400 Subject: [PATCH 3/3] Eliminate special-casing for Fortran gcc/ChangeLog: * diagnostic-show-locus.c (adjust_line): Delete. (layout::get_state_at_point): Update the suppression code for before leading/after trailing whitespace to only act on underlines, not on carets. (diagnostic_show_locus): Eliminate the "frontend_calls_diagnostic_print_caret_line_p" special-casing, and absorb the body of diagnostic_print_ranges. (diagnostic_print_caret_line): Delete. (diagnostic_print_ranges): Move body inside diagnostic_show_locus. * diagnostic.h (struct diagnostic_context): Delete field "frontend_calls_diagnostic_print_caret_line_p". (diagnostic_print_caret_line): Delete. gcc/fortran/ChangeLog: * error.c (gfc_diagnostic_build_locus_prefix): Likewise. (gfc_diagnostic_starter): When handling a location that will involve a call to diagnostic_show_locus, only attempt to print the locus for the primary location, and don't call into diagnostic_print_caret_line. (gfc_diagnostics_init): Remove setting of field "frontend_calls_diagnostic_print_caret_line_p". gcc/testsuite/ChangeLog: * gcc.dg/plugin/diagnostic-test-show-locus-bw.c (test_caret_on_leading_whitespace): New. * gcc.dg/plugin/diagnostic-test-show-locus-color.c (test_caret_on_leading_whitespace): New. * gcc.dg/plugin/diagnostic_plugin_test_show_locus.c (test_show_locus): Add test_caret_on_leading_whitespace. --- gcc/diagnostic-show-locus.c | 151 ++------------------- gcc/diagnostic.h | 12 -- gcc/fortran/error.c | 71 +--------- .../gcc.dg/plugin/diagnostic-test-show-locus-bw.c | 14 ++ .../plugin/diagnostic-test-show-locus-color.c | 15 ++ .../plugin/diagnostic_plugin_test_show_locus.c | 21 +++ 6 files changed, 65 insertions(+), 219 deletions(-) diff --git a/gcc/diagnostic-show-locus.c b/gcc/diagnostic-show-locus.c index c3a941d..f7b6d9a 100644 --- a/gcc/diagnostic-show-locus.c +++ b/gcc/diagnostic-show-locus.c @@ -39,34 +39,6 @@ along with GCC; see the file COPYING3. If not see static void show_ruler (diagnostic_context *context, int max_width, int x_offset); -static void -diagnostic_print_ranges (diagnostic_context * context, - const diagnostic_info *diagnostic); - -/* If LINE is longer than MAX_WIDTH, and COLUMN is not smaller than - MAX_WIDTH by some margin, then adjust the start of the line such - that the COLUMN is smaller than MAX_WIDTH minus the margin. The - margin is either CARET_LINE_MARGIN characters or the difference - between the column and the length of the line, whatever is smaller. - The length of LINE is given by LINE_WIDTH. */ -static const char * -adjust_line (const char *line, int line_width, - int max_width, int *column_p) -{ - int right_margin = CARET_LINE_MARGIN; - int column = *column_p; - - gcc_checking_assert (line_width >= column); - right_margin = MIN (line_width - column, right_margin); - right_margin = max_width - right_margin; - if (line_width >= max_width && column > right_margin) - { - line += column - right_margin; - *column_p = right_margin; - } - return line; -} - /* Classes for rendering source code and diagnostics, within an anonymous namespace. The work is done by "class layout", which embeds and uses @@ -603,11 +575,6 @@ layout::get_state_at_point (/* Inputs. */ /* Outputs. */ point_state *out_state) { - /* Within a multiline range, don't display any underline or caret - in any leading or trailing whitespace on a line. */ - if (column < first_non_ws || column > last_non_ws) - return false; - layout_range *range; int i; FOR_EACH_VEC_ELT (m_layout_ranges, i, range) @@ -633,6 +600,13 @@ layout::get_state_at_point (/* Inputs. */ && column == range->m_caret.m_column) out_state->draw_caret_p = range->m_show_caret_p; + /* Within a multiline range, don't display any underline + in any leading or trailing whitespace on a line. + We do display carets, however. */ + if (!out_state->draw_caret_p) + if (column < first_non_ws || column > last_non_ws) + return false; + /* We are within a range. */ return true; } @@ -719,10 +693,7 @@ show_ruler (diagnostic_context *context, int max_width, int x_offset) } /* Print the physical source code corresponding to the location of - this diagnostic, with additional annotations. - If CONTEXT has set frontend_calls_diagnostic_print_caret_line_p, - the code is printed using diagnostic_print_caret_line; otherwise - it is printed using diagnostic_print_ranges. */ + this diagnostic, with additional annotations. */ void diagnostic_show_locus (diagnostic_context * context, @@ -735,112 +706,6 @@ diagnostic_show_locus (diagnostic_context * context, context->last_location = diagnostic_location (diagnostic, 0); - if (context->frontend_calls_diagnostic_print_caret_line_p) - { - /* The GCC < 6 routine. */ - expanded_location s0 = diagnostic_expand_location (diagnostic, 0); - expanded_location s1 = { }; - /* Zero-initialized. This is checked later by - diagnostic_print_caret_line. */ - - if (diagnostic_num_locations (diagnostic) >= 2) - s1 = diagnostic->message.m_richloc->get_range (1)->m_start; - - diagnostic_print_caret_line (context, s0, s1, - context->caret_chars[0], - context->caret_chars[1]); - } - else - /* The GCC >= 6 routine. */ - diagnostic_print_ranges (context, diagnostic); -} - -/* Print (part) of the source line given by xloc1 with caret1 pointing - at the column. If xloc2.column != 0 and it fits within the same - line as xloc1 according to diagnostic_same_line (), then caret2 is - printed at xloc2.colum. Otherwise, the caller has to set up things - to print a second caret line for xloc2. */ -void -diagnostic_print_caret_line (diagnostic_context * context, - expanded_location xloc1, - expanded_location xloc2, - char caret1, char caret2) -{ - if (!diagnostic_same_line (context, xloc1, xloc2)) - /* This will mean ignore xloc2. */ - xloc2.column = 0; - else if (xloc1.column == xloc2.column) - xloc2.column++; - - int cmax = MAX (xloc1.column, xloc2.column); - int line_width; - const char *line = location_get_source_line (xloc1.file, xloc1.line, - &line_width); - if (line == NULL || cmax > line_width) - return; - - /* Center the interesting part of the source line to fit in - max_width, and adjust all columns accordingly. */ - int max_width = context->caret_max_width; - int offset = (int) cmax; - line = adjust_line (line, line_width, max_width, &offset); - offset -= cmax; - cmax += offset; - xloc1.column += offset; - if (xloc2.column) - xloc2.column += offset; - - /* Print the source line. */ - pp_newline (context->printer); - const char *saved_prefix = pp_get_prefix (context->printer); - pp_set_prefix (context->printer, NULL); - pp_space (context->printer); - while (max_width > 0 && line_width > 0) - { - char c = *line == '\t' ? ' ' : *line; - if (c == '\0') - c = ' '; - pp_character (context->printer, c); - max_width--; - line_width--; - line++; - } - pp_newline (context->printer); - - /* Print the caret under the line. */ - const char *caret_cs, *caret_ce; - caret_cs = colorize_start (pp_show_color (context->printer), "caret"); - caret_ce = colorize_stop (pp_show_color (context->printer)); - int cmin = xloc2.column - ? MIN (xloc1.column, xloc2.column) : xloc1.column; - int caret_min = cmin == xloc1.column ? caret1 : caret2; - int caret_max = cmin == xloc1.column ? caret2 : caret1; - - /* cmin is >= 1, but we indent with an extra space at the start like - we did above. */ - int i; - for (i = 0; i < cmin; i++) - pp_space (context->printer); - pp_printf (context->printer, "%s%c%s", caret_cs, caret_min, caret_ce); - - if (xloc2.column) - { - for (i++; i < cmax; i++) - pp_space (context->printer); - pp_printf (context->printer, "%s%c%s", caret_cs, caret_max, caret_ce); - } - pp_set_prefix (context->printer, saved_prefix); - pp_needs_newline (context->printer) = true; -} - -/* Print all source lines covered by the locations and any ranges - within DIAGNOSTIC, displaying one or more carets and zero or more - underlines as appropriate. */ - -static void -diagnostic_print_ranges (diagnostic_context * context, - const diagnostic_info *diagnostic) -{ pp_newline (context->printer); const char *saved_prefix = pp_get_prefix (context->printer); diff --git a/gcc/diagnostic.h b/gcc/diagnostic.h index 66a867c..d4ebf86 100644 --- a/gcc/diagnostic.h +++ b/gcc/diagnostic.h @@ -183,11 +183,6 @@ struct diagnostic_context int lock; bool inhibit_notes_p; - - /* Does the frontend make calls to diagnostic_print_caret_line? - If so, we fall back to the old implementation of - diagnostic_show_locus. */ - bool frontend_calls_diagnostic_print_caret_line_p; }; static inline void @@ -348,13 +343,6 @@ diagnostic_same_line (const diagnostic_context *context, && context->caret_max_width - CARET_LINE_MARGIN > abs (s1.column - s2.column); } -void -diagnostic_print_caret_line (diagnostic_context * context, - expanded_location xloc1, - expanded_location xloc2, - char caret1, char caret2); - - extern const char * diagnostic_get_color_for_kind (diagnostic_t kind); diff --git a/gcc/fortran/error.c b/gcc/fortran/error.c index 3d9deb0..4b3d31c 100644 --- a/gcc/fortran/error.c +++ b/gcc/fortran/error.c @@ -1027,48 +1027,21 @@ gfc_diagnostic_build_locus_prefix (diagnostic_context *context, } /* This function prints the locus (file:line:column), the diagnostic kind - (Error, Warning) and (optionally) the caret line (a source line - with '1' and/or '2' below it). + (Error, Warning) and (optionally) the relevant lines of code with + annotation lines with '1' and/or '2' below them. - With -fdiagnostic-show-caret (the default) and for valid locations, - it prints for one location: + With -fdiagnostic-show-caret (the default) it prints: - [locus]: + [locus of primary range]: some code 1 Error: Some error at (1) - for two locations that fit in the same locus line: + With -fno-diagnostic-show-caret or if the primary range is not + valid, it prints: - [locus]: - - some code and some more code - 1 2 - Error: Some error at (1) and (2) - - and for two locations that do not fit in the same locus line: - - [locus]: - - some code - 1 - [locus2]: - - some other code - 2 - Error: Some error at (1) and (2) - - With -fno-diagnostic-show-caret or if one of the locations is not - valid, it prints for one location (or for two locations that fit in - the same locus line): - - [locus]: Error: Some error at (1) and (2) - - and for two locations that do not fit in the same locus line: - - [name]:[locus]: Error: (1) - [name]:[locus2]: Error: Some error at (1) and (2) + [locus of primary range]: Error: Some error at (1) and (2) */ static void gfc_diagnostic_starter (diagnostic_context *context, @@ -1128,35 +1101,6 @@ gfc_diagnostic_starter (diagnostic_context *context, /* If the caret line was shown, the prefix does not contain the locus. */ pp_set_prefix (context->printer, kind_prefix); - - if (one_locus || same_locus) - return; - - locus_prefix = gfc_diagnostic_build_locus_prefix (context, s2); - if (diagnostic_location (diagnostic, 1) <= BUILTINS_LOCATION) - { - /* No caret line for the second location. Override the previous - prefix with [locus2]:[prefix]. */ - pp_set_prefix (context->printer, - concat (locus_prefix, " ", kind_prefix, NULL)); - free (kind_prefix); - free (locus_prefix); - } - else - { - /* We print the caret for the second location. */ - pp_verbatim (context->printer, locus_prefix); - free (locus_prefix); - /* Fortran uses an empty line between locus and caret line. */ - pp_newline (context->printer); - s1.column = 0; /* Print only a caret line for s2. */ - diagnostic_print_caret_line (context, s2, s1, - context->caret_chars[1], '\0'); - pp_newline (context->printer); - /* If the caret line was shown, the prefix does not contain the - locus. */ - pp_set_prefix (context->printer, kind_prefix); - } } } @@ -1481,7 +1425,6 @@ gfc_diagnostics_init (void) diagnostic_format_decoder (global_dc) = gfc_format_decoder; global_dc->caret_chars[0] = '1'; global_dc->caret_chars[1] = '2'; - global_dc->frontend_calls_diagnostic_print_caret_line_p = true; pp_warning_buffer = new (XNEW (output_buffer)) output_buffer (); pp_warning_buffer->flush_p = false; /* pp_error_buffer is statically allocated. This simplifies memory diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-bw.c b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-bw.c index ab74a11..a4b16da 100644 --- a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-bw.c +++ b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-bw.c @@ -133,3 +133,17 @@ void test_multiple_carets (void) { dg-end-multiline-output "" } */ #endif } + +void test_caret_on_leading_whitespace (void) +{ +#if 0 + ASSOCIATE (y => x) + y = 5 /* { dg-warning "6: test" } */ +/* { dg-begin-multiline-output "" } + ASSOCIATE (y => x) + 2 + y = 5 + 1 + { dg-end-multiline-output "" } */ +#endif +} diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-color.c b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-color.c index 6789a47..47639b2 100644 --- a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-color.c +++ b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-color.c @@ -141,3 +141,18 @@ void test_multiple_carets (void) { dg-end-multiline-output "" } */ #endif } + +void test_caret_on_leading_whitespace (void) +{ +#if 0 + ASSOCIATE (y => x) + y = 5 /* { dg-warning "6: test" } */ +/* { dg-begin-multiline-output "" } + ASSOCIATE (y => x) + 2 +  y = 5 + 1 + + { dg-end-multiline-output "" } */ +#endif +} diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_show_locus.c b/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_show_locus.c index 4917fad..e49cf46 100644 --- a/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_show_locus.c +++ b/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_show_locus.c @@ -256,6 +256,27 @@ test_show_locus (function *fun) global_dc->caret_chars[0] = '^'; global_dc->caret_chars[1] = '^'; } + + /* 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. + In an earlier version of the printer, the printing of caret 0 aka + "1" was suppressed due to it appearing within the leading whitespace + before the text in its line. Ensure that we at least faithfully + print both carets, at the given (erroneous) locations. */ + if (0 == strcmp (fnname, "test_caret_on_leading_whitespace")) + { + const int line = fnstart_line + 3; + location_t caret_a = get_loc (line, 5); + location_t caret_b = get_loc (line - 1, 19); + rich_location richloc (caret_a); + richloc.add_range (caret_b, caret_b, true); + global_dc->caret_chars[0] = '1'; + global_dc->caret_chars[1] = '2'; + warning_at_rich_loc (&richloc, 0, "test"); + global_dc->caret_chars[0] = '^'; + global_dc->caret_chars[1] = '^'; + } } unsigned int -- 1.8.5.3