On Wed, 2019-12-04 at 10:36 -0700, Martin Sebor wrote:
> On 11/15/19 6:22 PM, David Malcolm wrote:
> > This patch adds support for associating a diagnostic with an
> > optional
> > diagnostic_metadata object, so that plugins can add extra data to
> > their
> > diagnostics (e.g. mapping a diagnostic to a taxonomy or coding
> > standard
> > such as from CERT or MISRA).
> > 
> > Currently this only supports associating a CWE identifier with a
> > diagnostic (which is what I'm using for the analyzer warnings later
> > in
> > the patch kit), but adding a diagnostic_metadata class allows for
> > future
> > growth in this area without an explosion of further "warning_at"
> > overloads
> > for all of the different kinds of custom data that a plugin might
> > want to
> > add.
> 
> We discussed this in the past so I'll be repeating some of my
> comments from that thread.  I like the feature at a high level,
> but I'm not sure I see how to make it work in a robust way.
> 
> There is no one-to-one mapping between GCC warnings and any of
> these classifications.  A single GCC warning might map to several
> CERT or MISRA guidelines, and a single guideline might map to two
> or more different GCC warnings.  This is an M to N mapping times
> the number of coding standards/classifications.  I haven't looked
> at the patch kit in enough detail to understand how it tries to
> handle it.  Can you explain?

The patch kit gives the ability to (optionally) specify a single CWE
identifier when emitting a diagnostic.

