aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog60
-rw-r--r--gcc/c-family/ChangeLog15
-rw-r--r--gcc/c-family/c-format.c179
-rw-r--r--gcc/c/ChangeLog11
-rw-r--r--gcc/c/c-objc-common.c124
-rw-r--r--gcc/c/c-typeck.c108
-rw-r--r--gcc/common.opt4
-rw-r--r--gcc/cp/ChangeLog12
-rw-r--r--gcc/cp/call.c18
-rw-r--r--gcc/cp/error.c28
-rw-r--r--gcc/cp/typeck.c11
-rw-r--r--gcc/diagnostic-show-locus.c346
-rw-r--r--gcc/diagnostic.c1
-rw-r--r--gcc/diagnostic.h3
-rw-r--r--gcc/doc/invoke.texi19
-rw-r--r--gcc/dwarf2out.c1
-rw-r--r--gcc/gcc-rich-location.c14
-rw-r--r--gcc/gcc-rich-location.h71
-rw-r--r--gcc/gimple-ssa-sprintf.c7
-rw-r--r--gcc/lto-wrapper.c3
-rw-r--r--gcc/opts.c4
-rw-r--r--gcc/selftest-diagnostic.c1
-rw-r--r--gcc/substring-locations.c53
-rw-r--r--gcc/substring-locations.h16
-rw-r--r--gcc/testsuite/ChangeLog43
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/aka3.C25
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/param-type-mismatch-2.C6
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/param-type-mismatch.C20
-rw-r--r--gcc/testsuite/g++.dg/plugin/plugin.exp1
-rw-r--r--gcc/testsuite/g++.dg/plugin/show-template-tree-color-labels.C38
-rw-r--r--gcc/testsuite/gcc.dg/bad-binary-ops.c26
-rw-r--r--gcc/testsuite/gcc.dg/cpp/pr66415-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/format/diagnostic-ranges.c55
-rw-r--r--gcc/testsuite/gcc.dg/format/pr72858.c108
-rw-r--r--gcc/testsuite/gcc.dg/format/pr78498.c2
-rw-r--r--gcc/testsuite/gcc.dg/param-type-mismatch.c56
-rw-r--r--gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-bw-line-numbers.c14
-rw-r--r--gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-bw.c72
-rw-r--r--gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-color-line-numbers.c2
-rw-r--r--gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-color.c15
-rw-r--r--gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-no-labels.c27
-rw-r--r--gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_show_trees.c2
-rw-r--r--gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_show_locus.c51
-rw-r--r--gcc/testsuite/gcc.dg/plugin/plugin.exp1
-rw-r--r--gcc/testsuite/gcc.dg/pr69554-1.c29
-rw-r--r--gcc/testsuite/gcc.dg/pr69627.c4
-rw-r--r--gcc/testsuite/lib/multiline.exp20
-rw-r--r--gcc/toplev.c2
-rw-r--r--libcpp/ChangeLog14
-rw-r--r--libcpp/include/line-map.h78
-rw-r--r--libcpp/line-map.c9
51 files changed, 1637 insertions, 194 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index e575b553c42..8ea97839c67 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,63 @@
+2018-08-15 David Malcolm <dmalcolm@redhat.com>
+
+ * 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.
+
2018-08-15 Qing Zhao <qing.zhao@oracle.com>
PR testsuite/86519
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index 3aec883dd1a..b94a7ae9ab7 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,18 @@
+2018-08-15 David Malcolm <dmalcolm@redhat.com>
+
+ * 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.
+
2018-08-13 Martin Sebor <msebor@redhat.com>
PR tree-optimization/71625
diff --git a/gcc/c-family/c-format.c b/gcc/c-family/c-format.c
index dc0e7567c94..5a04f050acd 100644
--- a/gcc/c-family/c-format.c
+++ b/gcc/c-family/c-format.c
@@ -32,8 +32,10 @@ along with GCC; see the file COPYING3. If not see
#include "diagnostic.h"
#include "substring-locations.h"
#include "selftest.h"
+#include "selftest-diagnostic.h"
#include "builtins.h"
#include "attribs.h"
+#include "gcc-rich-location.h"
/* Handle attributes associated with format checking. */
@@ -97,8 +99,8 @@ format_warning_at_char (location_t fmt_string_loc, tree format_string_cst,
substring_loc fmt_loc (fmt_string_loc, string_type, char_idx, char_idx,
char_idx);
- bool warned = format_warning_va (fmt_loc, UNKNOWN_LOCATION, NULL, opt,
- gmsgid, &ap);
+ bool warned = format_warning_va (fmt_loc, NULL, UNKNOWN_LOCATION, NULL,
+ NULL, opt, gmsgid, &ap);
va_end (ap);
return warned;
@@ -3510,6 +3512,82 @@ get_corrected_substring (const substring_loc &fmt_loc,
return result;
}
+/* Helper class for adding zero or more trailing '*' to types.
+
+ The format type and name exclude any '*' for pointers, so those
+ must be formatted manually. For all the types we currently have,
+ this is adequate, but formats taking pointers to functions or
+ arrays would require the full type to be built up in order to
+ print it with %T. */
+
+class indirection_suffix
+{
+ public:
+ indirection_suffix (int pointer_count) : m_pointer_count (pointer_count) {}
+
+ /* Determine the size of the buffer (including NUL-terminator). */
+
+ size_t get_buffer_size () const
+ {
+ return m_pointer_count + 2;
+ }
+
+ /* Write the '*' to DST and add a NUL-terminator. */
+
+ void fill_buffer (char *dst) const
+ {
+ if (m_pointer_count == 0)
+ dst[0] = 0;
+ else if (c_dialect_cxx ())
+ {
+ memset (dst, '*', m_pointer_count);
+ dst[m_pointer_count] = 0;
+ }
+ else
+ {
+ dst[0] = ' ';
+ memset (dst + 1, '*', m_pointer_count);
+ dst[m_pointer_count + 1] = 0;
+ }
+ }
+
+ private:
+ int m_pointer_count;
+};
+
+/* Subclass of range_label for labelling the range in the format string
+ with the type in question, adding trailing '*' for pointer_count. */
+
+class range_label_for_format_type_mismatch
+ : public range_label_for_type_mismatch
+{
+ public:
+ range_label_for_format_type_mismatch (tree labelled_type, tree other_type,
+ int pointer_count)
+ : range_label_for_type_mismatch (labelled_type, other_type),
+ m_pointer_count (pointer_count)
+ {
+ }
+
+ label_text get_text () const FINAL OVERRIDE
+ {
+ label_text text = range_label_for_type_mismatch::get_text ();
+ if (text.m_buffer == NULL)
+ return text;
+
+ indirection_suffix suffix (m_pointer_count);
+ char *p = (char *) alloca (suffix.get_buffer_size ());
+ suffix.fill_buffer (p);
+
+ char *result = concat (text.m_buffer, p, NULL);
+ text.maybe_free ();
+ return label_text (result, true);
+ }
+
+ private:
+ int m_pointer_count;
+};
+
/* Give a warning about a format argument of different type from that expected.
The range of the diagnostic is taken from WHOLE_FMT_LOC; the caret location
is based on the location of the char at TYPE->offset_loc.
@@ -3558,7 +3636,6 @@ format_type_warning (const substring_loc &whole_fmt_loc,
int pointer_count = type->pointer_count;
int arg_num = type->arg_num;
- char *p;
/* If ARG_TYPE is a typedef with a misleading name (for example,
size_t but not the standard size_t expected by printf %zu), avoid
printing the typedef name. */
@@ -3570,25 +3647,10 @@ format_type_warning (const substring_loc &whole_fmt_loc,
&& !strcmp (wanted_type_name,
lang_hooks.decl_printable_name (TYPE_NAME (arg_type), 2)))
arg_type = TYPE_MAIN_VARIANT (arg_type);
- /* The format type and name exclude any '*' for pointers, so those
- must be formatted manually. For all the types we currently have,
- this is adequate, but formats taking pointers to functions or
- arrays would require the full type to be built up in order to
- print it with %T. */
- p = (char *) alloca (pointer_count + 2);
- if (pointer_count == 0)
- p[0] = 0;
- else if (c_dialect_cxx ())
- {
- memset (p, '*', pointer_count);
- p[pointer_count] = 0;
- }
- else
- {
- p[0] = ' ';
- memset (p + 1, '*', pointer_count);
- p[pointer_count + 1] = 0;
- }
+
+ indirection_suffix suffix (pointer_count);
+ char *p = (char *) alloca (suffix.get_buffer_size ());
+ suffix.fill_buffer (p);
/* WHOLE_FMT_LOC has the caret at the end of the range.
Set the caret to be at the offset from TYPE. Subtract one
@@ -3596,6 +3658,10 @@ format_type_warning (const substring_loc &whole_fmt_loc,
substring_loc fmt_loc (whole_fmt_loc);
fmt_loc.set_caret_index (type->offset_loc - 1);
+ range_label_for_format_type_mismatch fmt_label (wanted_type, arg_type,
+ pointer_count);
+ range_label_for_type_mismatch param_label (arg_type, wanted_type);
+
/* Get a string for use as a replacement fix-it hint for the range in
fmt_loc, or NULL. */
char *corrected_substring
@@ -3606,7 +3672,7 @@ format_type_warning (const substring_loc &whole_fmt_loc,
{
if (arg_type)
format_warning_at_substring
- (fmt_loc, param_loc,
+ (fmt_loc, &fmt_label, param_loc, &param_label,
corrected_substring, OPT_Wformat_,
"%s %<%s%.*s%> expects argument of type %<%s%s%>, "
"but argument %d has type %qT",
@@ -3616,7 +3682,7 @@ format_type_warning (const substring_loc &whole_fmt_loc,
wanted_type_name, p, arg_num, arg_type);
else
format_warning_at_substring
- (fmt_loc, param_loc,
+ (fmt_loc, &fmt_label, param_loc, &param_label,
corrected_substring, OPT_Wformat_,
"%s %<%s%.*s%> expects a matching %<%s%s%> argument",
gettext (kind_descriptions[kind]),
@@ -3627,7 +3693,7 @@ format_type_warning (const substring_loc &whole_fmt_loc,
{
if (arg_type)
format_warning_at_substring
- (fmt_loc, param_loc,
+ (fmt_loc, &fmt_label, param_loc, &param_label,
corrected_substring, OPT_Wformat_,
"%s %<%s%.*s%> expects argument of type %<%T%s%>, "
"but argument %d has type %qT",
@@ -3637,7 +3703,7 @@ format_type_warning (const substring_loc &whole_fmt_loc,
wanted_type, p, arg_num, arg_type);
else
format_warning_at_substring
- (fmt_loc, param_loc,
+ (fmt_loc, &fmt_label, param_loc, &param_label,
corrected_substring, OPT_Wformat_,
"%s %<%s%.*s%> expects a matching %<%T%s%> argument",
gettext (kind_descriptions[kind]),
@@ -4217,6 +4283,66 @@ test_get_format_for_type_scanf ()
#undef ASSERT_FORMAT_FOR_TYPE_STREQ
+/* Exercise the type-printing label code, to give some coverage
+ under "make selftest-valgrind" (in particular, to ensure that
+ the label-printing machinery doesn't leak). */
+
+static void
+test_type_mismatch_range_labels ()
+{
+ /* Create a tempfile and write some text to it.
+ ....................0000000001 11111111 12 22222222
+ ....................1234567890 12345678 90 12345678. */
+ const char *content = " printf (\"msg: %i\\n\", msg);\n";
+ temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
+ line_table_test ltt;
+
+ linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 1);
+
+ location_t c17 = linemap_position_for_column (line_table, 17);
+ ASSERT_EQ (LOCATION_COLUMN (c17), 17);
+ location_t c18 = linemap_position_for_column (line_table, 18);
+ location_t c24 = linemap_position_for_column (line_table, 24);
+ location_t c26 = linemap_position_for_column (line_table, 26);
+
+ /* Don't attempt to run the tests if column data might be unavailable. */
+ if (c26 > LINE_MAP_MAX_LOCATION_WITH_COLS)
+ return;
+
+ location_t fmt = make_location (c18, c17, c18);
+ ASSERT_EQ (LOCATION_COLUMN (fmt), 18);
+
+ location_t param = make_location (c24, c24, c26);
+ ASSERT_EQ (LOCATION_COLUMN (param), 24);
+
+ range_label_for_format_type_mismatch fmt_label (char_type_node,
+ integer_type_node, 1);
+ range_label_for_type_mismatch param_label (integer_type_node,
+ char_type_node);
+ gcc_rich_location richloc (fmt, &fmt_label);
+ richloc.add_range (param, false, &param_label);
+
+ test_diagnostic_context dc;
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ if (c_dialect_cxx ())
+ /* "char*", without a space. */
+ ASSERT_STREQ ("\n"
+ " printf (\"msg: %i\\n\", msg);\n"
+ " ~^ ~~~\n"
+ " | |\n"
+ " char* int\n",
+ pp_formatted_text (dc.printer));
+ else
+ /* "char *", with a space. */
+ ASSERT_STREQ ("\n"
+ " printf (\"msg: %i\\n\", msg);\n"
+ " ~^ ~~~\n"
+ " | |\n"
+ " | int\n"
+ " char *\n",
+ pp_formatted_text (dc.printer));
+}
+
/* Run all of the selftests within this file. */
void
@@ -4225,6 +4351,7 @@ c_format_c_tests ()
test_get_modifier_for_format_len ();
test_get_format_for_type_printf ();
test_get_format_for_type_scanf ();
+ test_type_mismatch_range_labels ();
}
} // namespace selftest
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index be714d28b4d..7bde11c1f19 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,14 @@
+2018-08-15 David Malcolm <dmalcolm@redhat.com>
+
+ * 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.
+
2018-08-15 Prathamesh Kulkarni <prathamesh.kulkarni@linaro.org>
* c-decl.c (start_decl): Do not warn if variables is named as main
diff --git a/gcc/c/c-objc-common.c b/gcc/c/c-objc-common.c
index ddbd60ce624..238af199ab5 100644
--- a/gcc/c/c-objc-common.c
+++ b/gcc/c/c-objc-common.c
@@ -27,6 +27,7 @@ along with GCC; see the file COPYING3. If not see
#include "gimple-pretty-print.h"
#include "langhooks.h"
#include "c-objc-common.h"
+#include "gcc-rich-location.h"
static bool c_tree_printer (pretty_printer *, text_info *, const char *,
int, bool, bool, bool, bool *, const char **);
@@ -61,6 +62,60 @@ c_objc_common_init (void)
return c_common_init ();
}
+/* Print T to CPP. */
+
+static void
+print_type (c_pretty_printer *cpp, tree t, bool *quoted)
+{
+ gcc_assert (TYPE_P (t));
+ struct obstack *ob = pp_buffer (cpp)->obstack;
+ char *p = (char *) obstack_base (ob);
+ /* Remember the end of the initial dump. */
+ int len = obstack_object_size (ob);
+
+ tree name = TYPE_NAME (t);
+ if (name && TREE_CODE (name) == TYPE_DECL && DECL_NAME (name))
+ pp_identifier (cpp, lang_hooks.decl_printable_name (name, 2));
+ else
+ cpp->type_id (t);
+
+ /* If we're printing a type that involves typedefs, also print the
+ stripped version. But sometimes the stripped version looks
+ exactly the same, so we don't want it after all. To avoid
+ printing it in that case, we play ugly obstack games. */
+ if (TYPE_CANONICAL (t) && t != TYPE_CANONICAL (t))
+ {
+ c_pretty_printer cpp2;
+ /* Print the stripped version into a temporary printer. */
+ cpp2.type_id (TYPE_CANONICAL (t));
+ struct obstack *ob2 = cpp2.buffer->obstack;
+ /* Get the stripped version from the temporary printer. */
+ const char *aka = (char *) obstack_base (ob2);
+ int aka_len = obstack_object_size (ob2);
+ int type1_len = obstack_object_size (ob) - len;
+
+ /* If they are identical, bail out. */
+ if (aka_len == type1_len && memcmp (p + len, aka, aka_len) == 0)
+ return;
+
+ /* They're not, print the stripped version now. */
+ if (*quoted)
+ pp_end_quote (cpp, pp_show_color (cpp));
+ pp_c_whitespace (cpp);
+ pp_left_brace (cpp);
+ pp_c_ws_string (cpp, _("aka"));
+ pp_c_whitespace (cpp);
+ if (*quoted)
+ pp_begin_quote (cpp, pp_show_color (cpp));
+ cpp->type_id (TYPE_CANONICAL (t));
+ if (*quoted)
+ pp_end_quote (cpp, pp_show_color (cpp));
+ pp_right_brace (cpp);
+ /* No further closing quotes are needed. */
+ *quoted = false;
+ }
+}
+
/* Called during diagnostic message formatting process to print a
source-level entity onto BUFFER. The meaning of the format specifiers
is as follows:
@@ -82,7 +137,6 @@ c_tree_printer (pretty_printer *pp, text_info *text, const char *spec,
bool *quoted, const char **)
{
tree t = NULL_TREE;
- tree name;
// FIXME: the next cast should be a dynamic_cast, when it is permitted.
c_pretty_printer *cpp = (c_pretty_printer *) pp;
pp->padding = pp_none;
@@ -133,56 +187,8 @@ c_tree_printer (pretty_printer *pp, text_info *text, const char *spec,
break;
case 'T':
- {
- gcc_assert (TYPE_P (t));
- struct obstack *ob = pp_buffer (cpp)->obstack;
- char *p = (char *) obstack_base (ob);
- /* Remember the end of the initial dump. */
- int len = obstack_object_size (ob);
-
- name = TYPE_NAME (t);
- if (name && TREE_CODE (name) == TYPE_DECL && DECL_NAME (name))
- pp_identifier (cpp, lang_hooks.decl_printable_name (name, 2));
- else
- cpp->type_id (t);
-
- /* If we're printing a type that involves typedefs, also print the
- stripped version. But sometimes the stripped version looks
- exactly the same, so we don't want it after all. To avoid
- printing it in that case, we play ugly obstack games. */
- if (TYPE_CANONICAL (t) && t != TYPE_CANONICAL (t))
- {
- c_pretty_printer cpp2;
- /* Print the stripped version into a temporary printer. */
- cpp2.type_id (TYPE_CANONICAL (t));
- struct obstack *ob2 = cpp2.buffer->obstack;
- /* Get the stripped version from the temporary printer. */
- const char *aka = (char *) obstack_base (ob2);
- int aka_len = obstack_object_size (ob2);
- int type1_len = obstack_object_size (ob) - len;
-
- /* If they are identical, bail out. */
- if (aka_len == type1_len && memcmp (p + len, aka, aka_len) == 0)
- return true;
-
- /* They're not, print the stripped version now. */
- if (*quoted)
- pp_end_quote (pp, pp_show_color (pp));
- pp_c_whitespace (cpp);
- pp_left_brace (cpp);
- pp_c_ws_string (cpp, _("aka"));
- pp_c_whitespace (cpp);
- if (*quoted)
- pp_begin_quote (pp, pp_show_color (pp));
- cpp->type_id (TYPE_CANONICAL (t));
- if (*quoted)
- pp_end_quote (pp, pp_show_color (pp));
- pp_right_brace (cpp);
- /* No further closing quotes are needed. */
- *quoted = false;
- }
- return true;
- }
+ print_type (cpp, t, quoted);
+ return true;
case 'E':
if (TREE_CODE (t) == IDENTIFIER_NODE)
@@ -207,6 +213,22 @@ c_tree_printer (pretty_printer *pp, text_info *text, const char *spec,
return true;
}
+/* C-specific implementation of range_label::get_text () vfunc for
+ range_label_for_type_mismatch. */
+
+label_text
+range_label_for_type_mismatch::get_text () const
+{
+ if (m_labelled_type == NULL_TREE)
+ return label_text (NULL, false);
+
+ c_pretty_printer cpp;
+ bool quoted = false;
+ print_type (&cpp, m_labelled_type, &quoted);
+ return label_text (xstrdup (pp_formatted_text (&cpp)), true);
+}
+
+
/* In C and ObjC, all decls have "C" linkage. */
bool
has_c_linkage (const_tree decl ATTRIBUTE_UNUSED)
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index 2e9338e3458..726ea832ae1 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -6924,13 +6924,15 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
switch (errtype)
{
case ic_argpass:
- if (pedwarn (expr_loc, OPT_Wpointer_sign,
- "pointer targets in passing argument %d of "
- "%qE differ in signedness", parmnum, rname))
- inform ((fundecl && !DECL_IS_BUILTIN (fundecl))
- ? DECL_SOURCE_LOCATION (fundecl) : expr_loc,
- "expected %qT but argument is of type %qT",
- type, rhstype);
+ {
+ range_label_for_type_mismatch rhs_label (rhstype, type);
+ gcc_rich_location richloc (expr_loc, &rhs_label);
+ if (pedwarn (&richloc, OPT_Wpointer_sign,
+ "pointer targets in passing argument %d of "
+ "%qE differ in signedness", parmnum, rname))
+ inform_for_arg (fundecl, expr_loc, parmnum, type,
+ rhstype);
+ }
break;
case ic_assign:
pedwarn (location, OPT_Wpointer_sign,
@@ -6981,10 +6983,14 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
switch (errtype)
{
case ic_argpass:
- if (pedwarn (expr_loc, OPT_Wincompatible_pointer_types,
- "passing argument %d of %qE from incompatible "
- "pointer type", parmnum, rname))
- inform_for_arg (fundecl, expr_loc, parmnum, type, rhstype);
+ {
+ range_label_for_type_mismatch rhs_label (rhstype, type);
+ gcc_rich_location richloc (expr_loc, &rhs_label);
+ if (pedwarn (&richloc, OPT_Wincompatible_pointer_types,
+ "passing argument %d of %qE from incompatible "
+ "pointer type", parmnum, rname))
+ inform_for_arg (fundecl, expr_loc, parmnum, type, rhstype);
+ }
break;
case ic_assign:
pedwarn (location, OPT_Wincompatible_pointer_types,
@@ -7024,10 +7030,14 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
switch (errtype)
{
case ic_argpass:
- if (pedwarn (expr_loc, OPT_Wint_conversion,
- "passing argument %d of %qE makes pointer from "
- "integer without a cast", parmnum, rname))
- inform_for_arg (fundecl, expr_loc, parmnum, type, rhstype);
+ {
+ range_label_for_type_mismatch rhs_label (rhstype, type);
+ gcc_rich_location richloc (expr_loc, &rhs_label);
+ if (pedwarn (&richloc, OPT_Wint_conversion,
+ "passing argument %d of %qE makes pointer from "
+ "integer without a cast", parmnum, rname))
+ inform_for_arg (fundecl, expr_loc, parmnum, type, rhstype);
+ }
break;
case ic_assign:
pedwarn (location, OPT_Wint_conversion,
@@ -7055,10 +7065,14 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
switch (errtype)
{
case ic_argpass:
- if (pedwarn (expr_loc, OPT_Wint_conversion,
- "passing argument %d of %qE makes integer from "
- "pointer without a cast", parmnum, rname))
- inform_for_arg (fundecl, expr_loc, parmnum, type, rhstype);
+ {
+ range_label_for_type_mismatch rhs_label (rhstype, type);
+ gcc_rich_location richloc (expr_loc, &rhs_label);
+ if (pedwarn (&richloc, OPT_Wint_conversion,
+ "passing argument %d of %qE makes integer from "
+ "pointer without a cast", parmnum, rname))
+ inform_for_arg (fundecl, expr_loc, parmnum, type, rhstype);
+ }
break;
case ic_assign:
pedwarn (location, OPT_Wint_conversion,
@@ -7094,9 +7108,13 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
switch (errtype)
{
case ic_argpass:
- error_at (expr_loc, "incompatible type for argument %d of %qE", parmnum,
- rname);
- inform_for_arg (fundecl, expr_loc, parmnum, type, rhstype);
+ {
+ range_label_for_type_mismatch rhs_label (rhstype, type);
+ gcc_rich_location richloc (expr_loc, &rhs_label);
+ error_at (&richloc, "incompatible type for argument %d of %qE", parmnum,
+ rname);
+ inform_for_arg (fundecl, expr_loc, parmnum, type, rhstype);
+ }
break;
case ic_assign:
error_at (location, "incompatible types when assigning to type %qT from "
@@ -10992,6 +11010,38 @@ build_vec_cmp (tree_code code, tree type,
return build3 (VEC_COND_EXPR, type, cmp, minus_one_vec, zero_vec);
}
+/* Subclass of range_label for labelling the type of EXPR when reporting
+ a type mismatch between EXPR and OTHER_EXPR.
+ Either or both of EXPR and OTHER_EXPR could be NULL. */
+
+class maybe_range_label_for_tree_type_mismatch : public range_label
+{
+ public:
+ maybe_range_label_for_tree_type_mismatch (tree expr, tree other_expr)
+ : m_expr (expr), m_other_expr (other_expr)
+ {
+ }
+
+ label_text get_text () const FINAL OVERRIDE
+ {
+ if (m_expr == NULL_TREE
+ || !EXPR_P (m_expr))
+ return label_text (NULL, false);
+ tree expr_type = TREE_TYPE (m_expr);
+
+ tree other_type = NULL_TREE;
+ if (m_other_expr && EXPR_P (m_other_expr))
+ other_type = TREE_TYPE (m_other_expr);
+
+ range_label_for_type_mismatch inner (expr_type, other_type);
+ return inner.get_text ();
+ }
+
+ private:
+ tree m_expr;
+ tree m_other_expr;
+};
+
/* Build a binary-operation expression without default conversions.
CODE is the kind of expression to build.
LOCATION is the operator's location.
@@ -11864,8 +11914,11 @@ build_binary_op (location_t location, enum tree_code code,
|| !vector_types_compatible_elements_p (type0, type1)))
{
gcc_rich_location richloc (location);
- richloc.maybe_add_expr (orig_op0);
- richloc.maybe_add_expr (orig_op1);
+ maybe_range_label_for_tree_type_mismatch
+ label_for_op0 (orig_op0, orig_op1),
+ label_for_op1 (orig_op1, orig_op0);
+ richloc.maybe_add_expr (orig_op0, &label_for_op0);
+ richloc.maybe_add_expr (orig_op1, &label_for_op1);
binary_op_error (&richloc, code, type0, type1);
return error_mark_node;
}
@@ -12106,8 +12159,11 @@ build_binary_op (location_t location, enum tree_code code,
if (!result_type)
{
gcc_rich_location richloc (location);
- richloc.maybe_add_expr (orig_op0);
- richloc.maybe_add_expr (orig_op1);
+ maybe_range_label_for_tree_type_mismatch
+ label_for_op0 (orig_op0, orig_op1),
+ label_for_op1 (orig_op1, orig_op0);
+ richloc.maybe_add_expr (orig_op0, &label_for_op0);
+ richloc.maybe_add_expr (orig_op1, &label_for_op1);
binary_op_error (&richloc, code, TREE_TYPE (op0), TREE_TYPE (op1));
return error_mark_node;
}
diff --git a/gcc/common.opt b/gcc/common.opt
index b2f2215ecc6..507291f4394 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -1233,6 +1233,10 @@ fdiagnostics-show-caret
Common Var(flag_diagnostics_show_caret) Init(1)
Show the source line with a caret indicating the column.
+fdiagnostics-show-labels
+Common Var(flag_diagnostics_show_labels) Init(1)
+Show labels annotating ranges of source code when showing source
+
fdiagnostics-show-line-numbers
Common Var(flag_diagnostics_show_line_numbers) Init(1)
Show line numbers in the left margin when showing source
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 8e123713873..0b695907cf1 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,15 @@
+2018-08-15 David Malcolm <dmalcolm@redhat.com>
+
+ * 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.
+
2018-08-15 Paolo Carlini <paolo.carlini@oracle.com>
* decl.c (check_previous_goto_1): When decl_jump_unsafe returns 2
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 62654a9e407..16bb6bfd467 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -41,6 +41,7 @@ along with GCC; see the file COPYING3. If not see
#include "internal-fn.h"
#include "stringpool.h"
#include "attribs.h"
+#include "gcc-rich-location.h"
/* The various kinds of conversion. */
@@ -6748,8 +6749,13 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
break;
}
if (!complained)
- complained = permerror (loc, "invalid conversion from %qH to %qI",
- TREE_TYPE (expr), totype);
+ {
+ range_label_for_type_mismatch label (TREE_TYPE (expr), totype);
+ gcc_rich_location richloc (loc, &label);
+ complained = permerror (&richloc,
+ "invalid conversion from %qH to %qI",
+ TREE_TYPE (expr), totype);
+ }
if (complained && fn)
inform (get_fndecl_argument_location (fn, argnum),
" initializing argument %P of %qD", argnum, fn);
@@ -10755,8 +10761,12 @@ perform_implicit_conversion_flags (tree type, tree expr,
else if (invalid_nonstatic_memfn_p (loc, expr, complain))
/* We gave an error. */;
else
- error_at (loc, "could not convert %qE from %qH to %qI", expr,
- TREE_TYPE (expr), type);
+ {
+ range_label_for_type_mismatch label (TREE_TYPE (expr), type);
+ gcc_rich_location rich_loc (loc, &label);
+ error_at (&rich_loc, "could not convert %qE from %qH to %qI",
+ expr, TREE_TYPE (expr), type);
+ }
}
expr = error_mark_node;
}
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index c49f4d7c378..355a5e82f15 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -31,6 +31,7 @@ along with GCC; see the file COPYING3. If not see
#include "c-family/c-objc.h"
#include "ubsan.h"
#include "internal-fn.h"
+#include "gcc-rich-location.h"
#define pp_separate_with_comma(PP) pp_cxx_separate_with (PP, ',')
#define pp_separate_with_semicolon(PP) pp_cxx_separate_with (PP, ';')
@@ -4279,3 +4280,30 @@ qualified_name_lookup_error (tree scope, tree name,
suggest_alternatives_for (location, name, true);
}
}
+
+/* C++-specific implementation of range_label::get_text () vfunc for
+ range_label_for_type_mismatch.
+
+ Compare with print_template_differences above. */
+
+label_text
+range_label_for_type_mismatch::get_text () const
+{
+ if (m_labelled_type == NULL_TREE)
+ return label_text (NULL, false);
+
+ const bool verbose = false;
+ const bool show_color = false;
+
+ const char *result;
+ if (m_other_type
+ && comparable_template_types_p (m_labelled_type, m_other_type))
+ result = type_to_string_with_compare (m_labelled_type, m_other_type,
+ verbose, show_color);
+ else
+ result = type_to_string (m_labelled_type, verbose, true, NULL, show_color);
+
+ /* Both of the above return GC-allocated buffers, so the caller mustn't
+ free them. */
+ return label_text (const_cast <char *> (result), false);
+}
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 1335da5e9bc..64b3d583356 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -8805,7 +8805,16 @@ convert_for_assignment (tree type, tree rhs,
}
else if (fndecl)
{
- error_at (cp_expr_loc_or_loc (rhs, input_location),
+ location_t loc = cp_expr_location (rhs);
+ range_label_for_type_mismatch rhs_label (rhstype, type);
+ range_label *label = &rhs_label;
+ if (loc == UNKNOWN_LOCATION)
+ {
+ loc = input_location;
+ label = NULL;
+ }
+ gcc_rich_location richloc (loc, label);
+ error_at (&richloc,
"cannot convert %qH to %qI",
rhstype, type);
inform (get_fndecl_argument_location (fndecl, parmnum),
diff --git a/gcc/diagnostic-show-locus.c b/gcc/diagnostic-show-locus.c
index 238c689be1a..c9edaab4e22 100644
--- a/gcc/diagnostic-show-locus.c
+++ b/gcc/diagnostic-show-locus.c
@@ -127,7 +127,8 @@ class layout_range
layout_range (const expanded_location *start_exploc,
const expanded_location *finish_exploc,
bool show_caret_p,
- const expanded_location *caret_exploc);
+ const expanded_location *caret_exploc,
+ const range_label *label);
bool contains_point (linenum_type row, int column) const;
bool intersects_line_p (linenum_type row) const;
@@ -136,6 +137,7 @@ class layout_range
layout_point m_finish;
bool m_show_caret_p;
layout_point m_caret;
+ const range_label *m_label;
};
/* A struct for use by layout::print_source_line for telling
@@ -253,6 +255,7 @@ class layout
bool should_print_annotation_line_p (linenum_type row) const;
void start_annotation_line () const;
void print_annotation_line (linenum_type row, const line_bounds lbounds);
+ void print_any_labels (linenum_type row);
void print_trailing_fixits (linenum_type row);
bool annotation_line_showed_range_p (linenum_type line, int start_column,
@@ -287,6 +290,7 @@ class layout
expanded_location m_exploc;
colorizer m_colorizer;
bool m_colorize_source_p;
+ bool m_show_labels_p;
bool m_show_line_numbers_p;
auto_vec <layout_range> m_layout_ranges;
auto_vec <const fixit_hint *> m_fixit_hints;
@@ -408,11 +412,13 @@ colorizer::get_color_by_name (const char *name)
layout_range::layout_range (const expanded_location *start_exploc,
const expanded_location *finish_exploc,
bool show_caret_p,
- const expanded_location *caret_exploc)
+ const expanded_location *caret_exploc,
+ const range_label *label)
: m_start (*start_exploc),
m_finish (*finish_exploc),
m_show_caret_p (show_caret_p),
- m_caret (*caret_exploc)
+ m_caret (*caret_exploc),
+ m_label (label)
{
}
@@ -539,7 +545,7 @@ make_range (int start_line, int start_col, int end_line, int end_col)
const expanded_location finish_exploc
= {"test.c", end_line, end_col, NULL, false};
return layout_range (&start_exploc, &finish_exploc, false,
- &start_exploc);
+ &start_exploc, NULL);
}
/* Selftests for layout_range::contains_point and
@@ -879,6 +885,7 @@ layout::layout (diagnostic_context * context,
m_exploc (richloc->get_expanded_location (0)),
m_colorizer (context, diagnostic_kind),
m_colorize_source_p (context->colorize_source_p),
+ m_show_labels_p (context->show_labels_p),
m_show_line_numbers_p (context->show_line_numbers_p),
m_layout_ranges (richloc->get_num_locations ()),
m_fixit_hints (richloc->get_num_fixit_hints ()),
@@ -989,7 +996,8 @@ layout::maybe_add_location_range (const location_range *loc_range,
/* Everything is now known to be in the correct source file,
but it may require further sanitization. */
- layout_range ri (&start, &finish, loc_range->m_show_caret_p, &caret);
+ layout_range ri (&start, &finish, loc_range->m_show_caret_p, &caret,
+ loc_range->m_label);
/* If we have a range that finishes before it starts (perhaps
from something built via macro expansion), printing the
@@ -1379,6 +1387,180 @@ layout::print_annotation_line (linenum_type row, const line_bounds lbounds)
print_newline ();
}
+/* Implementation detail of layout::print_any_labels.
+
+ A label within the given row of source. */
+
+struct line_label
+{
+ line_label (int state_idx, int column, label_text text)
+ : m_state_idx (state_idx), m_column (column),
+ m_text (text), m_length (strlen (text.m_buffer)),
+ m_label_line (0)
+ {}
+
+ /* Sorting is primarily by column, then by state index. */
+ static int comparator (const void *p1, const void *p2)
+ {
+ const line_label *ll1 = (const line_label *)p1;
+ const line_label *ll2 = (const line_label *)p2;
+ int column_cmp = compare (ll1->m_column, ll2->m_column);
+ if (column_cmp)
+ return column_cmp;
+ return compare (ll1->m_state_idx, ll2->m_state_idx);
+ }
+
+ int m_state_idx;
+ int m_column;
+ label_text m_text;
+ size_t m_length;
+ int m_label_line;
+};
+
+/* Print any labels in this row. */
+void
+layout::print_any_labels (linenum_type row)
+{
+ int i;
+ auto_vec<line_label> labels;
+
+ /* Gather the labels that are to be printed into "labels". */
+ {
+ layout_range *range;
+ FOR_EACH_VEC_ELT (m_layout_ranges, i, range)
+ {
+ /* Most ranges don't have labels, so reject this first. */
+ if (range->m_label == NULL)
+ continue;
+
+ /* The range's caret must be on this line. */
+ if (range->m_caret.m_line != row)
+ continue;
+
+ /* Reject labels that aren't fully visible due to clipping
+ by m_x_offset. */
+ if (range->m_caret.m_column <= m_x_offset)
+ continue;
+
+ label_text text;
+ text = range->m_label->get_text ();
+
+ /* Allow for labels that return NULL from their get_text
+ implementation (so e.g. such labels can control their own
+ visibility). */
+ if (text.m_buffer == NULL)
+ continue;
+
+ labels.safe_push (line_label (i, range->m_caret.m_column, text));
+ }
+ }
+
+ /* Bail out if there are no labels on this row. */
+ if (labels.length () == 0)
+ return;
+
+ /* Sort them. */
+ labels.qsort(line_label::comparator);
+
+ /* Figure out how many "label lines" we need, and which
+ one each label is printed in.
+
+ For example, if the labels aren't too densely packed,
+ we can fit them on the same line, giving two "label lines":
+
+ foo + bar
+ ~~~ ~~~
+ | | : label line 0
+ l0 l1 : label line 1
+
+ If they would touch each other or overlap, then we need
+ additional "label lines":
+
+ foo + bar
+ ~~~ ~~~
+ | | : label line 0
+ | label 1 : label line 1
+ label 0 : label line 2
+
+ Place the final label on label line 1, and work backwards, adding
+ label lines as needed.
+
+ If multiple labels are at the same place, put them on separate
+ label lines:
+
+ foo + bar
+ ^ : label line 0
+ | : label line 1
+ label 1 : label line 2
+ label 0 : label line 3. */
+
+ int max_label_line = 1;
+ {
+ int next_column = INT_MAX;
+ line_label *label;
+ FOR_EACH_VEC_ELT_REVERSE (labels, i, label)
+ {
+ /* Would this label "touch" or overlap the next label? */
+ if (label->m_column + label->m_length >= (size_t)next_column)
+ max_label_line++;
+
+ label->m_label_line = max_label_line;
+ next_column = label->m_column;
+ }
+ }
+
+ /* Print the "label lines". For each label within the line, print
+ either a vertical bar ('|') for the labels that are lower down, or the
+ labels themselves once we've reached their line. */
+ {
+ /* Keep track of in which column we last printed a vertical bar.
+ This allows us to suppress duplicate vertical bars for the case
+ where multiple labels are on one column. */
+ int last_vbar = 0;
+ for (int label_line = 0; label_line <= max_label_line; label_line++)
+ {
+ start_annotation_line ();
+ pp_space (m_pp);
+ int column = 1 + m_x_offset;
+ line_label *label;
+ FOR_EACH_VEC_ELT (labels, i, label)
+ {
+ if (label_line > label->m_label_line)
+ /* We've printed all the labels for this label line. */
+ break;
+
+ if (label_line == label->m_label_line)
+ {
+ gcc_assert (column <= label->m_column);
+ move_to_column (&column, label->m_column, true);
+ m_colorizer.set_range (label->m_state_idx);
+ pp_string (m_pp, label->m_text.m_buffer);
+ m_colorizer.set_normal_text ();
+ column += label->m_length;
+ }
+ else if (label->m_column != last_vbar)
+ {
+ gcc_assert (column <= label->m_column);
+ move_to_column (&column, label->m_column, true);
+ m_colorizer.set_range (label->m_state_idx);
+ pp_character (m_pp, '|');
+ m_colorizer.set_normal_text ();
+ last_vbar = column;
+ column++;
+ }
+ }
+ print_newline ();
+ }
+ }
+
+ /* Clean up. */
+ {
+ line_label *label;
+ FOR_EACH_VEC_ELT (labels, i, label)
+ label->m_text.maybe_free ();
+ }
+}
+
/* If there are any fixit hints inserting new lines before source line ROW,
print them.
@@ -2023,6 +2205,8 @@ layout::print_line (linenum_type row)
print_source_line (row, line.get_buffer (), line.length (), &lbounds);
if (should_print_annotation_line_p (row))
print_annotation_line (row, lbounds);
+ if (m_show_labels_p)
+ print_any_labels (row);
print_trailing_fixits (row);
}
@@ -2429,6 +2613,157 @@ test_one_liner_many_fixits_2 ()
pp_formatted_text (dc.printer));
}
+/* Test of labeling the ranges within a rich_location. */
+
+static void
+test_one_liner_labels ()
+{
+ location_t foo
+ = make_location (linemap_position_for_column (line_table, 1),
+ linemap_position_for_column (line_table, 1),
+ linemap_position_for_column (line_table, 3));
+ location_t bar
+ = make_location (linemap_position_for_column (line_table, 7),
+ linemap_position_for_column (line_table, 7),
+ linemap_position_for_column (line_table, 9));
+ location_t field
+ = make_location (linemap_position_for_column (line_table, 11),
+ linemap_position_for_column (line_table, 11),
+ linemap_position_for_column (line_table, 15));
+
+ /* Example where all the labels fit on one line. */
+ {
+ text_range_label label0 ("0");
+ text_range_label label1 ("1");
+ text_range_label label2 ("2");
+ gcc_rich_location richloc (foo, &label0);
+ richloc.add_range (bar, false, &label1);
+ richloc.add_range (field, false, &label2);
+
+ {
+ test_diagnostic_context dc;
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ ("\n"
+ " foo = bar.field;\n"
+ " ^~~ ~~~ ~~~~~\n"
+ " | | |\n"
+ " 0 1 2\n",
+ pp_formatted_text (dc.printer));
+ }
+
+ /* Verify that we can disable label-printing. */
+ {
+ test_diagnostic_context dc;
+ dc.show_labels_p = false;
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ ("\n"
+ " foo = bar.field;\n"
+ " ^~~ ~~~ ~~~~~\n",
+ pp_formatted_text (dc.printer));
+ }
+ }
+
+ /* Example where the labels need extra lines. */
+ {
+ text_range_label label0 ("label 0");
+ text_range_label label1 ("label 1");
+ text_range_label label2 ("label 2");
+ gcc_rich_location richloc (foo, &label0);
+ richloc.add_range (bar, false, &label1);
+ richloc.add_range (field, false, &label2);
+
+ test_diagnostic_context dc;
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ ("\n"
+ " foo = bar.field;\n"
+ " ^~~ ~~~ ~~~~~\n"
+ " | | |\n"
+ " | | label 2\n"
+ " | label 1\n"
+ " label 0\n",
+ pp_formatted_text (dc.printer));
+ }
+
+ /* Example of boundary conditions: label 0 and 1 have just enough clearance,
+ but label 1 just touches label 2. */
+ {
+ text_range_label label0 ("aaaaa");
+ text_range_label label1 ("bbbb");
+ text_range_label label2 ("c");
+ gcc_rich_location richloc (foo, &label0);
+ richloc.add_range (bar, false, &label1);
+ richloc.add_range (field, false, &label2);
+
+ test_diagnostic_context dc;
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ ("\n"
+ " foo = bar.field;\n"
+ " ^~~ ~~~ ~~~~~\n"
+ " | | |\n"
+ " | | c\n"
+ " aaaaa bbbb\n",
+ pp_formatted_text (dc.printer));
+ }
+
+ /* Example of out-of-order ranges (thus requiring a sort). */
+ {
+ text_range_label label0 ("0");
+ text_range_label label1 ("1");
+ text_range_label label2 ("2");
+ gcc_rich_location richloc (field, &label0);
+ richloc.add_range (bar, false, &label1);
+ richloc.add_range (foo, false, &label2);
+
+ test_diagnostic_context dc;
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ ("\n"
+ " foo = bar.field;\n"
+ " ~~~ ~~~ ^~~~~\n"
+ " | | |\n"
+ " 2 1 0\n",
+ pp_formatted_text (dc.printer));
+ }
+
+ /* Ensure we don't ICE if multiple ranges with labels are on
+ the same point. */
+ {
+ text_range_label label0 ("label 0");
+ text_range_label label1 ("label 1");
+ text_range_label label2 ("label 2");
+ gcc_rich_location richloc (bar, &label0);
+ richloc.add_range (bar, false, &label1);
+ richloc.add_range (bar, false, &label2);
+
+ test_diagnostic_context dc;
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ ("\n"
+ " foo = bar.field;\n"
+ " ^~~\n"
+ " |\n"
+ " label 2\n"
+ " label 1\n"
+ " label 0\n",
+ pp_formatted_text (dc.printer));
+ }
+
+ /* Verify that a NULL result from range_label::get_text is
+ handled gracefully. */
+ {
+ text_range_label label (NULL);
+ gcc_rich_location richloc (bar, &label);
+
+ test_diagnostic_context dc;
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ ("\n"
+ " foo = bar.field;\n"
+ " ^~~\n",
+ pp_formatted_text (dc.printer));
+ }
+
+ /* TODO: example of formatted printing (needs to be in
+ gcc-rich-location.c due to Makefile.in issues). */
+}
+
/* Run the various one-liner tests. */
static void
@@ -2465,6 +2800,7 @@ test_diagnostic_show_locus_one_liner (const line_table_case &case_)
test_one_liner_fixit_validation_adhoc_locations ();
test_one_liner_many_fixits_1 ();
test_one_liner_many_fixits_2 ();
+ test_one_liner_labels ();
}
/* Verify that gcc_rich_location::add_location_if_nearby works. */
diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c
index e9d93d531d5..59477ce93f6 100644
--- a/gcc/diagnostic.c
+++ b/gcc/diagnostic.c
@@ -175,6 +175,7 @@ diagnostic_initialize (diagnostic_context *context, int n_opts)
context->lock = 0;
context->inhibit_notes_p = false;
context->colorize_source_p = false;
+ context->show_labels_p = false;
context->show_line_numbers_p = false;
context->show_ruler_p = false;
context->parseable_fixits_p = false;
diff --git a/gcc/diagnostic.h b/gcc/diagnostic.h
index 744aec1a68f..fe3130bdf9d 100644
--- a/gcc/diagnostic.h
+++ b/gcc/diagnostic.h
@@ -204,6 +204,9 @@ struct diagnostic_context
a token, which would look strange). */
bool colorize_source_p;
+ /* When printing source code, should labelled ranges be printed? */
+ bool show_labels_p;
+
/* When printing source code, should there be a left-hand margin
showing line numbers? */
bool show_line_numbers_p;
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index d7fd0e17555..586af1787c7 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -267,7 +267,7 @@ Objective-C and Objective-C++ Dialects}.
-fdiagnostics-show-location=@r{[}once@r{|}every-line@r{]} @gol
-fdiagnostics-color=@r{[}auto@r{|}never@r{|}always@r{]} @gol
-fno-diagnostics-show-option -fno-diagnostics-show-caret @gol
--fno-diagnostics-show-line-numbers @gol
+-fno-diagnostics-show-labels -fno-diagnostics-show-line-numbers @gol
-fdiagnostics-parseable-fixits -fdiagnostics-generate-patch @gol
-fdiagnostics-show-template-tree -fno-elide-type @gol
-fno-show-column}
@@ -3711,6 +3711,23 @@ the @option{-fmessage-length=n} option is given. When the output is done
to the terminal, the width is limited to the width given by the
@env{COLUMNS} environment variable or, if not set, to the terminal width.
+@item -fno-diagnostics-show-labels
+@opindex fno-diagnostics-show-labels
+@opindex fdiagnostics-show-labels
+By default, when printing source code (via @option{-fdiagnostics-show-caret}),
+diagnostics can label ranges of source code with pertinent information, such
+as the types of expressions:
+
+@smallexample
+ printf ("foo %s bar", long_i + long_j);
+ ~^ ~~~~~~~~~~~~~~~
+ | |
+ char * long int
+@end smallexample
+
+This option suppresses the printing of these labels (in the example above,
+the vertical bars and the ``char *'' and ``long int'' text).
+
@item -fno-diagnostics-show-line-numbers
@opindex fno-diagnostics-show-line-numbers
@opindex fdiagnostics-show-line-numbers
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 9ed473088e7..5a74131d332 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -24247,6 +24247,7 @@ gen_producer_string (void)
case OPT_fdiagnostics_show_location_:
case OPT_fdiagnostics_show_option:
case OPT_fdiagnostics_show_caret:
+ case OPT_fdiagnostics_show_labels:
case OPT_fdiagnostics_show_line_numbers:
case OPT_fdiagnostics_color_:
case OPT_fverbose_asm:
diff --git a/gcc/gcc-rich-location.c b/gcc/gcc-rich-location.c
index 0a0adf932c1..2576c7387ee 100644
--- a/gcc/gcc-rich-location.c
+++ b/gcc/gcc-rich-location.c
@@ -38,24 +38,26 @@ along with GCC; see the file COPYING3. If not see
#include "cpplib.h"
#include "diagnostic.h"
-/* Add a range to the rich_location, covering expression EXPR. */
+/* Add a range to the rich_location, covering expression EXPR,
+ using LABEL if non-NULL. */
void
-gcc_rich_location::add_expr (tree expr)
+gcc_rich_location::add_expr (tree expr, range_label *label)
{
gcc_assert (expr);
if (CAN_HAVE_RANGE_P (expr))
- add_range (EXPR_LOCATION (expr), false);
+ add_range (EXPR_LOCATION (expr), false, label);
}
-/* If T is an expression, add a range for it to the rich_location. */
+/* If T is an expression, add a range for it to the rich_location,
+ using LABEL if non-NULL. */
void
-gcc_rich_location::maybe_add_expr (tree t)
+gcc_rich_location::maybe_add_expr (tree t, range_label *label)
{
if (EXPR_P (t))
- add_expr (t);
+ add_expr (t, label);
}
/* Add a fixit hint suggesting replacing the range at MISSPELLED_TOKEN_LOC
diff --git a/gcc/gcc-rich-location.h b/gcc/gcc-rich-location.h
index 9c705c86a72..dc11ee87552 100644
--- a/gcc/gcc-rich-location.h
+++ b/gcc/gcc-rich-location.h
@@ -28,15 +28,17 @@ class gcc_rich_location : public rich_location
/* Constructors. */
/* Constructing from a location. */
- gcc_rich_location (source_location loc) :
- rich_location (line_table, loc) {}
+ gcc_rich_location (source_location loc, const range_label *label = NULL)
+ : rich_location (line_table, loc, label)
+ {
+ }
/* Methods for adding ranges via gcc entities. */
void
- add_expr (tree expr);
+ add_expr (tree expr, range_label *label);
void
- maybe_add_expr (tree t);
+ maybe_add_expr (tree t, range_label *label);
void add_fixit_misspelled_id (location_t misspelled_token_loc,
tree hint_id);
@@ -99,4 +101,65 @@ class gcc_rich_location : public rich_location
location_t indent);
};
+/* Concrete subclass of libcpp's range_label.
+ Simple implementation using a string literal. */
+
+class text_range_label : public range_label
+{
+ public:
+ text_range_label (const char *text) : m_text (text) {}
+
+ label_text get_text () const FINAL OVERRIDE
+ {
+ return label_text (const_cast <char *> (m_text), false);
+ }
+
+ private:
+ const char *m_text;
+};
+
+/* Concrete subclass of libcpp's range_label for use in
+ diagnostics involving mismatched types.
+
+ Each frontend that uses this should supply its own implementation.
+
+ Generate a label describing LABELLED_TYPE. The frontend may use
+ OTHER_TYPE where appropriate for highlighting the differences between
+ the two types (analogous to C++'s use of %H and %I with
+ template types).
+
+ Either or both of LABELLED_TYPE and OTHER_TYPE may be NULL_TREE.
+ If LABELLED_TYPE is NULL_TREE, then there is no label.
+
+ For example, this rich_location could use two instances of
+ range_label_for_type_mismatch:
+
+ printf ("arg0: %i arg1: %s arg2: %i",
+ ^~
+ |
+ const char *
+ 100, 101, 102);
+ ~~~
+ |
+ int
+
+ (a) the label for "%s" with LABELLED_TYPE for "const char*" and
+ (b) the label for "101" with LABELLED TYPE for "int"
+ where each one uses the other's type as OTHER_TYPE. */
+
+class range_label_for_type_mismatch : public range_label
+{
+ public:
+ range_label_for_type_mismatch (tree labelled_type, tree other_type)
+ : m_labelled_type (labelled_type), m_other_type (other_type)
+ {
+ }
+
+ label_text get_text () const OVERRIDE;
+
+ protected:
+ tree m_labelled_type;
+ tree m_other_type;
+};
+
#endif /* GCC_RICH_LOCATION_H */
diff --git a/gcc/gimple-ssa-sprintf.c b/gcc/gimple-ssa-sprintf.c
index c652c556f97..5213e17d68f 100644
--- a/gcc/gimple-ssa-sprintf.c
+++ b/gcc/gimple-ssa-sprintf.c
@@ -601,8 +601,8 @@ fmtwarn (const substring_loc &fmt_loc, location_t param_loc,
{
va_list ap;
va_start (ap, gmsgid);
- bool warned = format_warning_va (fmt_loc, param_loc, corrected_substring,
- opt, gmsgid, &ap);
+ bool warned = format_warning_va (fmt_loc, NULL, param_loc, NULL,
+ corrected_substring, opt, gmsgid, &ap);
va_end (ap);
return warned;
@@ -616,7 +616,8 @@ fmtwarn_n (const substring_loc &fmt_loc, location_t param_loc,
{
va_list ap;
va_start (ap, plural_gmsgid);
- bool warned = format_warning_n_va (fmt_loc, param_loc, corrected_substring,
+ bool warned = format_warning_n_va (fmt_loc, NULL, param_loc, NULL,
+ corrected_substring,
opt, n, singular_gmsgid, plural_gmsgid,
&ap);
va_end (ap);
diff --git a/gcc/lto-wrapper.c b/gcc/lto-wrapper.c
index 39d9f088bc6..d44678694c3 100644
--- a/gcc/lto-wrapper.c
+++ b/gcc/lto-wrapper.c
@@ -255,6 +255,7 @@ merge_and_complain (struct cl_decoded_option **decoded_options,
/* Fallthru. */
case OPT_fdiagnostics_show_caret:
+ case OPT_fdiagnostics_show_labels:
case OPT_fdiagnostics_show_line_numbers:
case OPT_fdiagnostics_show_option:
case OPT_fdiagnostics_show_location_:
@@ -537,6 +538,7 @@ append_compiler_options (obstack *argv_obstack, struct cl_decoded_option *opts,
switch (option->opt_index)
{
case OPT_fdiagnostics_show_caret:
+ case OPT_fdiagnostics_show_labels:
case OPT_fdiagnostics_show_line_numbers:
case OPT_fdiagnostics_show_option:
case OPT_fdiagnostics_show_location_:
@@ -584,6 +586,7 @@ append_diag_options (obstack *argv_obstack, struct cl_decoded_option *opts,
{
case OPT_fdiagnostics_color_:
case OPT_fdiagnostics_show_caret:
+ case OPT_fdiagnostics_show_labels:
case OPT_fdiagnostics_show_line_numbers:
case OPT_fdiagnostics_show_option:
case OPT_fdiagnostics_show_location_:
diff --git a/gcc/opts.c b/gcc/opts.c
index 4153263fcab..a5c9ed9d09d 100644
--- a/gcc/opts.c
+++ b/gcc/opts.c
@@ -2175,6 +2175,10 @@ common_handle_option (struct gcc_options *opts,
dc->show_caret = value;
break;
+ case OPT_fdiagnostics_show_labels:
+ dc->show_labels_p = value;
+ break;
+
case OPT_fdiagnostics_show_line_numbers:
dc->show_line_numbers_p = value;
break;
diff --git a/gcc/selftest-diagnostic.c b/gcc/selftest-diagnostic.c
index 837488bd330..f3c255e3346 100644
--- a/gcc/selftest-diagnostic.c
+++ b/gcc/selftest-diagnostic.c
@@ -37,6 +37,7 @@ test_diagnostic_context::test_diagnostic_context ()
{
diagnostic_initialize (this, 0);
show_caret = true;
+ show_labels_p = true;
show_column = true;
start_span = start_span_cb;
}
diff --git a/gcc/substring-locations.c b/gcc/substring-locations.c
index 2d7f0c15133..82f2f4577f0 100644
--- a/gcc/substring-locations.c
+++ b/gcc/substring-locations.c
@@ -26,6 +26,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree.h"
#include "langhooks.h"
#include "substring-locations.h"
+#include "gcc-rich-location.h"
/* Emit a warning governed by option OPT, using SINGULAR_GMSGID as the
format string (or if PLURAL_GMSGID is different from SINGULAR_GMSGID,
@@ -89,6 +90,27 @@ along with GCC; see the file COPYING3. If not see
printf(fmt, msg);
^~~ ~~~
+ If non-NULL, then FMT_LABEL will be used to label the location within the
+ string for cases 1 and 2; if non-NULL, then PARAM_LABEL will be used to label
+ the parameter. For example with case 1:
+
+ test.c:90:16: warning: '%s' here but arg 2 has 'long' type [-Wformat=]
+ printf ("foo %s bar", long_i + long_j);
+ ~^ ~~~~~~~~~~~~~~~
+ |
+ int
+
+ and with case 2:
+
+ test.c:90:10: warning: problem with '%i' here [-Wformat=]
+ printf("hello " INT_FMT " world", msg);
+ ^~~~~~~~~~~~~~~~~~~~~~~~~
+ test.c:19: note: format string is defined here
+ #define INT_FMT "%i"
+ ~^
+ |
+ int
+
If CORRECTED_SUBSTRING is non-NULL, use it for cases 1 and 2 to provide
a fix-it hint, suggesting that it should replace the text within the
substring range. For example:
@@ -102,7 +124,9 @@ along with GCC; see the file COPYING3. If not see
bool
format_warning_n_va (const substring_loc &fmt_loc,
+ const range_label *fmt_label,
location_t param_loc,
+ const range_label *param_label,
const char *corrected_substring,
int opt, unsigned HOST_WIDE_INT n,
const char *singular_gmsgid,
@@ -138,10 +162,15 @@ format_warning_n_va (const substring_loc &fmt_loc,
}
}
- rich_location richloc (line_table, primary_loc);
+ /* Only use fmt_label in the initial warning for case 1. */
+ const range_label *primary_label = NULL;
+ if (substring_within_range)
+ primary_label = fmt_label;
+
+ gcc_rich_location richloc (primary_loc, primary_label);
if (param_loc != UNKNOWN_LOCATION)
- richloc.add_range (param_loc, false);
+ richloc.add_range (param_loc, false, param_label);
if (!err && corrected_substring && substring_within_range)
richloc.add_fixit_replace (fmt_substring_range, corrected_substring);
@@ -173,7 +202,9 @@ format_warning_n_va (const substring_loc &fmt_loc,
/* Case 2. */
if (warned)
{
- rich_location substring_richloc (line_table, fmt_substring_loc);
+ /* Use fmt_label in the note for case 2. */
+ rich_location substring_richloc (line_table, fmt_substring_loc,
+ fmt_label);
if (corrected_substring)
substring_richloc.add_fixit_replace (fmt_substring_range,
corrected_substring);
@@ -188,11 +219,14 @@ format_warning_n_va (const substring_loc &fmt_loc,
bool
format_warning_va (const substring_loc &fmt_loc,
+ const range_label *fmt_label,
location_t param_loc,
+ const range_label *param_label,
const char *corrected_substring,
int opt, const char *gmsgid, va_list *ap)
{
- return format_warning_n_va (fmt_loc, param_loc, corrected_substring, opt,
+ return format_warning_n_va (fmt_loc, fmt_label, param_loc, param_label,
+ corrected_substring, opt,
0, gmsgid, gmsgid, ap);
}
@@ -200,14 +234,16 @@ format_warning_va (const substring_loc &fmt_loc,
bool
format_warning_at_substring (const substring_loc &fmt_loc,
+ const range_label *fmt_label,
location_t param_loc,
+ const range_label *param_label,
const char *corrected_substring,
int opt, const char *gmsgid, ...)
{
va_list ap;
va_start (ap, gmsgid);
- bool warned = format_warning_va (fmt_loc, param_loc, corrected_substring,
- opt, gmsgid, &ap);
+ bool warned = format_warning_va (fmt_loc, fmt_label, param_loc, param_label,
+ corrected_substring, opt, gmsgid, &ap);
va_end (ap);
return warned;
@@ -217,7 +253,9 @@ format_warning_at_substring (const substring_loc &fmt_loc,
bool
format_warning_at_substring_n (const substring_loc &fmt_loc,
+ const range_label *fmt_label,
location_t param_loc,
+ const range_label *param_label,
const char *corrected_substring,
int opt, unsigned HOST_WIDE_INT n,
const char *singular_gmsgid,
@@ -225,7 +263,8 @@ format_warning_at_substring_n (const substring_loc &fmt_loc,
{
va_list ap;
va_start (ap, plural_gmsgid);
- bool warned = format_warning_n_va (fmt_loc, param_loc, corrected_substring,
+ bool warned = format_warning_n_va (fmt_loc, fmt_label, param_loc, param_label,
+ corrected_substring,
opt, n, singular_gmsgid, plural_gmsgid,
&ap);
va_end (ap);
diff --git a/gcc/substring-locations.h b/gcc/substring-locations.h
index fca6fd333c4..919fdf0127d 100644
--- a/gcc/substring-locations.h
+++ b/gcc/substring-locations.h
@@ -77,32 +77,40 @@ class substring_loc
/* Functions for emitting a warning about a format string. */
extern bool format_warning_va (const substring_loc &fmt_loc,
+ const range_label *fmt_label,
location_t param_loc,
+ const range_label *param_label,
const char *corrected_substring,
int opt, const char *gmsgid, va_list *ap)
- ATTRIBUTE_GCC_DIAG (5, 0);
+ ATTRIBUTE_GCC_DIAG (7, 0);
extern bool format_warning_n_va (const substring_loc &fmt_loc,
+ const range_label *fmt_label,
location_t param_loc,
+ const range_label *param_label,
const char *corrected_substring,
int opt, unsigned HOST_WIDE_INT n,
const char *singular_gmsgid,
const char *plural_gmsgid, va_list *ap)
- ATTRIBUTE_GCC_DIAG (6, 0) ATTRIBUTE_GCC_DIAG (7, 0);
+ ATTRIBUTE_GCC_DIAG (8, 0) ATTRIBUTE_GCC_DIAG (9, 0);
extern bool format_warning_at_substring (const substring_loc &fmt_loc,
+ const range_label *fmt_label,
location_t param_loc,
+ const range_label *param_label,
const char *corrected_substring,
int opt, const char *gmsgid, ...)
- ATTRIBUTE_GCC_DIAG (5, 6);
+ ATTRIBUTE_GCC_DIAG (7, 8);
extern bool format_warning_at_substring_n (const substring_loc &fmt_loc,
+ const range_label *fmt_label,
location_t param_loc,
+ const range_label *param_label,
const char *corrected_substring,
int opt, unsigned HOST_WIDE_INT n,
const char *singular_gmsgid,
const char *plural_gmsgid, ...)
- ATTRIBUTE_GCC_DIAG (6, 8) ATTRIBUTE_GCC_DIAG (7, 8);
+ ATTRIBUTE_GCC_DIAG (8, 10) ATTRIBUTE_GCC_DIAG (9, 10);
/* Implementation detail, for use when implementing
LANG_HOOKS_GET_SUBSTRING_LOCATION. */
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index bd167b3a77e..20e0b99f02a 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,46 @@
+2018-08-15 David Malcolm <dmalcolm@redhat.com>
+
+ * 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 '|'.
+
2018-08-15 Qing Zhao <qing.zhao@oracle.com>
PR testsuite/86519
diff --git a/gcc/testsuite/g++.dg/diagnostic/aka3.C b/gcc/testsuite/g++.dg/diagnostic/aka3.C
new file mode 100644
index 00000000000..1eb4fb2e26a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/aka3.C
@@ -0,0 +1,25 @@
+/* Verify the "aka" descriptions for typedefs are correctly
+ quoted and shown within labels. */
+
+/* { dg-options "-fdiagnostics-show-caret" } */
+
+typedef struct s1 t1;
+typedef struct s2 {int i;} t2;
+
+int foo(t1 *);
+
+void test_1 () {
+ t2 pos;
+
+ foo (&pos); // { dg-error "cannot convert 't2\\*' {aka 's2\\*'} to 't1\\*' {aka 's1\\*'}" }
+ /* { dg-begin-multiline-output "" }
+ foo (&pos);
+ ^~~~
+ |
+ t2* {aka s2*}
+ { dg-end-multiline-output "" } */
+ /* { dg-begin-multiline-output "" }
+ int foo(t1 *);
+ ^~~~
+ { dg-end-multiline-output "" } */
+}
diff --git a/gcc/testsuite/g++.dg/diagnostic/param-type-mismatch-2.C b/gcc/testsuite/g++.dg/diagnostic/param-type-mismatch-2.C
index c3b6f003b3e..8cf2dabca64 100644
--- a/gcc/testsuite/g++.dg/diagnostic/param-type-mismatch-2.C
+++ b/gcc/testsuite/g++.dg/diagnostic/param-type-mismatch-2.C
@@ -12,6 +12,8 @@ int test_1 (int first, const char *second, float third)
/* { dg-begin-multiline-output "" }
return callee_1 (first, second, third);
^~~~~~
+ |
+ const char*
{ dg-end-multiline-output "" } */
// { dg-message "initializing argument 2 of 'int callee_1\\(int, const char\\*\\*, float\\)'" "" { target *-*-* } callee_1 }
/* { dg-begin-multiline-output "" }
@@ -30,6 +32,8 @@ int test_2 (int first, const char *second, float third)
/* { dg-begin-multiline-output "" }
return callee_2 (first, second, third);
^~~~~~
+ |
+ const char*
{ dg-end-multiline-output "" } */
// { dg-message "initializing argument 2 of 'int callee_2\\(int, const char\\*\\*, float\\)'" "" { target *-*-* } callee_2 }
/* { dg-begin-multiline-output "" }
@@ -51,6 +55,8 @@ int test_3 (int first, const char *second, float third)
/* { dg-begin-multiline-output "" }
return callee_3 (first, second, third);
^~~~~~
+ |
+ const char*
{ dg-end-multiline-output "" } */
// { dg-message "initializing argument 2 of 'int callee_3\\(int, const char\\*\\*, float\\)'" "" { target *-*-* } callee_3 }
/* { dg-begin-multiline-output "" }
diff --git a/gcc/testsuite/g++.dg/diagnostic/param-type-mismatch.C b/gcc/testsuite/g++.dg/diagnostic/param-type-mismatch.C
index 5fcde0b7755..50bbd4ae94e 100644
--- a/gcc/testsuite/g++.dg/diagnostic/param-type-mismatch.C
+++ b/gcc/testsuite/g++.dg/diagnostic/param-type-mismatch.C
@@ -12,6 +12,8 @@ int test_1 (int first, int second, float third)
/* { dg-begin-multiline-output "" }
return callee_1 (first, second, third);
^~~~~~
+ |
+ int
{ dg-end-multiline-output "" } */
// { dg-message "initializing argument 2 of 'int callee_1\\(int, const char\\*, float\\)'" "" { target *-*-* } callee_1 }
/* { dg-begin-multiline-output "" }
@@ -30,6 +32,8 @@ int test_2 (int first, int second, float third)
/* { dg-begin-multiline-output "" }
return callee_2 (first, second, third);
^~~~~~
+ |
+ int
{ dg-end-multiline-output "" } */
// { dg-message "initializing argument 2 of 'int callee_2\\(int, const char\\*, float\\)'" "" { target *-*-* } callee_2 }
/* { dg-begin-multiline-output "" }
@@ -51,6 +55,8 @@ int test_3 (int first, int second, float third)
/* { dg-begin-multiline-output "" }
return callee_3 (first, second, third);
^~~~~~
+ |
+ int
{ dg-end-multiline-output "" } */
// { dg-message "initializing argument 2 of 'int callee_3\\(int, const char\\*, float\\)'" "" { target *-*-* } callee_3 }
/* { dg-begin-multiline-output "" }
@@ -69,6 +75,8 @@ int test_4 (int first, int second, float third)
/* { dg-begin-multiline-output "" }
return s4::member_1 (first, second, third);
^~~~~~
+ |
+ int
{ dg-end-multiline-output "" } */
/* { dg-begin-multiline-output "" }
struct s4 { static int member_1 (int one, const char *two, float three); };
@@ -87,6 +95,8 @@ int test_5 (int first, int second, float third)
/* { dg-begin-multiline-output "" }
return inst.member_1 (first, second, third);
^~~~~~
+ |
+ int
{ dg-end-multiline-output "" } */
/* { dg-begin-multiline-output "" }
struct s5 { int member_1 (int one, const char *two, float three); };
@@ -104,6 +114,8 @@ int test_6 (int first, int second, float third, s6 *ptr)
/* { dg-begin-multiline-output "" }
return ptr->member_1 (first, second, third);
^~~~~~
+ |
+ int
{ dg-end-multiline-output "" } */
/* { dg-begin-multiline-output "" }
struct s6 { int member_1 (int one, const char *two, float three); };
@@ -144,6 +156,8 @@ int test_8 (int first, int second, float third)
/* { dg-begin-multiline-output "" }
return s8 <const char *>::member_1 (first, second, third);
^~~~~~
+ |
+ int
{ dg-end-multiline-output "" } */
/* { dg-begin-multiline-output "" }
struct s8 { static int member_1 (int one, T two, float three); };
@@ -163,6 +177,8 @@ int test_9 (int first, int second, float third)
/* { dg-begin-multiline-output "" }
return inst.member_1 (first, second, third);
^~~~~~
+ |
+ int
{ dg-end-multiline-output "" } */
/* { dg-begin-multiline-output "" }
struct s9 { int member_1 (int one, T two, float three); };
@@ -180,6 +196,8 @@ int test_10 (int first, int second, float third)
/* { dg-begin-multiline-output "" }
return callee_10 (first, second, third);
^~~~~~
+ |
+ int
{ dg-end-multiline-output "" } */
// { dg-message "initializing argument 2 of 'int callee_10\\(int, int \\(\\*\\)\\(int, int\\), float\\)'" "" { target *-*-* } callee_10 }
/* { dg-begin-multiline-output "" }
@@ -198,6 +216,8 @@ int test_11 (int first, int second, float third)
/* { dg-begin-multiline-output "" }
return callee_11 (first, second, third);
^~~~~~
+ |
+ int
{ dg-end-multiline-output "" } */
// { dg-message "initializing argument 2 of 'int callee_11\\(int, int \\(\\*\\)\\(int, int\\), float\\)'" "" { target *-*-* } callee_11 }
/* { dg-begin-multiline-output "" }
diff --git a/gcc/testsuite/g++.dg/plugin/plugin.exp b/gcc/testsuite/g++.dg/plugin/plugin.exp
index 451c4a99e33..d9f54ab9877 100644
--- a/gcc/testsuite/g++.dg/plugin/plugin.exp
+++ b/gcc/testsuite/g++.dg/plugin/plugin.exp
@@ -69,6 +69,7 @@ set plugin_test_list [list \
diagnostic-test-inlining-1.C } \
{ show_template_tree_color_plugin.c \
show-template-tree-color.C \
+ show-template-tree-color-labels.C \
show-template-tree-color-no-elide-type.C } \
{ comment_plugin.c comments-1.C } \
]
diff --git a/gcc/testsuite/g++.dg/plugin/show-template-tree-color-labels.C b/gcc/testsuite/g++.dg/plugin/show-template-tree-color-labels.C
new file mode 100644
index 00000000000..462e1bd33ee
--- /dev/null
+++ b/gcc/testsuite/g++.dg/plugin/show-template-tree-color-labels.C
@@ -0,0 +1,38 @@
+/* Verify colorization of the labels in diagnostic-show-locus.c
+ for template comparisons.
+ Doing so requires a plugin; see the comments in the plugin for the
+ rationale. */
+
+// { dg-options "-fdiagnostics-color=always -fdiagnostics-show-caret" }
+
+template<typename> struct vector {};
+template<typename, typename> struct map {};
+
+void fn_1(vector<int>);
+void fn_2(map<int, int>);
+
+void test_1 (vector<double> vec)
+{
+ fn_1 (vec);
+ /* { dg-begin-multiline-output "" }
+could not convert 'vec' from 'vector<double>' to 'vector<int>'
+ fn_1 (vec);
+ ^~~
+ |
+ vector<double>
+ { dg-end-multiline-output "" } */
+ // TODO: we don't yet highlight the mismatching part with color
+}
+
+void test_2 (const map<int, double> &m)
+{
+ fn_2 (m);
+ /* { dg-begin-multiline-output "" }
+could not convert 'm' from 'map<[...],double>' to 'map<[...],int>'
+ fn_2 (m);
+ ^
+ |
+ map<[...],double>
+ { dg-end-multiline-output "" } */
+ // TODO: we don't yet highlight the mismatching part with color
+}
diff --git a/gcc/testsuite/gcc.dg/bad-binary-ops.c b/gcc/testsuite/gcc.dg/bad-binary-ops.c
index e1da4d615ee..46c158e6a5f 100644
--- a/gcc/testsuite/gcc.dg/bad-binary-ops.c
+++ b/gcc/testsuite/gcc.dg/bad-binary-ops.c
@@ -13,6 +13,8 @@ void test_1 ()
{ dg-begin-multiline-output "" }
myvec[1]/ptr;
~~~~~~~~^
+ |
+ __m128
{ dg-end-multiline-output "" } */
@@ -31,8 +33,12 @@ int test_2 (void)
/* { dg-begin-multiline-output "" }
return (some_function ()
~~~~~~~~~~~~~~~~
+ |
+ struct s
+ some_other_function ());
^ ~~~~~~~~~~~~~~~~~~~~~~
+ |
+ struct t
{ dg-end-multiline-output "" } */
}
@@ -46,3 +52,23 @@ int test_3 (struct s param_s, struct t param_t)
{ dg-end-multiline-output "" } */
/* TODO: ideally we'd underline both params here. */
}
+
+typedef struct s S;
+typedef struct t T;
+
+extern S callee_4a (void);
+extern T callee_4b (void);
+
+int test_4 (void)
+{
+ return callee_4a () + callee_4b (); /* { dg-error "invalid operands to binary \+" } */
+
+/* { dg-begin-multiline-output "" }
+ return callee_4a () + callee_4b ();
+ ~~~~~~~~~~~~ ^ ~~~~~~~~~~~~
+ | |
+ | T {aka struct t}
+ S {aka struct s}
+ { dg-end-multiline-output "" } */
+}
+
diff --git a/gcc/testsuite/gcc.dg/cpp/pr66415-1.c b/gcc/testsuite/gcc.dg/cpp/pr66415-1.c
index 515252cd023..cc4e41724a2 100644
--- a/gcc/testsuite/gcc.dg/cpp/pr66415-1.c
+++ b/gcc/testsuite/gcc.dg/cpp/pr66415-1.c
@@ -11,6 +11,8 @@ fn1 (void)
/* { dg-begin-multiline-output "" }
__builtin_printf ("xxxxxxxxxxxxxxxxx%dxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
~^
+ |
+ int
{ dg-end-multiline-output "" } */
}
diff --git a/gcc/testsuite/gcc.dg/format/diagnostic-ranges.c b/gcc/testsuite/gcc.dg/format/diagnostic-ranges.c
index e56e1595502..84535f018d7 100644
--- a/gcc/testsuite/gcc.dg/format/diagnostic-ranges.c
+++ b/gcc/testsuite/gcc.dg/format/diagnostic-ranges.c
@@ -11,6 +11,8 @@ void test_mismatching_types (const char *msg)
/* { dg-begin-multiline-output "" }
printf("hello %i", msg);
~^ ~~~
+ | |
+ int const char *
%s
{ dg-end-multiline-output "" } */
@@ -19,6 +21,9 @@ void test_mismatching_types (const char *msg)
/* { dg-begin-multiline-output "" }
printf("hello %s", 42);
~^ ~~
+ | |
+ | int
+ char *
%d
{ dg-end-multiline-output "" } */
@@ -26,6 +31,8 @@ void test_mismatching_types (const char *msg)
/* { dg-begin-multiline-output "" }
printf("hello %i", (long)0);
~^ ~~~~~~~
+ | |
+ int long int
%li
{ dg-end-multiline-output "" } */
}
@@ -37,9 +44,13 @@ void test_multiple_arguments (void)
/* { dg-begin-multiline-output "" }
printf ("arg0: %i arg1: %s arg 2: %i",
~^
+ |
+ char *
%d
100, 101, 102);
~~~
+ |
+ int
{ dg-end-multiline-output "" } */
}
@@ -50,9 +61,13 @@ void test_multiple_arguments_2 (int i, int j)
/* { dg-begin-multiline-output "" }
printf ("arg0: %i arg1: %s arg 2: %i",
~^
+ |
+ char *
%d
100, i + j, 102);
~~~~~
+ |
+ int
{ dg-end-multiline-output "" } */
}
@@ -72,6 +87,8 @@ void multiline_format_string (void) {
~~
"d"
~^
+ |
+ int
{ dg-end-multiline-output "" } */
}
@@ -84,6 +101,8 @@ void test_hex (const char *msg)
/* { dg-begin-multiline-output "" }
printf("hello \x25\x69", msg);
~~~~^~~~ ~~~
+ | |
+ int const char *
\x25s
{ dg-end-multiline-output "" } */
}
@@ -97,6 +116,8 @@ void test_oct (const char *msg)
/* { dg-begin-multiline-output "" }
printf("hello \045\151", msg);
~~~~^~~~ ~~~
+ | |
+ int const char *
\045s
{ dg-end-multiline-output "" } */
}
@@ -112,11 +133,15 @@ void test_multiple (const char *msg)
^~~~~~~~
msg);
~~~
+ |
+ const char *
{ dg-end-multiline-output "" } */
/* { dg-begin-multiline-output "" }
printf("prefix" "\x25" "\151" "suffix",
~~~~~~~~^~~~
+ |
+ int
\x25" "s
{ dg-end-multiline-output "" } */
}
@@ -127,6 +152,8 @@ void test_u8 (const char *msg)
/* { dg-begin-multiline-output "" }
printf(u8"hello %i", msg);
~^ ~~~
+ | |
+ int const char *
%s
{ dg-end-multiline-output "" } */
}
@@ -137,6 +164,8 @@ void test_param (long long_i, long long_j)
/* { dg-begin-multiline-output "" }
printf ("foo %s bar", long_i + long_j);
~^ ~~~~~~~~~~~~~~~
+ | |
+ char * long int
%ld
{ dg-end-multiline-output "" } */
}
@@ -147,6 +176,8 @@ void test_field_width_specifier (long l, int i1, int i2)
/* { dg-begin-multiline-output "" }
printf (" %*.*d ", l, i1, i2);
~^~~~ ~
+ | |
+ int long int
{ dg-end-multiline-output "" } */
}
@@ -158,12 +189,16 @@ void test_field_width_specifier_2 (char *d, long foo, long bar)
/* { dg-begin-multiline-output "" }
__builtin_sprintf (d, " %*ld ", foo, foo);
~^~~ ~~~
+ | |
+ int long int
{ dg-end-multiline-output "" } */
__builtin_sprintf (d, " %*ld ", foo + bar, foo); /* { dg-warning "28: field width specifier '\\*' expects argument of type 'int', but argument 3 has type 'long int'" } */
/* { dg-begin-multiline-output "" }
__builtin_sprintf (d, " %*ld ", foo + bar, foo);
~^~~ ~~~~~~~~~
+ | |
+ int long int
{ dg-end-multiline-output "" } */
}
@@ -173,12 +208,16 @@ void test_field_precision_specifier (char *d, long foo, long bar)
/* { dg-begin-multiline-output "" }
__builtin_sprintf (d, " %.*ld ", foo, foo);
~~^~~ ~~~
+ | |
+ int long int
{ dg-end-multiline-output "" } */
__builtin_sprintf (d, " %.*ld ", foo + bar, foo); /* { dg-warning "29: field precision specifier '\\.\\*' expects argument of type 'int', but argument 3 has type 'long int'" } */
/* { dg-begin-multiline-output "" }
__builtin_sprintf (d, " %.*ld ", foo + bar, foo);
~~^~~ ~~~~~~~~~
+ | |
+ int long int
{ dg-end-multiline-output "" } */
}
@@ -241,10 +280,14 @@ void test_macro (const char *msg)
/* { dg-begin-multiline-output "" }
printf("hello " INT_FMT " world", msg);
^~~~~~~~ ~~~
+ |
+ const char *
{ dg-end-multiline-output "" } */
/* { dg-begin-multiline-output "" }
#define INT_FMT "%i"
~^
+ |
+ int
%s
{ dg-end-multiline-output "" } */
#undef INT_FMT
@@ -257,10 +300,14 @@ void test_macro_2 (const char *msg)
/* { dg-begin-multiline-output "" }
printf("hello %" PRIu32 " world", msg);
^~~~~~~~~ ~~~
+ |
+ const char *
{ dg-end-multiline-output "" } */
/* { dg-begin-multiline-output "" }
#define PRIu32 "u"
^
+ |
+ unsigned int
{ dg-end-multiline-output "" } */
#undef PRIu32
}
@@ -295,6 +342,8 @@ void test_macro_4 (const char *msg)
/* { dg-begin-multiline-output "" }
#define FMT_STRING "hello %i world"
~^
+ |
+ int
%s
{ dg-end-multiline-output "" } */
#undef FMT_STRING
@@ -307,10 +356,14 @@ void test_non_contiguous_strings (void)
/* { dg-begin-multiline-output "" }
__builtin_printf(" %" "d ", 0.5);
^~~~ ~~~
+ |
+ double
{ dg-end-multiline-output "" } */
/* { dg-begin-multiline-output "" }
__builtin_printf(" %" "d ", 0.5);
~~~~^
+ |
+ int
%" "f
{ dg-end-multiline-output "" } */
}
@@ -324,5 +377,7 @@ void test_const_arrays (void)
/* { dg-begin-multiline-output "" }
__builtin_printf(a, 0.5);
^ ~~~
+ |
+ double
{ dg-end-multiline-output "" } */
}
diff --git a/gcc/testsuite/gcc.dg/format/pr72858.c b/gcc/testsuite/gcc.dg/format/pr72858.c
index b8c5829ed23..77260943c8c 100644
--- a/gcc/testsuite/gcc.dg/format/pr72858.c
+++ b/gcc/testsuite/gcc.dg/format/pr72858.c
@@ -28,12 +28,18 @@ test_x (char *d,
/* { dg-begin-multiline-output "" }
sprintf (d, " %-8x ", lexpr);
~~~^ ~~~~~
+ | |
+ | long int
+ unsigned int
%-8lx
{ dg-end-multiline-output "" } */
sprintf (d, " %-8x ", ulexpr); /* { dg-warning "20: format '%x' expects argument of type 'unsigned int', but argument 3 has type 'long unsigned int'" } */
/* { dg-begin-multiline-output "" }
sprintf (d, " %-8x ", ulexpr);
~~~^ ~~~~~~
+ | |
+ | long unsigned int
+ unsigned int
%-8lx
{ dg-end-multiline-output "" } */
@@ -41,12 +47,18 @@ test_x (char *d,
/* { dg-begin-multiline-output "" }
sprintf (d, " %-8x ", llexpr);
~~~^ ~~~~~~
+ | |
+ | long long int
+ unsigned int
%-8llx
{ dg-end-multiline-output "" } */
sprintf (d, " %-8x ", ullexpr); /* { dg-warning "20: format '%x' expects argument of type 'unsigned int', but argument 3 has type 'long long unsigned int'" } */
/* { dg-begin-multiline-output "" }
sprintf (d, " %-8x ", ullexpr);
~~~^ ~~~~~~~
+ | |
+ | long long unsigned int
+ unsigned int
%-8llx
{ dg-end-multiline-output "" } */
@@ -56,18 +68,27 @@ test_x (char *d,
/* { dg-begin-multiline-output "" }
sprintf (d, " %-8x ", fexpr);
~~~^ ~~~~~
+ | |
+ | double
+ unsigned int
%-8f
{ dg-end-multiline-output "" } */
sprintf (d, " %-8x ", dexpr); /* { dg-warning "20: format '%x' expects argument of type 'unsigned int', but argument 3 has type 'double'" } */
/* { dg-begin-multiline-output "" }
sprintf (d, " %-8x ", dexpr);
~~~^ ~~~~~
+ | |
+ | double
+ unsigned int
%-8f
{ dg-end-multiline-output "" } */
sprintf (d, " %-8x ", ldexpr); /* { dg-warning "20: format '%x' expects argument of type 'unsigned int', but argument 3 has type 'long double'" } */
/* { dg-begin-multiline-output "" }
sprintf (d, " %-8x ", ldexpr);
~~~^ ~~~~~~
+ | |
+ | long double
+ unsigned int
%-8Lf
{ dg-end-multiline-output "" } */
@@ -76,6 +97,9 @@ test_x (char *d,
/* { dg-begin-multiline-output "" }
sprintf (d, " %-8x ", ptr);
~~~^ ~~~
+ | |
+ | void *
+ unsigned int
%-8p
{ dg-end-multiline-output "" } */
@@ -86,6 +110,9 @@ test_x (char *d,
/* { dg-begin-multiline-output "" }
sprintf (d, " %-8x ", s);
~~~^ ~
+ | |
+ | struct s
+ unsigned int
{ dg-end-multiline-output "" } */
}
@@ -105,12 +132,18 @@ test_lx (char *d,
/* { dg-begin-multiline-output "" }
sprintf (d, " %-8lx ", iexpr);
~~~~^ ~~~~~
+ | |
+ | int
+ long unsigned int
%-8x
{ dg-end-multiline-output "" } */
sprintf (d, " %-8lx ", uiexpr); /* { dg-warning "21: format '%lx' expects argument of type 'long unsigned int', but argument 3 has type 'unsigned int'" } */
/* { dg-begin-multiline-output "" }
sprintf (d, " %-8lx ", uiexpr);
~~~~^ ~~~~~~
+ | |
+ | unsigned int
+ long unsigned int
%-8x
{ dg-end-multiline-output "" } */
@@ -121,12 +154,18 @@ test_lx (char *d,
/* { dg-begin-multiline-output "" }
sprintf (d, " %-8lx ", llexpr);
~~~~^ ~~~~~~
+ | |
+ | long long int
+ long unsigned int
%-8llx
{ dg-end-multiline-output "" } */
sprintf (d, " %-8lx ", ullexpr); /* { dg-warning "21: format '%lx' expects argument of type 'long unsigned int', but argument 3 has type 'long long unsigned int'" } */
/* { dg-begin-multiline-output "" }
sprintf (d, " %-8lx ", ullexpr);
~~~~^ ~~~~~~~
+ | |
+ | long long unsigned int
+ long unsigned int
%-8llx
{ dg-end-multiline-output "" } */
@@ -136,18 +175,27 @@ test_lx (char *d,
/* { dg-begin-multiline-output "" }
sprintf (d, " %-8lx ", fexpr);
~~~~^ ~~~~~
+ | |
+ | double
+ long unsigned int
%-8f
{ dg-end-multiline-output "" } */
sprintf (d, " %-8lx ", dexpr); /* { dg-warning "21: format '%lx' expects argument of type 'long unsigned int', but argument 3 has type 'double'" } */
/* { dg-begin-multiline-output "" }
sprintf (d, " %-8lx ", dexpr);
~~~~^ ~~~~~
+ | |
+ | double
+ long unsigned int
%-8f
{ dg-end-multiline-output "" } */
sprintf (d, " %-8lx ", ldexpr); /* { dg-warning "21: format '%lx' expects argument of type 'long unsigned int', but argument 3 has type 'long double'" } */
/* { dg-begin-multiline-output "" }
sprintf (d, " %-8lx ", ldexpr);
~~~~^ ~~~~~~
+ | |
+ | long double
+ long unsigned int
%-8Lf
{ dg-end-multiline-output "" } */
}
@@ -170,12 +218,18 @@ test_o (char *d,
/* { dg-begin-multiline-output "" }
sprintf (d, " %-8o ", lexpr);
~~~^ ~~~~~
+ | |
+ | long int
+ unsigned int
%-8lo
{ dg-end-multiline-output "" } */
sprintf (d, " %-8o ", ulexpr); /* { dg-warning "20: format '%o' expects argument of type 'unsigned int', but argument 3 has type 'long unsigned int'" } */
/* { dg-begin-multiline-output "" }
sprintf (d, " %-8o ", ulexpr);
~~~^ ~~~~~~
+ | |
+ | long unsigned int
+ unsigned int
%-8lo
{ dg-end-multiline-output "" } */
@@ -183,12 +237,18 @@ test_o (char *d,
/* { dg-begin-multiline-output "" }
sprintf (d, " %-8o ", llexpr);
~~~^ ~~~~~~
+ | |
+ | long long int
+ unsigned int
%-8llo
{ dg-end-multiline-output "" } */
sprintf (d, " %-8o ", ullexpr); /* { dg-warning "20: format '%o' expects argument of type 'unsigned int', but argument 3 has type 'long long unsigned int'" } */
/* { dg-begin-multiline-output "" }
sprintf (d, " %-8o ", ullexpr);
~~~^ ~~~~~~~
+ | |
+ | long long unsigned int
+ unsigned int
%-8llo
{ dg-end-multiline-output "" } */
}
@@ -208,12 +268,18 @@ test_lo (char *d,
/* { dg-begin-multiline-output "" }
sprintf (d, " %-8lo ", iexpr);
~~~~^ ~~~~~
+ | |
+ | int
+ long unsigned int
%-8o
{ dg-end-multiline-output "" } */
sprintf (d, " %-8lo ", uiexpr); /* { dg-warning "21: format '%lo' expects argument of type 'long unsigned int', but argument 3 has type 'unsigned int'" } */
/* { dg-begin-multiline-output "" }
sprintf (d, " %-8lo ", uiexpr);
~~~~^ ~~~~~~
+ | |
+ | unsigned int
+ long unsigned int
%-8o
{ dg-end-multiline-output "" } */
@@ -224,12 +290,18 @@ test_lo (char *d,
/* { dg-begin-multiline-output "" }
sprintf (d, " %-8lo ", llexpr);
~~~~^ ~~~~~~
+ | |
+ | long long int
+ long unsigned int
%-8llo
{ dg-end-multiline-output "" } */
sprintf (d, " %-8lo ", ullexpr); /* { dg-warning "21: format '%lo' expects argument of type 'long unsigned int', but argument 3 has type 'long long unsigned int'" } */
/* { dg-begin-multiline-output "" }
sprintf (d, " %-8lo ", ullexpr);
~~~~^ ~~~~~~~
+ | |
+ | long long unsigned int
+ long unsigned int
%-8llo
{ dg-end-multiline-output "" } */
}
@@ -246,6 +318,9 @@ test_e (char *d, int iexpr, float fexpr, double dexpr, long double ldexpr)
/* { dg-begin-multiline-output "" }
sprintf (d, " %-8e ", iexpr);
~~~^ ~~~~~
+ | |
+ | int
+ double
%-8d
{ dg-end-multiline-output "" } */
@@ -257,6 +332,9 @@ test_e (char *d, int iexpr, float fexpr, double dexpr, long double ldexpr)
/* { dg-begin-multiline-output "" }
sprintf (d, " %-8e ", ldexpr);
~~~^ ~~~~~~
+ | |
+ | long double
+ double
%-8Le
{ dg-end-multiline-output "" } */
}
@@ -273,6 +351,9 @@ test_Le (char *d, int iexpr, float fexpr, double dexpr, long double ldexpr)
/* { dg-begin-multiline-output "" }
sprintf (d, " %-8Le ", iexpr);
~~~~^ ~~~~~
+ | |
+ | int
+ long double
%-8d
{ dg-end-multiline-output "" } */
@@ -282,6 +363,9 @@ test_Le (char *d, int iexpr, float fexpr, double dexpr, long double ldexpr)
/* { dg-begin-multiline-output "" }
sprintf (d, " %-8Le ", fexpr);
~~~~^ ~~~~~
+ | |
+ | double
+ long double
%-8e
{ dg-end-multiline-output "" } */
@@ -289,6 +373,9 @@ test_Le (char *d, int iexpr, float fexpr, double dexpr, long double ldexpr)
/* { dg-begin-multiline-output "" }
sprintf (d, " %-8Le ", dexpr);
~~~~^ ~~~~~
+ | |
+ | double
+ long double
%-8e
{ dg-end-multiline-output "" } */
@@ -307,6 +394,9 @@ test_E (char *d, int iexpr, float fexpr, double dexpr, long double ldexpr)
/* { dg-begin-multiline-output "" }
sprintf (d, " %-8E ", iexpr);
~~~^ ~~~~~
+ | |
+ | int
+ double
%-8d
{ dg-end-multiline-output "" } */
@@ -318,6 +408,9 @@ test_E (char *d, int iexpr, float fexpr, double dexpr, long double ldexpr)
/* { dg-begin-multiline-output "" }
sprintf (d, " %-8E ", ldexpr);
~~~^ ~~~~~~
+ | |
+ | long double
+ double
%-8LE
{ dg-end-multiline-output "" } */
}
@@ -334,6 +427,9 @@ test_LE (char *d, int iexpr, float fexpr, double dexpr, long double ldexpr)
/* { dg-begin-multiline-output "" }
sprintf (d, " %-8LE ", iexpr);
~~~~^ ~~~~~
+ | |
+ | int
+ long double
%-8d
{ dg-end-multiline-output "" } */
@@ -341,6 +437,9 @@ test_LE (char *d, int iexpr, float fexpr, double dexpr, long double ldexpr)
/* { dg-begin-multiline-output "" }
sprintf (d, " %-8LE ", fexpr);
~~~~^ ~~~~~
+ | |
+ | double
+ long double
%-8E
{ dg-end-multiline-output "" } */
@@ -348,6 +447,9 @@ test_LE (char *d, int iexpr, float fexpr, double dexpr, long double ldexpr)
/* { dg-begin-multiline-output "" }
sprintf (d, " %-8LE ", dexpr);
~~~~^ ~~~~~
+ | |
+ | double
+ long double
%-8E
{ dg-end-multiline-output "" } */
@@ -367,18 +469,24 @@ test_everything (char *d, long lexpr)
/* { dg-begin-multiline-output "" }
sprintf (d, "before %-+*.*lld after", lexpr, lexpr, lexpr);
~~~^~~~~~ ~~~~~
+ | |
+ int long int
{ dg-end-multiline-output "" } */
/* { dg-warning "28: field precision specifier '\\.\\*' expects argument of type 'int', but argument 4 has type 'long int'" "" { target *-*-* } test_everything_sprintf } */
/* { dg-begin-multiline-output "" }
sprintf (d, "before %-+*.*lld after", lexpr, lexpr, lexpr);
~~~~~^~~~ ~~~~~
+ | |
+ int long int
{ dg-end-multiline-output "" } */
/* { dg-warning "31: format '%lld' expects argument of type 'long long int', but argument 5 has type 'long int'" "" { target *-*-* } test_everything_sprintf } */
/* { dg-begin-multiline-output "" }
sprintf (d, "before %-+*.*lld after", lexpr, lexpr, lexpr);
~~~~~~~~^ ~~~~~
+ | |
+ long long int long int
%-+*.*ld
{ dg-end-multiline-output "" } */
}
diff --git a/gcc/testsuite/gcc.dg/format/pr78498.c b/gcc/testsuite/gcc.dg/format/pr78498.c
index 4b53a68c2c0..b911b04eb7d 100644
--- a/gcc/testsuite/gcc.dg/format/pr78498.c
+++ b/gcc/testsuite/gcc.dg/format/pr78498.c
@@ -7,6 +7,8 @@ void f (void)
/* { dg-begin-multiline-output "" }
__builtin_printf ("%i", "");
~^ ~~
+ | |
+ int char *
%s
{ dg-end-multiline-output "" } */
}
diff --git a/gcc/testsuite/gcc.dg/param-type-mismatch.c b/gcc/testsuite/gcc.dg/param-type-mismatch.c
index 9498a748f30..9e654a9e9c6 100644
--- a/gcc/testsuite/gcc.dg/param-type-mismatch.c
+++ b/gcc/testsuite/gcc.dg/param-type-mismatch.c
@@ -1,4 +1,4 @@
-/* { dg-options "-fdiagnostics-show-caret" } */
+/* { dg-options "-fdiagnostics-show-caret -Wpointer-sign" } */
/* A collection of calls where argument 2 is of the wrong type. */
@@ -12,6 +12,8 @@ int test_1 (int first, int second, float third)
/* { dg-begin-multiline-output "" }
return callee_1 (first, second, third);
^~~~~~
+ |
+ int
{ dg-end-multiline-output "" } */
/* { dg-message "expected 'const char \\*' but argument is of type 'int'" "" { target *-*-* } callee_1 } */
/* { dg-begin-multiline-output "" }
@@ -30,6 +32,8 @@ int test_2 (int first, int second, float third)
/* { dg-begin-multiline-output "" }
return callee_2 (first, second, third);
^~~~~~
+ |
+ int
{ dg-end-multiline-output "" } */
/* { dg-message "expected 'const char \\*' but argument is of type 'int'" "" { target *-*-* } callee_2 } */
/* { dg-begin-multiline-output "" }
@@ -51,6 +55,8 @@ int test_3 (int first, int second, float third)
/* { dg-begin-multiline-output "" }
return callee_3 (first, second, third);
^~~~~~
+ |
+ int
{ dg-end-multiline-output "" } */
/* { dg-message "expected 'const char \\*' but argument is of type 'int'" "" { target *-*-* } callee_3 } */
/* { dg-begin-multiline-output "" }
@@ -69,6 +75,8 @@ int test_4 (int first, const char *second, float third)
/* { dg-begin-multiline-output "" }
return callee_4 (first, second, third);
^~~~~~
+ |
+ const char *
{ dg-end-multiline-output "" } */
/* { dg-message "expected 'float' but argument is of type 'const char \\*'" "" { target *-*-* } callee_4 } */
/* { dg-begin-multiline-output "" }
@@ -87,6 +95,8 @@ int test_5 (int first, const char *second, float third)
/* { dg-begin-multiline-output "" }
return callee_5 (first, second, third);
^~~~~~
+ |
+ const char *
{ dg-end-multiline-output "" } */
/* { dg-message "expected 'float' but argument is of type 'const char \\*'" "" { target *-*-* } callee_5 } */
/* { dg-begin-multiline-output "" }
@@ -105,6 +115,8 @@ int test_6 (int first, int second, float third)
/* { dg-begin-multiline-output "" }
return callee_6 (first, second, third);
^~~~~~
+ |
+ int
{ dg-end-multiline-output "" } */
/* { dg-message " expected 'int \\(\\*\\)\\(int, int\\)' but argument is of type 'int'" "" { target *-*-* } callee_6 } */
/* { dg-begin-multiline-output "" }
@@ -123,6 +135,8 @@ int test_7 (int first, int second, float third)
/* { dg-begin-multiline-output "" }
return callee_7 (first, second, third);
^~~~~~
+ |
+ int
{ dg-end-multiline-output "" } */
/* { dg-message " expected 'int \\(\\*\\)\\(int, int\\)' but argument is of type 'int'" "" { target *-*-* } callee_7 } */
/* { dg-begin-multiline-output "" }
@@ -130,3 +144,43 @@ int test_7 (int first, int second, float third)
^~~~~~~~~~~~~~~~~
{ dg-end-multiline-output "" } */
}
+
+/* -Wincompatible-pointer-types for a parameter. */
+
+extern int callee_8 (int one, float *two, float (three)); /* { dg-line callee_8 } */
+
+int test_8 (int first, int *second, float third)
+{
+ return callee_8 (first, second, third); /* { dg-warning "passing argument 2 of 'callee_8' from incompatible pointer type" } */
+ /* { dg-begin-multiline-output "" }
+ return callee_8 (first, second, third);
+ ^~~~~~
+ |
+ int *
+ { dg-end-multiline-output "" } */
+ /* { dg-message "expected 'float \\*' but argument is of type 'int \\*'" "" { target *-*-* } callee_8 } */
+ /* { dg-begin-multiline-output "" }
+ extern int callee_8 (int one, float *two, float (three));
+ ~~~~~~~^~~
+ { dg-end-multiline-output "" } */
+}
+
+/* -Wpointer-sign for a parameter. */
+
+extern int callee_9 (int one, int *two, float (three)); /* { dg-line callee_9 } */
+
+int test_9 (int first, unsigned int *second, float third)
+{
+ return callee_9 (first, second, third); /* { dg-warning "pointer targets in passing argument 2 of 'callee_9' differ in signedness" } */
+ /* { dg-begin-multiline-output "" }
+ return callee_9 (first, second, third);
+ ^~~~~~
+ |
+ unsigned int *
+ { dg-end-multiline-output "" } */
+ /* { dg-message "expected 'int \\*' but argument is of type 'unsigned int \\*'" "" { target *-*-* } callee_9 } */
+ /* { dg-begin-multiline-output "" }
+ extern int callee_9 (int one, int *two, float (three));
+ ~~~~~^~~
+ { dg-end-multiline-output "" } */
+}
diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-bw-line-numbers.c b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-bw-line-numbers.c
index 66a2faae40d..89213eb2b25 100644
--- a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-bw-line-numbers.c
+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-bw-line-numbers.c
@@ -31,6 +31,8 @@ void test_multiline (void)
| ~~~~~~~~~~~~~~~~~
27 | + second_function ());
| ^ ~~~~~~~~~~~~~~~~~~
+ | |
+ | label
{ dg-end-multiline-output "" } */
#endif
}
@@ -43,8 +45,10 @@ void test_very_wide_line (void)
| 0 0 0 0 0 0 1
| 4 5 6 7 8 9 0
| 0123456789012345678901234567890123456789012345678901234567890123456789
-41 | float f = foo * bar;
+43 | float f = foo * bar;
| ~~~~^~~~~
+ | |
+ | label
| bar * foo
{ dg-end-multiline-output "" } */
#endif
@@ -58,7 +62,7 @@ void test_fixit_insert (void)
#if 0
int a[2][2] = { 0, 1 , 2, 3 }; /* { dg-warning "insertion hints" } */
/* { dg-begin-multiline-output "" }
-59 | int a[2][2] = { 0, 1 , 2, 3 };
+63 | int a[2][2] = { 0, 1 , 2, 3 };
| ^~~~
| { }
{ dg-end-multiline-output "" } */
@@ -72,7 +76,7 @@ void test_fixit_remove (void)
#if 0
int a;; /* { dg-warning "example of a removal hint" } */
/* { dg-begin-multiline-output "" }
-73 | int a;;
+77 | int a;;
| ^
| -
{ dg-end-multiline-output "" } */
@@ -86,7 +90,7 @@ void test_fixit_replace (void)
#if 0
gtk_widget_showall (dlg); /* { dg-warning "example of a replacement hint" } */
/* { dg-begin-multiline-output "" }
-87 | gtk_widget_showall (dlg);
+91 | gtk_widget_showall (dlg);
| ^~~~~~~~~~~~~~~~~~
| gtk_widget_show_all
{ dg-end-multiline-output "" } */
@@ -108,7 +112,7 @@ void test_fixit_insert_newline (void)
}
/* { dg-begin-multiline-output "" }
|+ break;
-106 | case 'b':
+110 | case 'b':
| ^~~~~~~~
{ dg-end-multiline-output "" } */
#endif
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 513c0af772f..bdfa420d849 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
@@ -44,6 +44,8 @@ void test_multiline (void)
~~~~~~~~~~~~~~~~~
+ second_function ());
^ ~~~~~~~~~~~~~~~~~~
+ |
+ label
{ dg-end-multiline-output "" } */
#endif
}
@@ -66,6 +68,8 @@ void test_many_lines (void)
/* { dg-begin-multiline-output "" }
x = (first_function_with_a_very_long_name (lorem, ipsum, dolor, sit, amet,
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ |
+ label 1
consectetur, adipiscing, elit,
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sed, eiusmod, tempor,
@@ -76,6 +80,9 @@ void test_many_lines (void)
~~~~~~~~~~~~~~~~~~~~~~
+ second_function_with_a_very_long_name (lorem, ipsum, dolor, sit,
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | |
+ | label 2
+ label 0
amet, consectetur,
~~~~~~~~~~~~~~~~~~
adipiscing, elit, sed,
@@ -115,13 +122,32 @@ void test_caret_within_proper_range (void)
void test_very_wide_line (void)
{
#if 0
- float f = foo * bar; /* { dg-warning "95: test" } */
+ float x = foo * bar; /* { dg-warning "95: test" } */
/* { dg-begin-multiline-output "" }
0 0 0 0 0 0 1
4 5 6 7 8 9 0
6789012345678901234567890123456789012345678901234567890123456789012345
- float f = foo * bar;
+ x = foo * bar;
+ ~ ~~~~^~~~~
+ | |
+ label 1 label 0
+ bar * foo
+ { dg-end-multiline-output "" } */
+#endif
+}
+
+void test_very_wide_line_2 (void)
+{
+#if 0
+ float x = foo * bar; /* { dg-warning "95: test" } */
+/* { dg-begin-multiline-output "" }
+ 0 0 0 0 0 0 1
+ 4 5 6 7 8 9 0
+ 6789012345678901234567890123456789012345678901234567890123456789012345
+ = foo * bar;
~~~~^~~~~
+ |
+ label 0
bar * foo
{ dg-end-multiline-output "" } */
#endif
@@ -226,27 +252,69 @@ void test_many_nested_locations (void)
^
Lorem ipsum dolor sit amet, consectetur adipiscing elit,
^~~~~ ^~~~~ ^~~~~ ^~~ ^~~~ ^~~~~~~~~~~ ^~~~~~~~~~ ^~~~
+ | | | | | | | |
+ | | | | label label label label
+ label label label label
LOREM IPSUM DOLOR SIT AMET CONSECTETUR ADIPISCING ELIT
sed do eiusmod tempor incididunt ut labore et dolore magna
^~~ ^~ ^~~~~~~ ^~~~~~ ^~~~~~~~~~ ^~ ^~~~~~ ^~ ^~~~~~ ^~~~~
+ | | | | | | | | | |
+ | | | | | | | | label label
+ | | | | | | label label
+ | | label label label label
+ | label
+ label
SED DO EIUSMOD TEMPOR INCIDIDUNT UT LABORE ET DOLORE MAGNA
aliqua. Ut enim ad minim veniam, quis nostrud exercitation
^~~~~~ ^~ ^~~~ ^~ ^~~~~ ^~~~~~ ^~~~ ^~~~~~~ ^~~~~~~~~~~~
+ | | | | | | | | |
+ | | | | | | | label label
+ | | | | label label label
+ | | | label
+ | | label
+ label label
ALIQUA UT ENIM AD MINIM VENIAM QUIS NOSTRUD EXERCITATION
ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis
^~~~~~~ ^~~~~~~ ^~~~ ^~ ^~~~~~~ ^~ ^~ ^~~~~~~ ^~~~~~~~~ ^~~~
+ | | | | | | | | | |
+ | | | | | | | label label label
+ | | | | | | label
+ | | | | label label
+ | | | label
+ label label label
ULLAMCO LABORIS NISI UT ALIQUIP EX EA COMMODO CONSEQUAT DUIS
aute irure dolor in reprehenderit in voluptate velit esse cillum
^~~~ ^~~~~ ^~~~~ ^~ ^~~~~~~~~~~~~ ^~ ^~~~~~~~~ ^~~~~ ^~~~ ^~~~~~
+ | | | | | | | | | |
+ | | | | | | | | | label
+ | | | | | | label label label
+ | | | | label label
+ | label label label
+ label
AUTE IRURE DOLOR IN REPREHENDERIT IN VOLUPTATE VELIT ESSE CILLUM
dolore eu fugiat nulla pariatur. Excepteur sint occaecat
^~~~~~ ^~ ^~~~~~ ^~~~~ ^~~~~~~~ ^~~~~~~~~ ^~~~ ^~~~~~~~
+ | | | | | | | |
+ | | | | | | | label
+ | | label label label label label
+ label label
DOLORE EU FUGIAT NULLA PARIATUR EXCEPTEUR SINT OCCAECAT
cupidatat non proident, sunt in culpa qui officia deserunt
^~~~~~~~~ ^~~ ^~~~~~~~ ^~~~ ^~ ^~~~~ ^~~ ^~~~~~~ ^~~~~~~~
+ | | | | | | | | |
+ | | | | | | | label label
+ | | | | | label label
+ | | | | label
+ | | label label
+ label label
CUPIDATAT NON PROIDENT SUNT IN CULPA QUI OFFICIA DESERUNT
mollit anim id est laborum.
^~~~~~ ^~~~ ^~ ^~~ ^~~~~~~
+ | | | | |
+ | | | | label
+ | | | label
+ | | label
+ label label
MOLLIT ANIM ID EST LABORUM
{ dg-end-multiline-output "" } */
}
diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-color-line-numbers.c b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-color-line-numbers.c
index a80b6de3e68..0453c52b2cc 100644
--- a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-color-line-numbers.c
+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-color-line-numbers.c
@@ -19,6 +19,8 @@ void test_multiline (void)
| ~~~~~~~~~~~~~~~~~
15 | + second_function ());
| ^ ~~~~~~~~~~~~~~~~~~
+ | |
+ | label
{ 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 4cc406d76de..094bc6535d5 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
@@ -44,6 +44,8 @@ void test_multiline (void)
~~~~~~~~~~~~~~~~~
+ second_function ());
^ ~~~~~~~~~~~~~~~~~~
+ |
+ label
{ dg-end-multiline-output "" } */
#endif
}
@@ -66,6 +68,8 @@ void test_many_lines (void)
/* { dg-begin-multiline-output "" }
x = (first_function_with_a_very_long_name (lorem, ipsum, dolor, sit, amet,
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ |
+ label 1
 consectetur, adipiscing, elit,
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 sed, eiusmod, tempor,
@@ -76,6 +80,9 @@ void test_many_lines (void)
~~~~~~~~~~~~~~~~~~~~~~
+ second_function_with_a_very_long_name (lorem, ipsum, dolor, sit,
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | |
+ | label 2
+ label 0
 amet, consectetur,
~~~~~~~~~~~~~~~~~~
 adipiscing, elit, sed,
@@ -115,13 +122,15 @@ void test_caret_within_proper_range (void)
void test_very_wide_line (void)
{
#if 0
- float f = foo * bar; /* { dg-warning "95: test" } */
+ float x = foo * bar; /* { dg-warning "95: test" } */
/* { dg-begin-multiline-output "" }
0 0 0 0 0 0 1
4 5 6 7 8 9 0
6789012345678901234567890123456789012345678901234567890123456789012345
- float f = foo * bar;
- ~~~~^~~~~
+ x = foo * bar;
+ ~ ~~~~^~~~~
+ | |
+ label 1 label 0
bar * foo
{ dg-end-multiline-output "" } */
#endif
diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-no-labels.c b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-no-labels.c
new file mode 100644
index 00000000000..4c06368a201
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-no-labels.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdiagnostics-show-caret -fno-diagnostics-show-labels" } */
+
+/* Verify that -fno-diagnostics-show-labels works. */
+
+/* This is a collection of unittests for diagnostic_show_locus;
+ see the overview in diagnostic_plugin_test_show_locus.c.
+
+ In particular, note the discussion of why we need a very long line here:
+01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+ and that we can't use macros in this file. */
+
+void test_multiline (void)
+{
+#if 0
+ x = (first_function ()
+ + second_function ()); /* { dg-warning "test" } */
+
+ /* This shouldn't have a label. */
+ /* { dg-begin-multiline-output "" }
+ x = (first_function ()
+ ~~~~~~~~~~~~~~~~~
+ + second_function ());
+ ^ ~~~~~~~~~~~~~~~~~~
+ { dg-end-multiline-output "" } */
+#endif
+}
diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_show_trees.c b/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_show_trees.c
index 0bdd877dbd5..71e6740b178 100644
--- a/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_show_trees.c
+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_show_trees.c
@@ -41,7 +41,7 @@ show_tree (tree node)
return;
gcc_rich_location richloc (EXPR_LOCATION (node));
- richloc.add_expr (node);
+ richloc.add_expr (node, NULL);
if (richloc.get_num_locations () < 2)
{
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 1d340aa0e6a..3d7853813ae 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
@@ -145,9 +145,10 @@ custom_diagnostic_finalizer (diagnostic_context *context,
static void
add_range (rich_location *richloc, location_t start, location_t finish,
- bool show_caret_p)
+ bool show_caret_p, const range_label *label = NULL)
{
- richloc->add_range (make_location (start, start, finish), show_caret_p);
+ richloc->add_range (make_location (start, start, finish), show_caret_p,
+ label);
}
/* Exercise the diagnostic machinery to emit various warnings,
@@ -192,7 +193,8 @@ test_show_locus (function *fun)
if (0 == strcmp (fnname, "test_multiline"))
{
const int line = fnstart_line + 2;
- rich_location richloc (line_table, get_loc (line + 1, 7));
+ text_range_label label ("label");
+ rich_location richloc (line_table, get_loc (line + 1, 7), &label);
add_range (&richloc, get_loc (line, 7), get_loc (line, 23), false);
add_range (&richloc, get_loc (line + 1, 9), get_loc (line + 1, 26),
false);
@@ -202,10 +204,14 @@ test_show_locus (function *fun)
if (0 == strcmp (fnname, "test_many_lines"))
{
const int line = fnstart_line + 2;
- rich_location richloc (line_table, get_loc (line + 5, 7));
- add_range (&richloc, get_loc (line, 7), get_loc (line + 4, 65), false);
+ text_range_label label0 ("label 0");
+ text_range_label label1 ("label 1");
+ text_range_label label2 ("label 2");
+ rich_location richloc (line_table, get_loc (line + 5, 7), &label0);
+ add_range (&richloc, get_loc (line, 7), get_loc (line + 4, 65), false,
+ &label1);
add_range (&richloc, get_loc (line + 5, 9), get_loc (line + 10, 61),
- false);
+ false, &label2);
warning_at (&richloc, 0, "test");
}
@@ -231,16 +237,40 @@ test_show_locus (function *fun)
}
/* Example of a very wide line, where the information of interest
- is beyond the width of the terminal (hardcoded above). */
+ is beyond the width of the terminal (hardcoded above), with
+ a secondary location that exactly fits on the left-margin. */
if (0 == strcmp (fnname, "test_very_wide_line"))
{
const int line = fnstart_line + 2;
global_dc->show_ruler_p = true;
+ text_range_label label0 ("label 0");
+ text_range_label label1 ("label 1");
+ rich_location richloc (line_table,
+ make_location (get_loc (line, 94),
+ get_loc (line, 90),
+ get_loc (line, 98)),
+ &label0);
+ richloc.add_range (get_loc (line, 35), false, &label1);
+ richloc.add_fixit_replace ("bar * foo");
+ warning_at (&richloc, 0, "test");
+ global_dc->show_ruler_p = false;
+ }
+
+ /* Likewise, but with a secondary location that's immediately before
+ the left margin; the location and label should be gracefully dropped. */
+ if (0 == strcmp (fnname, "test_very_wide_line_2"))
+ {
+ const int line = fnstart_line + 2;
+ global_dc->show_ruler_p = true;
+ text_range_label label0 ("label 0");
+ text_range_label label1 ("label 1");
rich_location richloc (line_table,
make_location (get_loc (line, 94),
get_loc (line, 90),
- get_loc (line, 98)));
+ get_loc (line, 98)),
+ &label0);
richloc.add_fixit_replace ("bar * foo");
+ richloc.add_range (get_loc (line, 34), false, &label1);
warning_at (&richloc, 0, "test");
global_dc->show_ruler_p = false;
}
@@ -391,13 +421,14 @@ test_show_locus (function *fun)
/* Example of many locations and many fixits.
Underline (separately) every word in a comment, and convert them
- to upper case. */
+ to upper case. Give all of the ranges labels (sharing one label). */
if (0 == strcmp (fnname, "test_many_nested_locations"))
{
const char *file = LOCATION_FILE (fnstart);
const int start_line = fnstart_line + 2;
const int finish_line = start_line + 7;
location_t loc = get_loc (start_line - 1, 2);
+ text_range_label label ("label");
rich_location richloc (line_table, loc);
for (int line = start_line; line <= finish_line; line++)
{
@@ -418,7 +449,7 @@ test_show_locus (function *fun)
location_t word
= make_location (start_of_word, start_of_word,
end_of_word);
- richloc.add_range (word, true);
+ richloc.add_range (word, true, &label);
/* Add a fixit, converting to upper case. */
char_span word_span = content.subspan (start_idx, idx - start_idx);
diff --git a/gcc/testsuite/gcc.dg/plugin/plugin.exp b/gcc/testsuite/gcc.dg/plugin/plugin.exp
index b2f8507338a..86ab1dd8d93 100644
--- a/gcc/testsuite/gcc.dg/plugin/plugin.exp
+++ b/gcc/testsuite/gcc.dg/plugin/plugin.exp
@@ -72,6 +72,7 @@ set plugin_test_list [list \
{ diagnostic_plugin_test_show_locus.c \
diagnostic-test-show-locus-bw.c \
diagnostic-test-show-locus-color.c \
+ diagnostic-test-show-locus-no-labels.c \
diagnostic-test-show-locus-bw-line-numbers.c \
diagnostic-test-show-locus-color-line-numbers.c \
diagnostic-test-show-locus-parseable-fixits.c \
diff --git a/gcc/testsuite/gcc.dg/pr69554-1.c b/gcc/testsuite/gcc.dg/pr69554-1.c
index 07ad0db7cf6..b979b5596f2 100644
--- a/gcc/testsuite/gcc.dg/pr69554-1.c
+++ b/gcc/testsuite/gcc.dg/pr69554-1.c
@@ -12,6 +12,9 @@ int test_1 (const char *p, const char *q)
/* { dg-begin-multiline-output "" }
return (p + 1) + (q + 1);
~~~~~~~ ^ ~~~~~~~
+ | |
+ | const char *
+ const char *
{ dg-end-multiline-output "" } */
}
@@ -26,10 +29,14 @@ int test_2 (const char *p, const char *q)
/* { dg-begin-multiline-output "" }
return (p + 1)
~~~~~~~
+ |
+ const char *
+
^
(q + 1);
~~~~~~~
+ |
+ const char *
{ dg-end-multiline-output "" } */
}
@@ -43,16 +50,20 @@ int test_3 (const char *p, const char *q)
+ /* { dg-error "invalid operands" } */
(q + 1);
-/* { dg-locus "12" "" { target *-*-* } "44" } */
+/* { dg-locus "12" "" { target *-*-* } "51" } */
/* { dg-begin-multiline-output "" }
return (p + 1)
~~~~~~~
+ |
+ const char *
{ dg-end-multiline-output "" } */
/* { dg-begin-multiline-output "" }
+
^
(q + 1);
~~~~~~~
+ |
+ const char *
{ dg-end-multiline-output "" } */
}
@@ -68,12 +79,16 @@ int test_4 (const char *p, const char *q)
/* { dg-begin-multiline-output "" }
return (p + 1)
~~~~~~~
+ |
+ const char *
+
^
{ dg-end-multiline-output "" } */
/* { dg-begin-multiline-output "" }
(q + 1);
~~~~~~~
+ |
+ const char *
{ dg-end-multiline-output "" } */
}
@@ -88,10 +103,12 @@ int test_5 (const char *p, const char *q)
+ /* { dg-error "invalid operands" } */
(q + 1); /* { dg-locus "14" } */
-/* { dg-locus "12" "" { target *-*-* } "88" } */
+/* { dg-locus "12" "" { target *-*-* } "103" } */
/* { dg-begin-multiline-output "" }
return (p + 1)
~~~~~~~
+ |
+ const char *
{ dg-end-multiline-output "" } */
/* { dg-begin-multiline-output "" }
+
@@ -100,6 +117,8 @@ int test_5 (const char *p, const char *q)
/* { dg-begin-multiline-output "" }
(q + 1);
~~~~~~~
+ |
+ const char *
{ dg-end-multiline-output "" } */
}
@@ -136,10 +155,12 @@ int test_6 (const char *p, const char *q)
fringilla sapien elit vitae nisl. Fusce mattis commodo risus
nec convallis. */
(q + 1); /* { dg-locus "14" } */
-/* { dg-locus "12" "" { target *-*-* } "125" } */
+/* { dg-locus "12" "" { target *-*-* } "144" } */
/* { dg-begin-multiline-output "" }
return (p + 1)
~~~~~~~
+ |
+ const char *
{ dg-end-multiline-output "" } */
/* { dg-begin-multiline-output "" }
+
@@ -148,5 +169,7 @@ int test_6 (const char *p, const char *q)
/* { dg-begin-multiline-output "" }
(q + 1);
~~~~~~~
+ |
+ const char *
{ dg-end-multiline-output "" } */
}
diff --git a/gcc/testsuite/gcc.dg/pr69627.c b/gcc/testsuite/gcc.dg/pr69627.c
index b7f56cd4ac7..bc48bb1aa81 100644
--- a/gcc/testsuite/gcc.dg/pr69627.c
+++ b/gcc/testsuite/gcc.dg/pr69627.c
@@ -11,6 +11,8 @@ foo ()
/* { dg-begin-multiline-output "" }
t[1] / s;
~~~~ ^
+ |
+ float
{ dg-end-multiline-output "" } */
}
@@ -23,5 +25,7 @@ bar ()
/* { dg-begin-multiline-output "" }
t[1] / s[0];
~~~~ ^ ~~~~
+ | |
+ float const int *
{ dg-end-multiline-output "" } */
}
diff --git a/gcc/testsuite/lib/multiline.exp b/gcc/testsuite/lib/multiline.exp
index 84c59e1efd4..5f8b62fd301 100644
--- a/gcc/testsuite/lib/multiline.exp
+++ b/gcc/testsuite/lib/multiline.exp
@@ -202,26 +202,6 @@ proc _build_multiline_regex { multiline index } {
if {[string match "*^" $line] || [string match "*~" $line]} {
# Assume a line containing a caret/range. This must be
# an exact match.
- } elseif {[string match "*\\|" $line]} {
- # Assume a source line with a right-margin. Support
- # arbitrary text in place of any whitespace before the
- # right-margin, to deal with comments containing containing
- # DejaGnu directives.
-
- # Remove final "\|":
- set rexp [string range $rexp 0 [expr [string length $rexp] - 3]]
-
- # Trim off trailing whitespace:
- set old_length [string length $rexp]
- set rexp [string trimright $rexp]
- set new_length [string length $rexp]
-
- # Replace the trimmed whitespace with "." chars to match anything:
- set ws [string repeat "." [expr $old_length - $new_length]]
- set rexp "${rexp}${ws}"
-
- # Add back the trailing '\|':
- set rexp "${rexp}\\|"
} else {
# Assume that we have a quoted source line.
if {![string equal "" $line] } {
diff --git a/gcc/toplev.c b/gcc/toplev.c
index aa943a8655e..2789d71b24f 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -1112,6 +1112,8 @@ general_init (const char *argv0, bool init_signals)
global_dc->show_caret
= global_options_init.x_flag_diagnostics_show_caret;
+ global_dc->show_labels_p
+ = global_options_init.x_flag_diagnostics_show_labels;
global_dc->show_line_numbers_p
= global_options_init.x_flag_diagnostics_show_line_numbers;
global_dc->show_option_requested
diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog
index 3eaebfd812f..a39144c6b01 100644
--- a/libcpp/ChangeLog
+++ b/libcpp/ChangeLog
@@ -1,3 +1,17 @@
+2018-08-15 David Malcolm <dmalcolm@redhat.com>
+
+ * 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.
+
2018-08-08 Nathan Sidwell <nathan@acm.org>
Make linemap::included_from a location
diff --git a/libcpp/include/line-map.h b/libcpp/include/line-map.h
index 1061d201389..4f0ff8719a7 100644
--- a/libcpp/include/line-map.h
+++ b/libcpp/include/line-map.h
@@ -1281,8 +1281,11 @@ typedef struct
bool sysp;
} expanded_location;
+class range_label;
+
/* A location within a rich_location: a caret&range, with
- the caret potentially flagged for display. */
+ the caret potentially flagged for display, and an optional
+ label. */
struct location_range
{
@@ -1298,6 +1301,9 @@ struct location_range
where "1" and "2" are notionally carets. */
bool m_show_caret_p;
+
+ /* If non-NULL, the label for this range. */
+ const range_label *m_label;
};
/* A partially-embedded vec for use within rich_location for storing
@@ -1439,6 +1445,8 @@ class fixit_hint;
Additional ranges may be added to help the user identify other
pertinent clauses in a diagnostic.
+ Ranges can (optionally) be given labels via class range_label.
+
rich_location instances are intended to be allocated on the stack
when generating diagnostics, and to be short-lived.
@@ -1484,18 +1492,22 @@ class fixit_hint;
equal to their caret point. The frontend overrides the diagnostic
context's default caret character for these ranges.
- Example E
- *********
+ Example E (range labels)
+ ************************
printf ("arg0: %i arg1: %s arg2: %i",
^~
+ |
+ const char *
100, 101, 102);
~~~
+ |
+ int
This rich location has two ranges:
- range 0 is at the "%s" with start = caret = "%" and finish at
- the "s".
+ the "s". It has a range_label ("const char *").
- range 1 has start/finish covering the "101" and is not flagged for
- caret printing; it is perhaps at the start of "101".
-
+ caret printing. The caret is at the start of "101", where its
+ range_label is printed ("int").
Fix-it hints
------------
@@ -1587,7 +1599,8 @@ class rich_location
/* Constructors. */
/* Constructing from a location. */
- rich_location (line_maps *set, source_location loc);
+ rich_location (line_maps *set, source_location loc,
+ const range_label *label = NULL);
/* Destructor. */
~rich_location ();
@@ -1597,7 +1610,8 @@ class rich_location
source_location get_loc (unsigned int idx) const;
void
- add_range (source_location loc, bool show_caret_p);
+ add_range (source_location loc, bool show_caret_p,
+ const range_label *label = NULL);
void
set_range (unsigned int idx, source_location loc, bool show_caret_p);
@@ -1721,6 +1735,54 @@ protected:
bool m_fixits_cannot_be_auto_applied;
};
+/* A struct for the result of range_label::get_text: a NUL-terminated buffer
+ of localized text, and a flag to determine if the caller should "free" the
+ buffer. */
+
+struct label_text
+{
+ label_text ()
+ : m_buffer (NULL), m_caller_owned (false)
+ {}
+
+ label_text (char *buffer, bool caller_owned)
+ : m_buffer (buffer), m_caller_owned (caller_owned)
+ {}
+
+ void maybe_free ()
+ {
+ if (m_caller_owned)
+ free (m_buffer);
+ }
+
+ char *m_buffer;
+ bool m_caller_owned;
+};
+
+/* Abstract base class for labelling a range within a rich_location
+ (e.g. for labelling expressions with their type).
+
+ Generating the text could require non-trivial work, so this work
+ is delayed (via the "get_text" virtual function) until the diagnostic
+ printing code "knows" it needs it, thus avoiding doing it e.g. for
+ warnings that are filtered by command-line flags. This virtual
+ function also isolates libcpp and the diagnostics subsystem from
+ the front-end and middle-end-specific code for generating the text
+ for the labels.
+
+ Like the rich_location instances they annotate, range_label instances
+ are intended to be allocated on the stack when generating diagnostics,
+ and to be short-lived. */
+
+class range_label
+{
+ public:
+ virtual ~range_label () {}
+
+ /* Get localized text for the label. */
+ virtual label_text get_text () const = 0;
+};
+
/* A fix-it hint: a suggested insertion, replacement, or deletion of text.
We handle these three types of edit with one class, by representing
them as replacement of a half-open range:
diff --git a/libcpp/line-map.c b/libcpp/line-map.c
index 555cd129a9c..f0e6318e412 100644
--- a/libcpp/line-map.c
+++ b/libcpp/line-map.c
@@ -1988,7 +1988,8 @@ line_table_dump (FILE *stream, struct line_maps *set, unsigned int num_ordinary,
/* Construct a rich_location with location LOC as its initial range. */
-rich_location::rich_location (line_maps *set, source_location loc) :
+rich_location::rich_location (line_maps *set, source_location loc,
+ const range_label *label) :
m_line_table (set),
m_ranges (),
m_column_override (0),
@@ -1997,7 +1998,7 @@ rich_location::rich_location (line_maps *set, source_location loc) :
m_seen_impossible_fixit (false),
m_fixits_cannot_be_auto_applied (false)
{
- add_range (loc, true);
+ add_range (loc, true, label);
}
/* The destructor for class rich_location. */
@@ -2073,11 +2074,13 @@ rich_location::override_column (int column)
/* Add the given range. */
void
-rich_location::add_range (source_location loc, bool show_caret_p)
+rich_location::add_range (source_location loc, bool show_caret_p,
+ const range_label *label)
{
location_range range;
range.m_loc = loc;
range.m_show_caret_p = show_caret_p;
+ range.m_label = label;
m_ranges.push (range);
}