On 12/11/21 10:39 PM, Jason Merrill via Gcc-patches wrote:
In reading C++ diagnostics, it's often hard to find the name of the function
in the middle of the template header, return type, parameters, and template
arguments.  So let's colorize it, and maybe the template argument bindings
while we're at it.

I've somewhat arbitrarily chosen bold green for the function name, and
non-bold magenta for the template arguments.  I'm not at all attached to
these choices.

A side-effect is that when this happens in a quote (i.e. %qD), the
rest of the quote after the function name is no longer bold.  I think that's
acceptable; returning to the bold would require maintaining a colorize stack
instead of the on/off controls we have now.

Any thoughts?

I appreciate the problem but I can't say I find this solution
much of an improvement.  We end up with the same name in up to
four colors: cyan, magenta, green, and black, plus bold versions
of each, depending on where in the text the name appears.  It's
not apparent to me what the different colors mean or how they
help.

IMO, the underlying root cause for why relevant details are so
hard to find in G++ messages is that there's so much redundancy
and irrelevant context in the output.  For instance, for this
test case:

#include <map>

std::map<const char*, const char*> m ("123", "456");

GCC produces 10 screenfuls of output (more than 10 times as many
as Clang).  GCC produces so much more output because it repeats
the full set of included files before each candidate (even though
the headers are the same in each), and also because it repeats
the full set of template arguments each time.  E.g., like so:
In file included from /build/gcc-master/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/stl_algobase.h:64, from /build/gcc-master/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/stl_tree.h:63, from /build/gcc-master/x86_64-pc-linux-gnu/libstdc++-v3/include/map:60,
                 from t.C:1:
/build/gcc-master/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/stl_pair.h:558:28: note: candidate: ‘template<class _U1, class _U2, typename std::enable_if<(std::_PCC<((! std::is_same<const char* const, _U1>::value) || (! std::is_same<const char*, _U2>::value)), const char* const, const char*>::_MoveConstructiblePair<_U1, _U2>() && (! std::_PCC<((! std::is_same<const char* const, _U1>::value) || (! std::is_same<const char*, _U2>::value)), const char* const, const char*>::_ImplicitlyMoveConvertiblePair<_U1, _U2>())), bool>::type <anonymous> > constexpr std::pair<_T1, _T2>::pair(std::pair<_U1, _U2>&&) [with _U2 = _U1; typename std::enable_if<(std::_PCC<((! std::is_same<_T1, _U1>::value) || (! std::is_same<_T2, _U2>::value)), _T1, _T2>::_MoveConstructiblePair<_U1, _U2>() && (! std::_PCC<((! std::is_same<_T1, _U1>::value) || (! std::is_same<_T2, _U2>::value)), _T1, _T2>::_ImplicitlyMoveConvertiblePair<_U1, _U2>())), bool>::type <anonymous> = _U2; _T1 = const char* const; _T2 = const char*]’
  558 |         explicit constexpr pair(pair<_U1, _U2>&& __p)
      |                            ^~~~

I suspect focusing on reducing the amount of superfluous output
would be a better approach than colorizing the precious nuggets
of useful information in it.

Martin

