diff mbox series

[12/16] diagnostics: SARIF output: add "arguments" property (§3.20.2)

Message ID 20240724221824.585054-13-dmalcolm@redhat.com
State New
Headers show
Series Revamp of JSON/SARIF output | expand

Commit Message

David Malcolm July 24, 2024, 10:18 p.m. UTC
gcc/ChangeLog:
	* diagnostic-format-sarif.cc (sarif_invocation::sarif_invocation):
	Add "original_argv" param and use it to populate "arguments"
	property (§3.20.2).
	(sarif_builder::sarif_builder): Pass argv to m_invocation_obj's
	ctor.
	* diagnostic.cc (diagnostic_context::initialize): Initialize
	m_original_argv.
	(diagnostic_context::finish): Clean up m_original_argv.
	(diagnostic_context::set_original_argv): New.
	* diagnostic.h: Include "unique-argv.h".
	(diagnostic_context::set_original_argv): New decl.
	(diagnostic_context::get_original_argv): New decl.
	(diagnostic_context::m_original_argv): New field.
	* toplev.cc: Include "unique-argv.h".
	(general_init): Add "original_argv" param and move it to global_dc.
	(toplev::main): Stash a copy of the original argv before expansion,
	and pass it to general_init for use by SARIF output.
	* unique-argv.h: New file.

gcc/jit/ChangeLog:
	* jit-playback.cc (jit::playback_context::compile) Add a trailing
	null to argvec.

gcc/testsuite/ChangeLog:
	* c-c++-common/diagnostic-format-sarif-file-1.c: Verify that we
	have an "arguments" property (§3.20.2).

Signed-off-by: David Malcolm <dmalcolm@redhat.com>
---
 gcc/diagnostic-format-sarif.cc                | 25 +++++--
 gcc/diagnostic.cc                             | 17 +++++
 gcc/diagnostic.h                              | 10 +++
 gcc/jit/jit-playback.cc                       |  6 +-
 .../diagnostic-format-sarif-file-1.c          |  5 ++
 gcc/toplev.cc                                 | 13 +++-
 gcc/unique-argv.h                             | 67 +++++++++++++++++++
 7 files changed, 132 insertions(+), 11 deletions(-)
 create mode 100644 gcc/unique-argv.h
diff mbox series

Patch

