aboutsummaryrefslogtreecommitdiff
path: root/gcc/diagnostic-format-sarif.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/diagnostic-format-sarif.cc')
-rw-r--r--gcc/diagnostic-format-sarif.cc1044
1 files changed, 789 insertions, 255 deletions
diff --git a/gcc/diagnostic-format-sarif.cc b/gcc/diagnostic-format-sarif.cc
index 8dbc91e..d20ca86 100644
--- a/gcc/diagnostic-format-sarif.cc
+++ b/gcc/diagnostic-format-sarif.cc
@@ -28,6 +28,8 @@ along with GCC; see the file COPYING3. If not see
#include "coretypes.h"
#include "diagnostic.h"
#include "diagnostic-metadata.h"
+#include "diagnostic-digraphs.h"
+#include "diagnostic-state-graphs.h"
#include "diagnostic-path.h"
#include "diagnostic-format.h"
#include "diagnostic-buffer.h"
@@ -41,7 +43,6 @@ along with GCC; see the file COPYING3. If not see
#include "diagnostic-format-text.h"
#include "ordered-hash-map.h"
#include "sbitmap.h"
-#include "make-unique.h"
#include "selftest.h"
#include "selftest-diagnostic.h"
#include "selftest-diagnostic-show-locus.h"
@@ -51,6 +52,53 @@ along with GCC; see the file COPYING3. If not see
#include "pretty-print-urlifier.h"
#include "demangle.h"
#include "backtrace.h"
+#include "xml.h"
+
+/* A json::array where the values are "unique" as per
+ SARIF v2.1.0 section 3.7.3 ("Array properties with unique values"). */
+
+template <typename JsonElementType>
+class sarif_array_of_unique : public json::array
+{
+ public:
+ size_t append_uniquely (std::unique_ptr<JsonElementType> val)
+ {
+ /* This should be O(log(n)) due to the std::map. */
+ auto search = m_index_by_value.find (val.get ());
+ if (search != m_index_by_value.end())
+ return (*search).second;
+
+ const size_t insertion_idx = size ();
+ m_index_by_value.insert ({val.get (), insertion_idx});
+ append (std::move (val));
+ return insertion_idx;
+ }
+
+ /* For ease of reading output, add "index": idx to all
+ objects in the array.
+ We don't do this until we've added everything, since
+ the "index" property would otherwise confuse the
+ comparison against new elements. */
+ void add_explicit_index_values ()
+ {
+ for (size_t idx = 0; idx < length (); ++idx)
+ if (json::object *obj = get (idx)->dyn_cast_object ())
+ obj->set_integer ("index", idx);
+ }
+
+private:
+ struct comparator_t {
+ bool operator () (const json::value *a, const json::value *b) const
+ {
+ gcc_assert (a);
+ gcc_assert (b);
+ return json::value::compare (*a, *b) < 0;
+ }
+ };
+
+ // json::value * here is borrowed from m_elements
+ std::map<json::value *, int, comparator_t> m_index_by_value;
+};
/* Forward decls. */
class sarif_builder;
@@ -158,7 +206,7 @@ make_date_time_string_for_current_time ()
"%02i:%02i:%02iZ"),
tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec);
- return ::make_unique<json::string> (buf);
+ return std::make_unique<json::string> (buf);
}
/* Subclass of sarif_object for SARIF "invocation" objects
@@ -447,6 +495,13 @@ class sarif_physical_location : public sarif_object {};
class sarif_region : public sarif_object {};
+/* Subclass of sarif_object for SARIF "logicalLocation" objects
+ (SARIF v2.1.0 section 3.33). */
+
+class sarif_logical_location : public sarif_object
+{
+};
+
/* Subclass of sarif_object for SARIF "locationRelationship" objects
(SARIF v2.1.0 section 3.34). */
@@ -635,6 +690,18 @@ private:
std::vector<std::unique_ptr<sarif_result>> m_results;
};
+/* Classes for abstracting away JSON vs other serialization formats. */
+
+// class sarif_serialization_format_json : public sarif_serialization_format
+
+void
+sarif_serialization_format_json::write_to_file (FILE *outf,
+ const json::value &top)
+{
+ top.dump (outf, m_formatted);
+ fprintf (outf, "\n");
+}
+
/* A class for managing SARIF output (for -fdiagnostics-format=sarif-stderr
and -fdiagnostics-format=sarif-file).
@@ -687,9 +754,8 @@ public:
sarif_builder (diagnostic_context &context,
pretty_printer &printer,
const line_maps *line_maps,
- const char *main_input_filename_,
- bool formatted,
- enum sarif_version version);
+ std::unique_ptr<sarif_serialization_format> serialization_format,
+ const sarif_generation_options &sarif_gen_opts);
~sarif_builder ();
void set_printer (pretty_printer &printer)
@@ -697,12 +763,24 @@ public:
m_printer = &printer;
}
+ const logical_location_manager *
+ get_logical_location_manager () const
+ {
+ return m_logical_loc_mgr;
+ }
+
+ void
+ set_main_input_filename (const char *name);
+
void on_report_diagnostic (const diagnostic_info &diagnostic,
diagnostic_t orig_diag_kind,
diagnostic_sarif_format_buffer *buffer);
void emit_diagram (const diagnostic_diagram &diagram);
void end_group ();
+ void
+ report_global_digraph (const diagnostics::digraphs::lazy_digraph &);
+
std::unique_ptr<sarif_result> take_current_result ()
{
return std::move (m_cur_group_result);
@@ -716,9 +794,9 @@ public:
const diagnostic_info &diagnostic,
enum diagnostic_artifact_role role);
std::unique_ptr<sarif_location>
- make_location_object (sarif_location_manager &loc_mgr,
+ make_location_object (sarif_location_manager *loc_mgr,
const rich_location &rich_loc,
- const logical_location *logical_loc,
+ logical_location logical_loc,
enum diagnostic_artifact_role role);
std::unique_ptr<sarif_location>
make_location_object (sarif_location_manager &loc_mgr,
@@ -743,7 +821,7 @@ public:
diagnostic_context &get_context () const { return m_context; }
pretty_printer *get_printer () const { return m_printer; }
token_printer &get_token_printer () { return m_token_printer; }
- enum sarif_version get_version () const { return m_version; }
+ enum sarif_version get_version () const { return m_sarif_gen_opts.m_version; }
size_t num_results () const { return m_results_array->size (); }
sarif_result &get_result (size_t idx)
@@ -753,6 +831,11 @@ public:
return *static_cast<sarif_result *> (element);
}
+ const sarif_generation_options &get_opts () const { return m_sarif_gen_opts; }
+
+ std::unique_ptr<sarif_logical_location>
+ make_minimal_sarif_logical_location (logical_location);
+
private:
class sarif_token_printer : public token_printer
{
@@ -777,7 +860,7 @@ private:
location_t where);
void
set_any_logical_locs_arr (sarif_location &location_obj,
- const logical_location *logical_loc);
+ logical_location logical_loc);
std::unique_ptr<sarif_location>
make_location_object (sarif_location_manager &loc_mgr,
const diagnostic_event &event,
@@ -810,6 +893,10 @@ private:
const content_renderer *snippet_renderer) const;
std::unique_ptr<sarif_region>
make_region_object_for_hint (const fixit_hint &hint) const;
+
+ int
+ ensure_sarif_logical_location_for (logical_location k);
+
std::unique_ptr<sarif_multiformat_message_string>
make_multiformat_message_string (const char *msg) const;
std::unique_ptr<sarif_log>
@@ -865,7 +952,8 @@ private:
pretty_printer *m_printer;
const line_maps *m_line_maps;
sarif_token_printer m_token_printer;
- enum sarif_version m_version;
+
+ const logical_location_manager *m_logical_loc_mgr;
/* The JSON object for the invocation object. */
std::unique_ptr<sarif_invocation> m_invocation_obj;
@@ -889,9 +977,14 @@ private:
/* The set of all CWE IDs we've seen, if any. */
hash_set <int_hash <int, 0, 1> > m_cwe_id_set;
+ std::unique_ptr<sarif_array_of_unique<sarif_logical_location>> m_cached_logical_locs;
+
+ std::unique_ptr<sarif_array_of_unique<sarif_graph>> m_run_graphs;
+
int m_tabstop;
- bool m_formatted;
+ std::unique_ptr<sarif_serialization_format> m_serialization_format;
+ const sarif_generation_options m_sarif_gen_opts;
unsigned m_next_result_idx;
sarif_code_flow *m_current_code_flow;
@@ -918,13 +1011,13 @@ sarif_object::get_or_create_properties ()
sarif_invocation::sarif_invocation (sarif_builder &builder,
const char * const *original_argv)
-: m_notifications_arr (::make_unique<json::array> ()),
+: m_notifications_arr (std::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> ();
+ auto arguments_arr = std::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));
@@ -951,9 +1044,9 @@ sarif_invocation::add_notification_for_ice (const diagnostic_info &diagnostic,
m_success = false;
auto notification
- = ::make_unique<sarif_ice_notification> (diagnostic,
- builder,
- std::move (backtrace));
+ = std::make_unique<sarif_ice_notification> (diagnostic,
+ builder,
+ std::move (backtrace));
/* Support for related locations within a notification was added
in SARIF 2.2; see https://github.com/oasis-tcs/sarif-spec/issues/540 */
@@ -1068,7 +1161,7 @@ sarif_artifact::populate_roles ()
{
if (bitmap_empty_p (m_roles))
return;
- auto roles_arr (::make_unique<json::array> ());
+ auto roles_arr (std::make_unique<json::array> ());
for (int i = 0; i < (int)diagnostic_artifact_role::NUM_ROLES; i++)
if (bitmap_bit_p (m_roles, i))
{
@@ -1219,7 +1312,8 @@ sarif_result::on_nested_diagnostic (const diagnostic_info &diagnostic,
sometimes these will related to current_function_decl, but
often they won't. */
auto location_obj
- = builder.make_location_object (*this, *diagnostic.richloc, nullptr,
+ = builder.make_location_object (this, *diagnostic.richloc,
+ logical_location (),
diagnostic_artifact_role::result_file);
auto message_obj
= builder.make_message_object (pp_formatted_text (builder.get_printer ()));
@@ -1245,7 +1339,7 @@ void
sarif_result::on_diagram (const diagnostic_diagram &diagram,
sarif_builder &builder)
{
- auto location_obj = ::make_unique<sarif_location> ();
+ auto location_obj = std::make_unique<sarif_location> ();
auto message_obj = builder.make_message_object_for_diagram (diagram);
location_obj->set<sarif_message> ("message", std::move (message_obj));
@@ -1344,7 +1438,7 @@ sarif_location::lazily_add_relationship_object (sarif_location &target,
/* No existing locationRelationship from THIS to TARGET; make one,
record it, and add it to the "relationships" array. */
auto relationship_obj
- = ::make_unique<sarif_location_relationship> (target, loc_mgr);
+ = std::make_unique<sarif_location_relationship> (target, loc_mgr);
sarif_location_relationship *relationship = relationship_obj.get ();
auto kv
= std::pair<sarif_location *,
@@ -1472,7 +1566,7 @@ sarif_code_flow::sarif_code_flow (sarif_result &parent,
m_idx_within_parent (idx_within_parent)
{
/* "threadFlows" property (SARIF v2.1.0 section 3.36.3). */
- auto thread_flows_arr = ::make_unique<json::array> ();
+ auto thread_flows_arr = std::make_unique<json::array> ();
m_thread_flows_arr = thread_flows_arr.get (); // borrowed
set<json::array> ("threadFlows", std::move (thread_flows_arr));
}
@@ -1487,7 +1581,7 @@ sarif_code_flow::get_or_append_thread_flow (const diagnostic_thread &thread,
unsigned next_thread_flow_idx = m_thread_flows_arr->size ();
auto thread_flow_obj
- = ::make_unique<sarif_thread_flow> (*this, thread, next_thread_flow_idx);
+ = std::make_unique<sarif_thread_flow> (*this, thread, next_thread_flow_idx);
m_thread_id_map.put (thread_id, thread_flow_obj.get ()); // borrowed
sarif_thread_flow *result = thread_flow_obj.get ();
m_thread_flows_arr->append<sarif_thread_flow> (std::move (thread_flow_obj));
@@ -1559,39 +1653,36 @@ sarif_thread_flow::add_location ()
sarif_builder::sarif_builder (diagnostic_context &context,
pretty_printer &printer,
const line_maps *line_maps,
- const char *main_input_filename_,
- bool formatted,
- enum sarif_version version)
+ std::unique_ptr<sarif_serialization_format> serialization_format,
+ const sarif_generation_options &sarif_gen_opts)
: m_context (context),
m_printer (&printer),
m_line_maps (line_maps),
m_token_printer (*this),
- m_version (version),
+ m_logical_loc_mgr (nullptr),
m_invocation_obj
- (::make_unique<sarif_invocation> (*this,
- context.get_original_argv ())),
+ (std::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_rule_id_set (),
m_rules_arr (new json::array ()),
+ m_cached_logical_locs
+ (std::make_unique<sarif_array_of_unique<sarif_logical_location>> ()),
+ m_run_graphs
+ (std::make_unique<sarif_array_of_unique<sarif_graph>> ()),
m_tabstop (context.m_tabstop),
- m_formatted (formatted),
+ m_serialization_format (std::move (serialization_format)),
+ m_sarif_gen_opts (sarif_gen_opts),
m_next_result_idx (0),
m_current_code_flow (nullptr)
{
gcc_assert (m_line_maps);
+ gcc_assert (m_serialization_format);
- /* Mark MAIN_INPUT_FILENAME_ as the artifact that the tool was
- instructed to scan.
- Only quote the contents if it gets referenced by physical locations,
- since otherwise the "no diagnostics" case would quote the main input
- file, and doing so noticeably bloated the output seen in analyzer
- integration testing (build directory went from 20G -> 21G). */
- if (main_input_filename_)
- get_or_create_artifact (main_input_filename_,
- diagnostic_artifact_role::analysis_target,
- false);
+ if (auto client_data_hooks = context.get_client_data_hooks ())
+ m_logical_loc_mgr = client_data_hooks->get_logical_location_manager ();
}
sarif_builder::~sarif_builder ()
@@ -1640,12 +1731,12 @@ bt_callback (void *data, uintptr_t pc, const char *filename, int lineno,
/* If we don't have any useful information, don't print
anything. */
- if (filename == NULL && function == NULL)
+ if (filename == nullptr && function == nullptr)
return 0;
/* Skip functions in diagnostic.cc or diagnostic-global-context.cc. */
if (closure->m_frames_arr->size () == 0
- && filename != NULL
+ && filename != nullptr
&& (strcmp (lbasename (filename), "diagnostic.cc") == 0
|| strcmp (lbasename (filename),
"diagnostic-global-context.cc") == 0))
@@ -1659,13 +1750,13 @@ bt_callback (void *data, uintptr_t pc, const char *filename, int lineno,
return 1;
}
- char *alc = NULL;
- if (function != NULL)
+ char *alc = nullptr;
+ if (function != nullptr)
{
char *str = cplus_demangle_v3 (function,
(DMGL_VERBOSE | DMGL_ANSI
| DMGL_GNU_V3 | DMGL_PARAMS));
- if (str != NULL)
+ if (str != nullptr)
{
alc = str;
function = str;
@@ -1677,7 +1768,7 @@ bt_callback (void *data, uintptr_t pc, const char *filename, int lineno,
if (strncmp (function, bt_stop[i], len) == 0
&& (function[len] == '\0' || function[len] == '('))
{
- if (alc != NULL)
+ if (alc != nullptr)
free (alc);
/* Returning a non-zero value stops the backtrace. */
return 1;
@@ -1685,7 +1776,7 @@ bt_callback (void *data, uintptr_t pc, const char *filename, int lineno,
}
}
- auto frame_obj = ::make_unique<json::object> ();
+ auto frame_obj = std::make_unique<json::object> ();
/* I tried using sarifStack and sarifStackFrame for this
but it's not a good fit e.g. PC information. */
@@ -1699,7 +1790,7 @@ bt_callback (void *data, uintptr_t pc, const char *filename, int lineno,
frame_obj->set_integer ("lineno", lineno);
closure->m_frames_arr->append (std::move (frame_obj));
- if (alc != NULL)
+ if (alc != nullptr)
free (alc);
return 0;
@@ -1711,7 +1802,7 @@ bt_callback (void *data, uintptr_t pc, const char *filename, int lineno,
std::unique_ptr<json::object>
sarif_builder::make_stack_from_backtrace ()
{
- auto frames_arr = ::make_unique<json::array> ();
+ auto frames_arr = std::make_unique<json::array> ();
backtrace_state *state = nullptr;
state = backtrace_create_state (nullptr, 0, nullptr, nullptr);
@@ -1724,11 +1815,25 @@ sarif_builder::make_stack_from_backtrace ()
if (frames_arr->size () == 0)
return nullptr;
- auto stack = ::make_unique<json::object> ();
+ auto stack = std::make_unique<json::object> ();
stack->set ("frames", std::move (frames_arr));
return stack;
}
+void
+sarif_builder::set_main_input_filename (const char *name)
+{
+ /* Mark NAME as the artifact that the tool was instructed to scan.
+ Only quote the contents if it gets referenced by physical locations,
+ since otherwise the "no diagnostics" case would quote the main input
+ file, and doing so noticeably bloated the output seen in analyzer
+ integration testing (build directory went from 20G -> 21G). */
+ if (name)
+ get_or_create_artifact (name,
+ diagnostic_artifact_role::analysis_target,
+ false);
+}
+
/* Implementation of "on_report_diagnostic" for SARIF output. */
void
@@ -1799,6 +1904,17 @@ sarif_builder::end_group ()
}
}
+void
+sarif_builder::
+report_global_digraph (const diagnostics::digraphs::lazy_digraph &ldg)
+{
+ auto &dg = ldg.get_or_create_digraph ();
+
+ /* Presumably the location manager must be nullptr; see
+ https://github.com/oasis-tcs/sarif-spec/issues/712 */
+ m_run_graphs->append (make_sarif_graph (dg, this, nullptr));
+}
+
/* Create a top-level object, and add it to all the results
(and other entities) we've seen so far, moving ownership
to the object. */
@@ -1822,8 +1938,7 @@ void
sarif_builder::flush_to_file (FILE *outf)
{
std::unique_ptr<sarif_log> top = flush_to_object ();
- top->dump (outf, m_formatted);
- fprintf (outf, "\n");
+ m_serialization_format->write_to_file (outf, *top);
}
/* Attempt to convert DIAG_KIND to a suitable value for the "level"
@@ -1873,7 +1988,7 @@ sarif_builder::make_result_object (const diagnostic_info &diagnostic,
diagnostic_t orig_diag_kind,
unsigned idx_within_parent)
{
- auto result_obj = ::make_unique<sarif_result> (idx_within_parent);
+ auto result_obj = std::make_unique<sarif_result> (idx_within_parent);
/* "ruleId" property (SARIF v2.1.0 section 3.27.5). */
/* Ideally we'd have an option_name for these. */
@@ -1914,7 +2029,7 @@ sarif_builder::make_result_object (const diagnostic_info &diagnostic,
/* "taxa" property (SARIF v2.1.0 section 3.27.8). */
if (int cwe_id = diagnostic.metadata->get_cwe ())
{
- auto taxa_arr = ::make_unique<json::array> ();
+ auto taxa_arr = std::make_unique<json::array> ();
taxa_arr->append<sarif_reporting_descriptor_reference>
(make_reporting_descriptor_reference_object_for_cwe_id (cwe_id));
result_obj->set<json::array> ("taxa", std::move (taxa_arr));
@@ -1945,7 +2060,7 @@ sarif_builder::make_result_object (const diagnostic_info &diagnostic,
/* "codeFlows" property (SARIF v2.1.0 section 3.27.18). */
if (const diagnostic_path *path = diagnostic.richloc->get_path ())
{
- auto code_flows_arr = ::make_unique<json::array> ();
+ auto code_flows_arr = std::make_unique<json::array> ();
const unsigned code_flow_index = 0;
code_flows_arr->append<sarif_code_flow>
(make_code_flow_object (*result_obj.get (),
@@ -1954,6 +2069,19 @@ sarif_builder::make_result_object (const diagnostic_info &diagnostic,
result_obj->set<json::array> ("codeFlows", std::move (code_flows_arr));
}
+ // "graphs" property (SARIF v2.1.0 section 3.27.19). */
+ if (diagnostic.metadata)
+ if (auto ldg = diagnostic.metadata->get_lazy_digraphs ())
+ {
+ auto &digraphs = ldg->get_or_create_digraphs ();
+ auto graphs_arr = std::make_unique<json::array> ();
+ for (auto &iter : digraphs)
+ graphs_arr->append (make_sarif_graph (*iter, this,
+ result_obj.get ()));
+ if (graphs_arr->size () > 0)
+ result_obj->set<json::array> ("graphs", std::move (graphs_arr));
+ }
+
/* The "relatedLocations" property (SARIF v2.1.0 section 3.27.22) is
set up later, if any nested diagnostics occur within this diagnostic
group. */
@@ -1962,7 +2090,7 @@ sarif_builder::make_result_object (const diagnostic_info &diagnostic,
const rich_location *richloc = diagnostic.richloc;
if (richloc->get_num_fixit_hints ())
{
- auto fix_arr = ::make_unique<json::array> ();
+ auto fix_arr = std::make_unique<json::array> ();
fix_arr->append<sarif_fix> (make_fix_object (*richloc));
result_obj->set<json::array> ("fixes", std::move (fix_arr));
}
@@ -1979,7 +2107,7 @@ make_reporting_descriptor_object_for_warning (const diagnostic_info &diagnostic,
diagnostic_t /*orig_diag_kind*/,
const char *option_text)
{
- auto reporting_desc = ::make_unique<sarif_reporting_descriptor> ();
+ auto reporting_desc = std::make_unique<sarif_reporting_descriptor> ();
/* "id" property (SARIF v2.1.0 section 3.49.3). */
reporting_desc->set_string ("id", option_text);
@@ -2003,7 +2131,7 @@ make_reporting_descriptor_object_for_warning (const diagnostic_info &diagnostic,
std::unique_ptr<sarif_reporting_descriptor>
sarif_builder::make_reporting_descriptor_object_for_cwe_id (int cwe_id) const
{
- auto reporting_desc = ::make_unique<sarif_reporting_descriptor> ();
+ auto reporting_desc = std::make_unique<sarif_reporting_descriptor> ();
/* "id" property (SARIF v2.1.0 section 3.49.3). */
{
@@ -2030,7 +2158,7 @@ std::unique_ptr<sarif_reporting_descriptor_reference>
sarif_builder::
make_reporting_descriptor_reference_object_for_cwe_id (int cwe_id)
{
- auto desc_ref_obj = ::make_unique<sarif_reporting_descriptor_reference> ();
+ auto desc_ref_obj = std::make_unique<sarif_reporting_descriptor_reference> ();
/* "id" property (SARIF v2.1.0 section 3.52.4). */
{
@@ -2057,7 +2185,7 @@ std::unique_ptr<sarif_tool_component_reference>
sarif_builder::
make_tool_component_reference_object_for_cwe () const
{
- auto comp_ref_obj = ::make_unique<sarif_tool_component_reference> ();
+ auto comp_ref_obj = std::make_unique<sarif_tool_component_reference> ();
/* "name" property (SARIF v2.1.0 section 3.54.3). */
comp_ref_obj->set_string ("name", "cwe");
@@ -2075,13 +2203,13 @@ sarif_builder::make_locations_arr (sarif_location_manager &loc_mgr,
const diagnostic_info &diagnostic,
enum diagnostic_artifact_role role)
{
- auto locations_arr = ::make_unique<json::array> ();
- const logical_location *logical_loc = nullptr;
+ auto locations_arr = std::make_unique<json::array> ();
+ logical_location logical_loc;
if (auto client_data_hooks = m_context.get_client_data_hooks ())
logical_loc = client_data_hooks->get_current_logical_location ();
auto location_obj
- = make_location_object (loc_mgr, *diagnostic.richloc, logical_loc, role);
+ = make_location_object (&loc_mgr, *diagnostic.richloc, logical_loc, role);
/* Don't add entirely empty location objects to the array. */
if (!location_obj->is_empty ())
locations_arr->append<sarif_location> (std::move (location_obj));
@@ -2090,18 +2218,24 @@ sarif_builder::make_locations_arr (sarif_location_manager &loc_mgr,
}
/* If LOGICAL_LOC is non-null, use it to create a "logicalLocations" property
- within LOCATION_OBJ (SARIF v2.1.0 section 3.28.4). */
+ within LOCATION_OBJ (SARIF v2.1.0 section 3.28.4) with a minimal logical
+ location object referencing theRuns.logicalLocations (3.33.3). */
void
sarif_builder::
set_any_logical_locs_arr (sarif_location &location_obj,
- const logical_location *logical_loc)
+ logical_location logical_loc)
{
if (!logical_loc)
return;
- auto location_locs_arr = ::make_unique<json::array> ();
+ gcc_assert (m_logical_loc_mgr);
+ auto location_locs_arr = std::make_unique<json::array> ();
+
+ auto logical_loc_obj = make_minimal_sarif_logical_location (logical_loc);
+
location_locs_arr->append<sarif_logical_location>
- (make_sarif_logical_location_object (*logical_loc));
+ (std::move (logical_loc_obj));
+
location_obj.set<json::array> ("logicalLocations",
std::move (location_locs_arr));
}
@@ -2109,12 +2243,14 @@ set_any_logical_locs_arr (sarif_location &location_obj,
/* Make a "location" object (SARIF v2.1.0 section 3.28) for RICH_LOC
and LOGICAL_LOC.
Use LOC_MGR for any locations that need "id" values, and for
- any worklist items. */
+ any worklist items.
+ Note that we might not always have a LOC_MGR; see
+ https://github.com/oasis-tcs/sarif-spec/issues/712 */
std::unique_ptr<sarif_location>
-sarif_builder::make_location_object (sarif_location_manager &loc_mgr,
+sarif_builder::make_location_object (sarif_location_manager *loc_mgr,
const rich_location &rich_loc,
- const logical_location *logical_loc,
+ logical_location logical_loc,
enum diagnostic_artifact_role role)
{
class escape_nonascii_renderer : public content_renderer
@@ -2159,7 +2295,7 @@ sarif_builder::make_location_object (sarif_location_manager &loc_mgr,
} the_renderer (rich_loc,
m_context.get_escape_format ());
- auto location_obj = ::make_unique<sarif_location> ();
+ auto location_obj = std::make_unique<sarif_location> ();
/* Get primary loc from RICH_LOC. */
location_t loc = rich_loc.get_loc ();
@@ -2197,7 +2333,7 @@ sarif_builder::make_location_object (sarif_location_manager &loc_mgr,
if (region)
{
if (!annotations_arr)
- annotations_arr = ::make_unique<json::array> ();
+ annotations_arr = std::make_unique<json::array> ();
region->set<sarif_message>
("message", make_message_object (text.get ()));
annotations_arr->append<sarif_region> (std::move (region));
@@ -2208,8 +2344,8 @@ sarif_builder::make_location_object (sarif_location_manager &loc_mgr,
/* Add related locations for any secondary locations in RICH_LOC
that don't have labels (and thus aren't added to "annotations"). */
- if (i > 0 && !handled)
- loc_mgr.add_relationship_to_worklist
+ if (loc_mgr && i > 0 && !handled)
+ loc_mgr->add_relationship_to_worklist
(*location_obj.get (),
sarif_location_manager::worklist_item::kind::unlabelled_secondary_location,
range->m_loc);
@@ -2220,7 +2356,8 @@ sarif_builder::make_location_object (sarif_location_manager &loc_mgr,
std::move (annotations_arr));
}
- add_any_include_chain (loc_mgr, *location_obj.get (), loc);
+ if (loc_mgr)
+ add_any_include_chain (*loc_mgr, *location_obj.get (), loc);
/* A flag for hinting that the diagnostic involves issues at the
level of character encodings (such as homoglyphs, or misleading
@@ -2277,7 +2414,7 @@ sarif_builder::make_location_object (sarif_location_manager &loc_mgr,
location_t loc,
enum diagnostic_artifact_role role)
{
- auto location_obj = ::make_unique<sarif_location> ();
+ auto location_obj = std::make_unique<sarif_location> ();
/* "physicalLocation" property (SARIF v2.1.0 section 3.28.3). */
if (auto phs_loc_obj
@@ -2298,7 +2435,7 @@ sarif_builder::make_location_object (sarif_location_manager &loc_mgr,
const diagnostic_event &event,
enum diagnostic_artifact_role role)
{
- auto location_obj = ::make_unique<sarif_location> ();
+ auto location_obj = std::make_unique<sarif_location> ();
/* "physicalLocation" property (SARIF v2.1.0 section 3.28.3). */
location_t loc = event.get_location ();
@@ -2308,7 +2445,7 @@ sarif_builder::make_location_object (sarif_location_manager &loc_mgr,
std::move (phs_loc_obj));
/* "logicalLocations" property (SARIF v2.1.0 section 3.28.4). */
- const logical_location *logical_loc = event.get_logical_location ();
+ logical_location logical_loc = event.get_logical_location ();
set_any_logical_locs_arr (*location_obj, logical_loc);
/* "message" property (SARIF v2.1.0 section 3.28.5). */
@@ -2342,7 +2479,7 @@ maybe_make_physical_location_object (location_t loc,
if (loc <= BUILTINS_LOCATION || LOCATION_FILE (loc) == nullptr)
return nullptr;
- auto phys_loc_obj = ::make_unique<sarif_physical_location> ();
+ auto phys_loc_obj = std::make_unique<sarif_physical_location> ();
/* "artifactLocation" property (SARIF v2.1.0 section 3.29.3). */
phys_loc_obj->set<sarif_artifact_location>
@@ -2386,7 +2523,7 @@ sarif_builder::make_artifact_location_object (location_t loc)
std::unique_ptr<sarif_artifact_location>
sarif_builder::make_artifact_location_object (const char *filename)
{
- auto artifact_loc_obj = ::make_unique<sarif_artifact_location> ();
+ auto artifact_loc_obj = std::make_unique<sarif_artifact_location> ();
/* "uri" property (SARIF v2.1.0 section 3.4.3). */
artifact_loc_obj->set_string ("uri", filename);
@@ -2432,7 +2569,7 @@ make_pwd_uri_str ()
std::unique_ptr<sarif_artifact_location>
sarif_builder::make_artifact_location_object_for_pwd () const
{
- auto artifact_loc_obj = ::make_unique<sarif_artifact_location> ();
+ auto artifact_loc_obj = std::make_unique<sarif_artifact_location> ();
/* "uri" property (SARIF v2.1.0 section 3.4.3). */
if (char *pwd = make_pwd_uri_str ())
@@ -2492,7 +2629,7 @@ sarif_builder::maybe_make_region_object (location_t loc,
if (exploc_start.line <= 0)
return nullptr;
- auto region_obj = ::make_unique<sarif_region> ();
+ auto region_obj = std::make_unique<sarif_region> ();
/* "startLine" property (SARIF v2.1.0 section 3.30.5) */
region_obj->set_integer ("startLine", exploc_start.line);
@@ -2569,7 +2706,7 @@ maybe_make_region_object_for_context (location_t loc,
if (exploc_start.line <= 0)
return nullptr;
- auto region_obj = ::make_unique<sarif_region> ();
+ auto region_obj = std::make_unique<sarif_region> ();
/* "startLine" property (SARIF v2.1.0 section 3.30.5) */
region_obj->set_integer ("startLine", exploc_start.line);
@@ -2603,7 +2740,7 @@ sarif_builder::make_region_object_for_hint (const fixit_hint &hint) const
expanded_location exploc_start = expand_location (start_loc);
expanded_location exploc_next = expand_location (next_loc);
- auto region_obj = ::make_unique<sarif_region> ();
+ auto region_obj = std::make_unique<sarif_region> ();
/* "startLine" property (SARIF v2.1.0 section 3.30.5) */
region_obj->set_integer ("startLine", exploc_start.line);
@@ -2635,54 +2772,276 @@ maybe_get_sarif_kind (enum logical_location_kind kind)
{
default:
gcc_unreachable ();
- case LOGICAL_LOCATION_KIND_UNKNOWN:
+ case logical_location_kind::unknown:
return nullptr;
- case LOGICAL_LOCATION_KIND_FUNCTION:
+ /* Kinds within executable code. */
+ case logical_location_kind::function:
return "function";
- case LOGICAL_LOCATION_KIND_MEMBER:
+ case logical_location_kind::member:
return "member";
- case LOGICAL_LOCATION_KIND_MODULE:
+ case logical_location_kind::module_:
return "module";
- case LOGICAL_LOCATION_KIND_NAMESPACE:
+ case logical_location_kind::namespace_:
return "namespace";
- case LOGICAL_LOCATION_KIND_TYPE:
+ case logical_location_kind::type:
return "type";
- case LOGICAL_LOCATION_KIND_RETURN_TYPE:
+ case logical_location_kind::return_type:
return "returnType";
- case LOGICAL_LOCATION_KIND_PARAMETER:
+ case logical_location_kind::parameter:
return "parameter";
- case LOGICAL_LOCATION_KIND_VARIABLE:
+ case logical_location_kind::variable:
return "variable";
+
+ /* Kinds within XML or HTML documents. */
+ case logical_location_kind::element:
+ return "element";
+ case logical_location_kind::attribute:
+ return "attribute";
+ case logical_location_kind::text:
+ return "text";
+ case logical_location_kind::comment:
+ return "comment";
+ case logical_location_kind::processing_instruction:
+ return "processingInstruction";
+ case logical_location_kind::dtd:
+ return "dtd";
+ case logical_location_kind::declaration:
+ return "declaration";
+
+ /* Kinds within JSON documents. */
+ case logical_location_kind::object:
+ return "object";
+ case logical_location_kind::array:
+ return "array";
+ case logical_location_kind::property:
+ return "property";
+ case logical_location_kind::value:
+ return "value";
}
}
-/* Make a "logicalLocation" object (SARIF v2.1.0 section 3.33) for LOGICAL_LOC,
- or return nullptr. */
+/* Set PROPERTY_NAME within this bag to a "logicalLocation" object (SARIF v2.1.0
+ section 3.33) for LOGICAL_LOC. The object has an "index" property to refer to
+ theRuns.logicalLocations (3.33.3). */
-std::unique_ptr<sarif_logical_location>
-make_sarif_logical_location_object (const logical_location &logical_loc)
+void
+sarif_property_bag::set_logical_location (const char *property_name,
+ sarif_builder &builder,
+ logical_location logical_loc)
+{
+ set<sarif_logical_location>
+ (property_name,
+ builder.make_minimal_sarif_logical_location (logical_loc));
+}
+
+static void
+copy_any_property_bag (const diagnostics::digraphs::object &input_obj,
+ sarif_object &output_obj)
{
- auto logical_loc_obj = ::make_unique<sarif_logical_location> ();
+ if (input_obj.get_property_bag ())
+ {
+ const json::object &old_bag = *input_obj.get_property_bag ();
+ sarif_property_bag &new_bag = output_obj.get_or_create_properties ();
+ for (size_t i = 0; i < old_bag.get_num_keys (); ++i)
+ {
+ const char *key = old_bag.get_key (i);
+ json::value *val = old_bag.get (key);
+ new_bag.set (key, val->clone ());
+ }
+ }
+}
- /* "name" property (SARIF v2.1.0 section 3.33.4). */
- if (const char *short_name = logical_loc.get_short_name ())
- logical_loc_obj->set_string ("name", short_name);
+std::unique_ptr<sarif_graph>
+make_sarif_graph (const diagnostics::digraphs::digraph &g,
+ sarif_builder *builder,
+ sarif_location_manager *sarif_location_mgr)
+{
+ auto result = std::make_unique<sarif_graph> ();
+
+ // 3.39.2 description property
+ if (const char *desc = g.get_description ())
+ if (builder)
+ result->set<sarif_message> ("description",
+ builder->make_message_object (desc));
+
+ copy_any_property_bag (g, *result);
+
+ // 3.39.3 nodes property
+ auto nodes_arr = std::make_unique<json::array> ();
+ const int num_nodes = g.get_num_nodes ();
+ for (int i = 0; i < num_nodes; ++i)
+ nodes_arr->append (make_sarif_node (g.get_node (i),
+ builder,
+ sarif_location_mgr));
+ result->set ("nodes", std::move (nodes_arr));
+
+ // 3.39.4 edges property
+ auto edges_arr = std::make_unique<json::array> ();
+ const int num_edges = g.get_num_edges ();
+ for (int i = 0; i < num_edges; ++i)
+ edges_arr->append (make_sarif_edge (g.get_edge (i), builder));
+ result->set ("edges", std::move (edges_arr));
+
+ return result;
+}
+
+std::unique_ptr<sarif_node>
+make_sarif_node (const diagnostics::digraphs::node &n,
+ sarif_builder *builder,
+ sarif_location_manager *sarif_location_mgr)
+{
+ auto result = std::make_unique<sarif_node> ();
+
+ // 3.40.2 id property
+ result->set_string ("id", n.get_id ().c_str ());
+
+ copy_any_property_bag (n, *result);
+
+ // 3.40.3 label property
+ if (const char *label = n.get_label ())
+ if (builder)
+ result->set<sarif_message> ("label",
+ builder->make_message_object (label));
+
+ // 3.40.4 location property
+ if (n.get_logical_loc ()
+ || n.get_physical_loc () != UNKNOWN_LOCATION)
+ if (builder)
+ {
+ rich_location rich_loc
+ (line_table, n.get_physical_loc ());
+ auto loc_obj
+ = builder->make_location_object
+ (sarif_location_mgr,
+ rich_loc,
+ n.get_logical_loc (),
+ diagnostic_artifact_role::scanned_file);
+ result->set<sarif_location> ("location",
+ std::move (loc_obj));
+ }
+
+ // 3.40.5 children property
+ if (const int num_children = n.get_num_children ())
+ {
+ auto children_arr = std::make_unique<json::array> ();
+ for (int i = 0; i < num_children; ++i)
+ children_arr->append (make_sarif_node (n.get_child (i),
+ builder,
+ sarif_location_mgr));
+ result->set ("children", std::move (children_arr));
+ }
+
+ return result;
+}
+
+std::unique_ptr<sarif_edge>
+make_sarif_edge (const diagnostics::digraphs::edge &e,
+ sarif_builder *builder)
+{
+ auto result = std::make_unique<sarif_edge> ();
+
+ // 3.41.2 id property
+ result->set_string ("id", e.get_id ().c_str ());
+
+ copy_any_property_bag (e, *result);
+
+ // 3.41.3 label property
+ if (const char *label = e.get_label ())
+ if (builder)
+ result->set<sarif_message> ("label",
+ builder->make_message_object (label));
+
+ // 3.41.4 sourceNodeId property
+ result->set_string ("sourceNodeId", e.get_src_node ().get_id ().c_str ());
+
+ // 3.41.5 targetNodeId property
+ result->set_string ("targetNodeId", e.get_dst_node ().get_id ().c_str ());
+
+ return result;
+}
+
+void
+sarif_property_bag::set_graph (const char *property_name,
+ sarif_builder &builder,
+ sarif_location_manager *sarif_location_mgr,
+ const diagnostics::digraphs::digraph &g)
+{
+ set<sarif_graph> (property_name,
+ make_sarif_graph (g, &builder, sarif_location_mgr));
+}
+
+/* Ensure that m_cached_logical_locs has a "logicalLocation" object
+ (SARIF v2.1.0 section 3.33) for K, and return its index within the
+ array. */
+
+int
+sarif_builder::
+ensure_sarif_logical_location_for (logical_location k)
+{
+ gcc_assert (m_logical_loc_mgr);
+
+ auto sarif_logical_loc = std::make_unique<sarif_logical_location> ();
+
+ if (const char *short_name = m_logical_loc_mgr->get_short_name (k))
+ sarif_logical_loc->set_string ("name", short_name);
/* "fullyQualifiedName" property (SARIF v2.1.0 section 3.33.5). */
- if (const char *name_with_scope = logical_loc.get_name_with_scope ())
- logical_loc_obj->set_string ("fullyQualifiedName", name_with_scope);
+ if (const char *name_with_scope = m_logical_loc_mgr->get_name_with_scope (k))
+ sarif_logical_loc->set_string ("fullyQualifiedName", name_with_scope);
/* "decoratedName" property (SARIF v2.1.0 section 3.33.6). */
- if (const char *internal_name = logical_loc.get_internal_name ())
- logical_loc_obj->set_string ("decoratedName", internal_name);
+ if (const char *internal_name = m_logical_loc_mgr->get_internal_name (k))
+ sarif_logical_loc->set_string ("decoratedName", internal_name);
/* "kind" property (SARIF v2.1.0 section 3.33.7). */
- enum logical_location_kind kind = logical_loc.get_kind ();
+ enum logical_location_kind kind = m_logical_loc_mgr->get_kind (k);
if (const char *sarif_kind_str = maybe_get_sarif_kind (kind))
- logical_loc_obj->set_string ("kind", sarif_kind_str);
+ sarif_logical_loc->set_string ("kind", sarif_kind_str);
- return logical_loc_obj;
+ /* "parentIndex" property (SARIF v2.1.0 section 3.33.8). */
+ if (auto parent_key = m_logical_loc_mgr->get_parent (k))
+ {
+ /* Recurse upwards. */
+ int parent_index = ensure_sarif_logical_location_for (parent_key);
+ sarif_logical_loc->set_integer ("parentIndex", parent_index);
+ }
+
+ /* Consolidate if this logical location already exists. */
+ int index
+ = m_cached_logical_locs->append_uniquely (std::move (sarif_logical_loc));
+
+ return index;
+}
+
+/* Ensure that theRuns.logicalLocations (3.14.17) has a "logicalLocation" object
+ (SARIF v2.1.0 section 3.33) for LOGICAL_LOC.
+ Create and return a minimal logicalLocation object referring to the
+ full object by index. */
+
+std::unique_ptr<sarif_logical_location>
+sarif_builder::
+make_minimal_sarif_logical_location (logical_location logical_loc)
+{
+ gcc_assert (m_logical_loc_mgr);
+
+ /* Ensure that m_cached_logical_locs has a "logicalLocation" object
+ (SARIF v2.1.0 section 3.33) for LOGICAL_LOC, and return its index within
+ the array. */
+
+ auto sarif_logical_loc = std::make_unique <sarif_logical_location> ();
+
+ int index = ensure_sarif_logical_location_for (logical_loc);
+
+ // 3.33.3 index property
+ sarif_logical_loc->set_integer ("index", index);
+
+ /* "fullyQualifiedName" property (SARIF v2.1.0 section 3.33.5). */
+ if (const char *name_with_scope
+ = m_logical_loc_mgr->get_name_with_scope (logical_loc))
+ sarif_logical_loc->set_string ("fullyQualifiedName", name_with_scope);
+
+ return sarif_logical_loc;
}
label_text
@@ -2724,7 +3083,7 @@ sarif_builder::make_code_flow_object (sarif_result &result,
const diagnostic_path &path)
{
auto code_flow_obj
- = ::make_unique <sarif_code_flow> (result, idx_within_parent);
+ = std::make_unique <sarif_code_flow> (result, idx_within_parent);
/* First pass:
Create threadFlows and threadFlowLocation objects within them,
@@ -2771,7 +3130,25 @@ populate_thread_flow_location_object (sarif_result &result,
{
/* Give diagnostic_event subclasses a chance to add custom properties
via a property bag. */
- ev.maybe_add_sarif_properties (tfl_obj);
+ ev.maybe_add_sarif_properties (*this, tfl_obj);
+
+ if (get_opts ().m_state_graph)
+ if (auto state_graph = ev.maybe_make_diagnostic_state_graph (true))
+ {
+ sarif_property_bag &props = tfl_obj.get_or_create_properties ();
+
+#define PROPERTY_PREFIX "gcc/diagnostic_event/"
+ props.set_graph (PROPERTY_PREFIX "state_graph",
+ *this,
+ /* Use RESULT for any related locations in the graph's
+ nodes.
+ It's not clear if this is correct; see:
+ https://github.com/oasis-tcs/sarif-spec/issues/712
+ */
+ &result,
+ *state_graph);
+#undef PROPERTY_PREFIX
+ }
/* "location" property (SARIF v2.1.0 section 3.38.3). */
tfl_obj.set<sarif_location>
@@ -2804,12 +3181,12 @@ populate_thread_flow_location_object (sarif_result &result,
std::unique_ptr<json::array>
sarif_builder::maybe_make_kinds_array (diagnostic_event::meaning m) const
{
- if (m.m_verb == diagnostic_event::VERB_unknown
- && m.m_noun == diagnostic_event::NOUN_unknown
- && m.m_property == diagnostic_event::PROPERTY_unknown)
+ if (m.m_verb == diagnostic_event::verb::unknown
+ && m.m_noun == diagnostic_event::noun::unknown
+ && m.m_property == diagnostic_event::property::unknown)
return nullptr;
- auto kinds_arr = ::make_unique<json::array> ();
+ auto kinds_arr = std::make_unique<json::array> ();
if (const char *verb_str
= diagnostic_event::meaning::maybe_get_verb_str (m.m_verb))
kinds_arr->append_string (verb_str);
@@ -2859,7 +3236,7 @@ set_string_property_escaping_braces (json::object &obj,
std::unique_ptr<sarif_message>
sarif_builder::make_message_object (const char *msg) const
{
- auto message_obj = ::make_unique<sarif_message> ();
+ auto message_obj = std::make_unique<sarif_message> ();
/* "text" property (SARIF v2.1.0 section 3.11.8). */
set_string_property_escaping_braces (*message_obj,
@@ -2875,7 +3252,7 @@ sarif_builder::make_message_object (const char *msg) const
std::unique_ptr<sarif_message>
sarif_builder::make_message_object_for_diagram (const diagnostic_diagram &diagram)
{
- auto message_obj = ::make_unique<sarif_message> ();
+ auto message_obj = std::make_unique<sarif_message> ();
/* "text" property (SARIF v2.1.0 section 3.11.8). */
set_string_property_escaping_braces (*message_obj,
@@ -2906,7 +3283,7 @@ sarif_builder::make_message_object_for_diagram (const diagnostic_diagram &diagra
std::unique_ptr<sarif_multiformat_message_string>
sarif_builder::make_multiformat_message_string (const char *msg) const
{
- auto message_obj = ::make_unique<sarif_multiformat_message_string> ();
+ auto message_obj = std::make_unique<sarif_multiformat_message_string> ();
/* "text" property (SARIF v2.1.0 section 3.12.3). */
set_string_property_escaping_braces (*message_obj,
@@ -2958,16 +3335,16 @@ sarif_builder::
make_top_level_object (std::unique_ptr<sarif_invocation> invocation_obj,
std::unique_ptr<json::array> results)
{
- auto log_obj = ::make_unique<sarif_log> ();
+ auto log_obj = std::make_unique<sarif_log> ();
/* "$schema" property (SARIF v2.1.0 section 3.13.3) . */
- log_obj->set_string ("$schema", sarif_version_to_url (m_version));
+ log_obj->set_string ("$schema", sarif_version_to_url (get_version ()));
/* "version" property (SARIF v2.1.0 section 3.13.2). */
- log_obj->set_string ("version", sarif_version_to_property (m_version));
+ log_obj->set_string ("version", sarif_version_to_property (get_version ()));
/* "runs" property (SARIF v2.1.0 section 3.13.4). */
- auto run_arr = ::make_unique<json::array> ();
+ auto run_arr = std::make_unique<json::array> ();
auto run_obj = make_run_object (std::move (invocation_obj),
std::move (results));
run_arr->append<sarif_run> (std::move (run_obj));
@@ -2983,7 +3360,7 @@ sarif_builder::
make_run_object (std::unique_ptr<sarif_invocation> invocation_obj,
std::unique_ptr<json::array> results)
{
- auto run_obj = ::make_unique<sarif_run> ();
+ auto run_obj = std::make_unique<sarif_run> ();
/* "tool" property (SARIF v2.1.0 section 3.14.6). */
run_obj->set<sarif_tool> ("tool", make_tool_object ());
@@ -2994,7 +3371,7 @@ make_run_object (std::unique_ptr<sarif_invocation> invocation_obj,
/* "invocations" property (SARIF v2.1.0 section 3.14.11). */
{
- auto invocations_arr = ::make_unique<json::array> ();
+ auto invocations_arr = std::make_unique<json::array> ();
invocations_arr->append (std::move (invocation_obj));
run_obj->set<json::array> ("invocations", std::move (invocations_arr));
}
@@ -3002,7 +3379,7 @@ make_run_object (std::unique_ptr<sarif_invocation> invocation_obj,
/* "originalUriBaseIds (SARIF v2.1.0 section 3.14.14). */
if (m_seen_any_relative_paths)
{
- auto orig_uri_base_ids = ::make_unique<json::object> ();
+ auto orig_uri_base_ids = std::make_unique<json::object> ();
orig_uri_base_ids->set<sarif_artifact_location>
(PWD_PROPERTY_NAME, make_artifact_location_object_for_pwd ());
run_obj->set<json::object> ("originalUriBaseIds",
@@ -3010,7 +3387,7 @@ make_run_object (std::unique_ptr<sarif_invocation> invocation_obj,
}
/* "artifacts" property (SARIF v2.1.0 section 3.14.15). */
- auto artifacts_arr = ::make_unique<json::array> ();
+ auto artifacts_arr = std::make_unique<json::array> ();
for (auto iter : m_filename_to_artifact_map)
{
sarif_artifact *artifact_obj = iter.second;
@@ -3025,6 +3402,19 @@ make_run_object (std::unique_ptr<sarif_invocation> invocation_obj,
/* "results" property (SARIF v2.1.0 section 3.14.23). */
run_obj->set<json::array> ("results", std::move (results));
+ /* "logicalLocations" property (SARIF v2.1.0 3.14.17). */
+ if (m_cached_logical_locs->size () > 0)
+ {
+ m_cached_logical_locs->add_explicit_index_values ();
+ run_obj->set<json::array> ("logicalLocations",
+ std::move (m_cached_logical_locs));
+ }
+
+ // "graphs" property (SARIF v2.1.0 3.14.20)
+ if (m_run_graphs->size () > 0)
+ run_obj->set<json::array> ("graphs",
+ std::move (m_run_graphs));
+
return run_obj;
}
@@ -3033,7 +3423,7 @@ make_run_object (std::unique_ptr<sarif_invocation> invocation_obj,
std::unique_ptr<sarif_tool>
sarif_builder::make_tool_object ()
{
- auto tool_obj = ::make_unique<sarif_tool> ();
+ auto tool_obj = std::make_unique<sarif_tool> ();
/* "driver" property (SARIF v2.1.0 section 3.18.2). */
tool_obj->set<sarif_tool_component> ("driver",
@@ -3052,7 +3442,7 @@ sarif_builder::make_tool_object ()
{
/* Create a "toolComponent" object (SARIF v2.1.0 section 3.19)
for the plugin. */
- auto plugin_obj = ::make_unique<sarif_tool_component> ();
+ auto plugin_obj = std::make_unique<sarif_tool_component> ();
/* "name" property (SARIF v2.1.0 section 3.19.8). */
if (const char *short_name = p.get_short_name ())
@@ -3074,7 +3464,7 @@ sarif_builder::make_tool_object ()
vinfo->for_each_plugin (v);
if (v.m_plugin_objs.size () > 0)
{
- auto extensions_arr = ::make_unique<json::array> ();
+ auto extensions_arr = std::make_unique<json::array> ();
for (auto &iter : v.m_plugin_objs)
extensions_arr->append<sarif_tool_component> (std::move (iter));
tool_obj->set<json::array> ("extensions",
@@ -3094,7 +3484,7 @@ sarif_builder::make_tool_object ()
std::unique_ptr<sarif_tool_component>
sarif_builder::make_driver_tool_component_object ()
{
- auto driver_obj = ::make_unique<sarif_tool_component> ();
+ auto driver_obj = std::make_unique<sarif_tool_component> ();
if (auto client_data_hooks = m_context.get_client_data_hooks ())
if (const client_version_info *vinfo
@@ -3143,7 +3533,7 @@ sarif_builder::maybe_make_taxonomies_array () const
return nullptr;
/* "taxonomies" property (SARIF v2.1.0 section 3.14.8). */
- auto taxonomies_arr = ::make_unique<json::array> ();
+ auto taxonomies_arr = std::make_unique<json::array> ();
taxonomies_arr->append<sarif_tool_component> (std::move (cwe_obj));
return taxonomies_arr;
}
@@ -3160,7 +3550,7 @@ sarif_builder::maybe_make_cwe_taxonomy_object () const
if (m_cwe_id_set.is_empty ())
return nullptr;
- auto taxonomy_obj = ::make_unique<sarif_tool_component> ();
+ auto taxonomy_obj = std::make_unique<sarif_tool_component> ();
/* "name" property (SARIF v2.1.0 section 3.19.8). */
taxonomy_obj->set_string ("name", "CWE");
@@ -3178,7 +3568,7 @@ sarif_builder::maybe_make_cwe_taxonomy_object () const
" Common Weakness Enumeration"));
/* "taxa" property (SARIF v2.1.0 3.section 3.19.25). */
- auto taxa_arr = ::make_unique<json::array> ();
+ auto taxa_arr = std::make_unique<json::array> ();
for (auto cwe_id : m_cwe_id_set)
taxa_arr->append<sarif_reporting_descriptor>
(make_reporting_descriptor_object_for_cwe_id (cwe_id));
@@ -3252,10 +3642,10 @@ sarif_builder::maybe_make_artifact_content_object (const char *filename) const
if (!cpp_valid_utf8_p(utf8_content.get_buffer (), utf8_content.length ()))
return nullptr;
- auto artifact_content_obj = ::make_unique<sarif_artifact_content> ();
+ auto artifact_content_obj = std::make_unique<sarif_artifact_content> ();
artifact_content_obj->set<json::string>
("text",
- ::make_unique <json::string> (utf8_content.get_buffer (),
+ std::make_unique <json::string> (utf8_content.get_buffer (),
utf8_content.length ()));
return artifact_content_obj;
}
@@ -3310,7 +3700,7 @@ maybe_make_artifact_content_object (const char *filename,
return nullptr;
}
- auto artifact_content_obj = ::make_unique<sarif_artifact_content> ();
+ auto artifact_content_obj = std::make_unique<sarif_artifact_content> ();
artifact_content_obj->set_string ("text", text_utf8);
free (text_utf8);
@@ -3328,11 +3718,11 @@ maybe_make_artifact_content_object (const char *filename,
std::unique_ptr<sarif_fix>
sarif_builder::make_fix_object (const rich_location &richloc)
{
- auto fix_obj = ::make_unique<sarif_fix> ();
+ auto fix_obj = std::make_unique<sarif_fix> ();
/* "artifactChanges" property (SARIF v2.1.0 section 3.55.3). */
/* We assume that all fix-it hints in RICHLOC affect the same file. */
- auto artifact_change_arr = ::make_unique<json::array> ();
+ auto artifact_change_arr = std::make_unique<json::array> ();
artifact_change_arr->append<sarif_artifact_change>
(make_artifact_change_object (richloc));
fix_obj->set<json::array> ("artifactChanges",
@@ -3346,7 +3736,7 @@ sarif_builder::make_fix_object (const rich_location &richloc)
std::unique_ptr<sarif_artifact_change>
sarif_builder::make_artifact_change_object (const rich_location &richloc)
{
- auto artifact_change_obj = ::make_unique<sarif_artifact_change> ();
+ auto artifact_change_obj = std::make_unique<sarif_artifact_change> ();
/* "artifactLocation" property (SARIF v2.1.0 section 3.56.2). */
artifact_change_obj->set<sarif_artifact_location>
@@ -3354,7 +3744,7 @@ sarif_builder::make_artifact_change_object (const rich_location &richloc)
make_artifact_location_object (richloc.get_loc ()));
/* "replacements" property (SARIF v2.1.0 section 3.56.3). */
- auto replacement_arr = ::make_unique<json::array> ();
+ auto replacement_arr = std::make_unique<json::array> ();
for (unsigned int i = 0; i < richloc.get_num_fixit_hints (); i++)
{
const fixit_hint *hint = richloc.get_fixit_hint (i);
@@ -3372,7 +3762,7 @@ sarif_builder::make_artifact_change_object (const rich_location &richloc)
std::unique_ptr<sarif_replacement>
sarif_builder::make_replacement_object (const fixit_hint &hint) const
{
- auto replacement_obj = ::make_unique<sarif_replacement> ();
+ auto replacement_obj = std::make_unique<sarif_replacement> ();
/* "deletedRegion" property (SARIF v2.1.0 section 3.57.3). */
replacement_obj->set<sarif_region> ("deletedRegion",
@@ -3391,7 +3781,7 @@ sarif_builder::make_replacement_object (const fixit_hint &hint) const
std::unique_ptr<sarif_artifact_content>
sarif_builder::make_artifact_content_object (const char *text) const
{
- auto content_obj = ::make_unique<sarif_artifact_content> ();
+ auto content_obj = std::make_unique<sarif_artifact_content> ();
/* "text" property (SARIF v2.1.0 section 3.3.2). */
content_obj->set_string ("text", text);
@@ -3467,10 +3857,16 @@ public:
diagnostic_output_format::dump (out, indent);
}
+ void
+ set_main_input_filename (const char *name) final override
+ {
+ m_builder.set_main_input_filename (name);
+ }
+
std::unique_ptr<diagnostic_per_format_buffer>
make_per_format_buffer () final override
{
- return ::make_unique<diagnostic_sarif_format_buffer> (m_builder);
+ return std::make_unique<diagnostic_sarif_format_buffer> (m_builder);
}
void set_buffer (diagnostic_per_format_buffer *base_buffer) final override
{
@@ -3524,6 +3920,12 @@ public:
/* No-op. */
}
+ void
+ report_global_digraph (const diagnostics::digraphs::lazy_digraph &lazy_digraph) final override
+ {
+ m_builder.report_global_digraph (lazy_digraph);
+ }
+
sarif_builder &get_builder () { return m_builder; }
size_t num_results () const { return m_builder.num_results (); }
@@ -3532,12 +3934,11 @@ public:
protected:
sarif_output_format (diagnostic_context &context,
const line_maps *line_maps,
- const char *main_input_filename_,
- bool formatted,
- enum sarif_version version)
+ std::unique_ptr<sarif_serialization_format> serialization_format,
+ const sarif_generation_options &sarif_gen_opts)
: diagnostic_output_format (context),
- m_builder (context, *get_printer (), line_maps, main_input_filename_,
- formatted, version),
+ m_builder (context, *get_printer (), line_maps,
+ std::move (serialization_format), sarif_gen_opts),
m_buffer (nullptr)
{}
@@ -3550,12 +3951,11 @@ class sarif_stream_output_format : public sarif_output_format
public:
sarif_stream_output_format (diagnostic_context &context,
const line_maps *line_maps,
- const char *main_input_filename_,
- bool formatted,
- enum sarif_version version,
+ std::unique_ptr<sarif_serialization_format> serialization_format,
+ const sarif_generation_options &sarif_gen_opts,
FILE *stream)
- : sarif_output_format (context, line_maps, main_input_filename_,
- formatted, version),
+ : sarif_output_format (context, line_maps,
+ std::move (serialization_format), sarif_gen_opts),
m_stream (stream)
{
}
@@ -3576,12 +3976,11 @@ class sarif_file_output_format : public sarif_output_format
public:
sarif_file_output_format (diagnostic_context &context,
const line_maps *line_maps,
- const char *main_input_filename_,
- bool formatted,
- enum sarif_version version,
+ std::unique_ptr<sarif_serialization_format> serialization_format,
+ const sarif_generation_options &sarif_gen_opts,
diagnostic_output_file output_file)
- : sarif_output_format (context, line_maps, main_input_filename_,
- formatted, version),
+ : sarif_output_format (context, line_maps,
+ std::move (serialization_format), sarif_gen_opts),
m_output_file (std::move (output_file))
{
gcc_assert (m_output_file.get_open_file ());
@@ -3724,47 +4123,59 @@ sarif_builder::sarif_token_printer::print_tokens (pretty_printer *pp,
}
/* Populate CONTEXT in preparation for SARIF output (either to stderr, or
- to a file). */
+ to a file).
+ Return a reference to *FMT. */
-static void
+static diagnostic_output_format &
diagnostic_output_format_init_sarif (diagnostic_context &context,
std::unique_ptr<sarif_output_format> fmt)
{
+ gcc_assert (fmt);
+ diagnostic_output_format &out = *fmt;
+
fmt->update_printer ();
context.set_output_format (std::move (fmt));
+
+ return out;
}
-/* Populate CONTEXT in preparation for SARIF output to stderr. */
+/* Populate CONTEXT in preparation for SARIF output to stderr.
+ Return a reference to the new sink. */
-void
+diagnostic_output_format &
diagnostic_output_format_init_sarif_stderr (diagnostic_context &context,
const line_maps *line_maps,
- const char *main_input_filename_,
- bool formatted,
- enum sarif_version version)
+ bool formatted)
{
gcc_assert (line_maps);
- diagnostic_output_format_init_sarif
+ const sarif_generation_options sarif_gen_opts;
+ auto serialization
+ = std::make_unique<sarif_serialization_format_json> (formatted);
+ return diagnostic_output_format_init_sarif
(context,
- ::make_unique<sarif_stream_output_format> (context,
- line_maps,
- main_input_filename_,
- formatted,
- version,
- stderr));
+ std::make_unique<sarif_stream_output_format> (context,
+ line_maps,
+ std::move (serialization),
+ sarif_gen_opts,
+ stderr));
}
-/* Attempt to open BASE_FILE_NAME.sarif for writing.
+/* Attempt to open "BASE_FILE_NAME""EXTENSION" for writing.
Return a non-null diagnostic_output_file,
or return a null diagnostic_output_file and complain to CONTEXT
using LINE_MAPS. */
diagnostic_output_file
-diagnostic_output_format_open_sarif_file (diagnostic_context &context,
- line_maps *line_maps,
- const char *base_file_name)
+diagnostic_output_file::try_to_open (diagnostic_context &context,
+ line_maps *line_maps,
+ const char *base_file_name,
+ const char *extension,
+ bool is_binary)
{
+ gcc_assert (extension);
+ gcc_assert (extension[0] == '.');
+
if (!base_file_name)
{
rich_location richloc (line_maps, UNKNOWN_LOCATION);
@@ -3775,30 +4186,59 @@ diagnostic_output_format_open_sarif_file (diagnostic_context &context,
}
label_text filename = label_text::take (concat (base_file_name,
- ".sarif",
+ extension,
nullptr));
- FILE *outf = fopen (filename.get (), "w");
+ FILE *outf = fopen (filename.get (), is_binary ? "wb" : "w");
if (!outf)
{
rich_location richloc (line_maps, UNKNOWN_LOCATION);
context.emit_diagnostic_with_group
(DK_ERROR, richloc, nullptr, 0,
- "unable to open %qs for SARIF output: %m",
+ "unable to open %qs for diagnostic output: %m",
filename.get ());
return diagnostic_output_file ();
}
return diagnostic_output_file (outf, true, std::move (filename));
}
+/* Attempt to open BASE_FILE_NAME.sarif for writing JSON.
+ Return a non-null diagnostic_output_file,
+ or return a null diagnostic_output_file and complain to CONTEXT
+ using LINE_MAPS. */
+
+diagnostic_output_file
+diagnostic_output_format_open_sarif_file (diagnostic_context &context,
+ line_maps *line_maps,
+ const char *base_file_name,
+ enum sarif_serialization_kind serialization_kind)
+{
+ const char *suffix;
+ bool is_binary;
+ switch (serialization_kind)
+ {
+ default:
+ gcc_unreachable ();
+ case sarif_serialization_kind::json:
+ suffix = ".sarif";
+ is_binary = false;
+ break;
+ }
+
+ return diagnostic_output_file::try_to_open (context,
+ line_maps,
+ base_file_name,
+ suffix,
+ is_binary);
+}
+
/* Populate CONTEXT in preparation for SARIF output to a file named
- BASE_FILE_NAME.sarif. */
+ BASE_FILE_NAME.sarif.
+ Return a reference to the new sink. */
-void
+diagnostic_output_format &
diagnostic_output_format_init_sarif_file (diagnostic_context &context,
line_maps *line_maps,
- const char *main_input_filename_,
bool formatted,
- enum sarif_version version,
const char *base_file_name)
{
gcc_assert (line_maps);
@@ -3806,60 +4246,142 @@ diagnostic_output_format_init_sarif_file (diagnostic_context &context,
diagnostic_output_file output_file
= diagnostic_output_format_open_sarif_file (context,
line_maps,
- base_file_name);
+ base_file_name,
+ sarif_serialization_kind::json);
+ auto serialization
+ = std::make_unique<sarif_serialization_format_json> (formatted);
- diagnostic_output_format_init_sarif
+ const sarif_generation_options sarif_gen_opts;
+ return diagnostic_output_format_init_sarif
(context,
- ::make_unique<sarif_file_output_format> (context,
- line_maps,
- main_input_filename_,
- formatted,
- version,
- std::move (output_file)));
+ std::make_unique<sarif_file_output_format> (context,
+ line_maps,
+ std::move (serialization),
+ sarif_gen_opts,
+ std::move (output_file)));
}
-/* Populate CONTEXT in preparation for SARIF output to STREAM. */
+/* Populate CONTEXT in preparation for SARIF output to STREAM.
+ Return a reference to the new sink. */
-void
+diagnostic_output_format &
diagnostic_output_format_init_sarif_stream (diagnostic_context &context,
const line_maps *line_maps,
- const char *main_input_filename_,
bool formatted,
- enum sarif_version version,
FILE *stream)
{
gcc_assert (line_maps);
- diagnostic_output_format_init_sarif
+ const sarif_generation_options sarif_gen_opts;
+ auto serialization
+ = std::make_unique<sarif_serialization_format_json> (formatted);
+ return diagnostic_output_format_init_sarif
(context,
- ::make_unique<sarif_stream_output_format> (context,
- line_maps,
- main_input_filename_,
- formatted,
- version,
- stream));
+ std::make_unique<sarif_stream_output_format> (context,
+ line_maps,
+ std::move (serialization),
+ sarif_gen_opts,
+ stream));
}
std::unique_ptr<diagnostic_output_format>
make_sarif_sink (diagnostic_context &context,
const line_maps &line_maps,
- const char *main_input_filename_,
- enum sarif_version version,
+ std::unique_ptr<sarif_serialization_format> serialization,
+ const sarif_generation_options &sarif_gen_opts,
diagnostic_output_file output_file)
{
- auto sink = ::make_unique<sarif_file_output_format> (context,
- &line_maps,
- main_input_filename_,
- true,
- version,
- std::move (output_file));
+ auto sink
+ = std::make_unique<sarif_file_output_format> (context,
+ &line_maps,
+ std::move (serialization),
+ sarif_gen_opts,
+ std::move (output_file));
sink->update_printer ();
return sink;
}
+// struct sarif_generation_options
+
+sarif_generation_options::sarif_generation_options ()
+: m_version (sarif_version::v2_1_0),
+ m_state_graph (false)
+{
+}
+
#if CHECKING_P
namespace selftest {
+static void
+test_sarif_array_of_unique_1 ()
+{
+ sarif_array_of_unique<json::string> arr;
+
+ ASSERT_EQ (arr.length (), 0);
+
+ {
+ size_t idx = arr.append_uniquely (std::make_unique<json::string> ("foo"));
+ ASSERT_EQ (idx, 0);
+ ASSERT_EQ (arr.length (), 1);
+ }
+ {
+ size_t idx = arr.append_uniquely (std::make_unique<json::string> ("bar"));
+ ASSERT_EQ (idx, 1);
+ ASSERT_EQ (arr.length (), 2);
+ }
+
+ /* Try adding them again, should be idempotent. */
+ {
+ size_t idx = arr.append_uniquely (std::make_unique<json::string> ("foo"));
+ ASSERT_EQ (idx, 0);
+ ASSERT_EQ (arr.length (), 2);
+ }
+ {
+ size_t idx = arr.append_uniquely (std::make_unique<json::string> ("bar"));
+ ASSERT_EQ (idx, 1);
+ ASSERT_EQ (arr.length (), 2);
+ }
+}
+
+static void
+test_sarif_array_of_unique_2 ()
+{
+ sarif_array_of_unique<json::object> arr;
+
+ ASSERT_EQ (arr.length (), 0);
+
+ {
+ auto obj0 = std::make_unique<json::object> ();
+ size_t idx = arr.append_uniquely (std::move (obj0));
+ ASSERT_EQ (idx, 0);
+ ASSERT_EQ (arr.length (), 1);
+
+ // Attempting to add another empty objects should be idempotent.
+ idx = arr.append_uniquely (std::make_unique<json::object> ());
+ ASSERT_EQ (idx, 0);
+ ASSERT_EQ (arr.length (), 1);
+ }
+ {
+ auto obj1 = std::make_unique<json::object> ();
+ obj1->set_string ("foo", "bar");
+ size_t idx = arr.append_uniquely (std::move (obj1));
+ ASSERT_EQ (idx, 1);
+ ASSERT_EQ (arr.length (), 2);
+
+ // Attempting to add an equivalent object should be idempotent.
+ auto other = std::make_unique<json::object> ();
+ other->set_string ("foo", "bar");
+ idx = arr.append_uniquely (std::move (other));
+ ASSERT_EQ (idx, 1);
+ ASSERT_EQ (arr.length (), 2);
+ }
+
+ // Verify behavior of add_explicit_index_values.
+ arr.add_explicit_index_values ();
+ ASSERT_JSON_INT_PROPERTY_EQ (arr[0], "index", 0);
+ ASSERT_JSON_INT_PROPERTY_EQ (arr[1], "index", 1);
+}
+
/* A subclass of sarif_output_format for writing selftests.
The JSON output is cached internally, rather than written
out to a file. */
@@ -3868,15 +4390,15 @@ class test_sarif_diagnostic_context : public test_diagnostic_context
{
public:
test_sarif_diagnostic_context (const char *main_input_filename,
- enum sarif_version version)
+ const sarif_generation_options &sarif_gen_opts)
{
- auto format = ::make_unique<buffered_output_format> (*this,
- line_table,
- main_input_filename,
- true,
- version);
+ auto format = std::make_unique<buffered_output_format> (*this,
+ line_table,
+ true,
+ sarif_gen_opts);
m_format = format.get (); // borrowed
diagnostic_output_format_init_sarif (*this, std::move (format));
+ m_format->set_main_input_filename (main_input_filename);
}
std::unique_ptr<sarif_log> flush_to_object ()
@@ -3893,11 +4415,12 @@ private:
public:
buffered_output_format (diagnostic_context &context,
const line_maps *line_maps,
- const char *main_input_filename_,
bool formatted,
- enum sarif_version version)
- : sarif_output_format (context, line_maps, main_input_filename_,
- formatted, version)
+ const sarif_generation_options &sarif_gen_opts)
+ : sarif_output_format (context, line_maps,
+ std::make_unique<sarif_serialization_format_json>
+ (formatted),
+ sarif_gen_opts)
{
}
bool machine_readable_stderr_p () const final override
@@ -3917,8 +4440,8 @@ private:
with labels and escape-on-output. */
static void
-test_make_location_object (const line_table_case &case_,
- enum sarif_version version)
+test_make_location_object (const sarif_generation_options &sarif_gen_opts,
+ const line_table_case &case_)
{
diagnostic_show_locus_fixture_one_liner_utf8 f (case_);
location_t line_end = linemap_position_for_column (line_table, 31);
@@ -3929,8 +4452,10 @@ test_make_location_object (const line_table_case &case_,
test_diagnostic_context dc;
pretty_printer pp;
- sarif_builder builder (dc, pp, line_table, "MAIN_INPUT_FILENAME",
- true, version);
+ sarif_builder builder
+ (dc, pp, line_table,
+ std::make_unique<sarif_serialization_format_json> (true),
+ sarif_gen_opts);
/* These "columns" are byte offsets, whereas later on the columns
in the generated SARIF use sarif_builder::get_sarif_column and
@@ -3961,7 +4486,8 @@ test_make_location_object (const line_table_case &case_,
std::unique_ptr<sarif_location> location_obj
= builder.make_location_object
- (result, richloc, nullptr, diagnostic_artifact_role::analysis_target);
+ (&result, richloc, logical_location (),
+ diagnostic_artifact_role::analysis_target);
ASSERT_NE (location_obj, nullptr);
auto physical_location
@@ -4041,9 +4567,9 @@ test_make_location_object (const line_table_case &case_,
Verify various basic properties. */
static void
-test_simple_log (enum sarif_version version)
+test_simple_log (const sarif_generation_options &sarif_gen_opts)
{
- test_sarif_diagnostic_context dc ("MAIN_INPUT_FILENAME", version);
+ test_sarif_diagnostic_context dc ("MAIN_INPUT_FILENAME", sarif_gen_opts);
rich_location richloc (line_table, UNKNOWN_LOCATION);
dc.report (DK_ERROR, richloc, nullptr, 0, "this is a test: %i", 42);
@@ -4052,6 +4578,7 @@ test_simple_log (enum sarif_version version)
// 3.13 sarifLog:
auto log = log_ptr.get ();
+ const enum sarif_version version = sarif_gen_opts.m_version;
ASSERT_JSON_STRING_PROPERTY_EQ (log, "$schema",
sarif_version_to_url (version));
ASSERT_JSON_STRING_PROPERTY_EQ (log, "version",
@@ -4158,8 +4685,8 @@ test_simple_log (enum sarif_version version)
/* As above, but with a "real" location_t. */
static void
-test_simple_log_2 (const line_table_case &case_,
- enum sarif_version version)
+test_simple_log_2 (const sarif_generation_options &sarif_gen_opts,
+ const line_table_case &case_)
{
auto_fix_quotes fix_quotes;
@@ -4174,7 +4701,7 @@ test_simple_log_2 (const line_table_case &case_,
if (line_end > LINE_MAP_MAX_LOCATION_WITH_COLS)
return;
- test_sarif_diagnostic_context dc (f.get_filename (), version);
+ test_sarif_diagnostic_context dc (f.get_filename (), sarif_gen_opts);
const location_t typo_loc
= make_location (linemap_position_for_column (line_table, 1),
@@ -4304,11 +4831,11 @@ get_message_from_log (const sarif_log *log)
/* Tests of messages with embedded links; see SARIF v2.1.0 3.11.6. */
static void
-test_message_with_embedded_link (enum sarif_version version)
+test_message_with_embedded_link (const sarif_generation_options &sarif_gen_opts)
{
auto_fix_quotes fix_quotes;
{
- test_sarif_diagnostic_context dc ("test.c", version);
+ test_sarif_diagnostic_context dc ("test.c", sarif_gen_opts);
rich_location richloc (line_table, UNKNOWN_LOCATION);
dc.report (DK_ERROR, richloc, nullptr, 0,
"before %{text%} after",
@@ -4324,7 +4851,7 @@ test_message_with_embedded_link (enum sarif_version version)
/* Escaping in message text.
This is "EXAMPLE 1" from 3.11.6. */
{
- test_sarif_diagnostic_context dc ("test.c", version);
+ test_sarif_diagnostic_context dc ("test.c", sarif_gen_opts);
rich_location richloc (line_table, UNKNOWN_LOCATION);
/* Disable "unquoted sequence of 2 consecutive punctuation
@@ -4364,8 +4891,8 @@ test_message_with_embedded_link (enum sarif_version version)
}
};
- test_sarif_diagnostic_context dc ("test.c", version);
- dc.push_owned_urlifier (::make_unique<test_urlifier> ());
+ test_sarif_diagnostic_context dc ("test.c", sarif_gen_opts);
+ dc.push_owned_urlifier (std::make_unique<test_urlifier> ());
rich_location richloc (line_table, UNKNOWN_LOCATION);
dc.report (DK_ERROR, richloc, nullptr, 0,
"foo %<-foption%> %<unrecognized%> bar");
@@ -4382,11 +4909,11 @@ test_message_with_embedded_link (enum sarif_version version)
3.11.5 ("Messages with placeholders"). */
static void
-test_message_with_braces (enum sarif_version version)
+test_message_with_braces (const sarif_generation_options &sarif_gen_opts)
{
auto_fix_quotes fix_quotes;
{
- test_sarif_diagnostic_context dc ("test.c", version);
+ test_sarif_diagnostic_context dc ("test.c", sarif_gen_opts);
rich_location richloc (line_table, UNKNOWN_LOCATION);
dc.report (DK_ERROR, richloc, nullptr, 0,
"open brace: %qs close brace: %qs",
@@ -4401,9 +4928,9 @@ test_message_with_braces (enum sarif_version version)
}
static void
-test_buffering (enum sarif_version version)
+test_buffering (const sarif_generation_options &sarif_gen_opts)
{
- test_sarif_diagnostic_context dc ("test.c", version);
+ test_sarif_diagnostic_context dc ("test.c", sarif_gen_opts);
diagnostic_buffer buf_a (dc);
diagnostic_buffer buf_b (dc);
@@ -4487,41 +5014,48 @@ test_buffering (enum sarif_version version)
}
}
+template <class ...ArgTypes>
static void
-run_tests_per_version (const line_table_case &case_)
+for_each_sarif_gen_option (void (*callback) (const sarif_generation_options &,
+ ArgTypes ...),
+ ArgTypes ...args)
{
+ sarif_generation_options sarif_gen_opts;
for (int version_idx = 0;
version_idx < (int)sarif_version::num_versions;
++version_idx)
{
- enum sarif_version version
- = static_cast<enum sarif_version> (version_idx);
+ sarif_gen_opts.m_version = static_cast<enum sarif_version> (version_idx);
- test_make_location_object (case_, version);
- test_simple_log_2 (case_, version);
+ callback (sarif_gen_opts, args...);
}
}
+static void
+run_line_table_case_tests_per_version (const line_table_case &case_)
+{
+ for_each_sarif_gen_option<const line_table_case &>
+ (test_make_location_object, case_);
+
+ for_each_sarif_gen_option<const line_table_case &>
+ (test_simple_log_2, case_);
+}
+
/* Run all of the selftests within this file. */
void
diagnostic_format_sarif_cc_tests ()
{
- for (int version_idx = 0;
- version_idx < (int)sarif_version::num_versions;
- ++version_idx)
- {
- enum sarif_version version
- = static_cast<enum sarif_version> (version_idx);
+ test_sarif_array_of_unique_1 ();
+ test_sarif_array_of_unique_2 ();
- test_simple_log (version);
- test_message_with_embedded_link (version);
- test_message_with_braces (version);
- test_buffering (version);
- }
+ for_each_sarif_gen_option (test_simple_log);
+ for_each_sarif_gen_option (test_message_with_embedded_link);
+ for_each_sarif_gen_option (test_message_with_braces);
+ for_each_sarif_gen_option (test_buffering);
- /* Run tests per (line-table-case, SARIF version) pair. */
- for_each_line_table_case (run_tests_per_version);
+ /* Run tests per (SARIF gen-option, line-table-case) pair. */
+ for_each_line_table_case (run_line_table_case_tests_per_version);
}
} // namespace selftest