Add the property "roles" (SARIF v2.1 3.24.6) to artifacts. Populate it with: * "analysisTarget" for the top-level input file * "resultFile" for any other file a diagnostic is reported in * "tracedFile" for any file a diagnostic event is reported in
Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu. Successful run of analyzer integration tests on x86_64-pc-linux-gnu. Pushed to trunk as r15-999-ga67595d5c5d4bd. gcc/ChangeLog: * diagnostic-format-sarif.cc: Include "ordered-hash-map.h" and "sbitmap.h". (enum class diagnostic_artifact_role): New. (class sarif_artifact): New. (sarif_builder::maybe_make_artifact_content_object): Make public. (sarif_builder::m_filenames): Replace with... (sarif_builder::m_filename_to_artifact_map): ...this. (sarif_artifact::add_role): New. (sarif_artifact::populate_contents): New. (get_artifact_role_string): New. (sarif_artifact::populate_roles): New. (sarif_result::on_nested_diagnostic): Pass role to make_location_object. (sarif_ice_notification::sarif_ice_notification): Likewise. (sarif_builder::sarif_builder): Add "main_input_filename_" param. Mark it as the artifact that the tool was instructed to scan. (sarif_builder::make_result_object): Pass role to make_locations_arr. (sarif_builder::make_locations_arr): Add "role" param and pass it to make_location_object. (sarif_builder::make_location_object): Add "role" param and pass it to maybe_make_physical_location_object. (sarif_builder::maybe_make_physical_location_object): Add "role" param and pass it to call to get_or_create_artifact, rather than adding to now-removed "m_filenames". Flag the artifact for its contents to be embedded. (sarif_builder::make_thread_flow_location_object): Pass role to make_location_object. (sarif_builder::make_run_object): Update for change from m_filename to m_filename_to_artifact_map. Call populate_contents and populate_roles on each artifact_obj. (sarif_builder::make_artifact_object): Convert to... (sarif_builder::get_or_create_artifact): ...this, moving addition of contents to make_run_object, and conditionalizing setting of sourceLanguage on "role". (sarif_output_format::sarif_output_format): Add "main_input_filename_" param and pass to m_builder's ctor. (sarif_stream_output_format::sarif_stream_output_format): Likewise. (sarif_file_output_format::sarif_file_output_format): Likewise. (diagnostic_output_format_init_sarif_stderr): Add "main_input_filename_" param and pass to ctor. (diagnostic_output_format_init_sarif_file): Likewise. (diagnostic_output_format_init_sarif_stream): Likewise. * diagnostic.cc (diagnostic_output_format_init): Add "main_input_filename_" param and pass to the diagnostic_output_format_init_sarif_* calls. * diagnostic.h (diagnostic_output_format_init): Add main_input_filename_" param to decl. (diagnostic_output_format_init_sarif_stderr): Likewise. (diagnostic_output_format_init_sarif_file): Likewise. (diagnostic_output_format_init_sarif_stream): Likewise. * gcc.cc (driver_handle_option): Pass main input filename to diagnostic_output_format_init. * opts.cc (common_handle_option): Likewise. gcc/testsuite/ChangeLog: * c-c++-common/analyzer/sarif-path-role.c: New test. * c-c++-common/analyzer/sarif-path-role.h: New header for above test. * c-c++-common/diagnostic-format-sarif-file-1.c: Verify the artifact's "role" property. * c-c++-common/diagnostic-format-sarif-file-header-role.c: New test. * c-c++-common/diagnostic-format-sarif-file-header-role.h: New header for above test. * c-c++-common/diagnostic-format-sarif-file-no-results.c: New test. Signed-off-by: David Malcolm <dmalc...@redhat.com> --- gcc/diagnostic-format-sarif.cc | 297 +++++++++++++++--- gcc/diagnostic.cc | 3 + gcc/diagnostic.h | 4 + gcc/gcc.cc | 3 +- gcc/opts.cc | 3 +- .../c-c++-common/analyzer/sarif-path-role.c | 21 ++ .../c-c++-common/analyzer/sarif-path-role.h | 2 + .../diagnostic-format-sarif-file-1.c | 5 + ...diagnostic-format-sarif-file-header-role.c | 12 + ...diagnostic-format-sarif-file-header-role.h | 1 + .../diagnostic-format-sarif-file-no-results.c | 44 +++ 11 files changed, 344 insertions(+), 51 deletions(-) create mode 100644 gcc/testsuite/c-c++-common/analyzer/sarif-path-role.c create mode 100644 gcc/testsuite/c-c++-common/analyzer/sarif-path-role.h create mode 100644 gcc/testsuite/c-c++-common/diagnostic-format-sarif-file-header-role.c create mode 100644 gcc/testsuite/c-c++-common/diagnostic-format-sarif-file-header-role.h create mode 100644 gcc/testsuite/c-c++-common/diagnostic-format-sarif-file-no-results.c diff --git a/gcc/diagnostic-format-sarif.cc b/gcc/diagnostic-format-sarif.cc index 97c5943cd339..79116f051bc1 100644 --- a/gcc/diagnostic-format-sarif.cc +++ b/gcc/diagnostic-format-sarif.cc @@ -33,6 +33,8 @@ along with GCC; see the file COPYING3. If not see #include "diagnostic-diagram.h" #include "text-art/canvas.h" #include "diagnostic-format-sarif.h" +#include "ordered-hash-map.h" +#include "sbitmap.h" class sarif_builder; @@ -57,6 +59,51 @@ private: bool m_success; }; +/* Corresponds to values for the SARIF artifact objects "roles" property. + (SARIF v2.1.0 section 3.24.6). */ + +enum class diagnostic_artifact_role +{ + analysis_target, /* "analysisTarget". */ + debug_output_file, /* "debugOutputFile". */ + result_file, /* "resultFile". */ + traced_file, /* "tracedFile". */ + + NUM_ROLES +}; + +/* Subclass of sarif_object for SARIF artifact objects + (SARIF v2.1.0 section 3.24). */ + +class sarif_artifact : public sarif_object +{ +public: + sarif_artifact (const char *filename) + : m_filename (filename), + m_roles ((unsigned)diagnostic_artifact_role::NUM_ROLES), + m_embed_contents (false) + { + bitmap_clear (m_roles); + } + + void add_role (enum diagnostic_artifact_role role, + bool embed_contents); + + bool embed_contents_p () const { return m_embed_contents; } + void populate_contents (sarif_builder &builder); + void populate_roles (); + +private: + const char *m_filename; + auto_sbitmap m_roles; + + /* Flag to track whether this artifact should have a "contents" property + (SARIF v2.1.0 section 3.24.8). + We only add the contents for those artifacts that have a location + referencing them (so that a consumer might want to quote the source). */ + bool m_embed_contents; +}; + /* Subclass of sarif_object for SARIF result objects (SARIF v2.1.0 section 3.27). */ @@ -158,6 +205,7 @@ class sarif_builder { public: sarif_builder (diagnostic_context *context, + const char *main_input_filename_, bool formatted); void end_diagnostic (diagnostic_context *context, @@ -169,13 +217,16 @@ public: void flush_to_file (FILE *outf); - json::array *make_locations_arr (const diagnostic_info &diagnostic); + json::array *make_locations_arr (const diagnostic_info &diagnostic, + enum diagnostic_artifact_role role); json::object *make_location_object (const rich_location &rich_loc, - const logical_location *logical_loc); + const logical_location *logical_loc, + enum diagnostic_artifact_role role); json::object *make_message_object (const char *msg) const; json::object * make_message_object_for_diagram (diagnostic_context *context, const diagnostic_diagram &diagram); + json::object *maybe_make_artifact_content_object (const char *filename) const; private: sarif_result *make_result_object (diagnostic_context *context, @@ -183,13 +234,16 @@ private: diagnostic_t orig_diag_kind); void set_any_logical_locs_arr (json::object *location_obj, const logical_location *logical_loc); - json::object *make_location_object (const diagnostic_event &event); + json::object *make_location_object (const diagnostic_event &event, + enum diagnostic_artifact_role role); json::object *make_code_flow_object (const diagnostic_path &path); json::object * make_thread_flow_location_object (const diagnostic_event &event, int path_event_idx); json::array *maybe_make_kinds_array (diagnostic_event::meaning m) const; - json::object *maybe_make_physical_location_object (location_t loc); + json::object * + maybe_make_physical_location_object (location_t loc, + enum diagnostic_artifact_role role); json::object *make_artifact_location_object (location_t loc); json::object *make_artifact_location_object (const char *filename); json::object *make_artifact_location_object_for_pwd () const; @@ -214,11 +268,12 @@ private: json::object *make_reporting_descriptor_object_for_cwe_id (int cwe_id) const; json::object * make_reporting_descriptor_reference_object_for_cwe_id (int cwe_id); - json::object *make_artifact_object (const char *filename); + sarif_artifact &get_or_create_artifact (const char *filename, + enum diagnostic_artifact_role role, + bool embed_contents); char *get_source_lines (const char *filename, int start_line, int end_line) const; - json::object *maybe_make_artifact_content_object (const char *filename) const; json::object *maybe_make_artifact_content_object (const char *filename, int start_line, int end_line) const; @@ -240,7 +295,8 @@ private: diagnostic group. */ sarif_result *m_cur_group_result; - hash_set <const char *> m_filenames; + ordered_hash_map <nofree_string_hash, + sarif_artifact *> m_filename_to_artifact_map; bool m_seen_any_relative_paths; hash_set <free_string_hash> m_rule_id_set; json::array *m_rules_arr; @@ -302,6 +358,86 @@ sarif_invocation::prepare_to_flush (diagnostic_context *context) client_data_hooks->add_sarif_invocation_properties (*this); } +/* class sarif_artifact : public sarif_object. */ + +/* Add ROLE to this artifact's roles. + If EMBED_CONTENTS is true, then flag that we will attempt to embed the + contents of this artifact when writing it out. */ + +void +sarif_artifact::add_role (enum diagnostic_artifact_role role, + bool embed_contents) +{ + if (embed_contents) + m_embed_contents = true; + + /* In SARIF v2.1.0 section 3.24.6 "roles" property: + "resultFile" is for an artifact + "which the analysis tool was not explicitly instructed to scan", + whereas "analysisTarget" is for one where the + "analysis tool was instructed to scan this artifact". + Hence the latter excludes the former. */ + if (role == diagnostic_artifact_role::result_file) + if (bitmap_bit_p (m_roles, (int)diagnostic_artifact_role::analysis_target)) + return; + + bitmap_set_bit (m_roles, (int)role); +} + +/* Populate the "contents" property (SARIF v2.1.0 section 3.24.8). + We do this after initialization to + (a) ensure that any charset options have been set + (b) only populate it for artifacts that are referenced by a location. */ + +void +sarif_artifact::populate_contents (sarif_builder &builder) +{ + if (json::object *artifact_content_obj + = builder.maybe_make_artifact_content_object (m_filename)) + set ("contents", artifact_content_obj); +} + +/* Get a string for ROLE corresponding to the + SARIF v2.1.0 section 3.24.6 "roles" property. */ + +static const char * +get_artifact_role_string (enum diagnostic_artifact_role role) +{ + switch (role) + { + default: + gcc_unreachable (); + case diagnostic_artifact_role::analysis_target: + return "analysisTarget"; + case diagnostic_artifact_role::debug_output_file: + return "debugOutputFile"; + case diagnostic_artifact_role::result_file: + return "resultFile"; + case diagnostic_artifact_role::traced_file: + return "tracedFile"; + } +} + +/* Populate the "roles" property of this json::object with a new + json::array for the artifact.roles property (SARIF v2.1.0 section 3.24.6) + containing strings such as "analysisTarget", "resultFile" + and/or "tracedFile". */ + +void +sarif_artifact::populate_roles () +{ + if (bitmap_empty_p (m_roles)) + return; + json::array *roles_arr = new json::array (); + for (int i = 0; i < (int)diagnostic_artifact_role::NUM_ROLES; i++) + if (bitmap_bit_p (m_roles, i)) + { + enum diagnostic_artifact_role role = (enum diagnostic_artifact_role)i; + roles_arr->append (new json::string (get_artifact_role_string (role))); + } + set ("roles", roles_arr); +} + /* class sarif_result : public sarif_object. */ /* Handle secondary diagnostics that occur within a diagnostic group. @@ -320,7 +456,8 @@ sarif_result::on_nested_diagnostic (diagnostic_context *context, sometimes these will related to current_function_decl, but often they won't. */ json::object *location_obj - = builder->make_location_object (*diagnostic.richloc, NULL); + = builder->make_location_object (*diagnostic.richloc, NULL, + diagnostic_artifact_role::result_file); json::object *message_obj = builder->make_message_object (pp_formatted_text (context->printer)); pp_clear_output_area (context->printer); @@ -372,7 +509,9 @@ sarif_ice_notification::sarif_ice_notification (diagnostic_context *context, sarif_builder *builder) { /* "locations" property (SARIF v2.1.0 section 3.58.4). */ - json::array *locations_arr = builder->make_locations_arr (diagnostic); + json::array *locations_arr + = builder->make_locations_arr (diagnostic, + diagnostic_artifact_role::result_file); set ("locations", locations_arr); /* "message" property (SARIF v2.1.0 section 3.85.5). */ @@ -403,6 +542,7 @@ sarif_thread_flow::sarif_thread_flow (const diagnostic_thread &thread) /* sarif_builder's ctor. */ sarif_builder::sarif_builder (diagnostic_context *context, + const char *main_input_filename_, bool formatted) : m_context (context), m_invocation_obj (new sarif_invocation ()), @@ -414,6 +554,15 @@ sarif_builder::sarif_builder (diagnostic_context *context, m_tabstop (context->m_tabstop), m_formatted (formatted) { + /* 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). */ + get_or_create_artifact (main_input_filename_, + diagnostic_artifact_role::analysis_target, + false); } /* Implementation of "end_diagnostic" for SARIF output. */ @@ -599,7 +748,9 @@ sarif_builder::make_result_object (diagnostic_context *context, result_obj->set ("message", message_obj); /* "locations" property (SARIF v2.1.0 section 3.27.12). */ - json::array *locations_arr = make_locations_arr (diagnostic); + json::array *locations_arr + = make_locations_arr (diagnostic, + diagnostic_artifact_role::result_file); result_obj->set ("locations", locations_arr); /* "codeFlows" property (SARIF v2.1.0 section 3.27.18). */ @@ -729,7 +880,8 @@ make_tool_component_reference_object_for_cwe () const - a "notification" object (SARIF v2.1.0 section 3.58.4). */ json::array * -sarif_builder::make_locations_arr (const diagnostic_info &diagnostic) +sarif_builder::make_locations_arr (const diagnostic_info &diagnostic, + enum diagnostic_artifact_role role) { json::array *locations_arr = new json::array (); const logical_location *logical_loc = NULL; @@ -737,7 +889,7 @@ sarif_builder::make_locations_arr (const diagnostic_info &diagnostic) logical_loc = client_data_hooks->get_current_logical_location (); json::object *location_obj - = make_location_object (*diagnostic.richloc, logical_loc); + = make_location_object (*diagnostic.richloc, logical_loc, role); locations_arr->append (location_obj); return locations_arr; } @@ -763,7 +915,8 @@ set_any_logical_locs_arr (json::object *location_obj, json::object * sarif_builder::make_location_object (const rich_location &rich_loc, - const logical_location *logical_loc) + const logical_location *logical_loc, + enum diagnostic_artifact_role role) { json::object *location_obj = new json::object (); @@ -771,7 +924,8 @@ sarif_builder::make_location_object (const rich_location &rich_loc, location_t loc = rich_loc.get_loc (); /* "physicalLocation" property (SARIF v2.1.0 section 3.28.3). */ - if (json::object *phs_loc_obj = maybe_make_physical_location_object (loc)) + if (json::object *phs_loc_obj = maybe_make_physical_location_object (loc, + role)) location_obj->set ("physicalLocation", phs_loc_obj); /* "logicalLocations" property (SARIF v2.1.0 section 3.28.4). */ @@ -784,13 +938,15 @@ sarif_builder::make_location_object (const rich_location &rich_loc, within a diagnostic_path. */ json::object * -sarif_builder::make_location_object (const diagnostic_event &event) +sarif_builder::make_location_object (const diagnostic_event &event, + enum diagnostic_artifact_role role) { json::object *location_obj = new json::object (); /* "physicalLocation" property (SARIF v2.1.0 section 3.28.3). */ location_t loc = event.get_location (); - if (json::object *phs_loc_obj = maybe_make_physical_location_object (loc)) + if (json::object *phs_loc_obj + = maybe_make_physical_location_object (loc, role)) location_obj->set ("physicalLocation", phs_loc_obj); /* "logicalLocations" property (SARIF v2.1.0 section 3.28.4). */ @@ -806,11 +962,15 @@ sarif_builder::make_location_object (const diagnostic_event &event) } /* Make a physicalLocation object (SARIF v2.1.0 section 3.29) for LOC, - or return NULL; - Add any filename to the m_artifacts. */ + + Ensure that we have an artifact object for the file, adding ROLE to it, + and flagging that we will attempt to embed the contents of the artifact + when writing it out. */ json::object * -sarif_builder::maybe_make_physical_location_object (location_t loc) +sarif_builder:: +maybe_make_physical_location_object (location_t loc, + enum diagnostic_artifact_role role) { if (loc <= BUILTINS_LOCATION || LOCATION_FILE (loc) == NULL) return NULL; @@ -820,7 +980,7 @@ sarif_builder::maybe_make_physical_location_object (location_t loc) /* "artifactLocation" property (SARIF v2.1.0 section 3.29.3). */ json::object *artifact_loc_obj = make_artifact_location_object (loc); phys_loc_obj->set ("artifactLocation", artifact_loc_obj); - m_filenames.add (LOCATION_FILE (loc)); + get_or_create_artifact (LOCATION_FILE (loc), role, true); /* "region" property (SARIF v2.1.0 section 3.29.4). */ if (json::object *region_obj = maybe_make_region_object (loc)) @@ -1167,7 +1327,8 @@ sarif_builder::make_thread_flow_location_object (const diagnostic_event &ev, ev.maybe_add_sarif_properties (*thread_flow_loc_obj); /* "location" property (SARIF v2.1.0 section 3.38.3). */ - json::object *location_obj = make_location_object (ev); + json::object *location_obj + = make_location_object (ev, diagnostic_artifact_role::traced_file); thread_flow_loc_obj->set ("location", location_obj); /* "kinds" property (SARIF v2.1.0 section 3.38.8). */ @@ -1335,9 +1496,12 @@ sarif_builder::make_run_object (sarif_invocation *invocation_obj, /* "artifacts" property (SARIF v2.1.0 section 3.14.15). */ json::array *artifacts_arr = new json::array (); - for (auto iter : m_filenames) + for (auto iter : m_filename_to_artifact_map) { - json::object *artifact_obj = make_artifact_object (iter); + sarif_artifact *artifact_obj = iter.second; + if (artifact_obj->embed_contents_p ()) + artifact_obj->populate_contents (*this); + artifact_obj->populate_roles (); artifacts_arr->append (artifact_obj); } run_obj->set ("artifacts", artifacts_arr); @@ -1508,29 +1672,52 @@ sarif_builder::maybe_make_cwe_taxonomy_object () const return taxonomy_obj; } -/* Make an artifact object (SARIF v2.1.0 section 3.24). */ +/* Ensure that we have an artifact object (SARIF v2.1.0 section 3.24) + for FILENAME, adding it to m_filename_to_artifact_map if not already + found, and adding ROLE to it. + If EMBED_CONTENTS is true, then flag that we will attempt to embed the + contents of this artifact when writing it out. */ -json::object * -sarif_builder::make_artifact_object (const char *filename) +sarif_artifact & +sarif_builder::get_or_create_artifact (const char *filename, + enum diagnostic_artifact_role role, + bool embed_contents) { - json::object *artifact_obj = new json::object (); + if (auto *slot = m_filename_to_artifact_map.get (filename)) + { + (*slot)->add_role (role, embed_contents); + return **slot; + } + + sarif_artifact *artifact_obj = new sarif_artifact (filename); + artifact_obj->add_role (role, embed_contents); + m_filename_to_artifact_map.put (filename, artifact_obj); /* "location" property (SARIF v2.1.0 section 3.24.2). */ json::object *artifact_loc_obj = make_artifact_location_object (filename); artifact_obj->set ("location", artifact_loc_obj); - /* "contents" property (SARIF v2.1.0 section 3.24.8). */ - if (json::object *artifact_content_obj - = maybe_make_artifact_content_object (filename)) - artifact_obj->set ("contents", artifact_content_obj); - /* "sourceLanguage" property (SARIF v2.1.0 section 3.24.10). */ - if (auto client_data_hooks = m_context->get_client_data_hooks ()) - if (const char *source_lang - = client_data_hooks->maybe_get_sarif_source_language (filename)) - artifact_obj->set_string ("sourceLanguage", source_lang); + switch (role) + { + default: + gcc_unreachable (); + case diagnostic_artifact_role::analysis_target: + case diagnostic_artifact_role::result_file: + case diagnostic_artifact_role::traced_file: + /* Assume that these are in the source language. */ + if (auto client_data_hooks = m_context->get_client_data_hooks ()) + if (const char *source_lang + = client_data_hooks->maybe_get_sarif_source_language (filename)) + artifact_obj->set_string ("sourceLanguage", source_lang); + break; + + case diagnostic_artifact_role::debug_output_file: + /* Assume that these are not in the source language. */ + break; + } - return artifact_obj; + return *artifact_obj; } /* Make an artifactContent object (SARIF v2.1.0 section 3.3) for the @@ -1728,9 +1915,10 @@ public: protected: sarif_output_format (diagnostic_context &context, + const char *main_input_filename_, bool formatted) : diagnostic_output_format (context), - m_builder (&context, formatted) + m_builder (&context, main_input_filename_, formatted) {} sarif_builder m_builder; @@ -1740,9 +1928,10 @@ class sarif_stream_output_format : public sarif_output_format { public: sarif_stream_output_format (diagnostic_context &context, + const char *main_input_filename_, bool formatted, FILE *stream) - : sarif_output_format (context, formatted), + : sarif_output_format (context, main_input_filename_, formatted), m_stream (stream) { } @@ -1762,9 +1951,10 @@ class sarif_file_output_format : public sarif_output_format { public: sarif_file_output_format (diagnostic_context &context, + const char *main_input_filename_, bool formatted, const char *base_file_name) - : sarif_output_format (context, formatted), + : sarif_output_format (context, main_input_filename_, formatted), m_base_file_name (xstrdup (base_file_name)) { } @@ -1820,12 +2010,15 @@ diagnostic_output_format_init_sarif (diagnostic_context *context) void diagnostic_output_format_init_sarif_stderr (diagnostic_context *context, + const char *main_input_filename_, bool formatted) { diagnostic_output_format_init_sarif (context); - context->set_output_format (new sarif_stream_output_format (*context, - formatted, - stderr)); + context->set_output_format + (new sarif_stream_output_format (*context, + main_input_filename_, + formatted, + stderr)); } /* Populate CONTEXT in preparation for SARIF output to a file named @@ -1833,24 +2026,30 @@ diagnostic_output_format_init_sarif_stderr (diagnostic_context *context, void diagnostic_output_format_init_sarif_file (diagnostic_context *context, + const char *main_input_filename_, bool formatted, const char *base_file_name) { diagnostic_output_format_init_sarif (context); - context->set_output_format (new sarif_file_output_format (*context, - formatted, - base_file_name)); + context->set_output_format + (new sarif_file_output_format (*context, + main_input_filename_, + formatted, + base_file_name)); } /* Populate CONTEXT in preparation for SARIF output to STREAM. */ void diagnostic_output_format_init_sarif_stream (diagnostic_context *context, + const char *main_input_filename_, bool formatted, FILE *stream) { diagnostic_output_format_init_sarif (context); - context->set_output_format (new sarif_stream_output_format (*context, - formatted, - stream)); + context->set_output_format + (new sarif_stream_output_format (*context, + main_input_filename_, + formatted, + stream)); } diff --git a/gcc/diagnostic.cc b/gcc/diagnostic.cc index f27b2f1a492c..1b4def06f726 100644 --- a/gcc/diagnostic.cc +++ b/gcc/diagnostic.cc @@ -2446,6 +2446,7 @@ diagnostic_text_output_format::on_diagram (const diagnostic_diagram &diagram) void diagnostic_output_format_init (diagnostic_context *context, + const char *main_input_filename_, const char *base_file_name, enum diagnostics_output_format format, bool json_formatting) @@ -2471,11 +2472,13 @@ diagnostic_output_format_init (diagnostic_context *context, case DIAGNOSTICS_OUTPUT_FORMAT_SARIF_STDERR: diagnostic_output_format_init_sarif_stderr (context, + main_input_filename_, json_formatting); break; case DIAGNOSTICS_OUTPUT_FORMAT_SARIF_FILE: diagnostic_output_format_init_sarif_file (context, + main_input_filename_, json_formatting, base_file_name); break; diff --git a/gcc/diagnostic.h b/gcc/diagnostic.h index 7431f5a6e12c..4632aac73c6b 100644 --- a/gcc/diagnostic.h +++ b/gcc/diagnostic.h @@ -1082,6 +1082,7 @@ extern char *file_name_as_prefix (diagnostic_context *, const char *); extern char *build_message_string (const char *, ...) ATTRIBUTE_PRINTF_1; extern void diagnostic_output_format_init (diagnostic_context *, + const char *main_input_filename_, const char *base_file_name, enum diagnostics_output_format, bool json_formatting); @@ -1091,11 +1092,14 @@ extern void diagnostic_output_format_init_json_file (diagnostic_context *context bool formatted, const char *base_file_name); extern void diagnostic_output_format_init_sarif_stderr (diagnostic_context *context, + const char *main_input_filename_, bool formatted); extern void diagnostic_output_format_init_sarif_file (diagnostic_context *context, + const char *main_input_filename_, bool formatted, const char *base_file_name); extern void diagnostic_output_format_init_sarif_stream (diagnostic_context *context, + const char *main_input_filename_, bool formatted, FILE *stream); diff --git a/gcc/gcc.cc b/gcc/gcc.cc index 830a4700a87b..d80b604a48df 100644 --- a/gcc/gcc.cc +++ b/gcc/gcc.cc @@ -4354,7 +4354,8 @@ driver_handle_option (struct gcc_options *opts, { const char *basename = (opts->x_dump_base_name ? opts->x_dump_base_name : opts->x_main_input_basename); - diagnostic_output_format_init (dc, basename, + diagnostic_output_format_init (dc, + opts->x_main_input_filename, basename, (enum diagnostics_output_format)value, opts->x_flag_diagnostics_json_formatting); break; diff --git a/gcc/opts.cc b/gcc/opts.cc index f80d5d4ba8f9..1b1b46455af6 100644 --- a/gcc/opts.cc +++ b/gcc/opts.cc @@ -2961,7 +2961,8 @@ common_handle_option (struct gcc_options *opts, { const char *basename = (opts->x_dump_base_name ? opts->x_dump_base_name : opts->x_main_input_basename); - diagnostic_output_format_init (dc, basename, + diagnostic_output_format_init (dc, + opts->x_main_input_filename, basename, (enum diagnostics_output_format)value, opts->x_flag_diagnostics_json_formatting); break; diff --git a/gcc/testsuite/c-c++-common/analyzer/sarif-path-role.c b/gcc/testsuite/c-c++-common/analyzer/sarif-path-role.c new file mode 100644 index 000000000000..d0f6cefcf4d0 --- /dev/null +++ b/gcc/testsuite/c-c++-common/analyzer/sarif-path-role.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-additional-options " -fno-diagnostics-json-formatting -fdiagnostics-format=sarif-file" } */ + +#include <stdlib.h> + +void test_1 (void) +{ + void *ptr = malloc (1024); +#include "sarif-path-role.h" + free (ptr); +} + +/* Verify SARIF output. + + { dg-final { verify-sarif-file } } + + Verify that the artifact for the header has this role, given + that it's only referenced by an execution path event. + + { dg-final { scan-sarif-file "\"roles\": \\\[\"tracedFile\"\\\]" } } +*/ diff --git a/gcc/testsuite/c-c++-common/analyzer/sarif-path-role.h b/gcc/testsuite/c-c++-common/analyzer/sarif-path-role.h new file mode 100644 index 000000000000..fe620f9b82a3 --- /dev/null +++ b/gcc/testsuite/c-c++-common/analyzer/sarif-path-role.h @@ -0,0 +1,2 @@ +/* Generate an execution path event within a header. */ +free (ptr); 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 f0dcaa705ca6..50375465483d 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 @@ -20,6 +20,11 @@ { dg-final { scan-sarif-file "\"contents\": " } } { dg-final { scan-sarif-file "\"text\": " } } + + Verify that this file's "role" is "analysisTarget", as per + "NOTE 3" in SARIF v2.1.0 section 3.24.6. + { dg-final { scan-sarif-file "\"roles\": \\\[\"analysisTarget\"\\\]" } } + { dg-final { scan-sarif-file "\"tool\": " } } { dg-final { scan-sarif-file "\"driver\": " } } { dg-final { scan-sarif-file "\"name\": \"GNU C" } } diff --git a/gcc/testsuite/c-c++-common/diagnostic-format-sarif-file-header-role.c b/gcc/testsuite/c-c++-common/diagnostic-format-sarif-file-header-role.c new file mode 100644 index 000000000000..bfbbe4c2946b --- /dev/null +++ b/gcc/testsuite/c-c++-common/diagnostic-format-sarif-file-header-role.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-options "-fdiagnostics-format=sarif-file" } */ + +/* Generate a warning in a header file. */ +#include "diagnostic-format-sarif-file-header-role.h" + +/* Verify that some JSON was written to a file with the expected name. */ +/* { dg-final { verify-sarif-file } } */ + +/* Verify that the header file's "role" is "resultFile", as per "NOTE 3" + in SARIF v2.1.0 section 3.24.6. */ +/* { dg-final { scan-sarif-file "\"roles\": \\\[\"resultFile\"\\\]" } } */ diff --git a/gcc/testsuite/c-c++-common/diagnostic-format-sarif-file-header-role.h b/gcc/testsuite/c-c++-common/diagnostic-format-sarif-file-header-role.h new file mode 100644 index 000000000000..0111cd2fe7cc --- /dev/null +++ b/gcc/testsuite/c-c++-common/diagnostic-format-sarif-file-header-role.h @@ -0,0 +1 @@ +#warning this is a warning from a header file diff --git a/gcc/testsuite/c-c++-common/diagnostic-format-sarif-file-no-results.c b/gcc/testsuite/c-c++-common/diagnostic-format-sarif-file-no-results.c new file mode 100644 index 000000000000..9540c3335aa2 --- /dev/null +++ b/gcc/testsuite/c-c++-common/diagnostic-format-sarif-file-no-results.c @@ -0,0 +1,44 @@ +/* Verify behavior of SARIF output for the "no diagnostics" case. */ + +/* { dg-do compile } */ +/* { dg-options "-fdiagnostics-format=sarif-file" } */ + +int non_empty; + +/* Verify that some JSON was written to a file with the expected name. */ +/* { dg-final { verify-sarif-file } } */ + +/* We expect various properties. + The indentation here reflects the expected hierarchy, though these tests + don't check for that, merely the string fragments we expect. + { dg-final { scan-sarif-file "\"version\": \"2.1.0\"" } } + { dg-final { scan-sarif-file "\"runs\": \\\[" } } + { dg-final { scan-sarif-file "\"artifacts\": \\\[" } } + { dg-final { scan-sarif-file "\"location\": " } } + { dg-final { scan-sarif-file "\"uri\": " } } + + { dg-final { scan-sarif-file "\"sourceLanguage\": \"c\"" { target c } } } + { dg-final { scan-sarif-file "\"sourceLanguage\": \"cplusplus\"" { target c++ } } } + + We expect the contents of the file to *not* be quoted if + there are no results. + { dg-final { scan-sarif-file-not "\"contents\": " } } + { dg-final { scan-sarif-file-not "\"text\": " } } + + Verify that this file's "role" is "analysisTarget", as per + "NOTE 3" in SARIF v2.1.0 section 3.24.6. + { dg-final { scan-sarif-file "\"roles\": \\\[\"analysisTarget\"\\\]" } } + + { dg-final { scan-sarif-file "\"tool\": " } } + { dg-final { scan-sarif-file "\"driver\": " } } + { dg-final { scan-sarif-file "\"name\": \"GNU C" } } + { dg-final { scan-sarif-file "\"fullName\": \"GNU C" } } + { dg-final { scan-sarif-file "\"informationUri\": \"" } } + + { dg-final { scan-sarif-file "\"invocations\": \\\[" } } + { dg-final { scan-sarif-file "\"toolExecutionNotifications\": \\\[\\\]" } } + { dg-final { scan-sarif-file "\"executionSuccessful\": true" } } + + We expect an empty list for "results" + { dg-final { scan-sarif-file "\"results\": \\\[\\\]" } } */ + -- 2.26.3