On Thu, Nov 2, 2017 at 10:28 PM, Martin Sebor <mse...@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; >> >