On 12/12/19 7:59 PM, David Malcolm wrote:
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).

I wasn't necessarily asking about any classifications in particular,
or even about pre-existing warnings.  I think it would be nice to be
able to eventually make it work for them but I obviously realize that
will take quite a bit retrofitting.

What I'd like to understand how the warning X classification-id
mapping for the new analyzer warnings is supported in the design
of the (new) diagnostic infrastructure (or how you envision it
will be when it's more complete).

You said the analyzer currently only supports associating a CWE
identifier with a diagnostic.  By "diagnostic" do you mean
a particular instance of a given warning or all its instances?

Picking an uninitialized use as an example, there are three CWE's
that discuss it:

  CWE-457: Use of Uninitialized Variable
  CWE-824: Access of Uninitialized Pointer
  CWE-908: Use of Uninitialized Resource

but only one -Wanalyzer-use-of-uninitialized-value.  I'd like to
see how the mapping works (or will work) between these three CWE's
and instances of this analyzer option/warning.

I see on Goldbolt that for either the use of an uninitialized
pointer (CWE-457) or for its dereference (CWE-824) the analyzer
issues the same warning with the same CWE ID:

use of uninitialized value 'p' [CWE-457] [-Wanalyzer-use-of-uninitialized-value]

It doesn't differentiate between the two CWE's.

If this limitation is baked into the design of the infrastructure
then that's an obvious flaw that needs to be fixed.  There is no
point in issuing warnings with the wrong CWE's.  Anyone who cares
about CWE's would view those as bugs, and those who don't care
don't need to see them.

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).
I agree that dealing with evolving classifications is a secondary
goal that can probably be fairly easily met.  I wanted to know if
there already was a solution for it now.

But referencing the right IDs in the diagnostics seems like a basic
design requirement.  Unless the above example is due to the mapping
not being fully populated yet it seems clear that issuing a warning
with one CWE ID for a bug described under another CWE ID is
a problem.

Martin


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