We currently identify our diagnostics via command-line options, and by
the text of the option itself.

This patch adds a way to supply metadata with a diagnostic, classifying
the problem being reported, according to one of the software problem
taxonomies e.g. "INT15-C" within the CERT C Secure Coding Standard,
or "CWE-681" within the Common Weakness Enumeration (CWE).

The patch tags some of our diagnostics with CERT C IDs.

For example:

t.c: In function 'f1':
t.c:9:20: warning: division 'sizeof (int *) / sizeof (int)' does not
compute the number of array elements [-Wsizeof-pointer-div] [ARR01-C]
   i = sizeof array / sizeof *array;  /* { dg-warning "does not compute the 
number of array elements" } */
                    ^
t.c:6:10: note: first 'sizeof' operand was declared here
 f1 (int *array)
     ~~~~~^~~~~

Note the " [ARR01-C]" appended after the "[-Wsizeof-pointer-div]"
above.  The "ARR01-C" is colorized (assuming colorization is enabled).

Such metadata IDs can be useful for categorizing problems, or for
searching for helpful recommendations for addressing the diagnostic.

For example, if I search for on Google for "-Wsizeof-pointer-div",
I get no results (owing to the leading dash having meaning for
Google); if I drop the leading dash, I get a number of
different pages describing the implementation of the warning.

If I search instead for "ARR01-C", the first hit takes me to
the article about that issue within the SEI CERT C Coding Standard,
giving lots of useful information about the problem and how to fix it.

The new output can be suppressed using a new -fno-diagnostics-show-id
flag.

Implementation-wise, the patch replaces the "int opt" taken by our
internal APIs (like warning_at), in place of a "class diag_id" which
can be implicitly constructed from an "int opt", so no changes are
needed at callsites that emit diagnostics, until ID tags are added,
so e.g.:

  if (warning_at (body_loc, OPT_Wmultistatement_macros,
                  "macro expands to multiple statements"))
    ...

continues to compile, but can be converted to:

  if (warning_at (body_loc,
                  diag_id (OPT_Wmultistatement_macros, "PRE10-C"),
                  "macro expands to multiple statements"))
    ...

I didn't touch the Fortran error API.

Some known unknowns/questions:
- is this useful?  (I think so)
- if we implement this, should we go through the existing
  diagnostics tagging them?  if so, what taxonomy/taxonomies should we use?
  CERT vs CWE etc
- should the ID be tagged with the taxonomy it comes from? (so e.g.
  "ARR01-C" could be tagged as being from "CERT C", somehow).  How
  would this be presented to the end-user? Maybe:
    [-Wsizeof-pointer-div] [CERT-C: ARR01-C]
- could/should we support multiple taxonomies e.g. CERT vs CWE e.g.
    "[CERT-C: ARR01C] [CWE: CWE-467]" or somesuch
- if so, do we want taxonomies to be "pluggable"?  consider the
  use-case of a plugin that implements, say, the C++ Core Guidelines,
  and hence could print stuff like:
    "[c++-core-guidelines: C.128]" or somesuch
- are there license/trademark issues here?

Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.

Thoughts?

gcc/c-family/ChangeLog:
        * c-common.c (c_cpp_error): Provide NULL for new id parameter of
        diagnostic_set_info_translated.
        * c-warn.c (warn_for_multistatement_macros): Identify the
        diagnostic as "PRE10-C".

gcc/c/ChangeLog:
        * c-decl.c (warn_defaults_to): Convert param from int to
        const diag_id &, and pass on taxonomy id to the diagnostic_info.
        * c-errors.c (pedwarn_c99): Likewise.
        (pedwarn_c90): Likewise.
        * c-parser.c (c_parser_binary_expression): Mark
        OPT_Wsizeof_pointer_div warning as "ARR01-C".
        * c-tree.h (pedwarn_c90): Convert param from int to
        const diag_id &.
        (pedwarn_c99): Likewise.
        * c-typeck.c (c_expr_sizeof_expr): Mark OPT_Wsizeof_array_argument
        warning as "ARR01-C".

gcc/cp/ChangeLog:
        * cp-tree.h (pedwarn_cxx98): Convert param from int to
        const diag_id &.
        * error.c (pedwarn_cxx98): Likewise; pass on taxonomy id to the
        diagnostic_info.
        * typeck.c (cxx_sizeof_expr): Mark OPT_Wsizeof_array_argument
        warning as "ARR01-C".
        (cp_build_binary_op): Likewise for OPT_Wsizeof_pointer_div
        warning.

gcc/ChangeLog:
        * common.opt (fdiagnostics-show-id): New option.
        * diagnostic-core.h (class diag_id): New class.
        (warning): Convert param from int to const diag_id &.
        (warning_n): Likewise.
        (warning_at): Likewise.
        (pedwarn): Likewise.
        (emit_diagnostic): Likewise.
        (emit_diagnostic_valist): Likewise.
        * diagnostic.c (diagnostic_initialize): Initialize new "show_id"
        field.
        (diagnostic_set_info_translated): Add param "taxonomy_id" and
        use it to initialize new field of same name.
        (diagnostic_set_info): Add param "taxonomy_id" and pass through to
        diagnostic_set_info_translated.
        (print_taxonomy_information): New function.
        (diagnostic_report_diagnostic): Call it.
        (diagnostic_append_note): Pass NULL for new taxonomy_id param.
        (diagnostic_impl): Convert param from int to const diag_id &; pass
        id through to diagnostic_set_info.
        (diagnostic_n_impl): Likewise.
        (emit_diagnostic): Convert param from int to const diag_id &.
        (emit_diagnostic_valist): Likewise.
        (warning): Likewise.
        (warning_at): Likewise.
        (warning_n): Likewise.
        (pedwarn): Likewise.
        (selftest::assert_print_taxonomy_information): New function.
        (selftest::test_print_taxonomy_information): New function.
        (selftest::diagnostic_c_tests): Call it.
        * diagnostic.h (struct diagnostic_info): New field "taxonomy_id".
        (struct diagnostic_context): New field "show_id".
        (diagnostic_set_info): Add new "const char *" param.
        (diagnostic_set_info_translated): Likewise.
        * doc/invoke.texi (Diagnostic Message Formatting Options): Add
        -fno-diagnostics-show-id.
        (-fno-diagnostics-show-id): New option.
        * gimple-ssa-sprintf.c (get_format_string): Update fmtwarn for
        change of format_warning_at_substring signature.
        * opts.c (common_handle_option): Handle OPT_fdiagnostics_show_id.
        * rtl-error.c (diagnostic_for_asm): Add NULL for new "taxonomy_id" param
        of diagnostic_set_info.
        * substring-locations.c (format_warning_va): Convert param from
        int to const diag_id &.  Use it for taxonomy_id param in call to
        diagnostic_set_info.
        (format_warning_at_substring): Convert param from int to
        const diag_id &.
        * substring-locations.h (format_warning_va): Likewise.
        (format_warning_at_substring): Likewise.
        * toplev.c (general_init): Initialize global_dc->show_id.

