aboutsummaryrefslogtreecommitdiff
path: root/gcc/testsuite/g++.dg/warn/Wformat-gcc_diag-2.C
diff options
context:
space:
mode:
authorDavid Malcolm <dmalcolm@redhat.com>2024-07-13 10:34:51 -0400
committerDavid Malcolm <dmalcolm@redhat.com>2024-07-13 10:34:51 -0400
commit7d73c01ce6d1ab28157a7dadcd3be14f96a7c8f3 (patch)
tree19ff9b197aa6635ad127839f17933febd9503132 /gcc/testsuite/g++.dg/warn/Wformat-gcc_diag-2.C
parentabf3964711f05b6858d9775c3595ec2b45483e14 (diff)
downloadgcc-7d73c01ce6d1ab28157a7dadcd3be14f96a7c8f3.zip
gcc-7d73c01ce6d1ab28157a7dadcd3be14f96a7c8f3.tar.gz
gcc-7d73c01ce6d1ab28157a7dadcd3be14f96a7c8f3.tar.bz2
diagnostics: add highlight-a vs highlight-b in colorization and pp_markup
Since r6-4582-g8a64515099e645 (which added class rich_location), ranges of quoted source code have been colorized using the following rules: - the primary range used the same color of the kind of the diagnostic i.e. "error" vs "warning" etc (defaulting to bold red and bold magenta respectively) - secondary ranges alternate between "range1" and "range2" (defaulting to green and blue respectively) This works for cases with large numbers of highlighted ranges, but is suboptimal for common cases. The following patch adds a pair of color names: "highlight-a" and "highlight-b", and uses them whenever it makes sense to highlight and contrast two different things in the source code (e.g. a type mismatch). These are used by diagnostic-show-locus.cc for highlighting quoted source. In addition the patch adds colorization to fragments within the corresponding diagnostic messages themselves, using consistent colorization between the message and the quoted source code for the two different things being contrasted. For example, consider: demo.c: In function ‘test_bad_format_string_args’: ../../src/demo.c:25:18: warning: format ‘%i’ expects argument of type ‘int’, but argument 2 has type ‘const char *’ [-Wformat=] 25 | printf("hello %i", msg); | ~^ ~~~ | | | | int const char * | %s Previously, the types within the message in quotes would be in bold but not colorized, and the labelled ranges of quoted source code would use bold magenta for the "int" and non-bold green for the "const char *". With this patch: - the "%i" and "int" in the message and the "int" in the quoted source are all colored bold green - the "const char *" in the message and in the quoted source are both colored bold blue so that the consistent use of contrasting color draws the reader's eyes to the relationships between the diagnostic message and the source. I've tried this with gnome-terminal with many themes, including a variety of light versus dark backgrounds, solarized versus non-solarized themes, etc, and it was readable in all. My initial version of the patch used the existing %r and %R facilities within pretty-print.cc for the messages, but this turned out to be very uncomfortable, leading to error-prone format strings such as: error_at (richloc, "invalid operands to binary %s (have %<%r%T%R%> and %<%r%T%R%>)", opname, "highlight-a", type0, "highlight-b", type1); To avoid requiring monstrosities such as the above, the patch adds a new "%e" format code to pretty-print.cc, which expects a pp_element *, where pp_element is a new abstract base class (actually a pp_markup::element), along with various useful subclasses. This lets the above be written as: pp_markup::element_quoted_type element_0 (type0, highlight_colors::lhs); pp_markup::element_quoted_type element_1 (type1, highlight_colors::rhs); error_at (richloc, "invalid operands to binary %s (have %e and %e)", opname, &element_0, &element_1); which I feel is maintainable and clear to translators; the use of %e and pp_element * captures the type-unsafe part of the variadic call, and the subclasses allow for type-safety (so e.g. an element_quoted_type expects a type and a highlighting color). This approach allows for some nice simplifications within c-format.cc. The patch also extends -Wformat to "teach" it about the new %e and pp_element *. Doing so requires c-format.cc to be able to determine if a T * is a pp_element * (i.e. if T is a subclass). To do so I added a new comp_types callback for comparing types, where the C++ frontend supplies a suitable implementation (and %e will always be wrong for C). I've manually tested this on many diagnostics with both C and C++ and it seems a subtle but significant improvement in readability. I've added a new option -fno-diagnostics-show-highlight-colors in case people prefer the old behavior. gcc/c-family/ChangeLog: * c-common.cc: Include "tree-pretty-print-markup.h". (binary_op_error): Use pp_markup::element_quoted_type and %e. (check_function_arguments): Add "comp_types" param and pass it to check_function_format. * c-common.h (check_function_arguments): Add "comp_types" param. (check_function_format): Likewise. * c-format.cc: Include "tree-pretty-print-markup.h". (local_pp_element_ptr_node): New. (PP_FORMAT_CHAR_TABLE): Add entry for %e. (struct format_check_context): Add "m_comp_types" field. (check_function_format): Add "comp_types" param and pass it to check_format_info. (check_format_info): Likewise, passing it to format_ctx's ctor. (check_format_arg): Extract m_comp_types from format_ctx and pass it to check_format_info_main. (check_format_info_main): Add "comp_types" param and pass it to arg_parser's ctor. (class argument_parser): Add "m_comp_types" field. (argument_parser::check_argument_type): Pass m_comp_types to check_format_types. (handle_subclass_of_pp_element_p): New. (check_format_types): Add "comp_types" param, and use it to call handle_subclass_of_pp_element_p. (class element_format_substring): New. (class element_expected_type_with_indirection): New. (format_type_warning): Use element_expected_type_with_indirection to unify the if (wanted_type_name) branches, reducing from four emit_warning calls to two. Simplify these further using %e. Doing so also gives suitable colorization of the text within the diagnostics. (init_dynamic_diag_info): Initialize local_pp_element_ptr_node. (selftest::test_type_mismatch_range_labels): Add nullptr for new param of gcc_rich_location label overload. * c-format.h (T_PP_ELEMENT_PTR): New. * c-type-mismatch.cc: Include "diagnostic-highlight-colors.h". (binary_op_rich_location::binary_op_rich_location): Use highlight_colors::lhs and highlight_colors::rhs for the ranges. * c-type-mismatch.h (class binary_op_rich_location): Add comment about highlight_colors. gcc/c/ChangeLog: * c-objc-common.cc: Include "tree-pretty-print-markup.h". (print_type): Add optional "highlight_color" param and use it to show highlight colors in "aka" text. (pp_markup::element_quoted_type::print_type): New. * c-typeck.cc: Include "tree-pretty-print-markup.h". (comp_parm_types): New. (build_function_call_vec): Pass it to check_function_arguments. (inform_for_arg): Use %e and highlight colors to contrast actual versus expected. (convert_for_assignment): Use highlight_colors::actual for the rhs_label. (build_binary_op): Use highlight_colors::lhs and highlight_colors::rhs for the ranges. gcc/ChangeLog: * common.opt (fdiagnostics-show-highlight-colors): New option. * common.opt.urls: Regenerate. * coretypes.h (pp_markup::element): New forward decl. (pp_element): New typedef. * diagnostic-color.cc (gcc_color_defaults): Add "highlight-a" and "highlight-b". * diagnostic-format-json.cc (diagnostic_output_format_init_json): Disable highlight colors. * diagnostic-format-sarif.cc (diagnostic_output_format_init_sarif): Likewise. * diagnostic-highlight-colors.h: New file. * diagnostic-path.cc (struct event_range): Pass nullptr for highlight color of m_rich_loc. * diagnostic-show-locus.cc (colorizer::set_range): Handle ranges with m_highlight_color. (colorizer::STATE_NAMED_COLOR): New. (colorizer::m_richloc): New field. (colorizer::colorizer): Add richloc param for initializing m_richloc. (colorizer::set_named_color): New. (colorizer::begin_state): Add case STATE_NAMED_COLOR. (layout::layout): Pass richloc to m_colorizer's ctor. (selftest::test_one_liner_labels): Pass nullptr for new param of gcc_rich_location ctor for labels. (selftest::test_one_liner_labels_utf8): Likewise. * diagnostic.h (diagnostic_context::set_show_highlight_colors): New. * doc/invoke.texi: Add option -fdiagnostics-show-highlight-colors and highlight-a and highlight-b color caps. * doc/ux.texi (Use color consistently when highlighting mismatches): New subsection. * gcc-rich-location.cc (gcc_rich_location::add_expr): Add "highlight_color" param. (gcc_rich_location::maybe_add_expr): Likewise. * gcc-rich-location.h (gcc_rich_location::gcc_rich_location): Split out into a pair of ctors, where if a range_label is supplied the caller must also supply a highlight color. (gcc_rich_location::add_expr): Add "highlight_color" param. (gcc_rich_location::maybe_add_expr): Likewise. * gcc.cc (driver_handle_option): Handle OPT_fdiagnostics_show_highlight_colors. * lto-wrapper.cc (merge_and_complain): Likewise. (append_compiler_options): Likewise. (append_diag_options): Likewise. (run_gcc): Likewise. * opts-common.cc (decode_cmdline_options_to_array): Add comment about -fno-diagnostics-show-highlight-colors. * opts-global.cc (init_options_once): Preserve pp_show_highlight_colors in case the global_dc's printer is recreated. * opts.cc (common_handle_option): Handle OPT_fdiagnostics_show_highlight_colors. (gen_command_line_string): Likewise. * pretty-print-markup.h: New file. * pretty-print.cc: Include "pretty-print-markup.h" and "diagnostic-highlight-colors.h". (pretty_printer::format): Handle %e. (pretty_printer::pretty_printer): Handle new field m_show_highlight_colors. (pp_string_n): New. (pp_markup::context::begin_quote): New. (pp_markup::context::end_quote): New. (pp_markup::context::begin_color): New. (pp_markup::context::end_color): New. (highlight_colors::expected): New. (highlight_colors::actual): New. (highlight_colors::lhs): New. (highlight_colors::rhs): New. (class selftest::test_element): New. (selftest::test_pp_format): Add tests of %e. (selftest::test_urlification): Likewise. * pretty-print.h (pp_markup::context): New forward decl. (class chunk_info): Add friend class pp_markup::context. (class pretty_printer): Add friend pp_show_highlight_colors. (pretty_printer::m_show_highlight_colors): New field. (pp_show_highlight_colors): New inline function. (pp_string_n): New decl. * substring-locations.cc: Include "diagnostic-highlight-colors.h". (format_string_diagnostic_t::highlight_color_format_string): New. (format_string_diagnostic_t::highlight_color_param): New. (format_string_diagnostic_t::emit_warning_n_va): Use highlight colors. * substring-locations.h (format_string_diagnostic_t::highlight_color_format_string): New. (format_string_diagnostic_t::highlight_color_param): New. * toplev.cc (general_init): Initialize global_dc's show_highlight_colors. * tree-pretty-print-markup.h: New file. gcc/cp/ChangeLog: * call.cc: Include "tree-pretty-print-markup.h". (implicit_conversion_error): Use highlight_colors::percent_h for the labelled range. (op_error_string): Split out into... (concat_op_error_string): ...this. (binop_error_string): New. (op_error): Use %e, binop_error_string, highlight_colors::lhs, and highlight_colors::rhs. (maybe_inform_about_fndecl_for_bogus_argument_init): Add "highlight_color" param; use it for the richloc. (convert_like_internal): Use highlight_colors::percent_h for the labelled_range, and highlight_colors::percent_i for the call to maybe_inform_about_fndecl_for_bogus_argument_init. (build_over_call): Pass cp_comp_parm_types for new "comp_types" param of check_function_arguments. (complain_about_bad_argument): Use highlight_colors::percent_h for the labelled_range, and highlight_colors::percent_i for the call to maybe_inform_about_fndecl_for_bogus_argument_init. * cp-tree.h (maybe_inform_about_fndecl_for_bogus_argument_init): Add optional highlight_color param. (cp_comp_parm_types): New decl. (highlight_colors::const percent_h): New decl. (highlight_colors::const percent_i): New decl. * error.cc: Include "tree-pretty-print-markup.h". (highlight_colors::const percent_h): New defn. (highlight_colors::const percent_i): New defn. (type_to_string): Add param "highlight_color" and use it. (print_nonequal_arg): Likewise. (print_template_differences): Add params "highlight_color_a" and "highlight_color_b". (type_to_string_with_compare): Add params "this_highlight_color" and "peer_highlight_color". (print_template_tree_comparison): Add params "highlight_color_a" and "highlight_color_b". (cxx_format_postprocessor::handle): Use highlight_colors::percent_h and highlight_colors::percent_i. (pp_markup::element_quoted_type::print_type): New. (range_label_for_type_mismatch::get_text): Pass nullptr for new params of type_to_string_with_compare. * typeck.cc (cp_comp_parm_types): New. (cp_build_function_call_vec): Pass it to check_function_arguments. (convert_for_assignment): Use highlight_colors::percent_h for the labelled_range. gcc/testsuite/ChangeLog: * g++.dg/diagnostic/bad-binary-ops-highlight-colors.C: New test. * g++.dg/diagnostic/bad-binary-ops-no-highlight-colors.C: New test. * g++.dg/plugin/plugin.exp (plugin_test_list): Add show-template-tree-color-no-highlight-colors.C to show_template_tree_color_plugin.c. * g++.dg/plugin/show-template-tree-color-labels.C: Update expected output to reflect use of highlight-a and highlight-b to contrast mismatches. * g++.dg/plugin/show-template-tree-color-no-elide-type.C: Likewise. * g++.dg/plugin/show-template-tree-color-no-highlight-colors.C: New test. * g++.dg/plugin/show-template-tree-color.C: Update expected output to reflect use of highlight-a and highlight-b to contrast mismatches. * g++.dg/warn/Wformat-gcc_diag-1.C: New test. * g++.dg/warn/Wformat-gcc_diag-2.C: New test. * g++.dg/warn/Wformat-gcc_diag-3.C: New test. * gcc.dg/bad-binary-ops-highlight-colors.c: New test. * gcc.dg/format/colors.c: New test. * gcc.dg/plugin/diagnostic_plugin_show_trees.c (show_tree): Pass nullptr for new param of gcc_rich_location::add_expr. libcpp/ChangeLog: * include/rich-location.h (location_range::m_highlight_color): New field. (rich_location::rich_location): Add optional label_highlight_color param. (rich_location::set_highlight_color): New decl. (rich_location::add_range): Add optional label_highlight_color param. (rich_location::set_range): Likewise. * line-map.cc (rich_location::rich_location): Add "label_highlight_color" param and pass it to add_range. (rich_location::set_highlight_color): New. (rich_location::add_range): Add "label_highlight_color" param. (rich_location::set_range): Add "highlight_color" param. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
Diffstat (limited to 'gcc/testsuite/g++.dg/warn/Wformat-gcc_diag-2.C')
-rw-r--r--gcc/testsuite/g++.dg/warn/Wformat-gcc_diag-2.C52
1 files changed, 52 insertions, 0 deletions
diff --git a/gcc/testsuite/g++.dg/warn/Wformat-gcc_diag-2.C b/gcc/testsuite/g++.dg/warn/Wformat-gcc_diag-2.C
new file mode 100644
index 0000000..0cce53c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wformat-gcc_diag-2.C
@@ -0,0 +1,52 @@
+// Test of -Wformat for subclasses of pp_element
+// { dg-do compile }
+// { dg-options "-Wformat" }
+
+/* Magic identifiers must be set before the attribute is used. */
+
+typedef long long __gcc_host_wide_int__;
+
+typedef struct location_s
+{
+ const char *file;
+ int line;
+} location_t;
+
+union tree_node;
+typedef union tree_node *tree;
+
+/* Define gimple as a dummy type. The typedef must be provided for
+ the C test to find the symbol. */
+typedef struct gimple gimple;
+
+/* Likewise for gimple. */
+typedef struct cgraph_node cgraph_node;
+
+/* Likewise for diagnostic_event_id_t. */
+typedef struct diagnostic_event_id_t diagnostic_event_id_t;
+
+namespace pp_markup {
+class element
+{
+};
+} // namespace pp_markup
+typedef pp_markup::element pp_element;
+
+#define FORMAT(kind) __attribute__ ((format (__gcc_## kind ##__, 1, 2)))
+
+void diag (const char*, ...) FORMAT (diag);
+
+class sub_element : public pp_element
+{
+};
+
+class sub_sub_element : public sub_element
+{
+};
+
+void test_diag ()
+{
+ sub_element e1;
+ sub_sub_element e2;
+ diag ("%e %e", &e1, &e2);
+}