This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] RFC: add taxonomy IDs to diagnostics (CERT C, CWE, etc)


On Thu, Nov 2, 2017 at 10:28 PM, Martin Sebor <msebor@gmail.com> wrote:
> On 11/02/2017 02:51 PM, David Malcolm wrote:
>>
>> 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?
>
>
> I think it would be useful with some additional (likely substantial)
> effort.  My concern (and a pet peeve) with the CERT IDs is that they
> are not stable but tend to change from one release of the CERT coding
> standard to the next.  To avoid the problem of GCC getting out of sync
> with the current CERT standard we would need to maintain a mapping.
> Another consideration is that the CERT C and C++ coding standards
> don't always have the same ids and C++-specific aspects of certain
> problems have their own C++ ids distinct from the C ones (e.g.,
> EXP53-CPP. Do not read uninitialized memory vs EXP33-C. Do not read
> uninitialized memory).  This implies a finer-grained classification
> than a straightforward mapping from GCC OPT_Wfoo enums to CERT or
> CWE ids can support).
>
> In contrast to CERT, I have the impression that the CWE ids are more
> stable (I don't know for certain that they're guaranteed to be).  By
> their sheer number I would expect them to provide a finer-grained
> mapping that, if used to tag GCC diagnostiscs, could then be used to
> map them to other standards (and even GCC's own OPT_Wfoo ids).  This would
> suggest using CWE as the primary ID and mapping that to
> everything else.  But I'm pretty sure this would require a lot of
> effort to get right, and keep in sync as existing GCC warnings are
> tweaked and enhanced.
>
> Sorry if this sounds discouraging.  I like the idea but I worry
> about the implementation and maintenance challenges.

So you are suggesting we use our own (stable) IDs and for
diagnostic purposes allow a mapping to be applied?  Like
GCC_DIAG_MAP=lockheed-JSF.map g++ ....? (or via -fXYZ=...)

Sounds more useful and forward looking indeed.

I'd simply not report our own IDs if no mapping is specified then.

Richard.

> Martin
>
> PS A couple of other popular standards to consider are MISRA C and
> C++ and the Lockheed Martin JSF C++ coding standard.
>
>
>>
>> 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;
>>
>


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]