PS Years ago (in the early 2000's) when interviewing experienced
candidates for C++ template library positions, we'd sit them in
front of a machine with a few C++ compilers and the test case
above.  They were asked to find and explain and fix the problem
in the test case, using any or all of the compilers.  Of all
the people we interviewed only one guy was able to decipher
the errors enough to find the bug.  Looks like this could still
be a good exercise (though we might have to keep them from using
Clang ;)


gcc/cp/ChangeLog:

        * error.c (decl_to_string): Add show_color parameter.
        (cp_printer): Pass it.
        (dump_function_name): Use "fnname" color.
        (dump_template_bindings): Use "targs" color.
        (struct colorize_guard): New.
        (reinit_cxx_pp): Clear pp_show_color.
        (cp_print_error_function): Use %qD.
        (function_category): Use %qD.

gcc/ChangeLog:

        * diagnostic-color.c: Add fnname and targs color entries.
        * doc/invoke.texi: Document them.
---
  gcc/doc/invoke.texi    |  8 ++++++
  gcc/cp/error.c         | 64 ++++++++++++++++++++++++++++++------------
  gcc/diagnostic-color.c |  2 ++
  3 files changed, 56 insertions(+), 18 deletions(-)

diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 9b4371b9213..cdfddd75343 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -4803,6 +4803,14 @@ SGR substring for location information, @samp{file:line} 
or
  @vindex quote GCC_COLORS @r{capability}
  SGR substring for information printed within quotes.
+@item fnname=
+@vindex fnname GCC_COLORS @r{capability}
+SGR substring for names of C++ functions.
+
+@item targs=
+@vindex targs GCC_COLORS @r{capability}
+SGR substring for C++ function template parameter bindings.
+
  @item fixit-insert=
  @vindex fixit-insert GCC_COLORS @r{capability}
  SGR substring for fix-it hints suggesting text to
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index daea3b39a15..e03079e3b8f 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -1,4 +1,4 @@
-/* Call-backs for C++ error reporting.
+/* Call-backs for -*- C++ -*- error reporting.
     This code is non-reentrant.
     Copyright (C) 1993-2021 Free Software Foundation, Inc.
     This file is part of GCC.
@@ -25,6 +25,7 @@ along with GCC; see the file COPYING3.  If not see
  #include "cp-tree.h"
  #include "stringpool.h"
  #include "tree-diagnostic.h"
+#include "diagnostic-color.h"
  #include "langhooks-def.h"
  #include "intl.h"
  #include "cxx-pretty-print.h"
@@ -56,7 +57,7 @@ static cxx_pretty_printer * const cxx_pp = 
&actual_pretty_printer;
  static const char *args_to_string (tree, int);
  static const char *code_to_string (enum tree_code);
  static const char *cv_to_string (tree, int);
-static const char *decl_to_string (tree, int);
+static const char *decl_to_string (tree, int, bool);
  static const char *fndecl_to_string (tree, int);
  static const char *op_to_string       (bool, enum tree_code);
  static const char *parm_to_string (int);
@@ -390,6 +391,7 @@ dump_template_bindings (cxx_pretty_printer *pp, tree parms, 
tree args,
        else
        {
          pp_cxx_whitespace (pp);
+         pp_string (pp, colorize_start (pp_show_color (pp), "targs"));
          pp_cxx_left_bracket (pp);
          pp->translate_string ("with");
          pp_cxx_whitespace (pp);
@@ -400,7 +402,10 @@ dump_template_bindings (cxx_pretty_printer *pp, tree 
parms, tree args,
      ~prepost_semicolon ()
      {
        if (need_semicolon)
-       pp_cxx_right_bracket (pp);
+       {
+         pp_cxx_right_bracket (pp);
+         pp_string (pp, colorize_stop (pp_show_color (pp)));
+       }
      }
    } semicolon_or_introducer = {pp, false};
@@ -1158,6 +1163,22 @@ dump_simple_decl (cxx_pretty_printer *pp, tree t, tree type, int flags)
      dump_type_suffix (pp, type, flags);
  }
+struct colorize_guard
+{
+  bool colorize;
+  cxx_pretty_printer *pp;
+
+  colorize_guard (bool _colorize, cxx_pretty_printer *pp, const char *name)
+    : colorize (_colorize && pp_show_color (pp)), pp (pp)
+  {
+    pp_string (pp, colorize_start (colorize, name));
+  }
+  ~colorize_guard ()
+  {
+    pp_string (pp, colorize_stop (colorize));
+  }
+};
+
  /* Print an IDENTIFIER_NODE that is the name of a declaration.  */
static void
@@ -1928,6 +1949,11 @@ dump_exception_spec (cxx_pretty_printer *pp, tree t, int 
flags)
  static void
  dump_function_name (cxx_pretty_printer *pp, tree t, int flags)
  {
+  bool colorize = flags & (TFF_DECL_SPECIFIERS | TFF_RETURN_TYPE
+                          | TFF_TEMPLATE_HEADER);
+
+  colorize_guard g (colorize, pp, "fnname");
+
    tree name = DECL_NAME (t);
/* We can get here with a decl that was synthesized by language-
@@ -3062,6 +3088,7 @@ reinit_cxx_pp (void)
    cxx_pp->padding = pp_none;
    pp_indentation (cxx_pp) = 0;
    pp_needs_newline (cxx_pp) = false;
+  pp_show_color (cxx_pp) = false;
    cxx_pp->enclosing_scope = current_function_decl;
  }
@@ -3208,7 +3235,7 @@ location_of (tree t)
     function.  */
static const char *
-decl_to_string (tree decl, int verbose)
+decl_to_string (tree decl, int verbose, bool show_color)
  {
    int flags = 0;
@@ -3222,6 +3249,7 @@ decl_to_string (tree decl, int verbose)
    flags |= TFF_TEMPLATE_HEADER;
reinit_cxx_pp ();
+  pp_show_color (cxx_pp) = show_color;
    dump_decl (cxx_pp, decl, flags);
    return pp_ggc_formatted_text (cxx_pp);
  }
@@ -3517,7 +3545,7 @@ cp_print_error_function (diagnostic_context *context,
            fndecl = current_function_decl;
pp_printf (context->printer, function_category (fndecl),
-                    cxx_printable_name_translate (fndecl, 2));
+                    fndecl);
while (abstract_origin)
            {
@@ -3561,19 +3589,19 @@ cp_print_error_function (diagnostic_context *context,
                    {
                      if (context->show_column && s.column != 0)
                        pp_printf (context->printer,
-                                  _("    inlined from %qs at %r%s:%d:%d%R"),
-                                  cxx_printable_name_translate (fndecl, 2),
+                                  _("    inlined from %qD at %r%s:%d:%d%R"),
+                                  fndecl,
                                   "locus", s.file, s.line, s.column);
                      else
                        pp_printf (context->printer,
-                                  _("    inlined from %qs at %r%s:%d%R"),
-                                  cxx_printable_name_translate (fndecl, 2),
+                                  _("    inlined from %qD at %r%s:%d%R"),
+                                  fndecl,
                                   "locus", s.file, s.line);
}
                  else
-                   pp_printf (context->printer, _("    inlined from %qs"),
-                              cxx_printable_name_translate (fndecl, 2));
+                   pp_printf (context->printer, _("    inlined from %qD"),
+                              fndecl);
                }
            }
          pp_character (context->printer, ':');
@@ -3598,20 +3626,20 @@ function_category (tree fn)
        && DECL_FUNCTION_MEMBER_P (fn))
      {
        if (DECL_STATIC_FUNCTION_P (fn))
-       return _("In static member function %qs");
+       return _("In static member function %qD");
        else if (DECL_COPY_CONSTRUCTOR_P (fn))
-       return _("In copy constructor %qs");
+       return _("In copy constructor %qD");
        else if (DECL_CONSTRUCTOR_P (fn))
-       return _("In constructor %qs");
+       return _("In constructor %qD");
        else if (DECL_DESTRUCTOR_P (fn))
-       return _("In destructor %qs");
+       return _("In destructor %qD");
        else if (LAMBDA_FUNCTION_P (fn))
        return _("In lambda function");
        else
-       return _("In member function %qs");
+       return _("In member function %qD");
      }
    else
-    return _("In function %qs");
+    return _("In function %qD");
  }
