public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: David Malcolm <dmalcolm@redhat.com>
To: gcc-patches@gcc.gnu.org
Subject: [PATCH 01/12] diagnostics: add ability to associate diagnostics with rules from coding standards
Date: Wed, 22 Jun 2022 18:34:36 -0400	[thread overview]
Message-ID: <20220622223447.2462880-2-dmalcolm@redhat.com> (raw)
In-Reply-To: <20220622223447.2462880-1-dmalcolm@redhat.com>

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>
---
 gcc/common.opt                                |  4 ++
 gcc/diagnostic-format-json.cc                 |  1 +
 gcc/diagnostic-format-sarif.cc                |  1 +
 gcc/diagnostic-metadata.h                     | 47 +++++++++++++++++-
 gcc/diagnostic.cc                             | 48 +++++++++++++++++++
 gcc/diagnostic.h                              |  3 ++
 gcc/doc/invoke.texi                           | 10 ++++
 gcc/opts.cc                                   |  4 ++
 .../gcc.dg/plugin/diagnostic-test-metadata.c  |  2 +-
 .../plugin/diagnostic_plugin_test_metadata.c  |  9 +++-
 gcc/toplev.cc                                 |  2 +
 11 files changed, 127 insertions(+), 4 deletions(-)

diff --git a/gcc/common.opt b/gcc/common.opt
index 32917aafcae..3a842847a74 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -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.
diff --git a/gcc/diagnostic-format-json.cc b/gcc/diagnostic-format-json.cc
index 051fa6c2e48..d1d8d3f2081 100644
--- a/gcc/diagnostic-format-json.cc
+++ b/gcc/diagnostic-format-json.cc
@@ -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;
diff --git a/gcc/diagnostic-format-sarif.cc b/gcc/diagnostic-format-sarif.cc
index 0c33179e8cf..a7bb9fb639d 100644
--- a/gcc/diagnostic-format-sarif.cc
+++ b/gcc/diagnostic-format-sarif.cc
@@ -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;
diff --git a/gcc/diagnostic-metadata.h b/gcc/diagnostic-metadata.h
index ae59942c65e..80017d35fa9 100644
--- a/gcc/diagnostic-metadata.h
+++ b/gcc/diagnostic-metadata.h
@@ -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 */
diff --git a/gcc/diagnostic.cc b/gcc/diagnostic.cc
index f2a82fff462..22f7b0b6d6e 100644
--- a/gcc/diagnostic.cc
+++ b/gcc/diagnostic.cc
@@ -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);
diff --git a/gcc/diagnostic.h b/gcc/diagnostic.h
index 96c9a7202f9..ae6f2dfb7f4 100644
--- a/gcc/diagnostic.h
+++ b/gcc/diagnostic.h
@@ -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;
 
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 50f57877477..4bd73c197e7 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -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
diff --git a/gcc/opts.cc b/gcc/opts.cc
index 959d48d173f..ef485455093 100644
--- a/gcc/opts.cc
+++ b/gcc/opts.cc
@@ -2872,6 +2872,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;
diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-metadata.c b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-metadata.c
index d2babd35753..38ecf0a6d95 100644
--- a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-metadata.c
+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-metadata.c
@@ -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\\\]" } */
 }
diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_metadata.c b/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_metadata.c
index 4b13afc093d..b86a8b3650e 100644
--- a/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_metadata.c
+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_metadata.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");
 	  }
diff --git a/gcc/toplev.cc b/gcc/toplev.cc
index 055e0642f77..a24ad5db438 100644
--- a/gcc/toplev.cc
+++ b/gcc/toplev.cc
@@ -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
-- 
2.26.3


  reply	other threads:[~2022-06-22 22:34 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-06-22 22:34 [PATCH 00/12] RFC: Replay of serialized diagnostics David Malcolm
2022-06-22 22:34 ` David Malcolm [this message]
2022-06-23 19:04   ` [PATCH 01/12] diagnostics: add ability to associate diagnostics with rules from coding standards David Malcolm
2022-06-22 22:34 ` [PATCH 02/12] diagnostics: associate rules with plugins in SARIF output David Malcolm
2022-06-22 22:34 ` [PATCH 03/12] Add more emit_diagnostic overloads David Malcolm
2022-06-23 16:39   ` Joseph Myers
2022-06-22 22:34 ` [PATCH 04/12] json: add json parsing support David Malcolm
2022-06-22 22:34 ` [PATCH 05/12] Placeholder libcpp fixups David Malcolm
2022-06-22 22:34 ` [PATCH 06/12] prune.exp: move multiline-handling to before other pruning David Malcolm
2022-06-22 22:34 ` [PATCH 07/12] Add deferred-locations.h/cc David Malcolm
2022-06-22 22:34 ` [PATCH 08/12] Add json-reader.h/cc David Malcolm
2022-06-22 22:34 ` [PATCH 09/12] Add json frontend David Malcolm
2022-06-22 22:34 ` [PATCH 10/12] Add sarif frontend David Malcolm
2022-06-22 22:34 ` [PATCH 11/12] Fixups to diagnostic-format-sarif.cc David Malcolm
2022-06-22 22:34 ` [PATCH 12/12] Work-in-progress of path remapping David Malcolm
2022-07-08 18:40 ` [PATCH 00/12] RFC: Replay of serialized diagnostics David Malcolm

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220622223447.2462880-2-dmalcolm@redhat.com \
    --to=dmalcolm@redhat.com \
    --cc=gcc-patches@gcc.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).