Add diagnostic_metadata and CWE support
This patch adds support for associating a diagnostic message with an optional diagnostic_metadata object, so that plugins can add extra data to their diagnostics (e.g. mapping a diagnostic to a taxonomy or coding standard such as from CERT or MISRA). Currently this only supports associating a CWE identifier with a diagnostic (which is what I'm using for the warnings in the analyzer patch kit), but adding a diagnostic_metadata class allows for future growth in this area without an explosion of further "warning_at" overloads for all of the different kinds of custom data that a plugin might want to add. This version of the patch renames the overly-general -fdiagnostics-show-metadata to -fdiagnostics-show-cwe and adds test coverage for it via a plugin. It also adds a note to the documentation that no GCC diagnostics currently use this; it's a feature for plugins (and, at some point, I hope, the analyzer). gcc/ChangeLog: * common.opt (fdiagnostics-show-cwe): Add. * diagnostic-core.h (class diagnostic_metadata): New forward decl. (warning_at): Add overload taking a const diagnostic_metadata &. (emit_diagnostic_valist): Add overload taking a const diagnostic_metadata *. * diagnostic-format-json.cc: Include "diagnostic-metadata.h". (json_from_metadata): New function. (json_end_diagnostic): Call it to add "metadata" child for diagnostics with metadata. (diagnostic_output_format_init): Clear context->show_cwe. * diagnostic-metadata.h: New file. * diagnostic.c: Include "diagnostic-metadata.h". (diagnostic_impl): Add const diagnostic_metadata * param. (diagnostic_n_impl): Likewise. (diagnostic_initialize): Initialize context->show_cwe. (diagnostic_set_info_translated): Initialize diagnostic->metadata. (get_cwe_url): New function. (print_any_cwe): New function. (diagnostic_report_diagnostic): Call print_any_cwe if the diagnostic has non-NULL metadata. (emit_diagnostic): Pass NULL as the metadata in the call to diagnostic_impl. (emit_diagnostic_valist): Likewise. (emit_diagnostic_valist): New overload taking a const diagnostic_metadata *. (inform): Pass NULL as the metadata in the call to diagnostic_impl. (inform_n): Likewise for diagnostic_n_impl. (warning): Likewise. (warning_at): Likewise. Add overload that takes a const diagnostic_metadata &. (warning_n): Pass NULL as the metadata in the call to diagnostic_n_impl. (pedwarn): Likewise for diagnostic_impl. (permerror): Likewise. (error): Likewise. (error_n): Likewise. (error_at): Likewise. (sorry): Likewise. (sorry_at): Likewise. (fatal_error): Likewise. (internal_error): Likewise. (internal_error_no_backtrace): Likewise. * diagnostic.h (diagnostic_info::metadata): New field. (diagnostic_context::show_cwe): New field. * doc/invoke.texi (-fno-diagnostics-show-cwe): New option. * opts.c (common_handle_option): Handle OPT_fdiagnostics_show_cwe. * toplev.c (general_init): Initialize global_dc->show_cwe. gcc/testsuite/ChangeLog: * gcc.dg/plugin/diagnostic-test-metadata.c: New test. * gcc.dg/plugin/diagnostic_plugin_test_metadata.c: New test plugin. * gcc.dg/plugin/plugin.exp (plugin_test_list): Add them. From-SVN: r279556
This commit is contained in:
parent
a7a09efa24
commit
6d4a35ca57
@ -1,3 +1,54 @@
|
||||
2019-12-18 David Malcolm <dmalcolm@redhat.com>
|
||||
|
||||
* common.opt (fdiagnostics-show-cwe): Add.
|
||||
* diagnostic-core.h (class diagnostic_metadata): New forward decl.
|
||||
(warning_at): Add overload taking a const diagnostic_metadata &.
|
||||
(emit_diagnostic_valist): Add overload taking a
|
||||
const diagnostic_metadata *.
|
||||
* diagnostic-format-json.cc: Include "diagnostic-metadata.h".
|
||||
(json_from_metadata): New function.
|
||||
(json_end_diagnostic): Call it to add "metadata" child for
|
||||
diagnostics with metadata.
|
||||
(diagnostic_output_format_init): Clear context->show_cwe.
|
||||
* diagnostic-metadata.h: New file.
|
||||
* diagnostic.c: Include "diagnostic-metadata.h".
|
||||
(diagnostic_impl): Add const diagnostic_metadata * param.
|
||||
(diagnostic_n_impl): Likewise.
|
||||
(diagnostic_initialize): Initialize context->show_cwe.
|
||||
(diagnostic_set_info_translated): Initialize diagnostic->metadata.
|
||||
(get_cwe_url): New function.
|
||||
(print_any_cwe): New function.
|
||||
(diagnostic_report_diagnostic): Call print_any_cwe if the
|
||||
diagnostic has non-NULL metadata.
|
||||
(emit_diagnostic): Pass NULL as the metadata in the call to
|
||||
diagnostic_impl.
|
||||
(emit_diagnostic_valist): Likewise.
|
||||
(emit_diagnostic_valist): New overload taking a
|
||||
const diagnostic_metadata *.
|
||||
(inform): Pass NULL as the metadata in the call to
|
||||
diagnostic_impl.
|
||||
(inform_n): Likewise for diagnostic_n_impl.
|
||||
(warning): Likewise.
|
||||
(warning_at): Likewise. Add overload that takes a
|
||||
const diagnostic_metadata &.
|
||||
(warning_n): Pass NULL as the metadata in the call to
|
||||
diagnostic_n_impl.
|
||||
(pedwarn): Likewise for diagnostic_impl.
|
||||
(permerror): Likewise.
|
||||
(error): Likewise.
|
||||
(error_n): Likewise.
|
||||
(error_at): Likewise.
|
||||
(sorry): Likewise.
|
||||
(sorry_at): Likewise.
|
||||
(fatal_error): Likewise.
|
||||
(internal_error): Likewise.
|
||||
(internal_error_no_backtrace): Likewise.
|
||||
* diagnostic.h (diagnostic_info::metadata): New field.
|
||||
(diagnostic_context::show_cwe): New field.
|
||||
* doc/invoke.texi (-fno-diagnostics-show-cwe): New option.
|
||||
* opts.c (common_handle_option): Handle OPT_fdiagnostics_show_cwe.
|
||||
* toplev.c (general_init): Initialize global_dc->show_cwe.
|
||||
|
||||
2019-12-19 Julian Brown <julian@codesourcery.com>
|
||||
Maciej W. Rozycki <macro@codesourcery.com>
|
||||
Tobias Burnus <tobias@codesourcery.com>
|
||||
|
@ -1334,6 +1334,10 @@ fdiagnostics-show-option
|
||||
Common Var(flag_diagnostics_show_option) Init(1)
|
||||
Amend appropriate diagnostic messages with the command line option that controls them.
|
||||
|
||||
fdiagnostics-show-cwe
|
||||
Common Var(flag_diagnostics_show_cwe) Init(1)
|
||||
Print CWE identifiers for diagnostic messages, where available.
|
||||
|
||||
fdiagnostics-minimum-margin-width=
|
||||
Common Joined UInteger Var(diagnostics_minimum_margin_width) Init(6)
|
||||
Set minimum width of left margin of source code when showing source.
|
||||
|
@ -45,6 +45,9 @@ class auto_diagnostic_group
|
||||
~auto_diagnostic_group ();
|
||||
};
|
||||
|
||||
/* Forward decl. */
|
||||
class diagnostic_metadata; /* See diagnostic-metadata.h. */
|
||||
|
||||
extern const char *progname;
|
||||
|
||||
extern const char *trim_filename (const char *);
|
||||
@ -78,6 +81,9 @@ extern bool warning_at (location_t, int, const char *, ...)
|
||||
ATTRIBUTE_GCC_DIAG(3,4);
|
||||
extern bool warning_at (rich_location *, int, const char *, ...)
|
||||
ATTRIBUTE_GCC_DIAG(3,4);
|
||||
extern bool warning_at (rich_location *, const diagnostic_metadata &, int,
|
||||
const char *, ...)
|
||||
ATTRIBUTE_GCC_DIAG(4,5);
|
||||
extern void error (const char *, ...) ATTRIBUTE_GCC_DIAG(1,2);
|
||||
extern void error_n (location_t, unsigned HOST_WIDE_INT, const char *,
|
||||
const char *, ...)
|
||||
@ -109,6 +115,10 @@ extern bool emit_diagnostic (diagnostic_t, rich_location *, int,
|
||||
const char *, ...) ATTRIBUTE_GCC_DIAG(4,5);
|
||||
extern bool emit_diagnostic_valist (diagnostic_t, location_t, int, const char *,
|
||||
va_list *) ATTRIBUTE_GCC_DIAG (4,0);
|
||||
extern bool emit_diagnostic_valist (diagnostic_t, rich_location *,
|
||||
const diagnostic_metadata *metadata,
|
||||
int, const char *, va_list *)
|
||||
ATTRIBUTE_GCC_DIAG (5,0);
|
||||
extern bool seen_error (void);
|
||||
|
||||
#ifdef BUFSIZ
|
||||
|
@ -23,6 +23,7 @@ along with GCC; see the file COPYING3. If not see
|
||||
#include "system.h"
|
||||
#include "coretypes.h"
|
||||
#include "diagnostic.h"
|
||||
#include "diagnostic-metadata.h"
|
||||
#include "json.h"
|
||||
#include "selftest.h"
|
||||
|
||||
@ -103,6 +104,20 @@ json_from_fixit_hint (const fixit_hint *hint)
|
||||
return fixit_obj;
|
||||
}
|
||||
|
||||
/* Generate a JSON object for METADATA. */
|
||||
|
||||
static json::object *
|
||||
json_from_metadata (const diagnostic_metadata *metadata)
|
||||
{
|
||||
json::object *metadata_obj = new json::object ();
|
||||
|
||||
if (metadata->get_cwe ())
|
||||
metadata_obj->set ("cwe",
|
||||
new json::integer_number (metadata->get_cwe ()));
|
||||
|
||||
return metadata_obj;
|
||||
}
|
||||
|
||||
/* No-op implementation of "begin_diagnostic" for JSON output. */
|
||||
|
||||
static void
|
||||
@ -211,6 +226,12 @@ json_end_diagnostic (diagnostic_context *context, diagnostic_info *diagnostic,
|
||||
TODO: functions
|
||||
TODO: inlining information
|
||||
TODO: macro expansion information. */
|
||||
|
||||
if (diagnostic->metadata)
|
||||
{
|
||||
json::object *metadata_obj = json_from_metadata (diagnostic->metadata);
|
||||
diag_obj->set ("metadata", metadata_obj);
|
||||
}
|
||||
}
|
||||
|
||||
/* No-op implementation of "begin_group_cb" for JSON output. */
|
||||
@ -268,6 +289,9 @@ diagnostic_output_format_init (diagnostic_context *context,
|
||||
context->end_group_cb = json_end_group;
|
||||
context->final_cb = json_final_cb;
|
||||
|
||||
/* The metadata is handled in JSON format, rather than as text. */
|
||||
context->show_cwe = false;
|
||||
|
||||
/* The option is handled in JSON format, rather than as text. */
|
||||
context->show_option_requested = false;
|
||||
|
||||
|
42
gcc/diagnostic-metadata.h
Normal file
42
gcc/diagnostic-metadata.h
Normal file
@ -0,0 +1,42 @@
|
||||
/* Additional metadata for a diagnostic.
|
||||
Copyright (C) 2019 Free Software Foundation, Inc.
|
||||
Contributed by David Malcolm <dmalcolm@redhat.com>
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation; either version 3, or (at your option) any later
|
||||
version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING3. If not see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef GCC_DIAGNOSTIC_METADATA_H
|
||||
#define GCC_DIAGNOSTIC_METADATA_H
|
||||
|
||||
/* A bundle of additional metadata that can be associated with a
|
||||
diagnostic.
|
||||
|
||||
Currently this only supports associating a CWE identifier with a
|
||||
diagnostic. */
|
||||
|
||||
class diagnostic_metadata
|
||||
{
|
||||
public:
|
||||
diagnostic_metadata () : m_cwe (0) {}
|
||||
|
||||
void add_cwe (int cwe) { m_cwe = cwe; }
|
||||
int get_cwe () const { return m_cwe; }
|
||||
|
||||
private:
|
||||
int m_cwe;
|
||||
};
|
||||
|
||||
#endif /* ! GCC_DIAGNOSTIC_METADATA_H */
|
142
gcc/diagnostic.c
142
gcc/diagnostic.c
@ -32,6 +32,7 @@ along with GCC; see the file COPYING3. If not see
|
||||
#include "diagnostic.h"
|
||||
#include "diagnostic-color.h"
|
||||
#include "diagnostic-url.h"
|
||||
#include "diagnostic-metadata.h"
|
||||
#include "edit-context.h"
|
||||
#include "selftest.h"
|
||||
#include "selftest-diagnostic.h"
|
||||
@ -58,11 +59,13 @@ along with GCC; see the file COPYING3. If not see
|
||||
#define permissive_error_option(DC) ((DC)->opt_permissive)
|
||||
|
||||
/* Prototypes. */
|
||||
static bool diagnostic_impl (rich_location *, int, const char *,
|
||||
va_list *, diagnostic_t) ATTRIBUTE_GCC_DIAG(3,0);
|
||||
static bool diagnostic_n_impl (rich_location *, int, unsigned HOST_WIDE_INT,
|
||||
static bool diagnostic_impl (rich_location *, const diagnostic_metadata *,
|
||||
int, const char *,
|
||||
va_list *, diagnostic_t) ATTRIBUTE_GCC_DIAG(4,0);
|
||||
static bool diagnostic_n_impl (rich_location *, const diagnostic_metadata *,
|
||||
int, unsigned HOST_WIDE_INT,
|
||||
const char *, const char *, va_list *,
|
||||
diagnostic_t) ATTRIBUTE_GCC_DIAG(5,0);
|
||||
diagnostic_t) ATTRIBUTE_GCC_DIAG(6,0);
|
||||
|
||||
static void error_recursion (diagnostic_context *) ATTRIBUTE_NORETURN;
|
||||
static void real_abort (void) ATTRIBUTE_NORETURN;
|
||||
@ -183,6 +186,7 @@ diagnostic_initialize (diagnostic_context *context, int n_opts)
|
||||
diagnostic_set_caret_max_width (context, pp_line_cutoff (context->printer));
|
||||
for (i = 0; i < rich_location::STATICALLY_ALLOCATED_RANGES; i++)
|
||||
context->caret_chars[i] = '^';
|
||||
context->show_cwe = false;
|
||||
context->show_option_requested = false;
|
||||
context->abort_on_error = false;
|
||||
context->show_column = false;
|
||||
@ -299,6 +303,7 @@ diagnostic_set_info_translated (diagnostic_info *diagnostic, const char *msg,
|
||||
diagnostic->message.format_spec = msg;
|
||||
diagnostic->message.m_richloc = richloc;
|
||||
diagnostic->richloc = richloc;
|
||||
diagnostic->metadata = NULL;
|
||||
diagnostic->kind = kind;
|
||||
diagnostic->option_index = 0;
|
||||
}
|
||||
@ -898,6 +903,47 @@ update_effective_level_from_pragmas (diagnostic_context *context,
|
||||
return diag_class;
|
||||
}
|
||||
|
||||
/* Generate a URL string describing CWE. The caller is responsible for
|
||||
freeing the string. */
|
||||
|
||||
static char *
|
||||
get_cwe_url (int cwe)
|
||||
{
|
||||
return xasprintf ("https://cwe.mitre.org/data/definitions/%i.html", cwe);
|
||||
}
|
||||
|
||||
/* If DIAGNOSTIC has a CWE identifier, print it.
|
||||
|
||||
For example, if the diagnostic metadata associates it with CWE-119,
|
||||
" [CWE-119]" will be printed, suitably colorized, and with a URL of a
|
||||
description of the security issue. */
|
||||
|
||||
static void
|
||||
print_any_cwe (diagnostic_context *context,
|
||||
const diagnostic_info *diagnostic)
|
||||
{
|
||||
if (diagnostic->metadata == NULL)
|
||||
return;
|
||||
|
||||
int cwe = diagnostic->metadata->get_cwe ();
|
||||
if (cwe)
|
||||
{
|
||||
pretty_printer *pp = context->printer;
|
||||
char *saved_prefix = pp_take_prefix (context->printer);
|
||||
pp_string (pp, " [");
|
||||
pp_string (pp, colorize_start (pp_show_color (pp),
|
||||
diagnostic_kind_color[diagnostic->kind]));
|
||||
char *cwe_url = get_cwe_url (cwe);
|
||||
pp_begin_url (pp, cwe_url);
|
||||
free (cwe_url);
|
||||
pp_printf (pp, "CWE-%i", cwe);
|
||||
pp_set_prefix (context->printer, saved_prefix);
|
||||
pp_end_url (pp);
|
||||
pp_string (pp, colorize_stop (pp_show_color (pp)));
|
||||
pp_character (pp, ']');
|
||||
}
|
||||
}
|
||||
|
||||
/* Print any metadata about the option used to control DIAGNOSTIC to CONTEXT's
|
||||
printer, e.g. " [-Werror=uninitialized]".
|
||||
Subroutine of diagnostic_report_diagnostic. */
|
||||
@ -1058,6 +1104,8 @@ diagnostic_report_diagnostic (diagnostic_context *context,
|
||||
pp_format (context->printer, &diagnostic->message);
|
||||
(*diagnostic_starter (context)) (context, diagnostic);
|
||||
pp_output_formatted_text (context->printer);
|
||||
if (context->show_cwe)
|
||||
print_any_cwe (context, diagnostic);
|
||||
if (context->show_option_requested)
|
||||
print_option_information (context, diagnostic, orig_diag_kind);
|
||||
(*diagnostic_finalizer (context)) (context, diagnostic, orig_diag_kind);
|
||||
@ -1183,8 +1231,8 @@ diagnostic_append_note (diagnostic_context *context,
|
||||
permerror, error, error_at, error_at, sorry, fatal_error, internal_error,
|
||||
and internal_error_no_backtrace, as documented and defined below. */
|
||||
static bool
|
||||
diagnostic_impl (rich_location *richloc, int opt,
|
||||
const char *gmsgid,
|
||||
diagnostic_impl (rich_location *richloc, const diagnostic_metadata *metadata,
|
||||
int opt, const char *gmsgid,
|
||||
va_list *ap, diagnostic_t kind)
|
||||
{
|
||||
diagnostic_info diagnostic;
|
||||
@ -1200,13 +1248,15 @@ diagnostic_impl (rich_location *richloc, int opt,
|
||||
if (kind == DK_WARNING || kind == DK_PEDWARN)
|
||||
diagnostic.option_index = opt;
|
||||
}
|
||||
diagnostic.metadata = metadata;
|
||||
return diagnostic_report_diagnostic (global_dc, &diagnostic);
|
||||
}
|
||||
|
||||
/* Implement inform_n, warning_n, and error_n, as documented and
|
||||
defined below. */
|
||||
static bool
|
||||
diagnostic_n_impl (rich_location *richloc, int opt, unsigned HOST_WIDE_INT n,
|
||||
diagnostic_n_impl (rich_location *richloc, const diagnostic_metadata *metadata,
|
||||
int opt, unsigned HOST_WIDE_INT n,
|
||||
const char *singular_gmsgid,
|
||||
const char *plural_gmsgid,
|
||||
va_list *ap, diagnostic_t kind)
|
||||
@ -1226,6 +1276,7 @@ diagnostic_n_impl (rich_location *richloc, int opt, unsigned HOST_WIDE_INT n,
|
||||
diagnostic_set_info_translated (&diagnostic, text, ap, richloc, kind);
|
||||
if (kind == DK_WARNING)
|
||||
diagnostic.option_index = opt;
|
||||
diagnostic.metadata = metadata;
|
||||
return diagnostic_report_diagnostic (global_dc, &diagnostic);
|
||||
}
|
||||
|
||||
@ -1239,7 +1290,7 @@ emit_diagnostic (diagnostic_t kind, location_t location, int opt,
|
||||
va_list ap;
|
||||
va_start (ap, gmsgid);
|
||||
rich_location richloc (line_table, location);
|
||||
bool ret = diagnostic_impl (&richloc, opt, gmsgid, &ap, kind);
|
||||
bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, kind);
|
||||
va_end (ap);
|
||||
return ret;
|
||||
}
|
||||
@ -1253,7 +1304,7 @@ emit_diagnostic (diagnostic_t kind, rich_location *richloc, int opt,
|
||||
auto_diagnostic_group d;
|
||||
va_list ap;
|
||||
va_start (ap, gmsgid);
|
||||
bool ret = diagnostic_impl (richloc, opt, gmsgid, &ap, kind);
|
||||
bool ret = diagnostic_impl (richloc, NULL, opt, gmsgid, &ap, kind);
|
||||
va_end (ap);
|
||||
return ret;
|
||||
}
|
||||
@ -1265,7 +1316,18 @@ emit_diagnostic_valist (diagnostic_t kind, location_t location, int opt,
|
||||
const char *gmsgid, va_list *ap)
|
||||
{
|
||||
rich_location richloc (line_table, location);
|
||||
return diagnostic_impl (&richloc, opt, gmsgid, ap, kind);
|
||||
return diagnostic_impl (&richloc, NULL, opt, gmsgid, ap, kind);
|
||||
}
|
||||
|
||||
/* Wrapper around diagnostic_impl taking a va_list parameter. */
|
||||
|
||||
bool
|
||||
emit_diagnostic_valist (diagnostic_t kind, rich_location *richloc,
|
||||
const diagnostic_metadata *metadata,
|
||||
int opt,
|
||||
const char *gmsgid, va_list *ap)
|
||||
{
|
||||
return diagnostic_impl (richloc, metadata, opt, gmsgid, ap, kind);
|
||||
}
|
||||
|
||||
/* An informative note at LOCATION. Use this for additional details on an error
|
||||
@ -1277,7 +1339,7 @@ inform (location_t location, const char *gmsgid, ...)
|
||||
va_list ap;
|
||||
va_start (ap, gmsgid);
|
||||
rich_location richloc (line_table, location);
|
||||
diagnostic_impl (&richloc, -1, gmsgid, &ap, DK_NOTE);
|
||||
diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_NOTE);
|
||||
va_end (ap);
|
||||
}
|
||||
|
||||
@ -1290,7 +1352,7 @@ inform (rich_location *richloc, const char *gmsgid, ...)
|
||||
auto_diagnostic_group d;
|
||||
va_list ap;
|
||||
va_start (ap, gmsgid);
|
||||
diagnostic_impl (richloc, -1, gmsgid, &ap, DK_NOTE);
|
||||
diagnostic_impl (richloc, NULL, -1, gmsgid, &ap, DK_NOTE);
|
||||
va_end (ap);
|
||||
}
|
||||
|
||||
@ -1304,7 +1366,7 @@ inform_n (location_t location, unsigned HOST_WIDE_INT n,
|
||||
va_start (ap, plural_gmsgid);
|
||||
auto_diagnostic_group d;
|
||||
rich_location richloc (line_table, location);
|
||||
diagnostic_n_impl (&richloc, -1, n, singular_gmsgid, plural_gmsgid,
|
||||
diagnostic_n_impl (&richloc, NULL, -1, n, singular_gmsgid, plural_gmsgid,
|
||||
&ap, DK_NOTE);
|
||||
va_end (ap);
|
||||
}
|
||||
@ -1319,7 +1381,7 @@ warning (int opt, const char *gmsgid, ...)
|
||||
va_list ap;
|
||||
va_start (ap, gmsgid);
|
||||
rich_location richloc (line_table, input_location);
|
||||
bool ret = diagnostic_impl (&richloc, opt, gmsgid, &ap, DK_WARNING);
|
||||
bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, DK_WARNING);
|
||||
va_end (ap);
|
||||
return ret;
|
||||
}
|
||||
@ -1335,7 +1397,7 @@ warning_at (location_t location, int opt, const char *gmsgid, ...)
|
||||
va_list ap;
|
||||
va_start (ap, gmsgid);
|
||||
rich_location richloc (line_table, location);
|
||||
bool ret = diagnostic_impl (&richloc, opt, gmsgid, &ap, DK_WARNING);
|
||||
bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, DK_WARNING);
|
||||
va_end (ap);
|
||||
return ret;
|
||||
}
|
||||
@ -1350,7 +1412,25 @@ warning_at (rich_location *richloc, int opt, const char *gmsgid, ...)
|
||||
auto_diagnostic_group d;
|
||||
va_list ap;
|
||||
va_start (ap, gmsgid);
|
||||
bool ret = diagnostic_impl (richloc, opt, gmsgid, &ap, DK_WARNING);
|
||||
bool ret = diagnostic_impl (richloc, NULL, opt, gmsgid, &ap, DK_WARNING);
|
||||
va_end (ap);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Same as "warning at" above, but using METADATA. */
|
||||
|
||||
bool
|
||||
warning_at (rich_location *richloc, const diagnostic_metadata &metadata,
|
||||
int opt, const char *gmsgid, ...)
|
||||
{
|
||||
gcc_assert (richloc);
|
||||
|
||||
auto_diagnostic_group d;
|
||||
va_list ap;
|
||||
va_start (ap, gmsgid);
|
||||
bool ret
|
||||
= diagnostic_impl (richloc, &metadata, opt, gmsgid, &ap,
|
||||
DK_WARNING);
|
||||
va_end (ap);
|
||||
return ret;
|
||||
}
|
||||
@ -1366,7 +1446,7 @@ warning_n (rich_location *richloc, int opt, unsigned HOST_WIDE_INT n,
|
||||
auto_diagnostic_group d;
|
||||
va_list ap;
|
||||
va_start (ap, plural_gmsgid);
|
||||
bool ret = diagnostic_n_impl (richloc, opt, n,
|
||||
bool ret = diagnostic_n_impl (richloc, NULL, opt, n,
|
||||
singular_gmsgid, plural_gmsgid,
|
||||
&ap, DK_WARNING);
|
||||
va_end (ap);
|
||||
@ -1385,7 +1465,7 @@ warning_n (location_t location, int opt, unsigned HOST_WIDE_INT n,
|
||||
va_list ap;
|
||||
va_start (ap, plural_gmsgid);
|
||||
rich_location richloc (line_table, location);
|
||||
bool ret = diagnostic_n_impl (&richloc, opt, n,
|
||||
bool ret = diagnostic_n_impl (&richloc, NULL, opt, n,
|
||||
singular_gmsgid, plural_gmsgid,
|
||||
&ap, DK_WARNING);
|
||||
va_end (ap);
|
||||
@ -1412,7 +1492,7 @@ pedwarn (location_t location, int opt, const char *gmsgid, ...)
|
||||
va_list ap;
|
||||
va_start (ap, gmsgid);
|
||||
rich_location richloc (line_table, location);
|
||||
bool ret = diagnostic_impl (&richloc, opt, gmsgid, &ap, DK_PEDWARN);
|
||||
bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, DK_PEDWARN);
|
||||
va_end (ap);
|
||||
return ret;
|
||||
}
|
||||
@ -1427,7 +1507,7 @@ pedwarn (rich_location *richloc, int opt, const char *gmsgid, ...)
|
||||
auto_diagnostic_group d;
|
||||
va_list ap;
|
||||
va_start (ap, gmsgid);
|
||||
bool ret = diagnostic_impl (richloc, opt, gmsgid, &ap, DK_PEDWARN);
|
||||
bool ret = diagnostic_impl (richloc, NULL, opt, gmsgid, &ap, DK_PEDWARN);
|
||||
va_end (ap);
|
||||
return ret;
|
||||
}
|
||||
@ -1446,7 +1526,7 @@ permerror (location_t location, const char *gmsgid, ...)
|
||||
va_list ap;
|
||||
va_start (ap, gmsgid);
|
||||
rich_location richloc (line_table, location);
|
||||
bool ret = diagnostic_impl (&richloc, -1, gmsgid, &ap, DK_PERMERROR);
|
||||
bool ret = diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_PERMERROR);
|
||||
va_end (ap);
|
||||
return ret;
|
||||
}
|
||||
@ -1461,7 +1541,7 @@ permerror (rich_location *richloc, const char *gmsgid, ...)
|
||||
auto_diagnostic_group d;
|
||||
va_list ap;
|
||||
va_start (ap, gmsgid);
|
||||
bool ret = diagnostic_impl (richloc, -1, gmsgid, &ap, DK_PERMERROR);
|
||||
bool ret = diagnostic_impl (richloc, NULL, -1, gmsgid, &ap, DK_PERMERROR);
|
||||
va_end (ap);
|
||||
return ret;
|
||||
}
|
||||
@ -1475,7 +1555,7 @@ error (const char *gmsgid, ...)
|
||||
va_list ap;
|
||||
va_start (ap, gmsgid);
|
||||
rich_location richloc (line_table, input_location);
|
||||
diagnostic_impl (&richloc, -1, gmsgid, &ap, DK_ERROR);
|
||||
diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ERROR);
|
||||
va_end (ap);
|
||||
}
|
||||
|
||||
@ -1489,7 +1569,7 @@ error_n (location_t location, unsigned HOST_WIDE_INT n,
|
||||
va_list ap;
|
||||
va_start (ap, plural_gmsgid);
|
||||
rich_location richloc (line_table, location);
|
||||
diagnostic_n_impl (&richloc, -1, n, singular_gmsgid, plural_gmsgid,
|
||||
diagnostic_n_impl (&richloc, NULL, -1, n, singular_gmsgid, plural_gmsgid,
|
||||
&ap, DK_ERROR);
|
||||
va_end (ap);
|
||||
}
|
||||
@ -1502,7 +1582,7 @@ error_at (location_t loc, const char *gmsgid, ...)
|
||||
va_list ap;
|
||||
va_start (ap, gmsgid);
|
||||
rich_location richloc (line_table, loc);
|
||||
diagnostic_impl (&richloc, -1, gmsgid, &ap, DK_ERROR);
|
||||
diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ERROR);
|
||||
va_end (ap);
|
||||
}
|
||||
|
||||
@ -1516,7 +1596,7 @@ error_at (rich_location *richloc, const char *gmsgid, ...)
|
||||
auto_diagnostic_group d;
|
||||
va_list ap;
|
||||
va_start (ap, gmsgid);
|
||||
diagnostic_impl (richloc, -1, gmsgid, &ap, DK_ERROR);
|
||||
diagnostic_impl (richloc, NULL, -1, gmsgid, &ap, DK_ERROR);
|
||||
va_end (ap);
|
||||
}
|
||||
|
||||
@ -1530,7 +1610,7 @@ sorry (const char *gmsgid, ...)
|
||||
va_list ap;
|
||||
va_start (ap, gmsgid);
|
||||
rich_location richloc (line_table, input_location);
|
||||
diagnostic_impl (&richloc, -1, gmsgid, &ap, DK_SORRY);
|
||||
diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_SORRY);
|
||||
va_end (ap);
|
||||
}
|
||||
|
||||
@ -1542,7 +1622,7 @@ sorry_at (location_t loc, const char *gmsgid, ...)
|
||||
va_list ap;
|
||||
va_start (ap, gmsgid);
|
||||
rich_location richloc (line_table, loc);
|
||||
diagnostic_impl (&richloc, -1, gmsgid, &ap, DK_SORRY);
|
||||
diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_SORRY);
|
||||
va_end (ap);
|
||||
}
|
||||
|
||||
@ -1564,7 +1644,7 @@ fatal_error (location_t loc, const char *gmsgid, ...)
|
||||
va_list ap;
|
||||
va_start (ap, gmsgid);
|
||||
rich_location richloc (line_table, loc);
|
||||
diagnostic_impl (&richloc, -1, gmsgid, &ap, DK_FATAL);
|
||||
diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_FATAL);
|
||||
va_end (ap);
|
||||
|
||||
gcc_unreachable ();
|
||||
@ -1581,7 +1661,7 @@ internal_error (const char *gmsgid, ...)
|
||||
va_list ap;
|
||||
va_start (ap, gmsgid);
|
||||
rich_location richloc (line_table, input_location);
|
||||
diagnostic_impl (&richloc, -1, gmsgid, &ap, DK_ICE);
|
||||
diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ICE);
|
||||
va_end (ap);
|
||||
|
||||
gcc_unreachable ();
|
||||
@ -1597,7 +1677,7 @@ internal_error_no_backtrace (const char *gmsgid, ...)
|
||||
va_list ap;
|
||||
va_start (ap, gmsgid);
|
||||
rich_location richloc (line_table, input_location);
|
||||
diagnostic_impl (&richloc, -1, gmsgid, &ap, DK_ICE_NOBT);
|
||||
diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ICE_NOBT);
|
||||
va_end (ap);
|
||||
|
||||
gcc_unreachable ();
|
||||
|
@ -46,6 +46,10 @@ struct diagnostic_info
|
||||
/* The location at which the diagnostic is to be reported. */
|
||||
rich_location *richloc;
|
||||
|
||||
/* An optional bundle of metadata associated with the diagnostic
|
||||
(or NULL). */
|
||||
const diagnostic_metadata *metadata;
|
||||
|
||||
/* Auxiliary data for client. */
|
||||
void *x_data;
|
||||
/* The kind of diagnostic it is about. */
|
||||
@ -126,6 +130,10 @@ struct diagnostic_context
|
||||
/* Character used for caret diagnostics. */
|
||||
char caret_chars[rich_location::STATICALLY_ALLOCATED_RANGES];
|
||||
|
||||
/* True if we should print any CWE identifiers associated with
|
||||
diagnostics. */
|
||||
bool show_cwe;
|
||||
|
||||
/* True if we should print the command line option which controls
|
||||
each diagnostic, if known. */
|
||||
bool show_option_requested;
|
||||
|
@ -277,6 +277,7 @@ Objective-C and Objective-C++ Dialects}.
|
||||
-fdiagnostics-format=@r{[}text@r{|}json@r{]} @gol
|
||||
-fno-diagnostics-show-option -fno-diagnostics-show-caret @gol
|
||||
-fno-diagnostics-show-labels -fno-diagnostics-show-line-numbers @gol
|
||||
-fno-diagnostics-show-cwe @gol
|
||||
-fdiagnostics-minimum-margin-width=@var{width} @gol
|
||||
-fdiagnostics-parseable-fixits -fdiagnostics-generate-patch @gol
|
||||
-fdiagnostics-show-template-tree -fno-elide-type @gol
|
||||
@ -4005,6 +4006,15 @@ as the types of expressions:
|
||||
This option suppresses the printing of these labels (in the example above,
|
||||
the vertical bars and the ``char *'' and ``long int'' text).
|
||||
|
||||
@item -fno-diagnostics-show-cwe
|
||||
@opindex fno-diagnostics-show-cwe
|
||||
@opindex fdiagnostics-show-cwe
|
||||
Diagnostic messages can optionally have an associated
|
||||
@url{https://cwe.mitre.org/index.html, CWE} identifier.
|
||||
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
|
||||
|
@ -2407,6 +2407,10 @@ common_handle_option (struct gcc_options *opts,
|
||||
dc->parseable_fixits_p = value;
|
||||
break;
|
||||
|
||||
case OPT_fdiagnostics_show_cwe:
|
||||
dc->show_cwe = value;
|
||||
break;
|
||||
|
||||
case OPT_fdiagnostics_show_option:
|
||||
dc->show_option_requested = value;
|
||||
break;
|
||||
|
@ -1,3 +1,9 @@
|
||||
2019-12-18 David Malcolm <dmalcolm@redhat.com>
|
||||
|
||||
* gcc.dg/plugin/diagnostic-test-metadata.c: New test.
|
||||
* gcc.dg/plugin/diagnostic_plugin_test_metadata.c: New test plugin.
|
||||
* gcc.dg/plugin/plugin.exp (plugin_test_list): Add them.
|
||||
|
||||
2019-12-19 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR fortran/92977
|
||||
|
9
gcc/testsuite/gcc.dg/plugin/diagnostic-test-metadata.c
Normal file
9
gcc/testsuite/gcc.dg/plugin/diagnostic-test-metadata.c
Normal file
@ -0,0 +1,9 @@
|
||||
/* { dg-do compile } */
|
||||
|
||||
extern char *gets (char *s);
|
||||
|
||||
void test_cwe (void)
|
||||
{
|
||||
char buf[1024];
|
||||
gets (buf); /* { dg-warning "never use 'gets' \\\[CWE-242\\\]" } */
|
||||
}
|
140
gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_metadata.c
Normal file
140
gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_metadata.c
Normal file
@ -0,0 +1,140 @@
|
||||
/* This plugin exercises diagnostic_metadata. */
|
||||
|
||||
#include "gcc-plugin.h"
|
||||
#include "config.h"
|
||||
#include "system.h"
|
||||
#include "coretypes.h"
|
||||
#include "tm.h"
|
||||
#include "tree.h"
|
||||
#include "stringpool.h"
|
||||
#include "toplev.h"
|
||||
#include "basic-block.h"
|
||||
#include "hash-table.h"
|
||||
#include "vec.h"
|
||||
#include "ggc.h"
|
||||
#include "basic-block.h"
|
||||
#include "tree-ssa-alias.h"
|
||||
#include "internal-fn.h"
|
||||
#include "gimple-fold.h"
|
||||
#include "tree-eh.h"
|
||||
#include "gimple-expr.h"
|
||||
#include "is-a.h"
|
||||
#include "gimple.h"
|
||||
#include "gimple-iterator.h"
|
||||
#include "tree.h"
|
||||
#include "tree-pass.h"
|
||||
#include "intl.h"
|
||||
#include "plugin-version.h"
|
||||
#include "diagnostic.h"
|
||||
#include "context.h"
|
||||
#include "gcc-rich-location.h"
|
||||
#include "diagnostic-metadata.h"
|
||||
|
||||
int plugin_is_GPL_compatible;
|
||||
|
||||
const pass_data pass_data_test_metadata =
|
||||
{
|
||||
GIMPLE_PASS, /* type */
|
||||
"test_metadata", /* name */
|
||||
OPTGROUP_NONE, /* optinfo_flags */
|
||||
TV_NONE, /* tv_id */
|
||||
PROP_ssa, /* properties_required */
|
||||
0, /* properties_provided */
|
||||
0, /* properties_destroyed */
|
||||
0, /* todo_flags_start */
|
||||
0, /* todo_flags_finish */
|
||||
};
|
||||
|
||||
class pass_test_metadata : public gimple_opt_pass
|
||||
{
|
||||
public:
|
||||
pass_test_metadata(gcc::context *ctxt)
|
||||
: gimple_opt_pass(pass_data_test_metadata, ctxt)
|
||||
{}
|
||||
|
||||
/* opt_pass methods: */
|
||||
bool gate (function *) { return true; }
|
||||
virtual unsigned int execute (function *);
|
||||
|
||||
}; // class pass_test_metadata
|
||||
|
||||
/* Determine if STMT is a call with NUM_ARGS arguments to a function
|
||||
named FUNCNAME.
|
||||
If so, return STMT as a gcall *. Otherwise return NULL. */
|
||||
|
||||
static gcall *
|
||||
check_for_named_call (gimple *stmt,
|
||||
const char *funcname, unsigned int num_args)
|
||||
{
|
||||
gcc_assert (funcname);
|
||||
|
||||
gcall *call = dyn_cast <gcall *> (stmt);
|
||||
if (!call)
|
||||
return NULL;
|
||||
|
||||
tree fndecl = gimple_call_fndecl (call);
|
||||
if (!fndecl)
|
||||
return NULL;
|
||||
|
||||
if (strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)), funcname))
|
||||
return NULL;
|
||||
|
||||
if (gimple_call_num_args (call) != num_args)
|
||||
{
|
||||
error_at (stmt->location, "expected number of args: %i (got %i)",
|
||||
num_args, gimple_call_num_args (call));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return call;
|
||||
}
|
||||
|
||||
/* Exercise diagnostic_metadata. */
|
||||
|
||||
unsigned int
|
||||
pass_test_metadata::execute (function *fun)
|
||||
{
|
||||
gimple_stmt_iterator gsi;
|
||||
basic_block bb;
|
||||
|
||||
FOR_EACH_BB_FN (bb, fun)
|
||||
for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
|
||||
{
|
||||
gimple *stmt = gsi_stmt (gsi);
|
||||
|
||||
/* Example of CWE: complain about uses of gets. */
|
||||
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;
|
||||
m.add_cwe (242);
|
||||
warning_at (&richloc, m, 0,
|
||||
"never use %qs", "gets");
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
plugin_init (struct plugin_name_args *plugin_info,
|
||||
struct plugin_gcc_version *version)
|
||||
{
|
||||
struct register_pass_info pass_info;
|
||||
const char *plugin_name = plugin_info->base_name;
|
||||
int argc = plugin_info->argc;
|
||||
struct plugin_argument *argv = plugin_info->argv;
|
||||
|
||||
if (!plugin_default_version_check (version, &gcc_version))
|
||||
return 1;
|
||||
|
||||
pass_info.pass = new pass_test_metadata (g);
|
||||
pass_info.reference_pass_name = "ssa";
|
||||
pass_info.ref_pass_instance_number = 1;
|
||||
pass_info.pos_op = PASS_POS_INSERT_AFTER;
|
||||
register_callback (plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL,
|
||||
&pass_info);
|
||||
|
||||
return 0;
|
||||
}
|
@ -94,6 +94,7 @@ set plugin_test_list [list \
|
||||
diagnostic-test-inlining-2.c \
|
||||
diagnostic-test-inlining-3.c \
|
||||
diagnostic-test-inlining-4.c } \
|
||||
{ diagnostic_plugin_test_metadata.c diagnostic-test-metadata.c } \
|
||||
{ location_overflow_plugin.c \
|
||||
location-overflow-test-1.c \
|
||||
location-overflow-test-2.c \
|
||||
|
@ -1179,6 +1179,8 @@ general_init (const char *argv0, bool init_signals)
|
||||
= global_options_init.x_flag_diagnostics_show_labels;
|
||||
global_dc->show_line_numbers_p
|
||||
= global_options_init.x_flag_diagnostics_show_line_numbers;
|
||||
global_dc->show_cwe
|
||||
= global_options_init.x_flag_diagnostics_show_cwe;
|
||||
global_dc->show_option_requested
|
||||
= global_options_init.x_flag_diagnostics_show_option;
|
||||
global_dc->min_margin_width
|
||||
|
Loading…
Reference in New Issue
Block a user