gcc/fortran/ChangeLog:
        * cpp.c (cb_cpp_error): Add NULL for new "taxonomy_id" param of
        diagnostic_set_info_translated.
        * error.c (gfc_warning): Likewise for new param of
        diagnostic_set_info.
        (gfc_warning_now_at): Likewise.
        (gfc_warning_now): Likewise.
        (gfc_warning_internal): Likewise.
        (gfc_error_now): Likewise.
        (gfc_fatal_error): Likewise.
        (gfc_error_opt): Likewise.
        (gfc_internal_error): Likewise.
---
 gcc/c-family/c-common.c   |   2 +-
 gcc/c-family/c-warn.c     |   3 +-
 gcc/c/c-decl.c            |  10 ++--
 gcc/c/c-errors.c          |  27 +++++-----
 gcc/c/c-parser.c          |   3 +-
 gcc/c/c-tree.h            |   4 +-
 gcc/c/c-typeck.c          |   2 +-
 gcc/common.opt            |   4 ++
 gcc/cp/cp-tree.h          |   2 +-
 gcc/cp/error.c            |   7 +--
 gcc/cp/typeck.c           |   6 ++-
 gcc/diagnostic-core.h     |  53 +++++++++++++++-----
 gcc/diagnostic.c          | 122 +++++++++++++++++++++++++++++++++-------------
 gcc/diagnostic.h          |  13 ++++-
 gcc/doc/invoke.texi       |  15 +++++-
 gcc/fortran/cpp.c         |   2 +-
 gcc/fortran/error.c       |  18 ++++---
 gcc/gimple-ssa-sprintf.c  |   2 +-
 gcc/opts.c                |   4 ++
 gcc/rtl-error.c           |   2 +-
 gcc/substring-locations.c |  13 ++---
 gcc/substring-locations.h |   8 ++-
 gcc/toplev.c              |   2 +
 23 files changed, 229 insertions(+), 95 deletions(-)

diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 24077c7..bae124d 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -6069,7 +6069,7 @@ c_cpp_error (cpp_reader *pfile ATTRIBUTE_UNUSED, int 
level, int reason,
   if (done_lexing)
     richloc->set_range (line_table, 0, input_location, true);
   diagnostic_set_info_translated (&diagnostic, msg, ap,
-                                 richloc, dlevel);
+                                 richloc, dlevel, NULL);
   diagnostic_override_option_index (&diagnostic,
                                     c_option_controlling_cpp_error (reason));
   ret = diagnostic_report_diagnostic (global_dc, &diagnostic);
diff --git a/gcc/c-family/c-warn.c b/gcc/c-family/c-warn.c
index 09ef685..f28f294 100644
--- a/gcc/c-family/c-warn.c
+++ b/gcc/c-family/c-warn.c
@@ -2562,7 +2562,8 @@ warn_for_multistatement_macros (location_t body_loc, 
location_t next_loc,
        return;
     }
 
-  if (warning_at (body_loc, OPT_Wmultistatement_macros,
+  if (warning_at (body_loc,
+                 diag_id (OPT_Wmultistatement_macros, "PRE10-C"),
                  "macro expands to multiple statements"))
     inform (guard_loc, "some parts of macro expansion are not guarded by "
            "this %qs clause", guard_tinfo_to_string (keyword));
diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index d95a2b6..ea35990 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -599,7 +599,7 @@ static tree grokdeclarator (const struct c_declarator *,
                            bool *, enum deprecated_states);
 static tree grokparms (struct c_arg_info *, bool);
 static void layout_array_type (tree);
-static void warn_defaults_to (location_t, int, const char *, ...)
+static void warn_defaults_to (location_t, const diag_id &, const char *, ...)
     ATTRIBUTE_GCC_DIAG(3,4);
 
 /* T is a statement.  Add it to the statement-tree.  This is the
@@ -5473,7 +5473,8 @@ warn_variable_length_array (tree name, tree size)
 /* Print warning about defaulting to int if necessary.  */
 
 static void
-warn_defaults_to (location_t location, int opt, const char *gmsgid, ...)
+warn_defaults_to (location_t location, const diag_id &di, const char *gmsgid,
+                 ...)
 {
   diagnostic_info diagnostic;
   va_list ap;
@@ -5481,8 +5482,9 @@ warn_defaults_to (location_t location, int opt, const 
char *gmsgid, ...)
 
   va_start (ap, gmsgid);
   diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc,
-                       flag_isoc99 ? DK_PEDWARN : DK_WARNING);
-  diagnostic.option_index = opt;
+                      flag_isoc99 ? DK_PEDWARN : DK_WARNING,
+                      di.get_id ());
+  diagnostic.option_index = di.get_option ();
   diagnostic_report_diagnostic (global_dc, &diagnostic);
   va_end (ap);
 }
diff --git a/gcc/c/c-errors.c b/gcc/c/c-errors.c
index aa9ce42..6b9c425 100644
--- a/gcc/c/c-errors.c
+++ b/gcc/c/c-errors.c
@@ -32,7 +32,7 @@ along with GCC; see the file COPYING3.  If not see
    when C11 is specified.  */
 
 bool
-pedwarn_c99 (location_t location, int opt, const char *gmsgid, ...)
+pedwarn_c99 (location_t location, const diag_id &di, const char *gmsgid, ...)
 {
   diagnostic_info diagnostic;
   va_list ap;
@@ -46,7 +46,7 @@ pedwarn_c99 (location_t location, int opt, const char 
*gmsgid, ...)
     {
       diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc,
                           (pedantic && !flag_isoc11)
-                          ? DK_PEDWARN : DK_WARNING);
+                          ? DK_PEDWARN : DK_WARNING, di.get_id ());
       diagnostic.option_index = OPT_Wc99_c11_compat;
       warned = diagnostic_report_diagnostic (global_dc, &diagnostic);
     }
@@ -56,8 +56,9 @@ pedwarn_c99 (location_t location, int opt, const char 
*gmsgid, ...)
   /* For -pedantic outside C11, issue a pedwarn.  */
   else if (pedantic && !flag_isoc11)
     {
-      diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_PEDWARN);
-      diagnostic.option_index = opt;
+      diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_PEDWARN,
+                          di.get_id ());
+      diagnostic.option_index = di.get_option ();
       warned = diagnostic_report_diagnostic (global_dc, &diagnostic);
     }
   va_end (ap);