The patch kit uses this in various places for its new warnings for the
cases where there is a well-defined CWE weakness identifier (and
doesn't otherwise).

It doesn't attempt to classify any existing warnings.

It doesn't attempt to support other classifications in this patch, but
it does introduce a diagnostic_metadata object that could gain this
functionality at some later time, if we come up with a scheme we're
happy with (a slight violation of YAGNI, but it's such a pain touching
all the diagnostic fns that I prefer to do it once).

> My other concern here is that these guidelines evolve.  New ones
> are being added, existing ones moved or broken up, etc.  Does
> the infrastructure cope with this evolution (e.g., by reading
> the mapping from a file)?

Let's cross that bridge when we come to it.  If it becomes a problem,
then we can come up with a fix (e.g. a command-line option to specify
the CWE version).

Dave

> Martin
> 
> > gcc/ChangeLog:
> >     * common.opt (fdiagnostics-show-metadata): New option.
> >     * diagnostic-core.h (class diagnostic_metadata): New forward
> > decl.
> >     (warning_at): Add overload taking a const diagnostic_metadata
> > &.
> >     (emit_diagnostic_valist): Add overload taking a
> >     const diagnostic_metadata *.
> >     * diagnostic-format-json.cc: Include "diagnostic-metadata.h".
> >     (json_from_metadata): New function.
> >     (json_end_diagnostic): Call it to add "metadata" child for
> >     diagnostics with metadata.
> >     (diagnostic_output_format_init): Clear context->show_metadata.
> >     * diagnostic-metadata.h: New file.
> >     * diagnostic.c: Include "diagnostic-metadata.h".
> >     (diagnostic_impl): Add const diagnostic_metadata * param.
> >     (diagnostic_n_impl): Likewise.
> >     (diagnostic_initialize): Initialize context->show_metadata.
> >     (diagnostic_set_info_translated): Initialize diagnostic-
> > >metadata.
> >     (get_cwe_url): New function.
> >     (print_any_metadata): New function.
> >     (diagnostic_report_diagnostic): Call print_any_metadata if the
> >     diagnostic has non-NULL metadata.
> >     (emit_diagnostic): Pass NULL as the metadata in the call to
> >     diagnostic_impl.
> >     (emit_diagnostic_valist): Likewise.
> >     (emit_diagnostic_valist): New overload taking a
> >     const diagnostic_metadata *.
> >     (inform): Pass NULL as the metadata in the call to
> >     diagnostic_impl.
> >     (inform_n): Likewise for diagnostic_n_impl.
> >     (warning): Likewise.
> >     (warning_at): Likewise.  Add overload that takes a
> >     const diagnostic_metadata &.
> >     (warning_n): Pass NULL as the metadata in the call to
> >     diagnostic_n_impl.
> >     (pedwarn): Likewise for diagnostic_impl.
> >     (permerror): Likewise.
> >     (error): Likewise.
> >     (error_n): Likewise.
> >     (error_at): Likewise.
> >     (sorry): Likewise.
> >     (sorry_at): Likewise.
> >     (fatal_error): Likewise.
> >     (internal_error): Likewise.
> >     (internal_error_no_backtrace): Likewise.
> >     * diagnostic.h (diagnostic_info::metadata): New field.
> >     (diagnostic_context::show_metadata): New field.
> >     * doc/invoke.texi (-fno-diagnostics-show-metadata): New option.
> >     * opts.c (common_handle_option): Handle
> >     OPT_fdiagnostics_show_metadata.
> >     * toplev.c (general_init): Initialize global_dc->show_metadata.
> > ---
> >   gcc/common.opt                |   4 ++
> >   gcc/diagnostic-core.h         |  10 +++
> >   gcc/diagnostic-format-json.cc |  23 +++++++
> >   gcc/diagnostic-metadata.h     |  42 +++++++++++++
> >   gcc/diagnostic.c              | 142
> > +++++++++++++++++++++++++++++++++---------
> >   gcc/diagnostic.h              |   7 +++
> >   gcc/doc/invoke.texi           |   8 +++
> >   gcc/opts.c                    |   4 ++
> >   gcc/toplev.c                  |   2 +
> >   9 files changed, 211 insertions(+), 31 deletions(-)
> >   create mode 100644 gcc/diagnostic-metadata.h
> > 
> > diff --git a/gcc/common.opt b/gcc/common.opt
> > index 3c024b3..228df32 100644
> > --- a/gcc/common.opt
> > +++ b/gcc/common.opt
> > @@ -1334,6 +1334,10 @@ fdiagnostics-show-option
> >   Common Var(flag_diagnostics_show_option) Init(1)
> >   Amend appropriate diagnostic messages with the command line
> > option that controls them.
> >   
> > +fdiagnostics-show-metadata
> > +Common Var(flag_diagnostics_show_metadata) Init(1)
> > +Print additional metadata for diagnostic messages, where
> > available.
> > +
> >   fdiagnostics-minimum-margin-width=
> >   Common Joined UInteger Var(diagnostics_minimum_margin_width)
> > Init(6)
> >   Set minimum width of left margin of source code when showing
> > source.
> > diff --git a/gcc/diagnostic-core.h b/gcc/diagnostic-core.h
> > index efafde4..2e7f120 100644
> > --- a/gcc/diagnostic-core.h
> > +++ b/gcc/diagnostic-core.h
> > @@ -45,6 +45,9 @@ class auto_diagnostic_group
> >     ~auto_diagnostic_group ();
> >   };
> >   
> > +/* Forward decl.  */
> > +class diagnostic_metadata; /* See diagnostic-metadata.h.  */
> > +
> >   extern const char *progname;
> >   
> >   extern const char *trim_filename (const char *);
> > @@ -78,6 +81,9 @@ extern bool warning_at (location_t, int, const
> > char *, ...)
> >       ATTRIBUTE_GCC_DIAG(3,4);
> >   extern bool warning_at (rich_location *, int, const char *, ...)
> >       ATTRIBUTE_GCC_DIAG(3,4);
> > +extern bool warning_at (rich_location *, const diagnostic_metadata
> > &, int,
> > +                   const char *, ...)
> > +    ATTRIBUTE_GCC_DIAG(4,5);
> >   extern void error (const char *, ...) ATTRIBUTE_GCC_DIAG(1,2);
> >   extern void error_n (location_t, unsigned HOST_WIDE_INT, const
> > char *,
> >                  const char *, ...)
> > @@ -109,6 +115,10 @@ extern bool emit_diagnostic (diagnostic_t,
> > rich_location *, int,
> >                          const char *, ...)
> > ATTRIBUTE_GCC_DIAG(4,5);
> >   extern bool emit_diagnostic_valist (diagnostic_t, location_t,
> > int, const char *,
> >                                 va_list *) ATTRIBUTE_GCC_DIAG
> > (4,0);
> > +extern bool emit_diagnostic_valist (diagnostic_t, rich_location *,
> > +                               const diagnostic_metadata
> > *metadata,
> > +                               int, const char *, va_list *)
> > +  ATTRIBUTE_GCC_DIAG (5,0);
> >   extern bool seen_error (void);
> >   
> >   #ifdef BUFSIZ
> > diff --git a/gcc/diagnostic-format-json.cc b/gcc/diagnostic-format-
> > json.cc
> > index eb99952..200e844 100644
> > --- a/gcc/diagnostic-format-json.cc
> > +++ b/gcc/diagnostic-format-json.cc
> > @@ -23,6 +23,7 @@ along with GCC; see the file COPYING3.  If not
> > see
> >   #include "system.h"
> >   #include "coretypes.h"
> >   #include "diagnostic.h"
> > +#include "diagnostic-metadata.h"
> >   #include "json.h"
> >   #include "selftest.h"
> >   
> > @@ -103,6 +104,19 @@ json_from_fixit_hint (const fixit_hint *hint)
> >     return fixit_obj;
> >   }
> >   
> > +/* Generate a JSON object for METADATA.  */
> > +
> > +static json::object *
> > +json_from_metadata (const diagnostic_metadata *metadata)
> > +{
> > +  json::object *metadata_obj = new json::object ();
> > +
> > +  if (metadata->get_cwe ())
> > +    metadata_obj->set ("cwe", new json::number (metadata->get_cwe
> > ()));
> > +
> > +  return metadata_obj;
> > +}
> > +
> >   /* No-op implementation of "begin_diagnostic" for JSON
> > output.  */
> >   
> >   static void
> > @@ -211,6 +225,12 @@ json_end_diagnostic (diagnostic_context
> > *context, diagnostic_info *diagnostic,
> >        TODO: functions
> >        TODO: inlining information
> >        TODO: macro expansion information.  */
> > +
> > +  if (diagnostic->metadata)
> > +    {
> > +      json::object *metadata_obj = json_from_metadata (diagnostic-
> > >metadata);
> > +      diag_obj->set ("metadata", metadata_obj);
> > +    }
> >   }
> >   
> >   /* No-op implementation of "begin_group_cb" for JSON output.  */
> > @@ -268,6 +288,9 @@ diagnostic_output_format_init
> > (diagnostic_context *context,
> >     context->end_group_cb =  json_end_group;
> >     context->final_cb =  json_final_cb;
> >   
> > +   /* The metadata is handled in JSON format, rather than as
> > text.  */
> > +   context->show_metadata = false;
> > +
> >     /* The option is handled in JSON format, rather than as
> > text.  */
> >     context->show_option_requested = false;
> >   
> > diff --git a/gcc/diagnostic-metadata.h b/gcc/diagnostic-metadata.h
> > new file mode 100644
> > index 0000000..a759d44
> > --- /dev/null
> > +++ b/gcc/diagnostic-metadata.h
> > @@ -0,0 +1,42 @@
> > +/* Additional metadata for a diagnostic.
> > +   Copyright (C) 2019 Free Software Foundation, Inc.
> > +   Contributed by David Malcolm <dmalc...@redhat.com>
> > +
> > +This file is part of GCC.
> > +
> > +GCC is free software; you can redistribute it and/or modify it
> > under
> > +the terms of the GNU General Public License as published by the
> > Free
> > +Software Foundation; either version 3, or (at your option) any
> > later
> > +version.
> > +
> > +GCC is distributed in the hope that it will be useful, but WITHOUT
> > ANY
> > +WARRANTY; without even the implied warranty of MERCHANTABILITY or
> > +FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
> > License
> > +for more details.
> > +
> > +You should have received a copy of the GNU General Public License
> > +along with GCC; see the file COPYING3.  If not see
> > +<http://www.gnu.org/licenses/>;.  */
> > +
> > +#ifndef GCC_DIAGNOSTIC_METADATA_H
> > +#define GCC_DIAGNOSTIC_METADATA_H
> > +
> > +/* A bundle of additional metadata that can be associated with a
> > +   diagnostic.
> > +
> > +   Currently this only supports associating a CWE identifier with
> > a
> > +   diagnostic.  */
> > +
> > +class diagnostic_metadata
> > +{
> > + public:
> > +  diagnostic_metadata () : m_cwe (0) {}
> > +
> > +  void add_cwe (int cwe) { m_cwe = cwe; }
> > +  int get_cwe () const { return m_cwe; }
> > +
> > + private:
> > +  int m_cwe;
> > +};
> > +
> > +#endif /* ! GCC_DIAGNOSTIC_METADATA_H */
> > diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c
> > index 81e0a10..e8d0613 100644
> > --- a/gcc/diagnostic.c
> > +++ b/gcc/diagnostic.c
> > @@ -32,6 +32,7 @@ along with GCC; see the file COPYING3.  If not
> > see
> >   #include "diagnostic.h"
> >   #include "diagnostic-color.h"
> >   #include "diagnostic-url.h"
> > +#include "diagnostic-metadata.h"
> >   #include "edit-context.h"
> >   #include "selftest.h"
> >   #include "selftest-diagnostic.h"
> > @@ -58,11 +59,13 @@ along with GCC; see the file COPYING3.  If not
> > see
> >   #define permissive_error_option(DC) ((DC)->opt_permissive)
> >   
> >   /* Prototypes.  */
> > -static bool diagnostic_impl (rich_location *, int, const char *,
> > -                        va_list *, diagnostic_t)
> > ATTRIBUTE_GCC_DIAG(3,0);
> > -static bool diagnostic_n_impl (rich_location *, int, unsigned
> > HOST_WIDE_INT,
> > +static bool diagnostic_impl (rich_location *, const
> > diagnostic_metadata *,
> > +                        int, const char *,
> > +                        va_list *, diagnostic_t)
> > ATTRIBUTE_GCC_DIAG(4,0);
> > +static bool diagnostic_n_impl (rich_location *, const
> > diagnostic_metadata *,
> > +                          int, unsigned HOST_WIDE_INT,
> >                            const char *, const char *, va_list *,
> > -                          diagnostic_t) ATTRIBUTE_GCC_DIAG(5,0);
> > +                          diagnostic_t) ATTRIBUTE_GCC_DIAG(6,0);
> >   
> >   static void error_recursion (diagnostic_context *)
> > ATTRIBUTE_NORETURN;
> >   static void real_abort (void) ATTRIBUTE_NORETURN;
> > @@ -183,6 +186,7 @@ diagnostic_initialize (diagnostic_context
> > *context, int n_opts)
> >     diagnostic_set_caret_max_width (context, pp_line_cutoff
> > (context->printer));
> >     for (i = 0; i < rich_location::STATICALLY_ALLOCATED_RANGES;
> > i++)
> >       context->caret_chars[i] = '^';
> > +  context->show_metadata = false;
> >     context->show_option_requested = false;
> >     context->abort_on_error = false;
> >     context->show_column = false;
> > @@ -300,6 +304,7 @@ diagnostic_set_info_translated (diagnostic_info
> > *diagnostic, const char *msg,
> >     diagnostic->message.format_spec = msg;
> >     diagnostic->message.m_richloc = richloc;
> >     diagnostic->richloc = richloc;
> > +  diagnostic->metadata = NULL;
> >     diagnostic->kind = kind;
> >     diagnostic->option_index = 0;
> >   }
> > @@ -899,6 +904,47 @@ update_effective_level_from_pragmas
> > (diagnostic_context *context,
> >     return diag_class;
> >   }
> >   
> > +/* Generate a URL string describing CWE.  The caller is
> > responsible for
> > +   freeing the string.  */
> > +
> > +static char *
> > +get_cwe_url (int cwe)
> > +{
> > +  return xasprintf ("
> > https://cwe.mitre.org/data/definitions/%i.html";, cwe);
> > +}
> > +
> > +/* If DIAGNOSTIC has metadata, print it.
> > +
> > +   For example, if the diagnostic metadata associates it with CWE-
> > 119,
> > +   " [CWE-119]" will be printed, suitably colorized, and with a
> > URL of a
> > +   description of the security issue.  */
> > +
> > +static void
> > +print_any_metadata (diagnostic_context *context,
> > +               const diagnostic_info *diagnostic)
> > +{
> > +  if (diagnostic->metadata == NULL)
> > +    return;
> > +
> > +  int cwe = diagnostic->metadata->get_cwe ();
> > +  if (cwe)
> > +    {
> > +      pretty_printer *pp = context->printer;
> > +      char *saved_prefix = pp_take_prefix (context->printer);
> > +      pp_string (pp, " [");
> > +      pp_string (pp, colorize_start (pp_show_color (pp),
> > +                                diagnostic_kind_color[diagnostic-
> > >kind]));
> > +      char *cwe_url = get_cwe_url (cwe);
> > +      pp_begin_url (pp, cwe_url);
> > +      free (cwe_url);
> > +      pp_printf (pp, "CWE-%i", cwe);
> > +      pp_set_prefix (context->printer, saved_prefix);
> > +      pp_end_url (pp);
> > +      pp_string (pp, colorize_stop (pp_show_color (pp)));
> > +      pp_character (pp, ']');
> > +    }
> > +}
> > +
> >   /* Print any metadata about the option used to control DIAGNOSTIC
> > to CONTEXT's
> >      printer, e.g. " [-Werror=uninitialized]".
> >      Subroutine of diagnostic_report_diagnostic.  */
> > @@ -1059,6 +1105,8 @@ diagnostic_report_diagnostic
> > (diagnostic_context *context,
> >     pp_format (context->printer, &diagnostic->message);
> >     (*diagnostic_starter (context)) (context, diagnostic);
> >     pp_output_formatted_text (context->printer);
> > +  if (context->show_metadata)
> > +    print_any_metadata (context, diagnostic);
> >     if (context->show_option_requested)
> >       print_option_information (context, diagnostic,
> > orig_diag_kind);
> >     (*diagnostic_finalizer (context)) (context, diagnostic,
> > orig_diag_kind);
> > @@ -1190,8 +1238,8 @@ diagnostic_append_note (diagnostic_context
> > *context,
> >      permerror, error, error_at, error_at, sorry, fatal_error,
> > internal_error,
> >      and internal_error_no_backtrace, as documented and defined
> > below.  */
> >   static bool
> > -diagnostic_impl (rich_location *richloc, int opt,
> > -            const char *gmsgid,
> > +diagnostic_impl (rich_location *richloc, const diagnostic_metadata
> > *metadata,
> > +            int opt, const char *gmsgid,
> >              va_list *ap, diagnostic_t kind)
> >   {
> >     diagnostic_info diagnostic;
> > @@ -1207,13 +1255,15 @@ diagnostic_impl (rich_location *richloc,
> > int opt,
> >         if (kind == DK_WARNING || kind == DK_PEDWARN)
> >     diagnostic.option_index = opt;
> >       }
> > +  diagnostic.metadata = metadata;
> >     return diagnostic_report_diagnostic (global_dc, &diagnostic);
> >   }
> >   
> >   /* Implement inform_n, warning_n, and error_n, as documented and
> >      defined below.  */
> >   static bool
> > -diagnostic_n_impl (rich_location *richloc, int opt, unsigned
> > HOST_WIDE_INT n,
> > +diagnostic_n_impl (rich_location *richloc, const
> > diagnostic_metadata *metadata,
> > +              int opt, unsigned HOST_WIDE_INT n,
> >                const char *singular_gmsgid,
> >                const char *plural_gmsgid,
> >                va_list *ap, diagnostic_t kind)
> > @@ -1233,6 +1283,7 @@ diagnostic_n_impl (rich_location *richloc,
> > int opt, unsigned HOST_WIDE_INT n,
> >     diagnostic_set_info_translated (&diagnostic, text, ap, richloc,
> > kind);
> >     if (kind == DK_WARNING)
> >       diagnostic.option_index = opt;
> > +  diagnostic.metadata = metadata;
> >     return diagnostic_report_diagnostic (global_dc, &diagnostic);
> >   }
> >   
> > @@ -1246,7 +1297,7 @@ emit_diagnostic (diagnostic_t kind,
> > location_t location, int opt,
> >     va_list ap;
> >     va_start (ap, gmsgid);
> >     rich_location richloc (line_table, location);
> > -  bool ret = diagnostic_impl (&richloc, opt, gmsgid, &ap, kind);
> > +  bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap,
> > kind);
> >     va_end (ap);
> >     return ret;
> >   }
> > @@ -1260,7 +1311,7 @@ emit_diagnostic (diagnostic_t kind,
> > rich_location *richloc, int opt,
> >     auto_diagnostic_group d;
> >     va_list ap;
> >     va_start (ap, gmsgid);
> > -  bool ret = diagnostic_impl (richloc, opt, gmsgid, &ap, kind);
> > +  bool ret = diagnostic_impl (richloc, NULL, opt, gmsgid, &ap,
> > kind);
> >     va_end (ap);
> >     return ret;
> >   }
> > @@ -1272,7 +1323,18 @@ emit_diagnostic_valist (diagnostic_t kind,
> > location_t location, int opt,
> >                     const char *gmsgid, va_list *ap)
> >   {
> >     rich_location richloc (line_table, location);
> > -  return diagnostic_impl (&richloc, opt, gmsgid, ap, kind);
> > +  return diagnostic_impl (&richloc, NULL, opt, gmsgid, ap, kind);
> > +}
> > +
> > +/* Wrapper around diagnostic_impl taking a va_list parameter.  */
> > +
> > +bool
> > +emit_diagnostic_valist (diagnostic_t kind, rich_location *richloc,
> > +                   const diagnostic_metadata *metadata,
> > +                   int opt,
> > +                   const char *gmsgid, va_list *ap)
> > +{
> > +  return diagnostic_impl (richloc, metadata, opt, gmsgid, ap,
> > kind);
> >   }
> >   
> >   /* An informative note at LOCATION.  Use this for additional
> > details on an error
> > @@ -1284,7 +1346,7 @@ inform (location_t location, const char
> > *gmsgid, ...)
> >     va_list ap;
> >     va_start (ap, gmsgid);
> >     rich_location richloc (line_table, location);
> > -  diagnostic_impl (&richloc, -1, gmsgid, &ap, DK_NOTE);
> > +  diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_NOTE);
> >     va_end (ap);
> >   }
> >   
> > @@ -1297,7 +1359,7 @@ inform (rich_location *richloc, const char
> > *gmsgid, ...)
> >     auto_diagnostic_group d;
> >     va_list ap;
> >     va_start (ap, gmsgid);
> > -  diagnostic_impl (richloc, -1, gmsgid, &ap, DK_NOTE);
> > +  diagnostic_impl (richloc, NULL, -1, gmsgid, &ap, DK_NOTE);
> >     va_end (ap);
> >   }
> >   
> > @@ -1311,7 +1373,7 @@ inform_n (location_t location, unsigned
> > HOST_WIDE_INT n,
> >     va_start (ap, plural_gmsgid);
> >     auto_diagnostic_group d;
> >     rich_location richloc (line_table, location);
> > -  diagnostic_n_impl (&richloc, -1, n, singular_gmsgid,
> > plural_gmsgid,
> > +  diagnostic_n_impl (&richloc, NULL, -1, n, singular_gmsgid,
> > plural_gmsgid,
> >                  &ap, DK_NOTE);
> >     va_end (ap);
> >   }
> > @@ -1326,7 +1388,7 @@ warning (int opt, const char *gmsgid, ...)
> >     va_list ap;
> >     va_start (ap, gmsgid);
> >     rich_location richloc (line_table, input_location);
> > -  bool ret = diagnostic_impl (&richloc, opt, gmsgid, &ap,
> > DK_WARNING);
> > +  bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap,
> > DK_WARNING);
> >     va_end (ap);
> >     return ret;
> >   }
> > @@ -1342,7 +1404,7 @@ warning_at (location_t location, int opt,
> > const char *gmsgid, ...)
> >     va_list ap;
> >     va_start (ap, gmsgid);
> >     rich_location richloc (line_table, location);
> > -  bool ret = diagnostic_impl (&richloc, opt, gmsgid, &ap,
> > DK_WARNING);
> > +  bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap,
> > DK_WARNING);
> >     va_end (ap);
> >     return ret;
> >   }
> > @@ -1357,7 +1419,25 @@ warning_at (rich_location *richloc, int opt,
> > const char *gmsgid, ...)
> >     auto_diagnostic_group d;
> >     va_list ap;
> >     va_start (ap, gmsgid);
> > -  bool ret = diagnostic_impl (richloc, opt, gmsgid, &ap,
> > DK_WARNING);
> > +  bool ret = diagnostic_impl (richloc, NULL, opt, gmsgid, &ap,
> > DK_WARNING);
> > +  va_end (ap);
> > +  return ret;
> > +}
> > +
> > +/* Same as "warning at" above, but using METADATA.  */
> > +
> > +bool
> > +warning_at (rich_location *richloc, const diagnostic_metadata
> > &metadata,
> > +       int opt, const char *gmsgid, ...)
> > +{
> > +  gcc_assert (richloc);
> > +
> > +  auto_diagnostic_group d;
> > +  va_list ap;
> > +  va_start (ap, gmsgid);
> > +  bool ret
> > +    = diagnostic_impl (richloc, &metadata, opt, gmsgid, &ap,
> > +                  DK_WARNING);
> >     va_end (ap);
> >     return ret;
> >   }
> > @@ -1373,7 +1453,7 @@ warning_n (rich_location *richloc, int opt,
> > unsigned HOST_WIDE_INT n,
> >     auto_diagnostic_group d;
> >     va_list ap;
> >     va_start (ap, plural_gmsgid);
> > -  bool ret = diagnostic_n_impl (richloc, opt, n,
> > +  bool ret = diagnostic_n_impl (richloc, NULL, opt, n,
> >                             singular_gmsgid, plural_gmsgid,
> >                             &ap, DK_WARNING);
> >     va_end (ap);
> > @@ -1392,7 +1472,7 @@ warning_n (location_t location, int opt,
> > unsigned HOST_WIDE_INT n,
> >     va_list ap;
> >     va_start (ap, plural_gmsgid);
> >     rich_location richloc (line_table, location);
> > -  bool ret = diagnostic_n_impl (&richloc, opt, n,
> > +  bool ret = diagnostic_n_impl (&richloc, NULL, opt, n,
> >                             singular_gmsgid, plural_gmsgid,
> >                             &ap, DK_WARNING);
> >     va_end (ap);
> > @@ -1419,7 +1499,7 @@ pedwarn (location_t location, int opt, const
> > char *gmsgid, ...)
> >     va_list ap;
> >     va_start (ap, gmsgid);
> >     rich_location richloc (line_table, location);
> > -  bool ret = diagnostic_impl (&richloc, opt, gmsgid, &ap,
> > DK_PEDWARN);
> > +  bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap,
> > DK_PEDWARN);
> >     va_end (ap);
> >     return ret;
> >   }
> > @@ -1434,7 +1514,7 @@ pedwarn (rich_location *richloc, int opt,
> > const char *gmsgid, ...)
> >     auto_diagnostic_group d;
> >     va_list ap;
> >     va_start (ap, gmsgid);
> > -  bool ret = diagnostic_impl (richloc, opt, gmsgid, &ap,
> > DK_PEDWARN);
> > +  bool ret = diagnostic_impl (richloc, NULL, opt, gmsgid, &ap,
> > DK_PEDWARN);
> >     va_end (ap);
> >     return ret;
> >   }
> > @@ -1453,7 +1533,7 @@ permerror (location_t location, const char
> > *gmsgid, ...)
> >     va_list ap;
> >     va_start (ap, gmsgid);
> >     rich_location richloc (line_table, location);
> > -  bool ret = diagnostic_impl (&richloc, -1, gmsgid, &ap,
> > DK_PERMERROR);
> > +  bool ret = diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap,
> > DK_PERMERROR);
> >     va_end (ap);
> >     return ret;
> >   }
> > @@ -1468,7 +1548,7 @@ permerror (rich_location *richloc, const char
> > *gmsgid, ...)
> >     auto_diagnostic_group d;
> >     va_list ap;
> >     va_start (ap, gmsgid);
> > -  bool ret = diagnostic_impl (richloc, -1, gmsgid, &ap,
> > DK_PERMERROR);
> > +  bool ret = diagnostic_impl (richloc, NULL, -1, gmsgid, &ap,
> > DK_PERMERROR);
> >     va_end (ap);
> >     return ret;
> >   }
> > @@ -1482,7 +1562,7 @@ error (const char *gmsgid, ...)
> >     va_list ap;
> >     va_start (ap, gmsgid);
> >     rich_location richloc (line_table, input_location);
> > -  diagnostic_impl (&richloc, -1, gmsgid, &ap, DK_ERROR);
> > +  diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ERROR);
> >     va_end (ap);
> >   }
> >   
> > @@ -1496,7 +1576,7 @@ error_n (location_t location, unsigned
> > HOST_WIDE_INT n,
> >     va_list ap;
> >     va_start (ap, plural_gmsgid);
> >     rich_location richloc (line_table, location);
> > -  diagnostic_n_impl (&richloc, -1, n, singular_gmsgid,
> > plural_gmsgid,
> > +  diagnostic_n_impl (&richloc, NULL, -1, n, singular_gmsgid,
> > plural_gmsgid,
> >                  &ap, DK_ERROR);
> >     va_end (ap);
> >   }
> > @@ -1509,7 +1589,7 @@ error_at (location_t loc, const char *gmsgid,
> > ...)
> >     va_list ap;
> >     va_start (ap, gmsgid);
> >     rich_location richloc (line_table, loc);
> > -  diagnostic_impl (&richloc, -1, gmsgid, &ap, DK_ERROR);
> > +  diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ERROR);
> >     va_end (ap);
> >   }
> >   
> > @@ -1523,7 +1603,7 @@ error_at (rich_location *richloc, const char
> > *gmsgid, ...)
> >     auto_diagnostic_group d;
> >     va_list ap;
> >     va_start (ap, gmsgid);
> > -  diagnostic_impl (richloc, -1, gmsgid, &ap, DK_ERROR);
> > +  diagnostic_impl (richloc, NULL, -1, gmsgid, &ap, DK_ERROR);
> >     va_end (ap);
> >   }
> >   
> > @@ -1537,7 +1617,7 @@ sorry (const char *gmsgid, ...)
> >     va_list ap;
> >     va_start (ap, gmsgid);
> >     rich_location richloc (line_table, input_location);
> > -  diagnostic_impl (&richloc, -1, gmsgid, &ap, DK_SORRY);
> > +  diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_SORRY);
> >     va_end (ap);
> >   }
> >   
> > @@ -1549,7 +1629,7 @@ sorry_at (location_t loc, const char *gmsgid,
> > ...)
> >     va_list ap;
> >     va_start (ap, gmsgid);
> >     rich_location richloc (line_table, loc);
> > -  diagnostic_impl (&richloc, -1, gmsgid, &ap, DK_SORRY);
> > +  diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_SORRY);
> >     va_end (ap);
> >   }
> >   
> > @@ -1571,7 +1651,7 @@ fatal_error (location_t loc, const char
> > *gmsgid, ...)
> >     va_list ap;
> >     va_start (ap, gmsgid);
> >     rich_location richloc (line_table, loc);
> > -  diagnostic_impl (&richloc, -1, gmsgid, &ap, DK_FATAL);
> > +  diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_FATAL);
> >     va_end (ap);
> >   
> >     gcc_unreachable ();
> > @@ -1588,7 +1668,7 @@ internal_error (const char *gmsgid, ...)
> >     va_list ap;
> >     va_start (ap, gmsgid);
> >     rich_location richloc (line_table, input_location);
> > -  diagnostic_impl (&richloc, -1, gmsgid, &ap, DK_ICE);
> > +  diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ICE);
> >     va_end (ap);
> >   
> >     gcc_unreachable ();
> > @@ -1604,7 +1684,7 @@ internal_error_no_backtrace (const char
> > *gmsgid, ...)
> >     va_list ap;
> >     va_start (ap, gmsgid);
> >     rich_location richloc (line_table, input_location);
> > -  diagnostic_impl (&richloc, -1, gmsgid, &ap, DK_ICE_NOBT);
> > +  diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ICE_NOBT);
> >     va_end (ap);
> >   
> >     gcc_unreachable ();
> > diff --git a/gcc/diagnostic.h b/gcc/diagnostic.h
> > index 2fb75e6..0e4b6ad 100644
> > --- a/gcc/diagnostic.h
> > +++ b/gcc/diagnostic.h
> > @@ -46,6 +46,10 @@ struct diagnostic_info
> >     /* The location at which the diagnostic is to be reported.  */
> >     rich_location *richloc;
> >   
> > +  /* An optional bundle of metadata associated with the diagnostic
> > +     (or NULL).  */
> > +  const diagnostic_metadata *metadata;
> > +
> >     /* Auxiliary data for client.  */
> >     void *x_data;
> >     /* The kind of diagnostic it is about.  */
> > @@ -126,6 +130,9 @@ struct diagnostic_context
> >     /* Character used for caret diagnostics.  */
> >     char caret_chars[rich_location::STATICALLY_ALLOCATED_RANGES];
> >   
> > +  /* True if we should print any metadata associated with
> > diagnostics.  */
> > +  bool show_metadata;
> > +
> >     /* True if we should print the command line option which
> > controls
> >        each diagnostic, if known.  */
> >     bool show_option_requested;
> > diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
> > index fc92913..209e2c6 100644
> > --- a/gcc/doc/invoke.texi
> > +++ b/gcc/doc/invoke.texi
> > @@ -279,6 +279,7 @@ Objective-C and Objective-C++ Dialects}.
> >   -fno-diagnostics-show-option  -fno-diagnostics-show-caret @gol
> >   -fno-diagnostics-show-labels  -fno-diagnostics-show-line-numbers
> > @gol
> >   -fdiagnostics-nn-line-numbers @gol
> > +-fno-diagnostics-show-metadata  @gol
> >   -fdiagnostics-minimum-margin-width=@var{width} @gol
> >   -fdiagnostics-parseable-fixits  -fdiagnostics-generate-patch @gol
> >   -fdiagnostics-show-template-tree  -fno-elide-type @gol
> > @@ -4012,6 +4013,13 @@ as the types of expressions:
> >   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-metadata
> > +@opindex fno-diagnostics-show-metadata
> > +@opindex fdiagnostics-show-metadata
> > +Diagnostics can optionally contain @url{
> > https://cwe.mitre.org/index.html, CWE}
> > +metadata.  By default, if this information is present, it will be
> > printed with
> > +the diagnostic.  This option suppresses the printing of this
> > metadata.
> > +
> >   @item -fno-diagnostics-show-line-numbers
> >   @opindex fno-diagnostics-show-line-numbers
> >   @opindex fdiagnostics-show-line-numbers
> > diff --git a/gcc/opts.c b/gcc/opts.c
> > index 9928d01..0caaf04 100644
> > --- a/gcc/opts.c
> > +++ b/gcc/opts.c
> > @@ -2491,6 +2491,10 @@ common_handle_option (struct gcc_options
> > *opts,
> >         dc->parseable_fixits_p = value;
> >         break;
> >   
> > +    case OPT_fdiagnostics_show_metadata:
> > +      dc->show_metadata = value;
> > +      break;
> > +
> >       case OPT_fdiagnostics_show_option:
> >         dc->show_option_requested = value;
> >         break;
> > diff --git a/gcc/toplev.c b/gcc/toplev.c
> > index 2d0a390..7136164 100644
> > --- a/gcc/toplev.c
> > +++ b/gcc/toplev.c
> > @@ -1102,6 +1102,8 @@ general_init (const char *argv0, bool
> > init_signals)
> >       = global_options_init.x_flag_diagnostics_show_line_numbers;
> >     global_dc->use_nn_for_line_numbers_p
> >       = global_options_init.x_flag_diagnostics_nn_line_numbers;
> > +  global_dc->show_metadata
> > +    = global_options_init.x_flag_diagnostics_show_metadata;
> >     global_dc->show_option_requested
> >       = global_options_init.x_flag_diagnostics_show_option;
> >     global_dc->min_margin_width
> > 

Reply via email to