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,
- 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)
/* 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",
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),
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;
delete m_urlifier;
m_urlifier = nullptr;
+
+ freeargv (m_original_argv);
+ m_original_argv = nullptr;
}
void
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,
#ifndef GCC_DIAGNOSTIC_H
#define GCC_DIAGNOSTIC_H
+#include "unique-argv.h"
#include "rich-location.h"
#include "pretty-print.h"
#include "diagnostic-core.h"
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;
text_art::theme *m_theme;
} m_diagrams;
+
+ /* Owned by the context. */
+ char **m_original_argv;
};
inline void
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");
{ 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" } }
#include "ipa-param-manipulation.h"
#include "dbgcnt.h"
#include "gcc-urlifier.h"
+#include "unique-argv.h"
#include "selftest.h"
#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 *);
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;
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
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. */
--- /dev/null
+/* 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 */