]> git.ipfire.org Git - thirdparty/gcc.git/commit
diagnostics: add labeling of source ranges
authordmalcolm <dmalcolm@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 15 Aug 2018 18:09:35 +0000 (18:09 +0000)
committerdmalcolm <dmalcolm@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 15 Aug 2018 18:09:35 +0000 (18:09 +0000)
commitb7bb52644cb759ef9c6433d216dd54d62fe77248
tree3ac7b1d0a088c0fb8d1ae7fe7866fa06b3d3f232
parentee1b788e96b04edf90ac8e7408d39427a8268018
diagnostics: add labeling of source ranges

This patch adds the ability to label source ranges within a rich_location,
to be printed by diagnostic_show_locus.

For example:

pr69554-1.c:11:18: error: invalid operands to binary + (have 'const char *' and 'const char *')
11 |   return (p + 1) + (q + 1);
   |          ~~~~~~~ ^ ~~~~~~~
   |             |         |
   |             |         const char *
   |             const char *

The patch implements labels for various type mismatch errors in the C and
C++ frontends, and in -Wformat.  I implemented it wherever accurate location
information was guaranteed (there are other places that could benefit, but
we need better location information in those places).

The labels can be disabled via -fno-diagnostics-show-labels.

Similarly:

param-type-mismatch.C: In function 'int test_1(int, int, float)':
param-type-mismatch.C:11:27: error: invalid conversion from 'int' to 'const char*' [-fpermissive]
11 |   return callee_1 (first, second, third);
   |                           ^~~~~~
   |                           |
   |                           int
param-type-mismatch.C:7:43: note:   initializing argument 2 of 'int callee_1(int, const char*, float)'
7 | extern int callee_1 (int one, const char *two, float three);
  |                               ~~~~~~~~~~~~^~~