@@ -72,7 +73,7 @@ pedwarn_c99 (location_t location, int opt, const char 
*gmsgid, ...)
    when C99 is specified.  (There is no flag_c90.)  */
 
 bool
-pedwarn_c90 (location_t location, int opt, const char *gmsgid, ...)
+pedwarn_c90 (location_t location, const diag_id &di, const char *gmsgid, ...)
 {
   diagnostic_info diagnostic;
   va_list ap;
@@ -81,17 +82,18 @@ pedwarn_c90 (location_t location, int opt, const char 
*gmsgid, ...)
 
   va_start (ap, gmsgid);
   /* Warnings such as -Wvla are the most specific ones.  */
-  if (opt != OPT_Wpedantic)
+  if (di.get_option () != OPT_Wpedantic)
     {
-      int opt_var = *(int *) option_flag_var (opt, &global_options);
+      int opt_var = *(int *) option_flag_var (di.get_option (),
+                                             &global_options);
       if (opt_var == 0)
         goto out;
       else if (opt_var > 0)
        {
          diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc,
                               (pedantic && !flag_isoc99)
-                              ? DK_PEDWARN : DK_WARNING);
-         diagnostic.option_index = opt;
+                              ? DK_PEDWARN : DK_WARNING, di.get_id ());
+         diagnostic.option_index = di.get_option ();
          diagnostic_report_diagnostic (global_dc, &diagnostic);
          warned = true;
          goto out;
@@ -103,7 +105,7 @@ pedwarn_c90 (location_t location, int opt, const char 
*gmsgid, ...)
     {
       diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc,
                           (pedantic && !flag_isoc99)
-                          ? DK_PEDWARN : DK_WARNING);
+                          ? DK_PEDWARN : DK_WARNING, di.get_id ());
       diagnostic.option_index = OPT_Wc90_c99_compat;
       diagnostic_report_diagnostic (global_dc, &diagnostic);
     }
@@ -113,8 +115,9 @@ pedwarn_c90 (location_t location, int opt, const char 
*gmsgid, ...)
   /* For -pedantic outside C99, issue a pedwarn.  */
   else if (pedantic && !flag_isoc99)
     {
-      diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_PEDWARN);
-      diagnostic.option_index = opt;
+      diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_PEDWARN,
+                          di.get_id ());
+      diagnostic.option_index = di.get_option ();
       diagnostic_report_diagnostic (global_dc, &diagnostic);
       warned = true;
     }
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index 7bca5f1..0405a4a 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -6989,7 +6989,8 @@ c_parser_binary_expression (c_parser *parser, struct 
c_expr *after,
                && !(TREE_CODE (first_arg) == PARM_DECL                       \
                     && C_ARRAY_PARAMETER (first_arg)                         \
                     && warn_sizeof_array_argument))                          \
