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 > >