where the first "error" describing the bad argument gets a label
describing the type inline (since it's non-obvious from "second").
The "note" describing the type of the param of the callee *doesn't*
get a label, since that information is explicit there in the
source ("const char *two").

The idea is that in any diagnostic where two aspects of the source aren't
in sync it ought to be easier for the user if we directly show them the
mismatching aspects inline (e.g. types).

As well as type mismatch errors, perhaps labels could also be used for
buffer overflow warnings, for describing the capacity of the destination
buffer vs the size of what's being written:

  sprintf (buf, "filename: %s\n", file);
           ^~~   ~~~~~~~~~~~^~~
           |                |
           capacity: 32     10 + strlen(file) + 2

or somesuch.  Another idea might be for macro expansion warnings:

warning: repeated side effects in macro expansion...
   x = MIN (p++, q++);
       ~~~~^~~~~~~~~~
note: ...expanded here as
 #define MIN(X,Y) (X<Y?X:Y)
         ^~~ ~ ~   ~ ~ ~ ~
             | |   | | | |
             | |   | | | q++
             | |   | | p++
             | |   | q++
             | q++ p++
             p++

The patch removes some logic from multiline.exp which special-cased
lines ending with a '|' character (thus complicating testing of this
patch).  I believe that this was a vestige from experiments I did to
support strippng dg directives from the output; it was present in the
earliest version of multiline.exp I posted:
  "[RFC, stage1] Richer source location information for gcc 6 (location ranges etc)"
    https://gcc.gnu.org/ml/gcc-patches/2015-03/msg00837.html
and I believe was neved used.

gcc/c-family/ChangeLog:
* c-format.c: Include "selftest-diagnostic.h" and
"gcc-rich-location.h".
(format_warning_at_char): Pass NULL for new label params of
format_warning_va.
(class indirection_suffix): New class.
(class range_label_for_format_type_mismatch): New class.
(format_type_warning): Move logic for generating "*" suffix to
class indirection_suffix.  Create "fmt_label" and "param_label"
to show their types, and pass them to the
format_warning_at_substring calls.
(selftest::test_type_mismatch_range_labels): New test.
(selftest::c_format_c_tests): Call it.

gcc/c/ChangeLog:
* c-objc-common.c: Include "gcc-rich-location.h".
(c_tree_printer): Move implemenation of '%T' to...
(print_type): ...this new function.
(range_label_for_type_mismatch::get_text): New function.
* c-typeck.c (convert_for_assignment): Add type labels to the rhs
range for the various ic_argpass cases.
(class maybe_range_label_for_tree_type_mismatch): New class.
(build_binary_op): Use it when calling binary_op_error.

gcc/cp/ChangeLog:
* call.c: Include "gcc-rich-location.h".
(convert_like_real): Add range label for "invalid conversion"
diagnostic.
(perform_implicit_conversion_flags): Add type label to the
"could not convert" error.
* error.c: Include "gcc-rich-location.h".
(range_label_for_type_mismatch::get_text): New function.
* typeck.c (convert_for_assignment): Add type label to
the "cannot convert" error if a location is available.

gcc/ChangeLog:
* common.opt (fdiagnostics-show-labels): New option.
* diagnostic-show-locus.c (class layout_range): Add field
"m_label".
(class layout): Add field "m_show_labels_p".
(layout_range::layout_range): Add param "label" and use it to
initialize m_label.
(make_range): Pass in NULL for new "label" param of layout_range's
ctor.
(layout::layout): Initialize m_show_labels_p.
(layout::maybe_add_location_range): Pass in loc_range->m_label
when constructing layout_range instances.
(struct line_label): New struct.
(layout::print_any_labels): New member function.
(layout::print_line): Call it if label-printing is enabled.
(selftest::test_one_liner_labels): New test.
(selftest::test_diagnostic_show_locus_one_liner): Call it.
* diagnostic.c (diagnostic_initialize): Initialize
context->show_labels_p.
* diagnostic.h (struct diagnostic_context): Add field
"show_labels_p".
* doc/invoke.texi (Diagnostic Message Formatting Options): Add
-fno-diagnostics-show-labels.
* dwarf2out.c (gen_producer_string): Add
OPT_fdiagnostics_show_labels to the ignored options.
* gcc-rich-location.c (gcc_rich_location::add_expr): Add "label"
param.
(gcc_rich_location::maybe_add_expr): Likewise.
* gcc-rich-location.h (gcc_rich_location::gcc_rich_location): Add
label" param, defaulting to NULL.
(gcc_rich_location::add_expr): Add "label" param.
(gcc_rich_location::maybe_add_expr): Likewise.
(class text_range_label): New class.
(class range_label_for_type_mismatch): New class.
* gimple-ssa-sprintf.c (fmtwarn): Pass NULL for new label params
of format_warning_va.
(fmtwarn_n): Likewise for new params of format_warning_n_va.
* lto-wrapper.c (merge_and_complain): Add
OPT_fdiagnostics_show_labels to the "pick one setting" options.
(append_compiler_options): Likewise to the dropped options.
(append_diag_options): Likewise to the passed-on options.
* opts.c (common_handle_option): Handle the new option.
* selftest-diagnostic.c
(test_diagnostic_context::test_diagnostic_context): Enable
show_labels_p.
* substring-locations.c: Include "gcc-rich-location.h".
(format_warning_n_va): Add "fmt_label" and "param_label" params
and use them as appropriate.
(format_warning_va): Add "fmt_label" and "param_label" params,
passing them on to format_warning_n_va.
(format_warning_at_substring): Likewise.
(format_warning_at_substring_n): Likewise.
* substring-locations.h (format_warning_va): Add "fmt_label" and
"param_label" params.
(format_warning_n_va): Likewise.
(format_warning_at_substring): Likewise.
(format_warning_at_substring_n): Likewise.
* toplev.c (general_init): Initialize global_dc->show_labels_p.

gcc/testsuite/ChangeLog:
* g++.dg/diagnostic/aka3.C: New test.
* g++.dg/diagnostic/param-type-mismatch-2.C: Update expected
output to show range labels.
* g++.dg/diagnostic/param-type-mismatch.C: Likewise.
* g++.dg/plugin/plugin.exp (plugin_test_list): Add...
* g++.dg/plugin/show-template-tree-color-labels.C: New test.
* gcc.dg/bad-binary-ops.c: Update expected output to show range
labels.  Add an "aka" example.
* gcc.dg/cpp/pr66415-1.c: Update expected output to show range
labels.
* gcc.dg/format/diagnostic-ranges.c: Likewise.
* gcc.dg/format/pr72858.c: Likewise.
* gcc.dg/format/pr78498.c: Likewise.
* gcc.dg/param-type-mismatch.c: Add "-Wpointer-sign" to options.
Update expected output to show range labels.  Add examples of
-Wincompatible-pointer-types and -Wpointer-sign for parameters.
* gcc.dg/plugin/diagnostic-test-show-locus-bw-line-numbers.c:
Update expected output to show range labels.
* gcc.dg/plugin/diagnostic-test-show-locus-bw.c: Likewise.
(test_very_wide_line): Adjust so that label is at left-clipping
boundary.
(test_very_wide_line_2): New test.
* gcc.dg/plugin/diagnostic-test-show-locus-color-line-numbers.c:
Update expected output to show range labels.
* gcc.dg/plugin/diagnostic-test-show-locus-color.c: Likewise.
* gcc.dg/plugin/diagnostic-test-show-locus-no-labels.c: New test.
* gcc.dg/plugin/diagnostic_plugin_show_trees.c (show_tree): Update
for new param to gcc_rich_location::add_expr.
* gcc.dg/plugin/diagnostic_plugin_test_show_locus.c (add_range):
Add "label" param.
(test_show_locus): Add examples of labels to various tests.  Tweak
the "very wide_line" test case and duplicate it, to cover the
boundary values for clipping of labels against the left-margin.
* gcc.dg/plugin/plugin.exp (plugin_test_list): Add
diagnostic-test-show-locus-no-labels.c.
* gcc.dg/pr69554-1.c: Update expected output to show range labels.
Update line numbers of dg-locus directives.
* gcc.dg/pr69627.c:  Update expected output to show range labels.
* lib/multiline.exp (proc _build_multiline_regex): Remove
special-case handling of lines with trailing '|'.

libcpp/ChangeLog:
* include/line-map.h (struct location_range): Add "m_label" field.
(class rich_location): Add description of labels to leading
comment.
(rich_location::rich_location): Add "label" param, defaulting to
NULL.
(rich_location::add_range): Likewise.
(struct label_text): New struct.
(class range_label): New abstract base class.
* line-map.c (rich_location::rich_location): Add "label" param;
use it.
(rich_location::add_range): Likewise.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@263564 138bc75d-0d04-0410-961f-82ee72b054a4
51 files changed:
gcc/ChangeLog
gcc/c-family/ChangeLog
gcc/c-family/c-format.c
gcc/c/ChangeLog
gcc/c/c-objc-common.c
gcc/c/c-typeck.c
gcc/common.opt
gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/error.c
gcc/cp/typeck.c
gcc/diagnostic-show-locus.c
gcc/diagnostic.c
gcc/diagnostic.h
gcc/doc/invoke.texi
gcc/dwarf2out.c
gcc/gcc-rich-location.c
gcc/gcc-rich-location.h
gcc/gimple-ssa-sprintf.c
gcc/lto-wrapper.c
gcc/opts.c
gcc/selftest-diagnostic.c
gcc/substring-locations.c
gcc/substring-locations.h
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/diagnostic/aka3.C [new file with mode: 0644]
gcc/testsuite/g++.dg/diagnostic/param-type-mismatch-2.C
gcc/testsuite/g++.dg/diagnostic/param-type-mismatch.C
gcc/testsuite/g++.dg/plugin/plugin.exp
gcc/testsuite/g++.dg/plugin/show-template-tree-color-labels.C [new file with mode: 0644]
gcc/testsuite/gcc.dg/bad-binary-ops.c
gcc/testsuite/gcc.dg/cpp/pr66415-1.c
gcc/testsuite/gcc.dg/format/diagnostic-ranges.c
gcc/testsuite/gcc.dg/format/pr72858.c
gcc/testsuite/gcc.dg/format/pr78498.c
gcc/testsuite/gcc.dg/param-type-mismatch.c
gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-bw-line-numbers.c
gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-bw.c
gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-color-line-numbers.c
gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-color.c
gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-no-labels.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_show_trees.c
gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_show_locus.c
gcc/testsuite/gcc.dg/plugin/plugin.exp
gcc/testsuite/gcc.dg/pr69554-1.c
gcc/testsuite/gcc.dg/pr69627.c
gcc/testsuite/lib/multiline.exp
gcc/toplev.c
libcpp/ChangeLog
libcpp/include/line-map.h
libcpp/line-map.c