-             if (warning_at (stack[sp].loc, OPT_Wsizeof_pointer_div,         \
+             if (warning_at (stack[sp].loc,                                  \
+                             diag_id (OPT_Wsizeof_pointer_div, "ARR01-C"),   \
                              "division %<sizeof (%T) / sizeof (%T)%> does "  \
                              "not compute the number of array elements",     \
                              type0, type1))                                  \
diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
index 1135647..c4d7921 100644
--- a/gcc/c/c-tree.h
+++ b/gcc/c/c-tree.h
@@ -756,9 +756,9 @@ extern void c_bind (location_t, tree, bool);
 extern bool tag_exists_p (enum tree_code, tree);
 
 /* In c-errors.c */
-extern bool pedwarn_c90 (location_t, int opt, const char *, ...)
+extern bool pedwarn_c90 (location_t, const diag_id &, const char *, ...)
     ATTRIBUTE_GCC_DIAG(3,4);
-extern bool pedwarn_c99 (location_t, int opt, const char *, ...)
+extern bool pedwarn_c99 (location_t, const diag_id &, const char *, ...)
     ATTRIBUTE_GCC_DIAG(3,4);
 
 extern void
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index 4bdc48a..394b556 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -2905,7 +2905,7 @@ c_expr_sizeof_expr (location_t loc, struct c_expr expr)
       if (TREE_CODE (expr.value) == PARM_DECL
          && C_ARRAY_PARAMETER (expr.value))
        {
-         if (warning_at (loc, OPT_Wsizeof_array_argument,
+         if (warning_at (loc, diag_id (OPT_Wsizeof_array_argument, "ARR01-C"),
                          "%<sizeof%> on array function parameter %qE will "
                          "return size of %qT", expr.value,
                          TREE_TYPE (expr.value)))
diff --git a/gcc/common.opt b/gcc/common.opt
index f8f2ed3..4c13205 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -1268,6 +1268,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-id
+Common Var(flag_diagnostics_show_id) Init(1)
+Amend appropriate diagnostic messages with an identifier within a problem 
taxonomy.
+
 fdisable-
 Common Joined RejectNegative Var(common_deferred_options) Defer
 -fdisable-[tree|rtl|ipa]-<pass>=range1+range2 disables an optimization pass.
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 257c877..3ff2703 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -6222,7 +6222,7 @@ extern const char *language_to_string             (enum 
languages);
 extern const char *class_key_or_enum_as_string (tree);
 extern void maybe_warn_variadic_templates       (void);
 extern void maybe_warn_cpp0x                   (cpp0x_warn_str str);
-extern bool pedwarn_cxx98                       (location_t, int, const char 
*, ...) ATTRIBUTE_GCC_DIAG(3,4);
+extern bool pedwarn_cxx98                       (location_t, const diag_id &, 
const char *, ...) ATTRIBUTE_GCC_DIAG(3,4);
 extern location_t location_of                   (tree);
 extern void qualified_name_lookup_error                (tree, tree, tree,
                                                 location_t);
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index 2537713..80e45bf 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -4181,7 +4181,7 @@ maybe_warn_variadic_templates (void)
    diagnostics for constructs that are invalid C++98, but valid
    C++0x.  */
 bool
-pedwarn_cxx98 (location_t location, int opt, const char *gmsgid, ...)
+pedwarn_cxx98 (location_t location, const diag_id &di, const char *gmsgid, ...)
 {
   diagnostic_info diagnostic;
   va_list ap;
@@ -4190,8 +4190,9 @@ pedwarn_cxx98 (location_t location, int opt, const char 
*gmsgid, ...)
 
   va_start (ap, gmsgid);
   diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc,
-                      (cxx_dialect == cxx98) ? DK_PEDWARN : DK_WARNING);
-  diagnostic.option_index = opt;
+                      (cxx_dialect == cxx98) ? DK_PEDWARN : DK_WARNING,
+                      di.get_id ());
+  diagnostic.option_index = di.get_option ();
   ret = diagnostic_report_diagnostic (global_dc, &diagnostic);
   va_end (ap);
   return ret;
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 285d8d2..5b279df 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -1637,7 +1637,8 @@ cxx_sizeof_expr (tree e, tsubst_flags_t complain)
       && DECL_ARRAY_PARAMETER_P (e)
       && (complain & tf_warning))
     {
-      if (warning (OPT_Wsizeof_array_argument, "%<sizeof%> on array function "
+      if (warning (diag_id (OPT_Wsizeof_array_argument, "ARR01-C"),
+                  "%<sizeof%> on array function "
                   "parameter %qE will return size of %qT", e, TREE_TYPE (e)))
        inform (DECL_SOURCE_LOCATION (e), "declared here");
     }
@@ -4374,7 +4375,8 @@ cp_build_binary_op (location_t location,
                   && DECL_ARRAY_PARAMETER_P (first_arg)
                   && warn_sizeof_array_argument)
              && (complain & tf_warning))
-           if (warning_at (location, OPT_Wsizeof_pointer_div,
+           if (warning_at (location,
+                           diag_id (OPT_Wsizeof_pointer_div, "ARR01-C"),
                            "division %<sizeof (%T) / sizeof (%T)%> does "
                            "not compute the number of array elements",
                            type0, type1))
diff --git a/gcc/diagnostic-core.h b/gcc/diagnostic-core.h
index 24025f1..7b23cf6 100644
--- a/gcc/diagnostic-core.h
+++ b/gcc/diagnostic-core.h
@@ -36,6 +36,36 @@ typedef enum
   DK_POP
 } diagnostic_t;
 
+/* A class for describing a diagnostic.
+
+   It wraps:
+
+   (a) one of the OPT_W* from options.h, describing the command-line
+   option controlling it (if any), and,
+
+   (b) optionally, an ID from a problem taxonomy (such as "PRE10-C" from the
+   CERT C Secure Coding Standard, or "CWE-681" from the Common Weakness
+   Enumeration).
+
+   It is in this header so that users of the simple diagnostic API (e.g.
+   warning_at) can pass in OPT_W* flags and have them be implicitly
+   converted to diag_id.  */
+
+class diag_id
+{
+ public:
+  /* Pass one of the OPT_W* from options.h as the first parameter.  */
+  diag_id (int opt) : m_opt (opt), m_id (NULL) {}
+  diag_id (int opt, const char *id) : m_opt (opt), m_id (id) {}
+
+  int get_option () const { return m_opt; }
+  const char *get_id () const { return m_id; }
+
+ private:
+  int m_opt;
+  const char *m_id;
+};
+
 extern const char *progname;
 
 extern const char *trim_filename (const char *);
@@ -57,16 +87,15 @@ extern void internal_error (const char *, ...) 
ATTRIBUTE_GCC_DIAG(1,2)
      ATTRIBUTE_NORETURN;
 extern void internal_error_no_backtrace (const char *, ...)
      ATTRIBUTE_GCC_DIAG(1,2) ATTRIBUTE_NORETURN;
-/* Pass one of the OPT_W* from options.h as the first parameter.  */
-extern bool warning (int, const char *, ...) ATTRIBUTE_GCC_DIAG(2,3);
-extern bool warning_n (location_t, int, int, const char *, const char *, ...)
+extern bool warning (const diag_id &, const char *, ...) 
ATTRIBUTE_GCC_DIAG(2,3);
+extern bool warning_n (location_t, const diag_id &, int, const char *, const 
char *, ...)
     ATTRIBUTE_GCC_DIAG(4,6) ATTRIBUTE_GCC_DIAG(5,6);
-extern bool warning_n (rich_location *, int, int, const char *,
+extern bool warning_n (rich_location *, const diag_id &, int, const char *,
                       const char *, ...)
     ATTRIBUTE_GCC_DIAG(4, 6) ATTRIBUTE_GCC_DIAG(5, 6);
-extern bool warning_at (location_t, int, const char *, ...)
+extern bool warning_at (location_t, const diag_id &, const char *, ...)
     ATTRIBUTE_GCC_DIAG(3,4);
-extern bool warning_at (rich_location *, int, const char *, ...)
+extern bool warning_at (rich_location *, const diag_id &, const char *, ...)
     ATTRIBUTE_GCC_DIAG(3,4);
 extern void error (const char *, ...) ATTRIBUTE_GCC_DIAG(1,2);
 extern void error_n (location_t, int, const char *, const char *, ...)
@@ -76,10 +105,9 @@ extern void error_at (rich_location *, const char *, ...)
   ATTRIBUTE_GCC_DIAG(2,3);
 extern void fatal_error (location_t, const char *, ...) ATTRIBUTE_GCC_DIAG(2,3)
      ATTRIBUTE_NORETURN;
-/* Pass one of the OPT_W* from options.h as the second parameter.  */
-extern bool pedwarn (location_t, int, const char *, ...)
+extern bool pedwarn (location_t, const diag_id &, const char *, ...)
      ATTRIBUTE_GCC_DIAG(3,4);
-extern bool pedwarn (rich_location *, int, const char *, ...)
+extern bool pedwarn (rich_location *, const diag_id &, const char *, ...)
      ATTRIBUTE_GCC_DIAG(3,4);
 extern bool permerror (location_t, const char *, ...) ATTRIBUTE_GCC_DIAG(2,3);
 extern bool permerror (rich_location *, const char *,
@@ -90,10 +118,11 @@ extern void inform (rich_location *, const char *, ...) 
ATTRIBUTE_GCC_DIAG(2,3);
 extern void inform_n (location_t, int, const char *, const char *, ...)
     ATTRIBUTE_GCC_DIAG(3,5) ATTRIBUTE_GCC_DIAG(4,5);
 extern void verbatim (const char *, ...) ATTRIBUTE_GCC_DIAG(1,2);
-extern bool emit_diagnostic (diagnostic_t, location_t, int,
+extern bool emit_diagnostic (diagnostic_t, location_t, const diag_id &,
                             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, location_t, const diag_id &,
+                                   const char *, va_list *)
+  ATTRIBUTE_GCC_DIAG (4,0);
 extern bool seen_error (void);
 
 #ifdef BUFSIZ
diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c
index 813bca6..a687b5e 100644
--- a/gcc/diagnostic.c
+++ b/gcc/diagnostic.c
@@ -49,10 +49,10 @@ 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 *,
+static bool diagnostic_impl (rich_location *, const diag_id &, const char *,
                             va_list *, diagnostic_t) ATTRIBUTE_GCC_DIAG(3,0);
-static bool diagnostic_n_impl (rich_location *, int, int, const char *,
-                              const char *, va_list *,
+static bool diagnostic_n_impl (rich_location *, const diag_id &, int,
+                              const char *, const char *, va_list *,
                               diagnostic_t) ATTRIBUTE_GCC_DIAG(5,0);
 
 static void error_recursion (diagnostic_context *) ATTRIBUTE_NORETURN;
@@ -153,6 +153,7 @@ diagnostic_initialize (diagnostic_context *context, int 
n_opts)
   for (i = 0; i < rich_location::STATICALLY_ALLOCATED_RANGES; i++)
     context->caret_chars[i] = '^';
   context->show_option_requested = false;
+  context->show_id = false;
   context->abort_on_error = false;
   context->show_column = false;
   context->pedantic_errors = false;
@@ -252,7 +253,7 @@ diagnostic_finish (diagnostic_context *context)
 void
 diagnostic_set_info_translated (diagnostic_info *diagnostic, const char *msg,
                                va_list *args, rich_location *richloc,
-                               diagnostic_t kind)
+                               diagnostic_t kind, const char *taxonomy_id)
 {
   gcc_assert (richloc);
   diagnostic->message.err_no = errno;
@@ -262,6 +263,7 @@ diagnostic_set_info_translated (diagnostic_info 
*diagnostic, const char *msg,
   diagnostic->richloc = richloc;
   diagnostic->kind = kind;
   diagnostic->option_index = 0;
+  diagnostic->taxonomy_id = taxonomy_id;
 }
 
 /* Initialize DIAGNOSTIC, where the message GMSGID has not yet been
@@ -269,10 +271,11 @@ diagnostic_set_info_translated (diagnostic_info 
*diagnostic, const char *msg,
 void
 diagnostic_set_info (diagnostic_info *diagnostic, const char *gmsgid,
                     va_list *args, rich_location *richloc,
-                    diagnostic_t kind)
+                    diagnostic_t kind, const char *taxonomy_id)
 {
   gcc_assert (richloc);
-  diagnostic_set_info_translated (diagnostic, _(gmsgid), args, richloc, kind);
+  diagnostic_set_info_translated (diagnostic, _(gmsgid), args, richloc, kind,
+                                 taxonomy_id);
 }
 
 static const char *const diagnostic_kind_color[] = {
@@ -859,6 +862,26 @@ print_option_information (diagnostic_context *context,
     }
 }
 
+/* Print any metadata identifying DIAGNOSTIC within a problem taxonomy
+   (such as CWE) to CONTEXT's printer, e.g. " [CWE-681]".
+   Subroutine of diagnostic_report_diagnostic.  */
+
+static void
+print_taxonomy_information (diagnostic_context *context,
+                           const diagnostic_info *diagnostic)
+{
+  if (diagnostic->taxonomy_id == NULL)
+    return;
+
+  pretty_printer *pp = context->printer;
+  pp_string (pp, " [");
+  pp_string (pp, colorize_start (pp_show_color (pp),
+                                diagnostic_kind_color[diagnostic->kind]));
+  pp_string (pp, diagnostic->taxonomy_id);
+  pp_string (pp, colorize_stop (pp_show_color (pp)));
+  pp_character (pp, ']');
+}
+
 /* Report a diagnostic message (an error or a warning) as specified by
    DC.  This function is *the* subroutine in terms of which front-ends
    should implement their specific diagnostic handling modules.  The
@@ -974,6 +997,8 @@ diagnostic_report_diagnostic (diagnostic_context *context,
   pp_output_formatted_text (context->printer);
   if (context->show_option_requested)
     print_option_information (context, diagnostic, orig_diag_kind);
+  if (context->show_id)
+    print_taxonomy_information (context, diagnostic);
   (*diagnostic_finalizer (context)) (context, diagnostic);
   if (context->parseable_fixits_p)
     {
@@ -1055,7 +1080,7 @@ diagnostic_append_note (diagnostic_context *context,
   rich_location richloc (line_table, location);
 
   va_start (ap, gmsgid);
-  diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_NOTE);
+  diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_NOTE, NULL);
   if (context->inhibit_notes_p)
     {
       va_end (ap);
@@ -1076,7 +1101,7 @@ 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,
+diagnostic_impl (rich_location *richloc, const diag_id &di,
                 const char *gmsgid,
                 va_list *ap, diagnostic_t kind)
 {
@@ -1084,14 +1109,16 @@ diagnostic_impl (rich_location *richloc, int opt,
   if (kind == DK_PERMERROR)
     {
       diagnostic_set_info (&diagnostic, gmsgid, ap, richloc,
-                          permissive_error_kind (global_dc));
+                          permissive_error_kind (global_dc),
+                          di.get_id ());
       diagnostic.option_index = permissive_error_option (global_dc);
     }
   else
     {
-      diagnostic_set_info (&diagnostic, gmsgid, ap, richloc, kind);
+      diagnostic_set_info (&diagnostic, gmsgid, ap, richloc, kind,
+                          di.get_id ());
       if (kind == DK_WARNING || kind == DK_PEDWARN)
-       diagnostic.option_index = opt;
+       diagnostic.option_index = di.get_option ();
     }
   return diagnostic_report_diagnostic (global_dc, &diagnostic);
 }
@@ -1099,7 +1126,7 @@ diagnostic_impl (rich_location *richloc, int opt,
 /* Implement inform_n, warning_n, and error_n, as documented and
    defined below.  */
 static bool
-diagnostic_n_impl (rich_location *richloc, int opt, int n,
+diagnostic_n_impl (rich_location *richloc, const diag_id &di, int n,
                   const char *singular_gmsgid,
                   const char *plural_gmsgid,
                   va_list *ap, diagnostic_t kind)
@@ -1107,22 +1134,22 @@ diagnostic_n_impl (rich_location *richloc, int opt, int 
n,
   diagnostic_info diagnostic;
   diagnostic_set_info_translated (&diagnostic,
                                   ngettext (singular_gmsgid, plural_gmsgid, n),
-                                  ap, richloc, kind);
+                                  ap, richloc, kind, di.get_id ());
   if (kind == DK_WARNING)
-    diagnostic.option_index = opt;
+    diagnostic.option_index = di.get_option ();
   return diagnostic_report_diagnostic (global_dc, &diagnostic);
 }
 
 /* Wrapper around diagnostic_impl taking a variable argument list.  */
 
 bool
-emit_diagnostic (diagnostic_t kind, location_t location, int opt,
+emit_diagnostic (diagnostic_t kind, location_t location, const diag_id &di,
                 const char *gmsgid, ...)
 {
   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, di, gmsgid, &ap, kind);
   va_end (ap);
   return ret;
 }
@@ -1130,11 +1157,12 @@ emit_diagnostic (diagnostic_t kind, location_t 
location, int opt,
 /* Wrapper around diagnostic_impl taking a va_list parameter.  */
 
 bool
-emit_diagnostic_valist (diagnostic_t kind, location_t location, int opt,
+emit_diagnostic_valist (diagnostic_t kind, location_t location,
+                       const diag_id &di,
                        const char *gmsgid, va_list *ap)
 {
   rich_location richloc (line_table, location);
-  return diagnostic_impl (&richloc, opt, gmsgid, ap, kind);
+  return diagnostic_impl (&richloc, di, gmsgid, ap, kind);
 }
 
 /* An informative note at LOCATION.  Use this for additional details on an 
error
@@ -1179,12 +1207,12 @@ inform_n (location_t location, int n, const char 
*singular_gmsgid,
    to the relevant language specification but is likely to be buggy anyway.
    Returns true if the warning was printed, false if it was inhibited.  */
 bool
-warning (int opt, const char *gmsgid, ...)
+warning (const diag_id &di, 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, di, gmsgid, &ap, DK_WARNING);
   va_end (ap);
   return ret;
 }
@@ -1194,12 +1222,12 @@ warning (int opt, const char *gmsgid, ...)
    Returns true if the warning was printed, false if it was inhibited.  */
 
 bool
-warning_at (location_t location, int opt, const char *gmsgid, ...)
+warning_at (location_t location, const diag_id &di, 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, di, gmsgid, &ap, DK_WARNING);
   va_end (ap);
   return ret;
 }
@@ -1207,13 +1235,14 @@ warning_at (location_t location, int opt, const char 
*gmsgid, ...)
 /* Same as "warning at" above, but using RICHLOC.  */
 
 bool
-warning_at (rich_location *richloc, int opt, const char *gmsgid, ...)
+warning_at (rich_location *richloc, const diag_id &di,
+           const char *gmsgid, ...)
 {
   gcc_assert (richloc);
 
   va_list ap;
   va_start (ap, gmsgid);
-  bool ret = diagnostic_impl (richloc, opt, gmsgid, &ap, DK_WARNING);
+  bool ret = diagnostic_impl (richloc, di, gmsgid, &ap, DK_WARNING);
   va_end (ap);
   return ret;
 }
@@ -1221,14 +1250,14 @@ warning_at (rich_location *richloc, int opt, const char 
*gmsgid, ...)
 /* Same as warning_n plural variant below, but using RICHLOC.  */
 
 bool
-warning_n (rich_location *richloc, int opt, int n,
+warning_n (rich_location *richloc, const diag_id &di, int n,
           const char *singular_gmsgid, const char *plural_gmsgid, ...)
 {
   gcc_assert (richloc);
 
   va_list ap;
   va_start (ap, plural_gmsgid);
-  bool ret = diagnostic_n_impl (richloc, opt, n,
+  bool ret = diagnostic_n_impl (richloc, di, n,
                                singular_gmsgid, plural_gmsgid,
                                &ap, DK_WARNING);
   va_end (ap);
@@ -1240,13 +1269,13 @@ warning_n (rich_location *richloc, int opt, int n,
    Returns true if the warning was printed, false if it was inhibited.  */
 
 bool
-warning_n (location_t location, int opt, int n, const char *singular_gmsgid,
-          const char *plural_gmsgid, ...)
+warning_n (location_t location, const diag_id &di, int n,
+          const char *singular_gmsgid, const char *plural_gmsgid, ...)
 {
   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, di, n,
                                singular_gmsgid, plural_gmsgid,
                                &ap, DK_WARNING);
   va_end (ap);
@@ -1267,12 +1296,12 @@ warning_n (location_t location, int opt, int n, const 
char *singular_gmsgid,
    Returns true if the warning was printed, false if it was inhibited.  */
 
 bool
-pedwarn (location_t location, int opt, const char *gmsgid, ...)
+pedwarn (location_t location, const diag_id &di, 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, di, gmsgid, &ap, DK_PEDWARN);
   va_end (ap);
   return ret;
 }
@@ -1280,13 +1309,13 @@ pedwarn (location_t location, int opt, const char 
*gmsgid, ...)
 /* Same as pedwarn above, but using RICHLOC.  */
 
 bool
-pedwarn (rich_location *richloc, int opt, const char *gmsgid, ...)
+pedwarn (rich_location *richloc, const diag_id &di, const char *gmsgid, ...)
 {
   gcc_assert (richloc);
 
   va_list ap;
   va_start (ap, gmsgid);
-  bool ret = diagnostic_impl (richloc, opt, gmsgid, &ap, DK_PEDWARN);
+  bool ret = diagnostic_impl (richloc, di, gmsgid, &ap, DK_PEDWARN);
   va_end (ap);
   return ret;
 }
@@ -1667,6 +1696,32 @@ test_diagnostic_get_location_text ()
   progname = old_progname;
 }
 
+/* Verify that print_taxonomy_information prints EXPECTED, given ID.  */
+
+static void
+assert_print_taxonomy_information (const char *expected, const char *id)
+{
+  test_diagnostic_context dc;
+  diagnostic_info diagnostic;
+
+  diagnostic.kind = DK_WARNING;
+
+  pretty_printer *pp = dc.printer;
+
+  diagnostic.taxonomy_id = id;
+  print_taxonomy_information (&dc, &diagnostic);
+  ASSERT_STREQ (expected, pp_formatted_text (pp));
+}
+
+/* Verify that print_taxonomy_information works as expected.  */
+
+static void
+test_print_taxonomy_information ()
+{
+  assert_print_taxonomy_information ("", NULL);
+  assert_print_taxonomy_information (" [CWE-681]", "CWE-681");
+}
+
 /* Run all of the selftests within this file.  */
 
 void
@@ -1678,6 +1733,7 @@ diagnostic_c_tests ()
   test_print_parseable_fixits_remove ();
   test_print_parseable_fixits_replace ();
   test_diagnostic_get_location_text ();
+  test_print_taxonomy_information ();
 }
 
 } // namespace selftest
diff --git a/gcc/diagnostic.h b/gcc/diagnostic.h
index dbd1703..70fbc4c 100644
--- a/gcc/diagnostic.h
+++ b/gcc/diagnostic.h
@@ -41,6 +41,10 @@ struct diagnostic_info
   diagnostic_t kind;
   /* Which OPT_* directly controls this diagnostic.  */
   int option_index;
+  /* An optional ID from a problem taxonomy (such as "PRE10-C" from the
+     CERT C Secure Coding Standard, or "CWE-681" from the Common Weakness
+     Enumeration).  */
+  const char *taxonomy_id;
 };
 
 /* Each time a diagnostic's classification is changed with a pragma,
@@ -117,6 +121,10 @@ struct diagnostic_context
      each diagnostic, if known.  */
   bool show_option_requested;
 
+  /* True if we should print any identifier within a problem taxonomy
+     for each diagnostic, if known.  */
+  bool show_id;
+
   /* True if we should raise a SIGABRT on errors.  */
   bool abort_on_error;
 
@@ -297,10 +305,11 @@ extern bool diagnostic_report_diagnostic 
(diagnostic_context *,
                                          diagnostic_info *);
 #ifdef ATTRIBUTE_GCC_DIAG
 extern void diagnostic_set_info (diagnostic_info *, const char *, va_list *,
-                                rich_location *, diagnostic_t) 
ATTRIBUTE_GCC_DIAG(2,0);
+                                rich_location *, diagnostic_t, const char *)
+  ATTRIBUTE_GCC_DIAG(2,0);
 extern void diagnostic_set_info_translated (diagnostic_info *, const char *,
                                            va_list *, rich_location *,
-                                           diagnostic_t)
+                                           diagnostic_t, const char *)
      ATTRIBUTE_GCC_DIAG(2,0);
 extern void diagnostic_append_note (diagnostic_context *, location_t,
                                     const char *, ...) ATTRIBUTE_GCC_DIAG(3,4);
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 43acbcb..9562898 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -250,7 +250,8 @@ Objective-C and Objective-C++ Dialects}.
 @gccoptlist{-fmessage-length=@var{n}  @gol
 -fdiagnostics-show-location=@r{[}once@r{|}every-line@r{]}  @gol
 -fdiagnostics-color=@r{[}auto@r{|}never@r{|}always@r{]}  @gol
--fno-diagnostics-show-option  -fno-diagnostics-show-caret @gol
+-fno-diagnostics-show-option  -fno-diagnostics-show-id @gol
+-fno-diagnostics-show-caret @gol
 -fdiagnostics-parseable-fixits  -fdiagnostics-generate-patch @gol
 -fdiagnostics-show-template-tree -fno-elide-type @gol
 -fno-show-column}
@@ -3575,6 +3576,18 @@ command-line option that directly controls the 
diagnostic (if such an
 option is known to the diagnostic machinery).  Specifying the
 @option{-fno-diagnostics-show-option} flag suppresses that behavior.
 
+@item -fno-diagnostics-show-id
+@opindex fno-diagnostics-show-id
+@opindex fdiagnostics-show-id
+By default, each diagnostic emitted can include text indicating an
+ID within a problem taxonomy, such as `INT15-C` within the
+CERT C Secure Coding Standard, or `CWE-681` within the
+Common Weakness Enumeration (CWE).
+Such IDs can be useful for categorizing problems, or for searching for
+helpful recommendations for addressing the diagnostic.
+Specifying the @option{-fno-diagnostics-show-id} flag suppresses that
+behavior.
+
 @item -fno-diagnostics-show-caret
 @opindex fno-diagnostics-show-caret
 @opindex fdiagnostics-show-caret
diff --git a/gcc/fortran/cpp.c b/gcc/fortran/cpp.c
index af8a69c..b657583 100644
--- a/gcc/fortran/cpp.c
+++ b/gcc/fortran/cpp.c
@@ -1059,7 +1059,7 @@ cb_cpp_error (cpp_reader *pfile ATTRIBUTE_UNUSED, int 
level, int reason,
       gcc_unreachable ();
     }
   diagnostic_set_info_translated (&diagnostic, msg, ap,
-                                 richloc, dlevel);
+                                 richloc, dlevel, NULL);
   if (reason == CPP_W_WARNING_DIRECTIVE)
     diagnostic_override_option_index (&diagnostic, OPT_Wcpp);
   ret = diagnostic_report_diagnostic (global_dc, &diagnostic);
diff --git a/gcc/fortran/error.c b/gcc/fortran/error.c
index 3ad1cf9..6bc9fef 100644
--- a/gcc/fortran/error.c
+++ b/gcc/fortran/error.c
@@ -787,7 +787,7 @@ gfc_warning (int opt, const char *gmsgid, va_list ap)
     }
 
   diagnostic_set_info (&diagnostic, gmsgid, &argp, &rich_loc,
-                      DK_WARNING);
+                      DK_WARNING, NULL);
   diagnostic.option_index = opt;
   bool ret = diagnostic_report_diagnostic (global_dc, &diagnostic);
 
@@ -1137,7 +1137,8 @@ gfc_warning_now_at (location_t loc, int opt, const char 
*gmsgid, ...)
   bool ret;
 
   va_start (argp, gmsgid);
-  diagnostic_set_info (&diagnostic, gmsgid, &argp, &rich_loc, DK_WARNING);
+  diagnostic_set_info (&diagnostic, gmsgid, &argp, &rich_loc, DK_WARNING,
+                      NULL);
   diagnostic.option_index = opt;
   ret = diagnostic_report_diagnostic (global_dc, &diagnostic);
   va_end (argp);
@@ -1156,7 +1157,7 @@ gfc_warning_now (int opt, const char *gmsgid, ...)
 
   va_start (argp, gmsgid);
   diagnostic_set_info (&diagnostic, gmsgid, &argp, &rich_loc,
-                      DK_WARNING);
+                      DK_WARNING, NULL);
   diagnostic.option_index = opt;
   ret = diagnostic_report_diagnostic (global_dc, &diagnostic);
   va_end (argp);
@@ -1175,7 +1176,7 @@ gfc_warning_internal (int opt, const char *gmsgid, ...)
 
   va_start (argp, gmsgid);
   diagnostic_set_info (&diagnostic, gmsgid, &argp, &rich_loc,
-                      DK_WARNING);
+                      DK_WARNING, NULL);
   diagnostic.option_index = opt;
   ret = diagnostic_report_diagnostic (global_dc, &diagnostic);
   va_end (argp);
@@ -1194,7 +1195,8 @@ gfc_error_now (const char *gmsgid, ...)
   error_buffer.flag = true;
 
   va_start (argp, gmsgid);
-  diagnostic_set_info (&diagnostic, gmsgid, &argp, &rich_loc, DK_ERROR);
+  diagnostic_set_info (&diagnostic, gmsgid, &argp, &rich_loc, DK_ERROR,
+                      NULL);
   diagnostic_report_diagnostic (global_dc, &diagnostic);
   va_end (argp);
 }
