diagnostics: add ability to associate diagnostics with rules from coding standards
gcc/ChangeLog: * common.opt (fdiagnostics-show-rules): New option. * diagnostic-format-json.cc (diagnostic_output_format_init_json): Fix up context->show_rules. * diagnostic-format-sarif.cc (diagnostic_output_format_init_sarif): Likewise. * diagnostic-metadata.h (diagnostic_metadata::rule): New class. (diagnostic_metadata::precanned_rule): New class. (diagnostic_metadata::add_rule): New. (diagnostic_metadata::get_num_rules): New. (diagnostic_metadata::get_rule): New. (diagnostic_metadata::m_rules): New field. * diagnostic.cc (diagnostic_initialize): Initialize show_rules. (print_any_rules): New. (diagnostic_report_diagnostic): Call it. * diagnostic.h (diagnostic_context::show_rules): New field. * doc/invoke.texi (-fno-diagnostics-show-rules): New option. * opts.cc (common_handle_option): Handle OPT_fdiagnostics_show_rules. * toplev.cc (general_init): Set up global_dc->show_rules. gcc/testsuite/ChangeLog: * gcc.dg/plugin/diagnostic-test-metadata.c: Expect " [STR34-C]" to be emitted at the "gets" call. * gcc.dg/plugin/diagnostic_plugin_test_metadata.c (pass_test_metadata::execute): Associate the "gets" diagnostic with a rule named "STR34-C". Signed-off-by: David Malcolm <dmalcolm@redhat.com>
This commit is contained in:
parent
7c1c7e120c
commit
0b14f590e3
|
@ -1466,6 +1466,10 @@ fdiagnostics-show-cwe
|
|||
Common Var(flag_diagnostics_show_cwe) Init(1)
|
||||
Print CWE identifiers for diagnostic messages, where available.
|
||||
|
||||
fdiagnostics-show-rules
|
||||
Common Var(flag_diagnostics_show_rules) Init(1)
|
||||
Print any rules associated with diagnostic messages.
|
||||
|
||||
fdiagnostics-path-format=
|
||||
Common Joined RejectNegative Var(flag_diagnostics_path_format) Enum(diagnostic_path_format) Init(DPF_INLINE_EVENTS)
|
||||
Specify how to print any control-flow path associated with a diagnostic.
|
||||
|
|
|
@ -345,6 +345,7 @@ diagnostic_output_format_init_json (diagnostic_context *context)
|
|||
|
||||
/* The metadata is handled in JSON format, rather than as text. */
|
||||
context->show_cwe = false;
|
||||
context->show_rules = false;
|
||||
|
||||
/* The option is handled in JSON format, rather than as text. */
|
||||
context->show_option_requested = false;
|
||||
|
|
|
@ -1556,6 +1556,7 @@ diagnostic_output_format_init_sarif (diagnostic_context *context)
|
|||
|
||||
/* The metadata is handled in SARIF format, rather than as text. */
|
||||
context->show_cwe = false;
|
||||
context->show_rules = false;
|
||||
|
||||
/* The option is handled in SARIF format, rather than as text. */
|
||||
context->show_option_requested = false;
|
||||
|
|
|
@ -24,19 +24,62 @@ along with GCC; see the file COPYING3. If not see
|
|||
/* A bundle of additional metadata that can be associated with a
|
||||
diagnostic.
|
||||
|
||||
Currently this only supports associating a CWE identifier with a
|
||||
diagnostic. */
|
||||
This supports an optional CWE identifier, and zero or more
|
||||
"rules". */
|
||||
|
||||
class diagnostic_metadata
|
||||
{
|
||||
public:
|
||||
/* Abstract base class for referencing a rule that has been violated,
|
||||
such as within a coding standard, or within a specification. */
|
||||
class rule
|
||||
{
|
||||
public:
|
||||
virtual char *make_description () const = 0;
|
||||
virtual char *make_url () const = 0;
|
||||
};
|
||||
|
||||
/* Concrete subclass. */
|
||||
class precanned_rule : public rule
|
||||
{
|
||||
public:
|
||||
precanned_rule (const char *desc, const char *url)
|
||||
: m_desc (desc), m_url (url)
|
||||
{}
|
||||
|
||||
char *make_description () const final override
|
||||
{
|
||||
return m_desc ? xstrdup (m_desc) : NULL;
|
||||
}
|
||||
|
||||
char *make_url () const final override
|
||||
{
|
||||
return m_url ? xstrdup (m_url) : NULL;
|
||||
}
|
||||
|
||||
private:
|
||||
const char *m_desc;
|
||||
const char *m_url;
|
||||
};
|
||||
|
||||
diagnostic_metadata () : m_cwe (0) {}
|
||||
|
||||
void add_cwe (int cwe) { m_cwe = cwe; }
|
||||
int get_cwe () const { return m_cwe; }
|
||||
|
||||
/* Associate R with the diagnostic. R must outlive
|
||||
the metadata. */
|
||||
void add_rule (const rule &r)
|
||||
{
|
||||
m_rules.safe_push (&r);
|
||||
}
|
||||
|
||||
unsigned get_num_rules () const { return m_rules.length (); }
|
||||
const rule &get_rule (unsigned idx) const { return *(m_rules[idx]); }
|
||||
|
||||
private:
|
||||
int m_cwe;
|
||||
auto_vec<const rule *> m_rules;
|
||||
};
|
||||
|
||||
#endif /* ! GCC_DIAGNOSTIC_METADATA_H */
|
||||
|
|
|
@ -190,6 +190,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_cwe = false;
|
||||
context->show_rules = false;
|
||||
context->path_format = DPF_NONE;
|
||||
context->show_path_depths = false;
|
||||
context->show_option_requested = false;
|
||||
|
@ -1291,6 +1292,51 @@ print_any_cwe (diagnostic_context *context,
|
|||
}
|
||||
}
|
||||
|
||||
/* If DIAGNOSTIC has any rules associated with it, print them.
|
||||
|
||||
For example, if the diagnostic metadata associates it with a rule
|
||||
named "STR34-C", then " [STR34-C]" will be printed, suitably colorized,
|
||||
with any URL provided by the rule. */
|
||||
|
||||
static void
|
||||
print_any_rules (diagnostic_context *context,
|
||||
const diagnostic_info *diagnostic)
|
||||
{
|
||||
if (diagnostic->metadata == NULL)
|
||||
return;
|
||||
|
||||
for (unsigned idx = 0; idx < diagnostic->metadata->get_num_rules (); idx++)
|
||||
{
|
||||
const diagnostic_metadata::rule &rule
|
||||
= diagnostic->metadata->get_rule (idx);
|
||||
if (char *desc = rule.make_description ())
|
||||
{
|
||||
pretty_printer *pp = context->printer;
|
||||
char *saved_prefix = pp_take_prefix (context->printer);
|
||||
pp_string (pp, " [");
|
||||
pp_string (pp,
|
||||
colorize_start (pp_show_color (pp),
|
||||
diagnostic_kind_color[diagnostic->kind]));
|
||||
char *url = NULL;
|
||||
if (pp->url_format != URL_FORMAT_NONE)
|
||||
{
|
||||
url = rule.make_url ();
|
||||
if (url)
|
||||
pp_begin_url (pp, url);
|
||||
}
|
||||
pp_string (pp, desc);
|
||||
pp_set_prefix (context->printer, saved_prefix);
|
||||
if (pp->url_format != URL_FORMAT_NONE)
|
||||
if (url)
|
||||
pp_end_url (pp);
|
||||
free (url);
|
||||
pp_string (pp, colorize_stop (pp_show_color (pp)));
|
||||
pp_character (pp, ']');
|
||||
free (desc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Print any metadata about the option used to control DIAGNOSTIC to CONTEXT's
|
||||
printer, e.g. " [-Werror=uninitialized]".
|
||||
Subroutine of diagnostic_report_diagnostic. */
|
||||
|
@ -1504,6 +1550,8 @@ diagnostic_report_diagnostic (diagnostic_context *context,
|
|||
pp_output_formatted_text (context->printer);
|
||||
if (context->show_cwe)
|
||||
print_any_cwe (context, diagnostic);
|
||||
if (context->show_rules)
|
||||
print_any_rules (context, diagnostic);
|
||||
if (context->show_option_requested)
|
||||
print_option_information (context, diagnostic, orig_diag_kind);
|
||||
(*diagnostic_finalizer (context)) (context, diagnostic, orig_diag_kind);
|
||||
|
|
|
@ -227,6 +227,9 @@ struct diagnostic_context
|
|||
diagnostics. */
|
||||
bool show_cwe;
|
||||
|
||||
/* True if we should print any rules associated with diagnostics. */
|
||||
bool show_rules;
|
||||
|
||||
/* How should diagnostic_path objects be printed. */
|
||||
enum diagnostic_path_format path_format;
|
||||
|
||||
|
|
|
@ -305,6 +305,7 @@ Objective-C and Objective-C++ Dialects}.
|
|||
-fno-diagnostics-show-option -fno-diagnostics-show-caret @gol
|
||||
-fno-diagnostics-show-labels -fno-diagnostics-show-line-numbers @gol
|
||||
-fno-diagnostics-show-cwe @gol
|
||||
-fno-diagnostics-show-rule @gol
|
||||
-fdiagnostics-minimum-margin-width=@var{width} @gol
|
||||
-fdiagnostics-parseable-fixits -fdiagnostics-generate-patch @gol
|
||||
-fdiagnostics-show-template-tree -fno-elide-type @gol
|
||||
|
@ -5028,6 +5029,15 @@ diagnostics. GCC plugins may also provide diagnostics with such metadata.
|
|||
By default, if this information is present, it will be printed with
|
||||
the diagnostic. This option suppresses the printing of this metadata.
|
||||
|
||||
@item -fno-diagnostics-show-rules
|
||||
@opindex fno-diagnostics-show-rules
|
||||
@opindex fdiagnostics-show-rules
|
||||
Diagnostic messages can optionally have rules associated with them, such
|
||||
as from a coding standard, or a specification.
|
||||
GCC itself does not do this for any of its diagnostics, but plugins may do so.
|
||||
By default, if this information is present, it will be printed with
|
||||
the diagnostic. This option suppresses the printing of this metadata.
|
||||
|
||||
@item -fno-diagnostics-show-line-numbers
|
||||
@opindex fno-diagnostics-show-line-numbers
|
||||
@opindex fdiagnostics-show-line-numbers
|
||||
|
|
|
@ -2876,6 +2876,10 @@ common_handle_option (struct gcc_options *opts,
|
|||
dc->show_cwe = value;
|
||||
break;
|
||||
|
||||
case OPT_fdiagnostics_show_rules:
|
||||
dc->show_rules = value;
|
||||
break;
|
||||
|
||||
case OPT_fdiagnostics_path_format_:
|
||||
dc->path_format = (enum diagnostic_path_format)value;
|
||||
break;
|
||||
|
|
|
@ -5,5 +5,5 @@ extern char *gets (char *s);
|
|||
void test_cwe (void)
|
||||
{
|
||||
char buf[1024];
|
||||
gets (buf); /* { dg-warning "never use 'gets' \\\[CWE-242\\\]" } */
|
||||
gets (buf); /* { dg-warning "never use 'gets' \\\[CWE-242\\\] \\\[STR34-C\\\]" } */
|
||||
}
|
||||
|
|
|
@ -106,9 +106,16 @@ pass_test_metadata::execute (function *fun)
|
|||
if (gcall *call = check_for_named_call (stmt, "gets", 1))
|
||||
{
|
||||
gcc_rich_location richloc (gimple_location (call));
|
||||
/* CWE-242: Use of Inherently Dangerous Function. */
|
||||
diagnostic_metadata m;
|
||||
|
||||
/* CWE-242: Use of Inherently Dangerous Function. */
|
||||
m.add_cwe (242);
|
||||
|
||||
/* Example of a diagnostic_metadata::rule. */
|
||||
diagnostic_metadata::precanned_rule
|
||||
test_rule ("STR34-C", "https://example.com/");
|
||||
m.add_rule (test_rule);
|
||||
|
||||
warning_meta (&richloc, m, 0,
|
||||
"never use %qs", "gets");
|
||||
}
|
||||
|
|
|
@ -1038,6 +1038,8 @@ general_init (const char *argv0, bool init_signals)
|
|||
= global_options_init.x_flag_diagnostics_show_line_numbers;
|
||||
global_dc->show_cwe
|
||||
= global_options_init.x_flag_diagnostics_show_cwe;
|
||||
global_dc->show_rules
|
||||
= global_options_init.x_flag_diagnostics_show_rules;
|
||||
global_dc->path_format
|
||||
= (enum diagnostic_path_format)global_options_init.x_flag_diagnostics_path_format;
|
||||
global_dc->show_path_depths
|
||||
|
|
Loading…
Reference in New Issue