/* Disable warnings about missing quoting in GCC diagnostics for
@@ -4393,7 +4421,7 @@ cp_printer (pretty_printer *pp, text_info *text, const 
char *spec,
                break;
              }
          }
-       result = decl_to_string (temp, verbose);
+       result = decl_to_string (temp, verbose, pp_show_color (pp));
        }
        break;
      case 'E': result = expr_to_string (next_tree);            break;
diff --git a/gcc/diagnostic-color.c b/gcc/diagnostic-color.c
index 1fc5a9079c7..c1406b45d8b 100644
--- a/gcc/diagnostic-color.c
+++ b/gcc/diagnostic-color.c
@@ -91,6 +91,8 @@ static struct color_cap color_dict[] =
    { "locus", SGR_SEQ (COLOR_BOLD), 5, false },
    { "quote", SGR_SEQ (COLOR_BOLD), 5, false },
    { "path", SGR_SEQ (COLOR_BOLD COLOR_SEPARATOR COLOR_FG_CYAN), 4, false },
+  { "fnname", SGR_SEQ (COLOR_BOLD COLOR_SEPARATOR COLOR_FG_GREEN), 6, false },
+  { "targs", SGR_SEQ (COLOR_FG_MAGENTA), 5, false },
    { "fixit-insert", SGR_SEQ (COLOR_FG_GREEN), 12, false },
    { "fixit-delete", SGR_SEQ (COLOR_FG_RED), 12, false },
    { "diff-filename", SGR_SEQ (COLOR_BOLD), 13, false },

base-commit: 2e8067041d1d69da02bd7578f58abc11eb35a04b


Reply via email to