@@ -1210,7 +1212,7 @@ gfc_fatal_error (const char *gmsgid, ...)
   rich_location rich_loc (line_table, UNKNOWN_LOCATION);
 
   va_start (argp, gmsgid);
-  diagnostic_set_info (&diagnostic, gmsgid, &argp, &rich_loc, DK_FATAL);
+  diagnostic_set_info (&diagnostic, gmsgid, &argp, &rich_loc, DK_FATAL, NULL);
   diagnostic_report_diagnostic (global_dc, &diagnostic);
   va_end (argp);
 
@@ -1295,7 +1297,7 @@ gfc_error_opt (int opt, const char *gmsgid, va_list ap)
       --errorcount;
     }
 
-  diagnostic_set_info (&diagnostic, gmsgid, &argp, &richloc, DK_ERROR);
+  diagnostic_set_info (&diagnostic, gmsgid, &argp, &richloc, DK_ERROR, NULL);
   diagnostic_report_diagnostic (global_dc, &diagnostic);
 
   if (buffered_p)
@@ -1345,7 +1347,7 @@ gfc_internal_error (const char *gmsgid, ...)
     exit(EXIT_FAILURE);
 
   va_start (argp, gmsgid);
-  diagnostic_set_info (&diagnostic, gmsgid, &argp, &rich_loc, DK_ICE);
+  diagnostic_set_info (&diagnostic, gmsgid, &argp, &rich_loc, DK_ICE, NULL);
   diagnostic_report_diagnostic (global_dc, &diagnostic);
   va_end (argp);
 