diff --git a/gcc/diagnostic-format-sarif.cc b/gcc/diagnostic-format-sarif.cc
index 9be84fb268a5..6c7216651627 100644
--- a/gcc/diagnostic-format-sarif.cc
+++ b/gcc/diagnostic-format-sarif.cc
@@ -125,7 +125,8 @@  class sarif_tool_component : public sarif_object {};
 class sarif_invocation : public sarif_object
 {
 public:
-  sarif_invocation (sarif_builder &builder);
+  sarif_invocation (sarif_builder &builder,
+		    const char * const *original_argv);
 
   void add_notification_for_ice (diagnostic_context &context,
 				 const diagnostic_info &diagnostic,
@@ -329,10 +330,8 @@  public:
    - GCC supports one-deep nesting of diagnostics (via auto_diagnostic_group),
      but we only capture location and message information from such nested
      diagnostics (e.g. we ignore fix-it hints on them)
-   - doesn't yet capture command-line arguments: would be run.invocations
-     property (SARIF v2.1.0 section 3.14.11), as invocation objects
-     (SARIF v2.1.0 section 3.20), but we'd want to capture the arguments to
-     toplev::main, and the response files.
+   - although we capture command-line arguments (section 3.20.2), we don't
+     yet capture response files.
    - doesn't capture secondary locations within a rich_location
      (perhaps we should use the "relatedLocations" property: SARIF v2.1.0
      section 3.27.22)
@@ -513,10 +512,20 @@  sarif_object::get_or_create_properties ()
 
 /* class sarif_invocation : public sarif_object.  */
 
-sarif_invocation::sarif_invocation (sarif_builder &builder)
+sarif_invocation::sarif_invocation (sarif_builder &builder,
+				    const char * const *original_argv)
 : m_notifications_arr (::make_unique<json::array> ()),
   m_success (true)
 {
+  // "arguments" property (SARIF v2.1.0 section 3.20.2)
+  if (original_argv)
+    {
+      auto arguments_arr = ::make_unique<json::array> ();
+      for (size_t i = 0; original_argv[i]; ++i)
+	arguments_arr->append_string (original_argv[i]);
+      set<json::array> ("arguments", std::move (arguments_arr));
+    }
+
   // "workingDirectory" property (SARIF v2.1.0 section 3.20.19)
   if (const char *pwd = getpwd ())
     set<sarif_artifact_location> ("workingDirectory",
@@ -752,7 +761,9 @@  sarif_builder::sarif_builder (diagnostic_context &context,
 			      const char *main_input_filename_,
 			      bool formatted)
 : m_context (context),
-  m_invocation_obj (::make_unique<sarif_invocation> (*this)),
+  m_invocation_obj
+    (::make_unique<sarif_invocation> (*this,
+				      context.get_original_argv ())),
   m_results_array (new json::array ()),
   m_cur_group_result (nullptr),
   m_seen_any_relative_paths (false),
diff --git a/gcc/diagnostic.cc b/gcc/diagnostic.cc
index aa8afd521fa2..c70c394f7ccd 100644
--- a/gcc/diagnostic.cc
+++ b/gcc/diagnostic.cc
@@ -261,6 +261,7 @@  diagnostic_context::initialize (int n_opts)
   m_includes_seen = nullptr;
   m_client_data_hooks = nullptr;
   m_diagrams.m_theme = nullptr;
+  m_original_argv = nullptr;
 
   enum diagnostic_text_art_charset text_art_charset
     = DIAGNOSTICS_TEXT_ART_CHARSET_EMOJI;
@@ -385,6 +386,9 @@  diagnostic_context::finish ()
 
   delete m_urlifier;
   m_urlifier = nullptr;
+
+  freeargv (m_original_argv);
+  m_original_argv = nullptr;
 }
 
 void
@@ -403,6 +407,19 @@  diagnostic_context::set_client_data_hooks (diagnostic_client_data_hooks *hooks)
   m_client_data_hooks = hooks;
 }
 
+void
+diagnostic_context::set_original_argv (unique_argv original_argv)
+{
+  /* Ideally we'd use a unique_argv for m_original_argv, but
+     diagnostic_context doesn't yet have a ctor/dtor pair.  */
+
+  // Ensure any old value is freed
+  freeargv (m_original_argv);
+
+  // Take ownership of the new value
+  m_original_argv = original_argv.release ();
+}
+
 void
 diagnostic_context::
 set_option_hooks (diagnostic_option_enabled_cb option_enabled_cb,
diff --git a/gcc/diagnostic.h b/gcc/diagnostic.h
index 84044b90dfcd..1d83879c50ef 100644
--- a/gcc/diagnostic.h
+++ b/gcc/diagnostic.h
@@ -21,6 +21,7 @@  along with GCC; see the file COPYING3.  If not see
 #ifndef GCC_DIAGNOSTIC_H
 #define GCC_DIAGNOSTIC_H
 
+#include "unique-argv.h"
 #include "rich-location.h"
 #include "pretty-print.h"
 #include "diagnostic-core.h"
@@ -391,6 +392,12 @@  public:
 
   void finish ();
 
+  void set_original_argv (unique_argv original_argv);
+  const char * const *get_original_argv ()
+  {
+    return const_cast<const char * const *> (m_original_argv);
+  }
+
   void set_set_locations_callback (set_locations_callback_t cb)
   {
     m_set_locations_cb = cb;
@@ -813,6 +820,9 @@  private:
     text_art::theme *m_theme;
 
   } m_diagrams;
+
+  /* Owned by the context.  */
+  char **m_original_argv;
 };
 
 inline void
diff --git a/gcc/jit/jit-playback.cc b/gcc/jit/jit-playback.cc
index 1b5445d61013..501d5700873e 100644
--- a/gcc/jit/jit-playback.cc
+++ b/gcc/jit/jit-playback.cc
@@ -2568,7 +2568,11 @@  compile ()
   if (get_logger ())
     for (unsigned i = 0; i < fake_args.length (); i++)
       get_logger ()->log ("argv[%i]: %s", i, fake_args[i]);
-  toplev.main (fake_args.length (),
+
+  /* Add a trailing null to argvec; this is not counted in argc.  */
+  fake_args.safe_push (nullptr);
+  toplev.main (/* The trailing null is not counted in argv.  */
+	       fake_args.length () - 1,
 	       const_cast <char **> (fake_args.address ()));
   exit_scope ("toplev::main");
 
diff --git a/gcc/testsuite/c-c++-common/diagnostic-format-sarif-file-1.c b/gcc/testsuite/c-c++-common/diagnostic-format-sarif-file-1.c
index 0a3778323792..c9ad0d238195 100644
--- a/gcc/testsuite/c-c++-common/diagnostic-format-sarif-file-1.c
+++ b/gcc/testsuite/c-c++-common/diagnostic-format-sarif-file-1.c
@@ -32,6 +32,11 @@ 
          { dg-final { scan-sarif-file "\"informationUri\": \"" } }
 
      { dg-final { scan-sarif-file "\"invocations\": \\\[" } }
+       3.20: "invocation" object:
+
+       3.20.2 invocation "arguments" property:
+       { dg-final { scan-sarif-file {"arguments": \[} } }
+
        { dg-final { scan-sarif-file {"workingDirectory": } } }
        { dg-final { scan-sarif-file "\"toolExecutionNotifications\": \\\[\\\]" } }
        { dg-final { scan-sarif-file "\"executionSuccessful\": true" } }
diff --git a/gcc/toplev.cc b/gcc/toplev.cc
index d9e8b34ae7ca..7f19d5c52bd9 100644
--- a/gcc/toplev.cc
+++ b/gcc/toplev.cc
@@ -93,6 +93,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "ipa-param-manipulation.h"
 #include "dbgcnt.h"
 #include "gcc-urlifier.h"
+#include "unique-argv.h"
 
 #include "selftest.h"
 
@@ -100,7 +101,7 @@  along with GCC; see the file COPYING3.  If not see
 #include <isl/version.h>
 #endif
 
-static void general_init (const char *, bool);
+static void general_init (const char *, bool, unique_argv original_argv);
 static void backend_init (void);
 static int lang_dependent_init (const char *);
 static void init_asm_output (const char *);
@@ -1000,7 +1001,7 @@  internal_error_function (diagnostic_context *, const char *, va_list *)
    options are parsed.  Signal handlers, internationalization etc.
    ARGV0 is main's argv[0].  */
 static void
-general_init (const char *argv0, bool init_signals)
+general_init (const char *argv0, bool init_signals, unique_argv original_argv)
 {
   const char *p;
 
@@ -1028,6 +1029,8 @@  general_init (const char *argv0, bool init_signals)
      override it later.  */
   tree_diagnostics_defaults (global_dc);
 
+  global_dc->set_original_argv (std::move (original_argv));
+
   global_dc->m_source_printing.enabled
     = global_options_init.x_flag_diagnostics_show_caret;
   global_dc->m_source_printing.show_event_links_p
@@ -2241,10 +2244,14 @@  toplev::main (int argc, char **argv)
      Increase stack size limits if possible.  */
   stack_limit_increase (64 * 1024 * 1024);
 
+  /* Stash a copy of the original argv before expansion
+     for use by SARIF output.  */
+  unique_argv original_argv (dupargv (argv));
+
   expandargv (&argc, &argv);
 
   /* Initialization of GCC's environment, and diagnostics.  */
-  general_init (argv[0], m_init_signals);
+  general_init (argv[0], m_init_signals, std::move (original_argv));
 
   /* One-off initialization of options that does not need to be
      repeated when options are added for particular functions.  */
diff --git a/gcc/unique-argv.h b/gcc/unique-argv.h
new file mode 100644
index 000000000000..41cabac6b762
--- /dev/null
+++ b/gcc/unique-argv.h
@@ -0,0 +1,67 @@ 
+/* C++11 wrapper around libiberty's argv.c
+   Copyright (C) 2024 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_UNIQUE_ARGV_H
+#define GCC_UNIQUE_ARGV_H
+
+/* C++11 wrapper around libiberty's argv.c, with
+   ownership of the underlying array and strings.  */
+
+struct unique_argv
+{
+  /* Take ownership of argv.  */
+  unique_argv (char **argv)
+  : m_argv (argv)
+  {
+  }
+
+  ~unique_argv ()
+  {
+    freeargv (m_argv);
+  }
+
+  unique_argv (const unique_argv &other) = delete;
+  unique_argv &operator= (const unique_argv &other) = delete;
+
+  unique_argv (unique_argv &&other)
+  : m_argv (other.m_argv)
+  {
+    other.m_argv = nullptr;
+  }
+
+  unique_argv &operator= (unique_argv &&other)
+  {
+    freeargv (m_argv);
+    m_argv = other.m_argv;
+    other.m_argv = nullptr;
+    return *this;
+  }
+
+  char **release ()
+  {
+    char **result = m_argv;
+    m_argv = nullptr;
+    return result;
+  }
+
+  char **m_argv;
+};
+
+#endif /* ! GCC_UNIQUE_ARGV_H */