https://gcc.gnu.org/g:29ee588129bf07d3adb62b6c2c189ba932c00ff4
commit r15-2289-g29ee588129bf07d3adb62b6c2c189ba932c00ff4 Author: David Malcolm <dmalc...@redhat.com> Date: Wed Jul 24 18:07:55 2024 -0400 diagnostics: SARIF output: add "arguments" property (§3.20.2) 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 <dmalc...@redhat.com> Diff: --- gcc/diagnostic-format-sarif.cc | 25 +++++--- gcc/diagnostic.cc | 17 ++++++ gcc/diagnostic.h | 10 ++++ gcc/jit/jit-playback.cc | 6 +- .../c-c++-common/diagnostic-format-sarif-file-1.c | 5 ++ gcc/toplev.cc | 13 ++++- gcc/unique-argv.h | 67 ++++++++++++++++++++++ 7 files changed, 132 insertions(+), 11 deletions(-) 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 <dmalc...@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 */