diff --git a/gcc/gimple-ssa-sprintf.c b/gcc/gimple-ssa-sprintf.c
index 7415413..1ca62c6 100644
--- a/gcc/gimple-ssa-sprintf.c
+++ b/gcc/gimple-ssa-sprintf.c
@@ -594,7 +594,7 @@ get_format_string (tree format, location_t *ploc)
 
 static bool
   (* const fmtwarn) (const substring_loc &, location_t,
-                    const char *, int, const char *, ...)
+                    const char *, const diag_id &, const char *, ...)
   = format_warning_at_substring;
 
 /* Format length modifiers.  */
diff --git a/gcc/opts.c b/gcc/opts.c
index ac383d4..9bcfa75 100644
--- a/gcc/opts.c
+++ b/gcc/opts.c
@@ -2098,6 +2098,10 @@ common_handle_option (struct gcc_options *opts,
       dc->show_option_requested = value;
       break;
 
+    case OPT_fdiagnostics_show_id:
+      dc->show_id = value;
+      break;
+
     case OPT_fdump_:
       /* Deferred.  */
       break;
diff --git a/gcc/rtl-error.c b/gcc/rtl-error.c
index e04bd7e..eab90ac 100644
--- a/gcc/rtl-error.c
+++ b/gcc/rtl-error.c
@@ -70,7 +70,7 @@ diagnostic_for_asm (const rtx_insn *insn, const char *msg, 
va_list *args_ptr,
   rich_location richloc (line_table, location_for_asm (insn));
 
   diagnostic_set_info (&diagnostic, msg, args_ptr,
-                      &richloc, kind);
+                      &richloc, kind, NULL);
   diagnostic_report_diagnostic (global_dc, &diagnostic);
 }
 
diff --git a/gcc/substring-locations.c b/gcc/substring-locations.c
index 7de435b..092d81f 100644
--- a/gcc/substring-locations.c
+++ b/gcc/substring-locations.c
@@ -26,7 +26,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "langhooks.h"
 #include "substring-locations.h"
 
-/* Emit a warning governed by option OPT, using GMSGID as the format
+/* Emit a warning governed by option DI, using GMSGID as the format
    string and AP as its arguments.
 
    Attempt to obtain precise location information within a string
@@ -102,7 +102,7 @@ bool
 format_warning_va (const substring_loc &fmt_loc,
                   location_t param_loc,
                   const char *corrected_substring,
-                  int opt, const char *gmsgid, va_list *ap)
+                  const diag_id &di, const char *gmsgid, va_list *ap)
 {
   bool substring_within_range = false;
   location_t primary_loc;
@@ -143,8 +143,9 @@ format_warning_va (const substring_loc &fmt_loc,
     richloc.add_fixit_replace (fmt_substring_range, corrected_substring);
 
   diagnostic_info diagnostic;
-  diagnostic_set_info (&diagnostic, gmsgid, ap, &richloc, DK_WARNING);
-  diagnostic.option_index = opt;
+  diagnostic_set_info (&diagnostic, gmsgid, ap, &richloc, DK_WARNING,
+                      di.get_id ());
+  diagnostic.option_index = di.get_option ();
   bool warned = diagnostic_report_diagnostic (global_dc, &diagnostic);
 
   if (!err && fmt_substring_loc && !substring_within_range)
@@ -168,12 +169,12 @@ bool
 format_warning_at_substring (const substring_loc &fmt_loc,
                             location_t param_loc,
                             const char *corrected_substring,
-                            int opt, const char *gmsgid, ...)
+                            const diag_id &di, const char *gmsgid, ...)
 {
   va_list ap;
   va_start (ap, gmsgid);
   bool warned = format_warning_va (fmt_loc, param_loc, corrected_substring,
-                                  opt, gmsgid, &ap);
+                                  di, gmsgid, &ap);
   va_end (ap);
 
   return warned;
diff --git a/gcc/substring-locations.h b/gcc/substring-locations.h
index 3d7796d..13df498 100644
--- a/gcc/substring-locations.h
+++ b/gcc/substring-locations.h
@@ -79,13 +79,17 @@ class substring_loc
 extern bool format_warning_va (const substring_loc &fmt_loc,
                               location_t param_loc,
                               const char *corrected_substring,
-                              int opt, const char *gmsgid, va_list *ap)
+                              const diag_id &di,
+                              const char *gmsgid,
+                              va_list *ap)
   ATTRIBUTE_GCC_DIAG (5,0);
 
 extern bool format_warning_at_substring (const substring_loc &fmt_loc,
                                         location_t param_loc,
                                         const char *corrected_substring,
-                                        int opt, const char *gmsgid, ...)
+                                        const diag_id &di,
+                                        const char *gmsgid,
+                                        ...)
   ATTRIBUTE_GCC_DIAG (5,0);
 
 /* Implementation detail, for use when implementing
diff --git a/gcc/toplev.c b/gcc/toplev.c
index eff1690..590ab58 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_caret;
   global_dc->show_option_requested
     = global_options_init.x_flag_diagnostics_show_option;
+  global_dc->show_id
+    = global_options_init.x_flag_diagnostics_show_id;
   global_dc->show_column
     = global_options_init.x_flag_show_column;
   global_dc->internal_error = internal_error_function;
-- 
1.8.5.3

Reply via email to