LCOV - code coverage report
Current view: top level - gcc - diagnostic-format-sarif.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 91.9 % 666 612
Test Date: 2024-03-23 14:05:01 Functions: 90.5 % 74 67
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : /* SARIF output for diagnostics
       2                 :             :    Copyright (C) 2018-2024 Free Software Foundation, Inc.
       3                 :             :    Contributed by David Malcolm <dmalcolm@redhat.com>.
       4                 :             : 
       5                 :             : This file is part of GCC.
       6                 :             : 
       7                 :             : GCC is free software; you can redistribute it and/or modify it under
       8                 :             : the terms of the GNU General Public License as published by the Free
       9                 :             : Software Foundation; either version 3, or (at your option) any later
      10                 :             : version.
      11                 :             : 
      12                 :             : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      13                 :             : WARRANTY; without even the implied warranty of MERCHANTABILITY or
      14                 :             : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      15                 :             : for more details.
      16                 :             : 
      17                 :             : You should have received a copy of the GNU General Public License
      18                 :             : along with GCC; see the file COPYING3.  If not see
      19                 :             : <http://www.gnu.org/licenses/>.  */
      20                 :             : 
      21                 :             : 
      22                 :             : #include "config.h"
      23                 :             : #define INCLUDE_VECTOR
      24                 :             : #include "system.h"
      25                 :             : #include "coretypes.h"
      26                 :             : #include "diagnostic.h"
      27                 :             : #include "diagnostic-metadata.h"
      28                 :             : #include "diagnostic-path.h"
      29                 :             : #include "json.h"
      30                 :             : #include "cpplib.h"
      31                 :             : #include "logical-location.h"
      32                 :             : #include "diagnostic-client-data-hooks.h"
      33                 :             : #include "diagnostic-diagram.h"
      34                 :             : #include "text-art/canvas.h"
      35                 :             : #include "diagnostic-format-sarif.h"
      36                 :             : 
      37                 :             : class sarif_builder;
      38                 :             : 
      39                 :             : /* Subclass of json::object for SARIF invocation objects
      40                 :             :    (SARIF v2.1.0 section 3.20).  */
      41                 :             : 
      42                 :             : class sarif_invocation : public sarif_object
      43                 :             : {
      44                 :             : public:
      45                 :          79 :   sarif_invocation ()
      46                 :         237 :   : m_notifications_arr (new json::array ()),
      47                 :          79 :     m_success (true)
      48                 :          79 :   {}
      49                 :             : 
      50                 :             :   void add_notification_for_ice (diagnostic_context *context,
      51                 :             :                                  const diagnostic_info &diagnostic,
      52                 :             :                                  sarif_builder *builder);
      53                 :             :   void prepare_to_flush (diagnostic_context *context);
      54                 :             : 
      55                 :             : private:
      56                 :             :   json::array *m_notifications_arr;
      57                 :             :   bool m_success;
      58                 :             : };
      59                 :             : 
      60                 :             : /* Subclass of sarif_object for SARIF result objects
      61                 :             :    (SARIF v2.1.0 section 3.27).  */
      62                 :             : 
      63                 :             : class sarif_result : public sarif_object
      64                 :             : {
      65                 :             : public:
      66                 :         164 :   sarif_result () : m_related_locations_arr (NULL) {}
      67                 :             : 
      68                 :             :   void
      69                 :             :   on_nested_diagnostic (diagnostic_context *context,
      70                 :             :                         const diagnostic_info &diagnostic,
      71                 :             :                         diagnostic_t orig_diag_kind,
      72                 :             :                         sarif_builder *builder);
      73                 :             :   void on_diagram (diagnostic_context *context,
      74                 :             :                    const diagnostic_diagram &diagram,
      75                 :             :                    sarif_builder *builder);
      76                 :             : 
      77                 :             : private:
      78                 :             :   void add_related_location (json::object *location_obj);
      79                 :             : 
      80                 :             :   json::array *m_related_locations_arr;
      81                 :             : };
      82                 :             : 
      83                 :             : /* Subclass of sarif_object for SARIF notification objects
      84                 :             :    (SARIF v2.1.0 section 3.58).
      85                 :             : 
      86                 :             :    This subclass is specifically for notifying when an
      87                 :             :    internal compiler error occurs.  */
      88                 :             : 
      89                 :             : class sarif_ice_notification : public sarif_object
      90                 :             : {
      91                 :             : public:
      92                 :             :   sarif_ice_notification (diagnostic_context *context,
      93                 :             :                           const diagnostic_info &diagnostic,
      94                 :             :                           sarif_builder *builder);
      95                 :             : };
      96                 :             : 
      97                 :             : /* Subclass of sarif_object for SARIF threadFlow objects
      98                 :             :    (SARIF v2.1.0 section 3.37) for PATH.  */
      99                 :             : 
     100                 :             : class sarif_thread_flow : public sarif_object
     101                 :             : {
     102                 :             : public:
     103                 :             :   sarif_thread_flow (const diagnostic_thread &thread);
     104                 :             : 
     105                 :          59 :   void add_location (json::object *thread_flow_loc_obj)
     106                 :             :   {
     107                 :          59 :     m_locations_arr->append (thread_flow_loc_obj);
     108                 :             :   }
     109                 :             : 
     110                 :             : private:
     111                 :             :   json::array *m_locations_arr;
     112                 :             : };
     113                 :             : 
     114                 :             : /* A class for managing SARIF output (for -fdiagnostics-format=sarif-stderr
     115                 :             :    and -fdiagnostics-format=sarif-file).
     116                 :             : 
     117                 :             :    As diagnostics occur, we build "result" JSON objects, and
     118                 :             :    accumulate state:
     119                 :             :    - which source files are referenced
     120                 :             :    - which warnings are emitted
     121                 :             :    - which CWEs are used
     122                 :             : 
     123                 :             :    At the end of the compile, we use the above to build the full SARIF
     124                 :             :    object tree, adding the result objects to the correct place, and
     125                 :             :    creating objects for the various source files, warnings and CWEs
     126                 :             :    referenced.
     127                 :             : 
     128                 :             :    Implemented:
     129                 :             :    - fix-it hints
     130                 :             :    - CWE metadata
     131                 :             :    - diagnostic groups (see limitations below)
     132                 :             :    - logical locations (e.g. cfun)
     133                 :             : 
     134                 :             :    Known limitations:
     135                 :             :    - GCC supports one-deep nesting of diagnostics (via auto_diagnostic_group),
     136                 :             :      but we only capture location and message information from such nested
     137                 :             :      diagnostics (e.g. we ignore fix-it hints on them)
     138                 :             :    - doesn't yet capture command-line arguments: would be run.invocations
     139                 :             :      property (SARIF v2.1.0 section 3.14.11), as invocation objects
     140                 :             :      (SARIF v2.1.0 section 3.20), but we'd want to capture the arguments to
     141                 :             :      toplev::main, and the response files.
     142                 :             :    - doesn't capture escape_on_output_p
     143                 :             :    - doesn't capture secondary locations within a rich_location
     144                 :             :      (perhaps we should use the "relatedLocations" property: SARIF v2.1.0
     145                 :             :      section 3.27.22)
     146                 :             :    - doesn't capture "artifact.encoding" property
     147                 :             :      (SARIF v2.1.0 section 3.24.9).
     148                 :             :    - doesn't capture hashes of the source files
     149                 :             :      ("artifact.hashes" property (SARIF v2.1.0 section 3.24.11).
     150                 :             :    - doesn't capture the "analysisTarget" property
     151                 :             :      (SARIF v2.1.0 section 3.27.13).
     152                 :             :    - doesn't capture labelled ranges
     153                 :             :    - doesn't capture -Werror cleanly
     154                 :             :    - doesn't capture inlining information (can SARIF handle this?)
     155                 :             :    - doesn't capture macro expansion information (can SARIF handle this?).  */
     156                 :             : 
     157                 :             : class sarif_builder
     158                 :             : {
     159                 :             : public:
     160                 :             :   sarif_builder (diagnostic_context *context,
     161                 :             :                  bool formatted);
     162                 :             : 
     163                 :             :   void end_diagnostic (diagnostic_context *context,
     164                 :             :                        const diagnostic_info &diagnostic,
     165                 :             :                        diagnostic_t orig_diag_kind);
     166                 :             :   void emit_diagram (diagnostic_context *context,
     167                 :             :                      const diagnostic_diagram &diagram);
     168                 :             :   void end_group ();
     169                 :             : 
     170                 :             :   void flush_to_file (FILE *outf);
     171                 :             : 
     172                 :             :   json::array *make_locations_arr (const diagnostic_info &diagnostic);
     173                 :             :   json::object *make_location_object (const rich_location &rich_loc,
     174                 :             :                                       const logical_location *logical_loc);
     175                 :             :   json::object *make_message_object (const char *msg) const;
     176                 :             :   json::object *
     177                 :             :   make_message_object_for_diagram (diagnostic_context *context,
     178                 :             :                                    const diagnostic_diagram &diagram);
     179                 :             : 
     180                 :             : private:
     181                 :             :   sarif_result *make_result_object (diagnostic_context *context,
     182                 :             :                                     const diagnostic_info &diagnostic,
     183                 :             :                                     diagnostic_t orig_diag_kind);
     184                 :             :   void set_any_logical_locs_arr (json::object *location_obj,
     185                 :             :                                  const logical_location *logical_loc);
     186                 :             :   json::object *make_location_object (const diagnostic_event &event);
     187                 :             :   json::object *make_code_flow_object (const diagnostic_path &path);
     188                 :             :   json::object *
     189                 :             :   make_thread_flow_location_object (const diagnostic_event &event,
     190                 :             :                                     int path_event_idx);
     191                 :             :   json::array *maybe_make_kinds_array (diagnostic_event::meaning m) const;
     192                 :             :   json::object *maybe_make_physical_location_object (location_t loc);
     193                 :             :   json::object *make_artifact_location_object (location_t loc);
     194                 :             :   json::object *make_artifact_location_object (const char *filename);
     195                 :             :   json::object *make_artifact_location_object_for_pwd () const;
     196                 :             :   json::object *maybe_make_region_object (location_t loc) const;
     197                 :             :   json::object *maybe_make_region_object_for_context (location_t loc) const;
     198                 :             :   json::object *make_region_object_for_hint (const fixit_hint &hint) const;
     199                 :             :   json::object *make_multiformat_message_string (const char *msg) const;
     200                 :             :   json::object *make_top_level_object (sarif_invocation *invocation_obj,
     201                 :             :                                        json::array *results);
     202                 :             :   json::object *make_run_object (sarif_invocation *invocation_obj,
     203                 :             :                                  json::array *results);
     204                 :             :   json::object *make_tool_object () const;
     205                 :             :   json::object *make_driver_tool_component_object () const;
     206                 :             :   json::array *maybe_make_taxonomies_array () const;
     207                 :             :   json::object *maybe_make_cwe_taxonomy_object () const;
     208                 :             :   json::object *make_tool_component_reference_object_for_cwe () const;
     209                 :             :   json::object *
     210                 :             :   make_reporting_descriptor_object_for_warning (diagnostic_context *context,
     211                 :             :                                                 const diagnostic_info &diagnostic,
     212                 :             :                                                 diagnostic_t orig_diag_kind,
     213                 :             :                                                 const char *option_text);
     214                 :             :   json::object *make_reporting_descriptor_object_for_cwe_id (int cwe_id) const;
     215                 :             :   json::object *
     216                 :             :   make_reporting_descriptor_reference_object_for_cwe_id (int cwe_id);
     217                 :             :   json::object *make_artifact_object (const char *filename);
     218                 :             :   char *get_source_lines (const char *filename,
     219                 :             :                           int start_line,
     220                 :             :                           int end_line) const;
     221                 :             :   json::object *maybe_make_artifact_content_object (const char *filename) const;
     222                 :             :   json::object *maybe_make_artifact_content_object (const char *filename,
     223                 :             :                                                     int start_line,
     224                 :             :                                                     int end_line) const;
     225                 :             :   json::object *make_fix_object (const rich_location &rich_loc);
     226                 :             :   json::object *make_artifact_change_object (const rich_location &richloc);
     227                 :             :   json::object *make_replacement_object (const fixit_hint &hint) const;
     228                 :             :   json::object *make_artifact_content_object (const char *text) const;
     229                 :             :   int get_sarif_column (expanded_location exploc) const;
     230                 :             : 
     231                 :             :   diagnostic_context *m_context;
     232                 :             : 
     233                 :             :   /* The JSON object for the invocation object.  */
     234                 :             :   sarif_invocation *m_invocation_obj;
     235                 :             : 
     236                 :             :   /* The JSON array of pending diagnostics.  */
     237                 :             :   json::array *m_results_array;
     238                 :             : 
     239                 :             :   /* The JSON object for the result object (if any) in the current
     240                 :             :      diagnostic group.  */
     241                 :             :   sarif_result *m_cur_group_result;
     242                 :             : 
     243                 :             :   hash_set <const char *> m_filenames;
     244                 :             :   bool m_seen_any_relative_paths;
     245                 :             :   hash_set <free_string_hash> m_rule_id_set;
     246                 :             :   json::array *m_rules_arr;
     247                 :             : 
     248                 :             :   /* The set of all CWE IDs we've seen, if any.  */
     249                 :             :   hash_set <int_hash <int, 0, 1> > m_cwe_id_set;
     250                 :             : 
     251                 :             :   int m_tabstop;
     252                 :             : 
     253                 :             :   bool m_formatted;
     254                 :             : };
     255                 :             : 
     256                 :             : /* class sarif_object : public json::object.  */
     257                 :             : 
     258                 :             : sarif_property_bag &
     259                 :         100 : sarif_object::get_or_create_properties ()
     260                 :             : {
     261                 :         100 :   json::value *properties_val = get ("properties");
     262                 :         100 :   if (properties_val)
     263                 :             :     {
     264                 :          25 :       if (properties_val->get_kind () == json::JSON_OBJECT)
     265                 :             :         return *static_cast <sarif_property_bag *> (properties_val);
     266                 :             :     }
     267                 :             : 
     268                 :          75 :   sarif_property_bag *bag = new sarif_property_bag ();
     269                 :          75 :   set ("properties", bag);
     270                 :          75 :   return *bag;
     271                 :             : }
     272                 :             : 
     273                 :             : /* class sarif_invocation : public sarif_object.  */
     274                 :             : 
     275                 :             : /* Handle an internal compiler error DIAGNOSTIC occurring on CONTEXT.
     276                 :             :    Add an object representing the ICE to the notifications array.  */
     277                 :             : 
     278                 :             : void
     279                 :           2 : sarif_invocation::add_notification_for_ice (diagnostic_context *context,
     280                 :             :                                             const diagnostic_info &diagnostic,
     281                 :             :                                             sarif_builder *builder)
     282                 :             : {
     283                 :           2 :   m_success = false;
     284                 :             : 
     285                 :           2 :   sarif_ice_notification *notification_obj
     286                 :           2 :     = new sarif_ice_notification (context, diagnostic, builder);
     287                 :           2 :   m_notifications_arr->append (notification_obj);
     288                 :           2 : }
     289                 :             : 
     290                 :             : void
     291                 :          79 : sarif_invocation::prepare_to_flush (diagnostic_context *context)
     292                 :             : {
     293                 :             :   /* "executionSuccessful" property (SARIF v2.1.0 section 3.20.14).  */
     294                 :          79 :   set_bool ("executionSuccessful", m_success);
     295                 :             : 
     296                 :             :   /* "toolExecutionNotifications" property (SARIF v2.1.0 section 3.20.21).  */
     297                 :          79 :   set ("toolExecutionNotifications", m_notifications_arr);
     298                 :             : 
     299                 :             :   /* Call client hook, allowing it to create a custom property bag for
     300                 :             :      this object (SARIF v2.1.0 section 3.8) e.g. for recording time vars.  */
     301                 :          79 :   if (auto client_data_hooks = context->get_client_data_hooks ())
     302                 :          79 :     client_data_hooks->add_sarif_invocation_properties (*this);
     303                 :          79 : }
     304                 :             : 
     305                 :             : /* class sarif_result : public sarif_object.  */
     306                 :             : 
     307                 :             : /* Handle secondary diagnostics that occur within a diagnostic group.
     308                 :             :    The closest SARIF seems to have to nested diagnostics is the
     309                 :             :    "relatedLocations" property of result objects (SARIF v2.1.0 section 3.27.22),
     310                 :             :    so we lazily set this property and populate the array if and when
     311                 :             :    secondary diagnostics occur (such as notes to a warning).  */
     312                 :             : 
     313                 :             : void
     314                 :         220 : sarif_result::on_nested_diagnostic (diagnostic_context *context,
     315                 :             :                                     const diagnostic_info &diagnostic,
     316                 :             :                                     diagnostic_t /*orig_diag_kind*/,
     317                 :             :                                     sarif_builder *builder)
     318                 :             : {
     319                 :             :   /* We don't yet generate meaningful logical locations for notes;
     320                 :             :      sometimes these will related to current_function_decl, but
     321                 :             :      often they won't.  */
     322                 :         220 :   json::object *location_obj
     323                 :         220 :     = builder->make_location_object (*diagnostic.richloc, NULL);
     324                 :         220 :   json::object *message_obj
     325                 :         220 :     = builder->make_message_object (pp_formatted_text (context->printer));
     326                 :         220 :   pp_clear_output_area (context->printer);
     327                 :         220 :   location_obj->set ("message", message_obj);
     328                 :             : 
     329                 :         220 :   add_related_location (location_obj);
     330                 :         220 : }
     331                 :             : 
     332                 :             : /* Handle diagrams that occur within a diagnostic group.
     333                 :             :    The closest thing in SARIF seems to be to add a location to the
     334                 :             :    "releatedLocations" property  (SARIF v2.1.0 section 3.27.22),
     335                 :             :    and to put the diagram into the "message" property of that location
     336                 :             :    (SARIF v2.1.0 section 3.28.5).  */
     337                 :             : 
     338                 :             : void
     339                 :           5 : sarif_result::on_diagram (diagnostic_context *context,
     340                 :             :                           const diagnostic_diagram &diagram,
     341                 :             :                           sarif_builder *builder)
     342                 :             : {
     343                 :           5 :   json::object *location_obj = new json::object ();
     344                 :           5 :   json::object *message_obj
     345                 :           5 :     = builder->make_message_object_for_diagram (context, diagram);
     346                 :           5 :   location_obj->set ("message", message_obj);
     347                 :             : 
     348                 :           5 :   add_related_location (location_obj);
     349                 :           5 : }
     350                 :             : 
     351                 :             : /* Add LOCATION_OBJ to this result's "relatedLocations" array,
     352                 :             :    creating it if it doesn't yet exist.  */
     353                 :             : 
     354                 :             : void
     355                 :         225 : sarif_result::add_related_location (json::object *location_obj)
     356                 :             : {
     357                 :         225 :   if (!m_related_locations_arr)
     358                 :             :     {
     359                 :          25 :       m_related_locations_arr = new json::array ();
     360                 :          25 :       set ("relatedLocations", m_related_locations_arr);
     361                 :             :     }
     362                 :         225 :   m_related_locations_arr->append (location_obj);
     363                 :         225 : }
     364                 :             : 
     365                 :             : /* class sarif_ice_notification : public sarif_object.  */
     366                 :             : 
     367                 :             : /* sarif_ice_notification's ctor.
     368                 :             :    DIAGNOSTIC is an internal compiler error.  */
     369                 :             : 
     370                 :           2 : sarif_ice_notification::sarif_ice_notification (diagnostic_context *context,
     371                 :             :                                                 const diagnostic_info &diagnostic,
     372                 :           2 :                                                 sarif_builder *builder)
     373                 :             : {
     374                 :             :   /* "locations" property (SARIF v2.1.0 section 3.58.4).  */
     375                 :           2 :   json::array *locations_arr = builder->make_locations_arr (diagnostic);
     376                 :           2 :   set ("locations", locations_arr);
     377                 :             : 
     378                 :             :   /* "message" property (SARIF v2.1.0 section 3.85.5).  */
     379                 :           2 :   json::object *message_obj
     380                 :           2 :     = builder->make_message_object (pp_formatted_text (context->printer));
     381                 :           2 :   pp_clear_output_area (context->printer);
     382                 :           2 :   set ("message", message_obj);
     383                 :             : 
     384                 :             :   /* "level" property (SARIF v2.1.0 section 3.58.6).  */
     385                 :           2 :   set_string ("level", "error");
     386                 :           2 : }
     387                 :             : 
     388                 :             : /* class sarif_thread_flow : public sarif_object.  */
     389                 :             : 
     390                 :          18 : sarif_thread_flow::sarif_thread_flow (const diagnostic_thread &thread)
     391                 :             : {
     392                 :             :   /* "id" property (SARIF v2.1.0 section 3.37.2).  */
     393                 :          18 :   label_text name (thread.get_name (false));
     394                 :          18 :   set_string ("id", name.get ());
     395                 :             : 
     396                 :             :   /* "locations" property (SARIF v2.1.0 section 3.37.6).  */
     397                 :          18 :   m_locations_arr = new json::array ();
     398                 :          18 :   set ("locations", m_locations_arr);
     399                 :          18 : }
     400                 :             : 
     401                 :             : /* class sarif_builder.  */
     402                 :             : 
     403                 :             : /* sarif_builder's ctor.  */
     404                 :             : 
     405                 :          79 : sarif_builder::sarif_builder (diagnostic_context *context,
     406                 :          79 :                               bool formatted)
     407                 :          79 : : m_context (context),
     408                 :          79 :   m_invocation_obj (new sarif_invocation ()),
     409                 :          79 :   m_results_array (new json::array ()),
     410                 :          79 :   m_cur_group_result (NULL),
     411                 :          79 :   m_seen_any_relative_paths (false),
     412                 :         158 :   m_rule_id_set (),
     413                 :          79 :   m_rules_arr (new json::array ()),
     414                 :          79 :   m_tabstop (context->m_tabstop),
     415                 :         158 :   m_formatted (formatted)
     416                 :             : {
     417                 :          79 : }
     418                 :             : 
     419                 :             : /* Implementation of "end_diagnostic" for SARIF output.  */
     420                 :             : 
     421                 :             : void
     422                 :         304 : sarif_builder::end_diagnostic (diagnostic_context *context,
     423                 :             :                                const diagnostic_info &diagnostic,
     424                 :             :                                diagnostic_t orig_diag_kind)
     425                 :             : {
     426                 :         304 :   if (diagnostic.kind == DK_ICE || diagnostic.kind == DK_ICE_NOBT)
     427                 :             :     {
     428                 :           2 :       m_invocation_obj->add_notification_for_ice (context, diagnostic, this);
     429                 :           2 :       return;
     430                 :             :     }
     431                 :             : 
     432                 :         302 :   if (m_cur_group_result)
     433                 :             :     /* Nested diagnostic.  */
     434                 :         220 :     m_cur_group_result->on_nested_diagnostic (context,
     435                 :             :                                               diagnostic,
     436                 :             :                                               orig_diag_kind,
     437                 :             :                                               this);
     438                 :             :   else
     439                 :             :     {
     440                 :             :       /* Top-level diagnostic.  */
     441                 :          82 :       sarif_result *result_obj
     442                 :          82 :         = make_result_object (context, diagnostic, orig_diag_kind);
     443                 :          82 :       m_results_array->append (result_obj);
     444                 :          82 :       m_cur_group_result = result_obj;
     445                 :             :     }
     446                 :             : }
     447                 :             : 
     448                 :             : /* Implementation of diagnostic_context::m_diagrams.m_emission_cb
     449                 :             :    for SARIF output.  */
     450                 :             : 
     451                 :             : void
     452                 :           5 : sarif_builder::emit_diagram (diagnostic_context *context,
     453                 :             :                              const diagnostic_diagram &diagram)
     454                 :             : {
     455                 :             :   /* We must be within the emission of a top-level diagnostic.  */
     456                 :           5 :   gcc_assert (m_cur_group_result);
     457                 :           5 :   m_cur_group_result->on_diagram (context, diagram, this);
     458                 :           5 : }
     459                 :             : 
     460                 :             : /* Implementation of "end_group_cb" for SARIF output.  */
     461                 :             : 
     462                 :             : void
     463                 :          56 : sarif_builder::end_group ()
     464                 :             : {
     465                 :          56 :   m_cur_group_result = NULL;
     466                 :          56 : }
     467                 :             : 
     468                 :             : /* Create a top-level object, and add it to all the results
     469                 :             :    (and other entities) we've seen so far.
     470                 :             : 
     471                 :             :    Flush it all to OUTF.  */
     472                 :             : 
     473                 :             : void
     474                 :          79 : sarif_builder::flush_to_file (FILE *outf)
     475                 :             : {
     476                 :          79 :   m_invocation_obj->prepare_to_flush (m_context);
     477                 :          79 :   json::object *top = make_top_level_object (m_invocation_obj, m_results_array);
     478                 :          79 :   top->dump (outf, m_formatted);
     479                 :          79 :   m_invocation_obj = NULL;
     480                 :          79 :   m_results_array = NULL;
     481                 :          79 :   fprintf (outf, "\n");
     482                 :          79 :   delete top;
     483                 :          79 : }
     484                 :             : 
     485                 :             : /* Attempt to convert DIAG_KIND to a suitable value for the "level"
     486                 :             :    property (SARIF v2.1.0 section 3.27.10).
     487                 :             : 
     488                 :             :    Return NULL if there isn't one.  */
     489                 :             : 
     490                 :             : static const char *
     491                 :          82 : maybe_get_sarif_level (diagnostic_t diag_kind)
     492                 :             : {
     493                 :           0 :   switch (diag_kind)
     494                 :             :     {
     495                 :             :     case DK_WARNING:
     496                 :             :       return "warning";
     497                 :          21 :     case DK_ERROR:
     498                 :           0 :       return "error";
     499                 :           0 :     case DK_NOTE:
     500                 :           0 :     case DK_ANACHRONISM:
     501                 :           0 :       return "note";
     502                 :           0 :     default:
     503                 :           0 :       return NULL;
     504                 :             :     }
     505                 :             : }
     506                 :             : 
     507                 :             : /* Make a string for DIAG_KIND suitable for use a ruleId
     508                 :             :    (SARIF v2.1.0 section 3.27.5) as a fallback for when we don't
     509                 :             :    have anything better to use.  */
     510                 :             : 
     511                 :             : static char *
     512                 :          23 : make_rule_id_for_diagnostic_kind (diagnostic_t diag_kind)
     513                 :             : {
     514                 :          23 :   static const char *const diagnostic_kind_text[] = {
     515                 :             : #define DEFINE_DIAGNOSTIC_KIND(K, T, C) (T),
     516                 :             : #include "diagnostic.def"
     517                 :             : #undef DEFINE_DIAGNOSTIC_KIND
     518                 :             :     "must-not-happen"
     519                 :             :   };
     520                 :             :   /* Lose the trailing ": ".  */
     521                 :          23 :   const char *kind_text = diagnostic_kind_text[diag_kind];
     522                 :          23 :   size_t len = strlen (kind_text);
     523                 :          23 :   gcc_assert (len > 2);
     524                 :          23 :   gcc_assert (kind_text[len - 2] == ':');
     525                 :          23 :   gcc_assert (kind_text[len - 1] == ' ');
     526                 :          23 :   char *rstrip = xstrdup (kind_text);
     527                 :          23 :   rstrip[len - 2] = '\0';
     528                 :          23 :   return rstrip;
     529                 :             : }
     530                 :             : 
     531                 :             : /* Make a result object (SARIF v2.1.0 section 3.27) for DIAGNOSTIC.  */
     532                 :             : 
     533                 :             : sarif_result *
     534                 :          82 : sarif_builder::make_result_object (diagnostic_context *context,
     535                 :             :                                    const diagnostic_info &diagnostic,
     536                 :             :                                    diagnostic_t orig_diag_kind)
     537                 :             : {
     538                 :          82 :   sarif_result *result_obj = new sarif_result ();
     539                 :             : 
     540                 :             :   /* "ruleId" property (SARIF v2.1.0 section 3.27.5).  */
     541                 :             :   /* Ideally we'd have an option_name for these.  */
     542                 :         164 :   if (char *option_text
     543                 :         164 :         = context->make_option_name (diagnostic.option_index,
     544                 :         164 :                                      orig_diag_kind, diagnostic.kind))
     545                 :             :     {
     546                 :             :       /* Lazily create reportingDescriptor objects for and add to m_rules_arr.
     547                 :             :          Set ruleId referencing them.  */
     548                 :          59 :       result_obj->set_string ("ruleId", option_text);
     549                 :          59 :       if (m_rule_id_set.contains (option_text))
     550                 :           0 :         free (option_text);
     551                 :             :       else
     552                 :             :         {
     553                 :             :           /* This is the first time we've seen this ruleId.  */
     554                 :             :           /* Add to set, taking ownership.  */
     555                 :          59 :           m_rule_id_set.add (option_text);
     556                 :             : 
     557                 :          59 :           json::object *reporting_desc_obj
     558                 :          59 :             = make_reporting_descriptor_object_for_warning (context,
     559                 :             :                                                             diagnostic,
     560                 :             :                                                             orig_diag_kind,
     561                 :             :                                                             option_text);
     562                 :          59 :           m_rules_arr->append (reporting_desc_obj);
     563                 :             :         }
     564                 :             :     }
     565                 :             :   else
     566                 :             :     {
     567                 :             :       /* Otherwise, we have an "error" or a stray "note"; use the
     568                 :             :          diagnostic kind as the ruleId, so that the result object at least
     569                 :             :          has a ruleId.
     570                 :             :          We don't bother creating reportingDescriptor objects for these.  */
     571                 :          23 :       char *rule_id = make_rule_id_for_diagnostic_kind (orig_diag_kind);
     572                 :          23 :       result_obj->set_string ("ruleId", rule_id);
     573                 :          23 :       free (rule_id);
     574                 :             :     }
     575                 :             : 
     576                 :          82 :   if (diagnostic.metadata)
     577                 :             :     {
     578                 :             :       /* "taxa" property (SARIF v2.1.0 section 3.27.8).  */
     579                 :          16 :       if (int cwe_id = diagnostic.metadata->get_cwe ())
     580                 :             :         {
     581                 :          15 :           json::array *taxa_arr = new json::array ();
     582                 :          15 :           json::object *cwe_id_obj
     583                 :          15 :             = make_reporting_descriptor_reference_object_for_cwe_id (cwe_id);
     584                 :          15 :           taxa_arr->append (cwe_id_obj);
     585                 :          15 :           result_obj->set ("taxa", taxa_arr);
     586                 :             :         }
     587                 :             : 
     588                 :          16 :       diagnostic.metadata->maybe_add_sarif_properties (*result_obj);
     589                 :             :     }
     590                 :             : 
     591                 :             :   /* "level" property (SARIF v2.1.0 section 3.27.10).  */
     592                 :          82 :   if (const char *sarif_level = maybe_get_sarif_level (diagnostic.kind))
     593                 :          82 :     result_obj->set_string ("level", sarif_level);
     594                 :             : 
     595                 :             :   /* "message" property (SARIF v2.1.0 section 3.27.11).  */
     596                 :          82 :   json::object *message_obj
     597                 :          82 :     = make_message_object (pp_formatted_text (context->printer));
     598                 :          82 :   pp_clear_output_area (context->printer);
     599                 :          82 :   result_obj->set ("message", message_obj);
     600                 :             : 
     601                 :             :   /* "locations" property (SARIF v2.1.0 section 3.27.12).  */
     602                 :          82 :   json::array *locations_arr = make_locations_arr (diagnostic);
     603                 :          82 :   result_obj->set ("locations", locations_arr);
     604                 :             : 
     605                 :             :   /* "codeFlows" property (SARIF v2.1.0 section 3.27.18).  */
     606                 :          82 :   if (const diagnostic_path *path = diagnostic.richloc->get_path ())
     607                 :             :     {
     608                 :          17 :       json::array *code_flows_arr = new json::array ();
     609                 :          17 :       json::object *code_flow_obj = make_code_flow_object (*path);
     610                 :          17 :       code_flows_arr->append (code_flow_obj);
     611                 :          17 :       result_obj->set ("codeFlows", code_flows_arr);
     612                 :             :     }
     613                 :             : 
     614                 :             :   /* The "relatedLocations" property (SARIF v2.1.0 section 3.27.22) is
     615                 :             :      set up later, if any nested diagnostics occur within this diagnostic
     616                 :             :      group.  */
     617                 :             : 
     618                 :             :   /* "fixes" property (SARIF v2.1.0 section 3.27.30).  */
     619                 :          82 :   const rich_location *richloc = diagnostic.richloc;
     620                 :          82 :   if (richloc->get_num_fixit_hints ())
     621                 :             :     {
     622                 :           5 :       json::array *fix_arr = new json::array ();
     623                 :           5 :       json::object *fix_obj = make_fix_object (*richloc);
     624                 :           5 :       fix_arr->append (fix_obj);
     625                 :           5 :       result_obj->set ("fixes", fix_arr);
     626                 :             :     }
     627                 :             : 
     628                 :          82 :   return result_obj;
     629                 :             : }
     630                 :             : 
     631                 :             : /* Make a reportingDescriptor object (SARIF v2.1.0 section 3.49)
     632                 :             :    for a GCC warning.  */
     633                 :             : 
     634                 :             : json::object *
     635                 :          59 : sarif_builder::
     636                 :             : make_reporting_descriptor_object_for_warning (diagnostic_context *context,
     637                 :             :                                               const diagnostic_info &diagnostic,
     638                 :             :                                               diagnostic_t /*orig_diag_kind*/,
     639                 :             :                                               const char *option_text)
     640                 :             : {
     641                 :          59 :   json::object *reporting_desc = new json::object ();
     642                 :             : 
     643                 :             :   /* "id" property (SARIF v2.1.0 section 3.49.3).  */
     644                 :          59 :   reporting_desc->set_string ("id", option_text);
     645                 :             : 
     646                 :             :   /* We don't implement "name" property (SARIF v2.1.0 section 3.49.7), since
     647                 :             :      it seems redundant compared to "id".  */
     648                 :             : 
     649                 :             :   /* "helpUri" property (SARIF v2.1.0 section 3.49.12).  */
     650                 :         118 :   if (char *option_url = context->make_option_url (diagnostic.option_index))
     651                 :             :     {
     652                 :          59 :       reporting_desc->set_string ("helpUri", option_url);
     653                 :          59 :       free (option_url);
     654                 :             :     }
     655                 :             : 
     656                 :          59 :   return reporting_desc;
     657                 :             : }
     658                 :             : 
     659                 :             : /* Make a reportingDescriptor object (SARIF v2.1.0 section 3.49)
     660                 :             :    for CWE_ID, for use within the CWE taxa array.  */
     661                 :             : 
     662                 :             : json::object *
     663                 :          15 : sarif_builder::make_reporting_descriptor_object_for_cwe_id (int cwe_id) const
     664                 :             : {
     665                 :          15 :   json::object *reporting_desc = new json::object ();
     666                 :             : 
     667                 :             :   /* "id" property (SARIF v2.1.0 section 3.49.3).  */
     668                 :          15 :   {
     669                 :          15 :     pretty_printer pp;
     670                 :          15 :     pp_printf (&pp, "%i", cwe_id);
     671                 :          15 :     reporting_desc->set_string ("id", pp_formatted_text (&pp));
     672                 :          15 :   }
     673                 :             : 
     674                 :             :   /* "helpUri" property (SARIF v2.1.0 section 3.49.12).  */
     675                 :          15 :   {
     676                 :          15 :     char *url = get_cwe_url (cwe_id);
     677                 :          15 :     reporting_desc->set_string ("helpUri", url);
     678                 :          15 :     free (url);
     679                 :             :   }
     680                 :             : 
     681                 :          15 :   return reporting_desc;
     682                 :             : }
     683                 :             : 
     684                 :             : /* Make a reportingDescriptorReference object (SARIF v2.1.0 section 3.52)
     685                 :             :    referencing CWE_ID, for use within a result object.
     686                 :             :    Also, add CWE_ID to m_cwe_id_set.  */
     687                 :             : 
     688                 :             : json::object *
     689                 :          15 : sarif_builder::
     690                 :             : make_reporting_descriptor_reference_object_for_cwe_id (int cwe_id)
     691                 :             : {
     692                 :          15 :   json::object *desc_ref_obj = new json::object ();
     693                 :             : 
     694                 :             :   /* "id" property (SARIF v2.1.0 section 3.52.4).  */
     695                 :          15 :   {
     696                 :          15 :     pretty_printer pp;
     697                 :          15 :     pp_printf (&pp, "%i", cwe_id);
     698                 :          15 :     desc_ref_obj->set_string ("id", pp_formatted_text (&pp));
     699                 :          15 :   }
     700                 :             : 
     701                 :             :   /* "toolComponent" property (SARIF v2.1.0 section 3.52.7).  */
     702                 :          15 :   json::object *comp_ref_obj = make_tool_component_reference_object_for_cwe ();
     703                 :          15 :   desc_ref_obj->set ("toolComponent", comp_ref_obj);
     704                 :             : 
     705                 :             :   /* Add CWE_ID to our set.  */
     706                 :          15 :   gcc_assert (cwe_id > 0);
     707                 :          15 :   m_cwe_id_set.add (cwe_id);
     708                 :             : 
     709                 :          15 :   return desc_ref_obj;
     710                 :             : }
     711                 :             : 
     712                 :             : /* Make a toolComponentReference object (SARIF v2.1.0 section 3.54) that
     713                 :             :    references the CWE taxonomy.  */
     714                 :             : 
     715                 :             : json::object *
     716                 :          15 : sarif_builder::
     717                 :             : make_tool_component_reference_object_for_cwe () const
     718                 :             : {
     719                 :          15 :   json::object *comp_ref_obj = new json::object ();
     720                 :             : 
     721                 :             :   /* "name" property  (SARIF v2.1.0 section 3.54.3).  */
     722                 :          15 :   comp_ref_obj->set_string ("name", "cwe");
     723                 :             : 
     724                 :          15 :   return comp_ref_obj;
     725                 :             : }
     726                 :             : 
     727                 :             : /* Make an array suitable for use as the "locations" property of:
     728                 :             :    - a "result" object (SARIF v2.1.0 section 3.27.12), or
     729                 :             :    - a "notification" object (SARIF v2.1.0 section 3.58.4).  */
     730                 :             : 
     731                 :             : json::array *
     732                 :          84 : sarif_builder::make_locations_arr (const diagnostic_info &diagnostic)
     733                 :             : {
     734                 :          84 :   json::array *locations_arr = new json::array ();
     735                 :          84 :   const logical_location *logical_loc = NULL;
     736                 :          84 :   if (auto client_data_hooks = m_context->get_client_data_hooks ())
     737                 :          84 :     logical_loc = client_data_hooks->get_current_logical_location ();
     738                 :             : 
     739                 :          84 :   json::object *location_obj
     740                 :          84 :     = make_location_object (*diagnostic.richloc, logical_loc);
     741                 :          84 :   locations_arr->append (location_obj);
     742                 :          84 :   return locations_arr;
     743                 :             : }
     744                 :             : 
     745                 :             : /* If LOGICAL_LOC is non-NULL, use it to create a "logicalLocations" property
     746                 :             :    within LOCATION_OBJ (SARIF v2.1.0 section 3.28.4).  */
     747                 :             : 
     748                 :             : void
     749                 :         363 : sarif_builder::
     750                 :             : set_any_logical_locs_arr (json::object *location_obj,
     751                 :             :                           const logical_location *logical_loc)
     752                 :             : {
     753                 :         363 :   if (!logical_loc)
     754                 :             :     return;
     755                 :          82 :   json::object *logical_loc_obj = make_sarif_logical_location_object (*logical_loc);
     756                 :          82 :   json::array *location_locs_arr = new json::array ();
     757                 :          82 :   location_locs_arr->append (logical_loc_obj);
     758                 :          82 :   location_obj->set ("logicalLocations", location_locs_arr);
     759                 :             : }
     760                 :             : 
     761                 :             : /* Make a location object (SARIF v2.1.0 section 3.28) for RICH_LOC
     762                 :             :    and LOGICAL_LOC.  */
     763                 :             : 
     764                 :             : json::object *
     765                 :         304 : sarif_builder::make_location_object (const rich_location &rich_loc,
     766                 :             :                                      const logical_location *logical_loc)
     767                 :             : {
     768                 :         304 :   json::object *location_obj = new json::object ();
     769                 :             : 
     770                 :             :   /* Get primary loc from RICH_LOC.  */
     771                 :         304 :   location_t loc = rich_loc.get_loc ();
     772                 :             : 
     773                 :             :   /* "physicalLocation" property (SARIF v2.1.0 section 3.28.3).  */
     774                 :         304 :   if (json::object *phs_loc_obj = maybe_make_physical_location_object (loc))
     775                 :         303 :     location_obj->set ("physicalLocation", phs_loc_obj);
     776                 :             : 
     777                 :             :   /* "logicalLocations" property (SARIF v2.1.0 section 3.28.4).  */
     778                 :         304 :   set_any_logical_locs_arr (location_obj, logical_loc);
     779                 :             : 
     780                 :         304 :   return location_obj;
     781                 :             : }
     782                 :             : 
     783                 :             : /* Make a location object (SARIF v2.1.0 section 3.28) for EVENT
     784                 :             :    within a diagnostic_path.  */
     785                 :             : 
     786                 :             : json::object *
     787                 :          59 : sarif_builder::make_location_object (const diagnostic_event &event)
     788                 :             : {
     789                 :          59 :   json::object *location_obj = new json::object ();
     790                 :             : 
     791                 :             :   /* "physicalLocation" property (SARIF v2.1.0 section 3.28.3).  */
     792                 :          59 :   location_t loc = event.get_location ();
     793                 :          59 :   if (json::object *phs_loc_obj = maybe_make_physical_location_object (loc))
     794                 :          58 :     location_obj->set ("physicalLocation", phs_loc_obj);
     795                 :             : 
     796                 :             :   /* "logicalLocations" property (SARIF v2.1.0 section 3.28.4).  */
     797                 :          59 :   const logical_location *logical_loc = event.get_logical_location ();
     798                 :          59 :   set_any_logical_locs_arr (location_obj, logical_loc);
     799                 :             : 
     800                 :             :   /* "message" property (SARIF v2.1.0 section 3.28.5).  */
     801                 :          59 :   label_text ev_desc = event.get_desc (false);
     802                 :          59 :   json::object *message_obj = make_message_object (ev_desc.get ());
     803                 :          59 :   location_obj->set ("message", message_obj);
     804                 :             : 
     805                 :          59 :   return location_obj;
     806                 :          59 : }
     807                 :             : 
     808                 :             : /* Make a physicalLocation object (SARIF v2.1.0 section 3.29) for LOC,
     809                 :             :    or return NULL;
     810                 :             :    Add any filename to the m_artifacts.  */
     811                 :             : 
     812                 :             : json::object *
     813                 :         363 : sarif_builder::maybe_make_physical_location_object (location_t loc)
     814                 :             : {
     815                 :         363 :   if (loc <= BUILTINS_LOCATION || LOCATION_FILE (loc) == NULL)
     816                 :           2 :     return NULL;
     817                 :             : 
     818                 :         361 :   json::object *phys_loc_obj = new json::object ();
     819                 :             : 
     820                 :             :   /* "artifactLocation" property (SARIF v2.1.0 section 3.29.3).  */
     821                 :         361 :   json::object *artifact_loc_obj = make_artifact_location_object (loc);
     822                 :         361 :   phys_loc_obj->set ("artifactLocation", artifact_loc_obj);
     823                 :         361 :   m_filenames.add (LOCATION_FILE (loc));
     824                 :             : 
     825                 :             :   /* "region" property (SARIF v2.1.0 section 3.29.4).  */
     826                 :         361 :   if (json::object *region_obj = maybe_make_region_object (loc))
     827                 :         361 :     phys_loc_obj->set ("region", region_obj);
     828                 :             : 
     829                 :             :   /* "contextRegion" property (SARIF v2.1.0 section 3.29.5).  */
     830                 :         722 :   if (json::object *context_region_obj
     831                 :         361 :         = maybe_make_region_object_for_context (loc))
     832                 :         361 :     phys_loc_obj->set ("contextRegion", context_region_obj);
     833                 :             : 
     834                 :             :   /* Instead, we add artifacts to the run as a whole,
     835                 :             :      with artifact.contents.
     836                 :             :      Could do both, though.  */
     837                 :             : 
     838                 :             :   return phys_loc_obj;
     839                 :             : }
     840                 :             : 
     841                 :             : /* Make an artifactLocation object (SARIF v2.1.0 section 3.4) for LOC,
     842                 :             :    or return NULL.  */
     843                 :             : 
     844                 :             : json::object *
     845                 :         366 : sarif_builder::make_artifact_location_object (location_t loc)
     846                 :             : {
     847                 :         366 :   return make_artifact_location_object (LOCATION_FILE (loc));
     848                 :             : }
     849                 :             : 
     850                 :             : /* The ID value for use in "uriBaseId" properties (SARIF v2.1.0 section 3.4.4)
     851                 :             :    for when we need to express paths relative to PWD.  */
     852                 :             : 
     853                 :             : #define PWD_PROPERTY_NAME ("PWD")
     854                 :             : 
     855                 :             : /* Make an artifactLocation object (SARIF v2.1.0 section 3.4) for FILENAME,
     856                 :             :    or return NULL.  */
     857                 :             : 
     858                 :             : json::object *
     859                 :         445 : sarif_builder::make_artifact_location_object (const char *filename)
     860                 :             : {
     861                 :         445 :   json::object *artifact_loc_obj = new json::object ();
     862                 :             : 
     863                 :             :   /* "uri" property (SARIF v2.1.0 section 3.4.3).  */
     864                 :         445 :   artifact_loc_obj->set_string ("uri", filename);
     865                 :             : 
     866                 :         445 :   if (filename[0] != '/')
     867                 :             :     {
     868                 :             :       /* If we have a relative path, set the "uriBaseId" property
     869                 :             :          (SARIF v2.1.0 section 3.4.4).  */
     870                 :          10 :       artifact_loc_obj->set_string ("uriBaseId", PWD_PROPERTY_NAME);
     871                 :          10 :       m_seen_any_relative_paths = true;
     872                 :             :     }
     873                 :             : 
     874                 :         445 :   return artifact_loc_obj;
     875                 :             : }
     876                 :             : 
     877                 :             : /* Get the PWD, or NULL, as an absolute file-based URI,
     878                 :             :    adding a trailing forward slash (as required by SARIF v2.1.0
     879                 :             :    section 3.14.14).  */
     880                 :             : 
     881                 :             : static char *
     882                 :           5 : make_pwd_uri_str ()
     883                 :             : {
     884                 :             :   /* The prefix of a file-based URI, up to, but not including the path. */
     885                 :             : #define FILE_PREFIX ("file://")
     886                 :             : 
     887                 :           5 :   const char *pwd = getpwd ();
     888                 :           5 :   if (!pwd)
     889                 :             :     return NULL;
     890                 :           5 :   size_t len = strlen (pwd);
     891                 :           5 :   if (len == 0 || pwd[len - 1] != '/')
     892                 :           5 :     return concat (FILE_PREFIX, pwd, "/", NULL);
     893                 :             :   else
     894                 :             :     {
     895                 :           0 :       gcc_assert (pwd[len - 1] == '/');
     896                 :           0 :       return concat (FILE_PREFIX, pwd, NULL);
     897                 :             :     }
     898                 :             : }
     899                 :             : 
     900                 :             : /* Make an artifactLocation object (SARIF v2.1.0 section 3.4) for the pwd,
     901                 :             :    for use in the "run.originalUriBaseIds" property (SARIF v2.1.0
     902                 :             :    section 3.14.14) when we have any relative paths.  */
     903                 :             : 
     904                 :             : json::object *
     905                 :           5 : sarif_builder::make_artifact_location_object_for_pwd () const
     906                 :             : {
     907                 :           5 :   json::object *artifact_loc_obj = new json::object ();
     908                 :             : 
     909                 :             :   /* "uri" property (SARIF v2.1.0 section 3.4.3).  */
     910                 :           5 :   if (char *pwd = make_pwd_uri_str ())
     911                 :             :     {
     912                 :           5 :       gcc_assert (strlen (pwd) > 0);
     913                 :           5 :       gcc_assert (pwd[strlen (pwd) - 1] == '/');
     914                 :           5 :       artifact_loc_obj->set_string ("uri", pwd);
     915                 :           5 :       free (pwd);
     916                 :             :     }
     917                 :             : 
     918                 :           5 :   return artifact_loc_obj;
     919                 :             : }
     920                 :             : 
     921                 :             : /* Get the column number within EXPLOC.  */
     922                 :             : 
     923                 :             : int
     924                 :         732 : sarif_builder::get_sarif_column (expanded_location exploc) const
     925                 :             : {
     926                 :         732 :   cpp_char_column_policy policy (m_tabstop, cpp_wcwidth);
     927                 :         732 :   return location_compute_display_column (m_context->get_file_cache (),
     928                 :         732 :                                           exploc, policy);
     929                 :             : }
     930                 :             : 
     931                 :             : /* Make a region object (SARIF v2.1.0 section 3.30) for LOC,
     932                 :             :    or return NULL.  */
     933                 :             : 
     934                 :             : json::object *
     935                 :         361 : sarif_builder::maybe_make_region_object (location_t loc) const
     936                 :             : {
     937                 :         361 :   location_t caret_loc = get_pure_location (loc);
     938                 :             : 
     939                 :         361 :   if (caret_loc <= BUILTINS_LOCATION)
     940                 :             :     return NULL;
     941                 :             : 
     942                 :         361 :   location_t start_loc = get_start (loc);
     943                 :         361 :   location_t finish_loc = get_finish (loc);
     944                 :             : 
     945                 :         361 :   expanded_location exploc_caret = expand_location (caret_loc);
     946                 :         361 :   expanded_location exploc_start = expand_location (start_loc);
     947                 :         361 :   expanded_location exploc_finish = expand_location (finish_loc);
     948                 :             : 
     949                 :         361 :   if (exploc_start.file !=exploc_caret.file)
     950                 :             :     return NULL;
     951                 :         361 :   if (exploc_finish.file !=exploc_caret.file)
     952                 :             :     return NULL;
     953                 :             : 
     954                 :         361 :   json::object *region_obj = new json::object ();
     955                 :             : 
     956                 :             :   /* "startLine" property (SARIF v2.1.0 section 3.30.5) */
     957                 :         361 :   region_obj->set_integer ("startLine", exploc_start.line);
     958                 :             : 
     959                 :             :   /* "startColumn" property (SARIF v2.1.0 section 3.30.6) */
     960                 :         361 :   region_obj->set_integer ("startColumn", get_sarif_column (exploc_start));
     961                 :             : 
     962                 :             :   /* "endLine" property (SARIF v2.1.0 section 3.30.7) */
     963                 :         361 :   if (exploc_finish.line != exploc_start.line)
     964                 :           0 :     region_obj->set_integer ("endLine", exploc_finish.line);
     965                 :             : 
     966                 :             :   /* "endColumn" property (SARIF v2.1.0 section 3.30.8).
     967                 :             :      This expresses the column immediately beyond the range.  */
     968                 :         361 :   {
     969                 :         361 :     int next_column = sarif_builder::get_sarif_column (exploc_finish) + 1;
     970                 :         361 :     region_obj->set_integer ("endColumn", next_column);
     971                 :             :   }
     972                 :             : 
     973                 :         361 :   return region_obj;
     974                 :             : }
     975                 :             : 
     976                 :             : /* Make a region object (SARIF v2.1.0 section 3.30) for the "contextRegion"
     977                 :             :    property (SARIF v2.1.0 section 3.29.5) of a physicalLocation.
     978                 :             : 
     979                 :             :    This is similar to maybe_make_region_object, but ignores column numbers,
     980                 :             :    covering the line(s) as a whole, and including a "snippet" property
     981                 :             :    embedding those source lines, making it easier for consumers to show
     982                 :             :    the pertinent source.  */
     983                 :             : 
     984                 :             : json::object *
     985                 :         361 : sarif_builder::maybe_make_region_object_for_context (location_t loc) const
     986                 :             : {
     987                 :         361 :   location_t caret_loc = get_pure_location (loc);
     988                 :             : 
     989                 :         361 :   if (caret_loc <= BUILTINS_LOCATION)
     990                 :             :     return NULL;
     991                 :             : 
     992                 :         361 :   location_t start_loc = get_start (loc);
     993                 :         361 :   location_t finish_loc = get_finish (loc);
     994                 :             : 
     995                 :         361 :   expanded_location exploc_caret = expand_location (caret_loc);
     996                 :         361 :   expanded_location exploc_start = expand_location (start_loc);
     997                 :         361 :   expanded_location exploc_finish = expand_location (finish_loc);
     998                 :             : 
     999                 :         361 :   if (exploc_start.file !=exploc_caret.file)
    1000                 :             :     return NULL;
    1001                 :         361 :   if (exploc_finish.file !=exploc_caret.file)
    1002                 :             :     return NULL;
    1003                 :             : 
    1004                 :         361 :   json::object *region_obj = new json::object ();
    1005                 :             : 
    1006                 :             :   /* "startLine" property (SARIF v2.1.0 section 3.30.5) */
    1007                 :         361 :   region_obj->set_integer ("startLine", exploc_start.line);
    1008                 :             : 
    1009                 :             :   /* "endLine" property (SARIF v2.1.0 section 3.30.7) */
    1010                 :         361 :   if (exploc_finish.line != exploc_start.line)
    1011                 :           0 :     region_obj->set_integer ("endLine", exploc_finish.line);
    1012                 :             : 
    1013                 :             :   /* "snippet" property (SARIF v2.1.0 section 3.30.13).  */
    1014                 :         722 :   if (json::object *artifact_content_obj
    1015                 :         361 :          = maybe_make_artifact_content_object (exploc_start.file,
    1016                 :             :                                                exploc_start.line,
    1017                 :             :                                                exploc_finish.line))
    1018                 :         141 :     region_obj->set ("snippet", artifact_content_obj);
    1019                 :             : 
    1020                 :             :   return region_obj;
    1021                 :             : }
    1022                 :             : 
    1023                 :             : /* Make a region object (SARIF v2.1.0 section 3.30) for the deletion region
    1024                 :             :    of HINT (as per SARIF v2.1.0 section 3.57.3).  */
    1025                 :             : 
    1026                 :             : json::object *
    1027                 :           5 : sarif_builder::make_region_object_for_hint (const fixit_hint &hint) const
    1028                 :             : {
    1029                 :           5 :   location_t start_loc = hint.get_start_loc ();
    1030                 :           5 :   location_t next_loc = hint.get_next_loc ();
    1031                 :             : 
    1032                 :           5 :   expanded_location exploc_start = expand_location (start_loc);
    1033                 :           5 :   expanded_location exploc_next = expand_location (next_loc);
    1034                 :             : 
    1035                 :           5 :   json::object *region_obj = new json::object ();
    1036                 :             : 
    1037                 :             :   /* "startLine" property (SARIF v2.1.0 section 3.30.5) */
    1038                 :           5 :   region_obj->set_integer ("startLine", exploc_start.line);
    1039                 :             : 
    1040                 :             :   /* "startColumn" property (SARIF v2.1.0 section 3.30.6) */
    1041                 :           5 :   int start_col = get_sarif_column (exploc_start);
    1042                 :           5 :   region_obj->set_integer ("startColumn", start_col);
    1043                 :             : 
    1044                 :             :   /* "endLine" property (SARIF v2.1.0 section 3.30.7) */
    1045                 :           5 :   if (exploc_next.line != exploc_start.line)
    1046                 :           0 :     region_obj->set_integer ("endLine", exploc_next.line);
    1047                 :             : 
    1048                 :             :   /* "endColumn" property (SARIF v2.1.0 section 3.30.8).
    1049                 :             :      This expresses the column immediately beyond the range.  */
    1050                 :           5 :   int next_col =  get_sarif_column (exploc_next);
    1051                 :           5 :   region_obj->set_integer ("endColumn", next_col);
    1052                 :             : 
    1053                 :           5 :   return region_obj;
    1054                 :             : }
    1055                 :             : 
    1056                 :             : /* Attempt to get a string for a logicalLocation's "kind" property
    1057                 :             :    (SARIF v2.1.0 section 3.33.7).
    1058                 :             :    Return NULL if unknown.  */
    1059                 :             : 
    1060                 :             : static const char *
    1061                 :          82 : maybe_get_sarif_kind (enum logical_location_kind kind)
    1062                 :             : {
    1063                 :          82 :   switch (kind)
    1064                 :             :     {
    1065                 :           0 :     default:
    1066                 :           0 :       gcc_unreachable ();
    1067                 :             :     case LOGICAL_LOCATION_KIND_UNKNOWN:
    1068                 :             :       return NULL;
    1069                 :             : 
    1070                 :          82 :     case LOGICAL_LOCATION_KIND_FUNCTION:
    1071                 :          82 :       return "function";
    1072                 :           0 :     case LOGICAL_LOCATION_KIND_MEMBER:
    1073                 :           0 :       return "member";
    1074                 :           0 :     case LOGICAL_LOCATION_KIND_MODULE:
    1075                 :           0 :       return "module";
    1076                 :           0 :     case LOGICAL_LOCATION_KIND_NAMESPACE:
    1077                 :           0 :       return "namespace";
    1078                 :           0 :     case LOGICAL_LOCATION_KIND_TYPE:
    1079                 :           0 :       return "type";
    1080                 :           0 :     case LOGICAL_LOCATION_KIND_RETURN_TYPE:
    1081                 :           0 :       return "returnType";
    1082                 :           0 :     case LOGICAL_LOCATION_KIND_PARAMETER:
    1083                 :           0 :       return "parameter";
    1084                 :           0 :     case LOGICAL_LOCATION_KIND_VARIABLE:
    1085                 :           0 :       return "variable";
    1086                 :             :     }
    1087                 :             : }
    1088                 :             : 
    1089                 :             : /* Make a logicalLocation object (SARIF v2.1.0 section 3.33) for LOGICAL_LOC,
    1090                 :             :    or return NULL.  */
    1091                 :             : 
    1092                 :             : json::object *
    1093                 :          82 : make_sarif_logical_location_object (const logical_location &logical_loc)
    1094                 :             : {
    1095                 :          82 :   json::object *logical_loc_obj = new json::object ();
    1096                 :             : 
    1097                 :             :   /* "name" property (SARIF v2.1.0 section 3.33.4).  */
    1098                 :          82 :   if (const char *short_name = logical_loc.get_short_name ())
    1099                 :          82 :     logical_loc_obj->set_string ("name", short_name);
    1100                 :             : 
    1101                 :             :   /* "fullyQualifiedName" property (SARIF v2.1.0 section 3.33.5).  */
    1102                 :          82 :   if (const char *name_with_scope = logical_loc.get_name_with_scope ())
    1103                 :          82 :     logical_loc_obj->set_string ("fullyQualifiedName", name_with_scope);
    1104                 :             : 
    1105                 :             :   /* "decoratedName" property (SARIF v2.1.0 section 3.33.6).  */
    1106                 :          82 :   if (const char *internal_name = logical_loc.get_internal_name ())
    1107                 :          82 :     logical_loc_obj->set_string ("decoratedName", internal_name);
    1108                 :             : 
    1109                 :             :   /* "kind" property (SARIF v2.1.0 section 3.33.7).  */
    1110                 :          82 :   enum logical_location_kind kind = logical_loc.get_kind ();
    1111                 :          82 :   if (const char *sarif_kind_str = maybe_get_sarif_kind (kind))
    1112                 :          82 :     logical_loc_obj->set_string ("kind", sarif_kind_str);
    1113                 :             : 
    1114                 :          82 :   return logical_loc_obj;
    1115                 :             : }
    1116                 :             : 
    1117                 :             : /* Make a codeFlow object (SARIF v2.1.0 section 3.36) for PATH.  */
    1118                 :             : 
    1119                 :             : json::object *
    1120                 :          17 : sarif_builder::make_code_flow_object (const diagnostic_path &path)
    1121                 :             : {
    1122                 :          17 :   json::object *code_flow_obj = new json::object ();
    1123                 :             : 
    1124                 :             :   /* "threadFlows" property (SARIF v2.1.0 section 3.36.3).  */
    1125                 :          17 :   json::array *thread_flows_arr = new json::array ();
    1126                 :             : 
    1127                 :             :   /* Walk the events, consolidating into per-thread threadFlow objects,
    1128                 :             :      using the index with PATH as the overall executionOrder.  */
    1129                 :          17 :   hash_map<int_hash<diagnostic_thread_id_t, -1, -2>,
    1130                 :          17 :            sarif_thread_flow *> thread_id_map;
    1131                 :          76 :   for (unsigned i = 0; i < path.num_events (); i++)
    1132                 :             :     {
    1133                 :          59 :       const diagnostic_event &event = path.get_event (i);
    1134                 :          59 :       const diagnostic_thread_id_t thread_id = event.get_thread_id ();
    1135                 :          59 :       sarif_thread_flow *thread_flow_obj;
    1136                 :             : 
    1137                 :          59 :       if (sarif_thread_flow **slot = thread_id_map.get (thread_id))
    1138                 :          41 :         thread_flow_obj = *slot;
    1139                 :             :       else
    1140                 :             :         {
    1141                 :          18 :           const diagnostic_thread &thread = path.get_thread (thread_id);
    1142                 :          18 :           thread_flow_obj = new sarif_thread_flow (thread);
    1143                 :          18 :           thread_flows_arr->append (thread_flow_obj);
    1144                 :          18 :           thread_id_map.put (thread_id, thread_flow_obj);
    1145                 :             :         }
    1146                 :             : 
    1147                 :             :       /* Add event to thread's threadFlow object.  */
    1148                 :          59 :       json::object *thread_flow_loc_obj
    1149                 :          59 :         = make_thread_flow_location_object (event, i);
    1150                 :          59 :       thread_flow_obj->add_location (thread_flow_loc_obj);
    1151                 :             :     }
    1152                 :          17 :   code_flow_obj->set ("threadFlows", thread_flows_arr);
    1153                 :             : 
    1154                 :          17 :   return code_flow_obj;
    1155                 :          17 : }
    1156                 :             : 
    1157                 :             : /* Make a threadFlowLocation object (SARIF v2.1.0 section 3.38) for EVENT.  */
    1158                 :             : 
    1159                 :             : json::object *
    1160                 :          59 : sarif_builder::make_thread_flow_location_object (const diagnostic_event &ev,
    1161                 :             :                                                  int path_event_idx)
    1162                 :             : {
    1163                 :          59 :   sarif_object *thread_flow_loc_obj = new sarif_object ();
    1164                 :             : 
    1165                 :             :   /* Give diagnostic_event subclasses a chance to add custom properties
    1166                 :             :      via a property bag.  */
    1167                 :          59 :   ev.maybe_add_sarif_properties (*thread_flow_loc_obj);
    1168                 :             : 
    1169                 :             :   /* "location" property (SARIF v2.1.0 section 3.38.3).  */
    1170                 :          59 :   json::object *location_obj = make_location_object (ev);
    1171                 :          59 :   thread_flow_loc_obj->set ("location", location_obj);
    1172                 :             : 
    1173                 :             :   /* "kinds" property (SARIF v2.1.0 section 3.38.8).  */
    1174                 :          59 :   diagnostic_event::meaning m = ev.get_meaning ();
    1175                 :          59 :   if (json::array *kinds_arr = maybe_make_kinds_array (m))
    1176                 :          35 :     thread_flow_loc_obj->set ("kinds", kinds_arr);
    1177                 :             : 
    1178                 :             :   /* "nestingLevel" property (SARIF v2.1.0 section 3.38.10).  */
    1179                 :          59 :   thread_flow_loc_obj->set_integer ("nestingLevel", ev.get_stack_depth ());
    1180                 :             : 
    1181                 :             :   /* "executionOrder" property (SARIF v2.1.0 3.38.11).
    1182                 :             :      Offset by 1 to match the human-readable values emitted by %@.  */
    1183                 :          59 :   thread_flow_loc_obj->set_integer ("executionOrder", path_event_idx + 1);
    1184                 :             : 
    1185                 :             :   /* It might be nice to eventually implement the following for -fanalyzer:
    1186                 :             :      - the "stack" property (SARIF v2.1.0 section 3.38.5)
    1187                 :             :      - the "state" property (SARIF v2.1.0 section 3.38.9)
    1188                 :             :      - the "importance" property (SARIF v2.1.0 section 3.38.13).  */
    1189                 :             : 
    1190                 :          59 :   return thread_flow_loc_obj;
    1191                 :             : }
    1192                 :             : 
    1193                 :             : /* If M has any known meaning, make a json array suitable for the "kinds"
    1194                 :             :    property of a threadFlowLocation object (SARIF v2.1.0 section 3.38.8).
    1195                 :             : 
    1196                 :             :    Otherwise, return NULL.  */
    1197                 :             : 
    1198                 :             : json::array *
    1199                 :          59 : sarif_builder::maybe_make_kinds_array (diagnostic_event::meaning m) const
    1200                 :             : {
    1201                 :          59 :   if (m.m_verb == diagnostic_event::VERB_unknown
    1202                 :          24 :       && m.m_noun == diagnostic_event::NOUN_unknown
    1203                 :          24 :       && m.m_property == diagnostic_event::PROPERTY_unknown)
    1204                 :             :     return NULL;
    1205                 :             : 
    1206                 :          35 :   json::array *kinds_arr = new json::array ();
    1207                 :          70 :   if (const char *verb_str
    1208                 :          35 :         = diagnostic_event::meaning::maybe_get_verb_str (m.m_verb))
    1209                 :          35 :     kinds_arr->append (new json::string (verb_str));
    1210                 :          70 :   if (const char *noun_str
    1211                 :          35 :         = diagnostic_event::meaning::maybe_get_noun_str (m.m_noun))
    1212                 :          10 :     kinds_arr->append (new json::string (noun_str));
    1213                 :          70 :   if (const char *property_str
    1214                 :          35 :         = diagnostic_event::meaning::maybe_get_property_str (m.m_property))
    1215                 :          10 :     kinds_arr->append (new json::string (property_str));
    1216                 :             :   return kinds_arr;
    1217                 :             : }
    1218                 :             : 
    1219                 :             : /* Make a message object (SARIF v2.1.0 section 3.11) for MSG.  */
    1220                 :             : 
    1221                 :             : json::object *
    1222                 :         363 : sarif_builder::make_message_object (const char *msg) const
    1223                 :             : {
    1224                 :         363 :   json::object *message_obj = new json::object ();
    1225                 :             : 
    1226                 :             :   /* "text" property (SARIF v2.1.0 section 3.11.8).  */
    1227                 :         363 :   message_obj->set_string ("text", msg);
    1228                 :             : 
    1229                 :         363 :   return message_obj;
    1230                 :             : }
    1231                 :             : 
    1232                 :             : /* Make a message object (SARIF v2.1.0 section 3.11) for DIAGRAM.
    1233                 :             :    We emit the diagram as a code block within the Markdown part
    1234                 :             :    of the message.  */
    1235                 :             : 
    1236                 :             : json::object *
    1237                 :           5 : sarif_builder::make_message_object_for_diagram (diagnostic_context *context,
    1238                 :             :                                                 const diagnostic_diagram &diagram)
    1239                 :             : {
    1240                 :           5 :   json::object *message_obj = new json::object ();
    1241                 :             : 
    1242                 :             :   /* "text" property (SARIF v2.1.0 section 3.11.8).  */
    1243                 :           5 :   message_obj->set_string ("text", diagram.get_alt_text ());
    1244                 :             : 
    1245                 :           5 :   char *saved_prefix = pp_take_prefix (context->printer);
    1246                 :           5 :   pp_set_prefix (context->printer, NULL);
    1247                 :             : 
    1248                 :             :   /* "To produce a code block in Markdown, simply indent every line of
    1249                 :             :      the block by at least 4 spaces or 1 tab."
    1250                 :             :      Here we use 4 spaces.  */
    1251                 :           5 :   diagram.get_canvas ().print_to_pp (context->printer, "    ");
    1252                 :           5 :   pp_set_prefix (context->printer, saved_prefix);
    1253                 :             : 
    1254                 :             :   /* "markdown" property (SARIF v2.1.0 section 3.11.9).  */
    1255                 :           5 :   message_obj->set_string ("markdown", pp_formatted_text (context->printer));
    1256                 :             : 
    1257                 :           5 :   pp_clear_output_area (context->printer);
    1258                 :             : 
    1259                 :           5 :   return message_obj;
    1260                 :             : }
    1261                 :             : 
    1262                 :             : /* Make a multiformatMessageString object (SARIF v2.1.0 section 3.12)
    1263                 :             :    for MSG.  */
    1264                 :             : 
    1265                 :             : json::object *
    1266                 :          15 : sarif_builder::make_multiformat_message_string (const char *msg) const
    1267                 :             : {
    1268                 :          15 :   json::object *message_obj = new json::object ();
    1269                 :             : 
    1270                 :             :   /* "text" property (SARIF v2.1.0 section 3.12.3).  */
    1271                 :          15 :   message_obj->set_string ("text", msg);
    1272                 :             : 
    1273                 :          15 :   return message_obj;
    1274                 :             : }
    1275                 :             : 
    1276                 :             : #define SARIF_SCHEMA "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json"
    1277                 :             : #define SARIF_VERSION "2.1.0"
    1278                 :             : 
    1279                 :             : /* Make a top-level sarifLog object (SARIF v2.1.0 section 3.13).
    1280                 :             :    Take ownership of INVOCATION_OBJ and RESULTS.  */
    1281                 :             : 
    1282                 :             : json::object *
    1283                 :          79 : sarif_builder::make_top_level_object (sarif_invocation *invocation_obj,
    1284                 :             :                                       json::array *results)
    1285                 :             : {
    1286                 :          79 :   json::object *log_obj = new json::object ();
    1287                 :             : 
    1288                 :             :   /* "$schema" property (SARIF v2.1.0 section 3.13.3) .  */
    1289                 :          79 :   log_obj->set_string ("$schema", SARIF_SCHEMA);
    1290                 :             : 
    1291                 :             :   /* "version" property (SARIF v2.1.0 section 3.13.2).  */
    1292                 :          79 :   log_obj->set_string ("version", SARIF_VERSION);
    1293                 :             : 
    1294                 :             :   /* "runs" property (SARIF v2.1.0 section 3.13.4).  */
    1295                 :          79 :   json::array *run_arr = new json::array ();
    1296                 :          79 :   json::object *run_obj = make_run_object (invocation_obj, results);
    1297                 :          79 :   run_arr->append (run_obj);
    1298                 :          79 :   log_obj->set ("runs", run_arr);
    1299                 :             : 
    1300                 :          79 :   return log_obj;
    1301                 :             : }
    1302                 :             : 
    1303                 :             : /* Make a run object (SARIF v2.1.0 section 3.14).
    1304                 :             :    Take ownership of INVOCATION_OBJ and RESULTS.  */
    1305                 :             : 
    1306                 :             : json::object *
    1307                 :          79 : sarif_builder::make_run_object (sarif_invocation *invocation_obj,
    1308                 :             :                                 json::array *results)
    1309                 :             : {
    1310                 :          79 :   json::object *run_obj = new json::object ();
    1311                 :             : 
    1312                 :             :   /* "tool" property (SARIF v2.1.0 section 3.14.6).  */
    1313                 :          79 :   json::object *tool_obj = make_tool_object ();
    1314                 :          79 :   run_obj->set ("tool", tool_obj);
    1315                 :             : 
    1316                 :             :   /* "taxonomies" property (SARIF v2.1.0 section 3.14.8).  */
    1317                 :          79 :   if (json::array *taxonomies_arr = maybe_make_taxonomies_array ())
    1318                 :          15 :     run_obj->set ("taxonomies", taxonomies_arr);
    1319                 :             : 
    1320                 :             :   /* "invocations" property (SARIF v2.1.0 section 3.14.11).  */
    1321                 :          79 :   {
    1322                 :          79 :     json::array *invocations_arr = new json::array ();
    1323                 :          79 :     invocations_arr->append (invocation_obj);
    1324                 :          79 :     run_obj->set ("invocations", invocations_arr);
    1325                 :             :   }
    1326                 :             : 
    1327                 :             :   /* "originalUriBaseIds (SARIF v2.1.0 section 3.14.14).  */
    1328                 :          79 :   if (m_seen_any_relative_paths)
    1329                 :             :     {
    1330                 :           5 :       json::object *orig_uri_base_ids = new json::object ();
    1331                 :           5 :       run_obj->set ("originalUriBaseIds", orig_uri_base_ids);
    1332                 :           5 :       json::object *pwd_art_loc_obj = make_artifact_location_object_for_pwd ();
    1333                 :           5 :       orig_uri_base_ids->set (PWD_PROPERTY_NAME, pwd_art_loc_obj);
    1334                 :             :     }
    1335                 :             : 
    1336                 :             :   /* "artifacts" property (SARIF v2.1.0 section 3.14.15).  */
    1337                 :          79 :   json::array *artifacts_arr = new json::array ();
    1338                 :         237 :   for (auto iter : m_filenames)
    1339                 :             :     {
    1340                 :          79 :       json::object *artifact_obj = make_artifact_object (iter);
    1341                 :          79 :       artifacts_arr->append (artifact_obj);
    1342                 :             :     }
    1343                 :          79 :   run_obj->set ("artifacts", artifacts_arr);
    1344                 :             : 
    1345                 :             :   /* "results" property (SARIF v2.1.0 section 3.14.23).  */
    1346                 :          79 :   run_obj->set ("results", results);
    1347                 :             : 
    1348                 :          79 :   return run_obj;
    1349                 :             : }
    1350                 :             : 
    1351                 :             : /* Make a tool object (SARIF v2.1.0 section 3.18).  */
    1352                 :             : 
    1353                 :             : json::object *
    1354                 :          79 : sarif_builder::make_tool_object () const
    1355                 :             : {
    1356                 :          79 :   json::object *tool_obj = new json::object ();
    1357                 :             : 
    1358                 :             :   /* "driver" property (SARIF v2.1.0 section 3.18.2).  */
    1359                 :          79 :   json::object *driver_obj = make_driver_tool_component_object ();
    1360                 :          79 :   tool_obj->set ("driver", driver_obj);
    1361                 :             : 
    1362                 :             :   /* Report plugins via the "extensions" property
    1363                 :             :      (SARIF v2.1.0 section 3.18.3).  */
    1364                 :          79 :   if (auto client_data_hooks = m_context->get_client_data_hooks ())
    1365                 :         158 :     if (const client_version_info *vinfo
    1366                 :          79 :           = client_data_hooks->get_any_version_info ())
    1367                 :             :       {
    1368                 :         237 :         class my_plugin_visitor : public client_version_info :: plugin_visitor
    1369                 :             :         {
    1370                 :             :         public:
    1371                 :           4 :           void on_plugin (const diagnostic_client_plugin_info &p) final override
    1372                 :             :           {
    1373                 :             :             /* Create a toolComponent object (SARIF v2.1.0 section 3.19)
    1374                 :             :                for the plugin.  */
    1375                 :           4 :             json::object *plugin_obj = new json::object ();
    1376                 :           4 :             m_plugin_objs.safe_push (plugin_obj);
    1377                 :             : 
    1378                 :             :             /* "name" property (SARIF v2.1.0 section 3.19.8).  */
    1379                 :           4 :             if (const char *short_name = p.get_short_name ())
    1380                 :           4 :               plugin_obj->set_string ("name", short_name);
    1381                 :             : 
    1382                 :             :             /* "fullName" property (SARIF v2.1.0 section 3.19.9).  */
    1383                 :           4 :             if (const char *full_name = p.get_full_name ())
    1384                 :           4 :               plugin_obj->set_string ("fullName", full_name);
    1385                 :             : 
    1386                 :             :             /* "version" property (SARIF v2.1.0 section 3.19.13).  */
    1387                 :           4 :             if (const char *version = p.get_version ())
    1388                 :           0 :               plugin_obj->set_string ("version", version);
    1389                 :           4 :           }
    1390                 :             :           auto_vec <json::object *> m_plugin_objs;
    1391                 :             :         };
    1392                 :          79 :         my_plugin_visitor v;
    1393                 :          79 :         vinfo->for_each_plugin (v);
    1394                 :          83 :         if (v.m_plugin_objs.length () > 0)
    1395                 :             :           {
    1396                 :           4 :             json::array *extensions_arr = new json::array ();
    1397                 :           4 :             tool_obj->set ("extensions", extensions_arr);
    1398                 :          16 :             for (auto iter : v.m_plugin_objs)
    1399                 :           4 :               extensions_arr->append (iter);
    1400                 :             :           }
    1401                 :          79 :       }
    1402                 :             : 
    1403                 :             :   /* Perhaps we could also show GMP, MPFR, MPC, isl versions as other
    1404                 :             :      "extensions" (see toplev.cc: print_version).  */
    1405                 :             : 
    1406                 :          79 :   return tool_obj;
    1407                 :             : }
    1408                 :             : 
    1409                 :             : /* Make a toolComponent object (SARIF v2.1.0 section 3.19) for what SARIF
    1410                 :             :    calls the "driver" (see SARIF v2.1.0 section 3.18.1).  */
    1411                 :             : 
    1412                 :             : json::object *
    1413                 :          79 : sarif_builder::make_driver_tool_component_object () const
    1414                 :             : {
    1415                 :          79 :   json::object *driver_obj = new json::object ();
    1416                 :             : 
    1417                 :          79 :   if (auto client_data_hooks = m_context->get_client_data_hooks ())
    1418                 :         158 :     if (const client_version_info *vinfo
    1419                 :          79 :           = client_data_hooks->get_any_version_info ())
    1420                 :             :       {
    1421                 :             :         /* "name" property (SARIF v2.1.0 section 3.19.8).  */
    1422                 :          79 :         if (const char *name = vinfo->get_tool_name ())
    1423                 :          79 :           driver_obj->set_string ("name", name);
    1424                 :             : 
    1425                 :             :         /* "fullName" property (SARIF v2.1.0 section 3.19.9).  */
    1426                 :          79 :         if (char *full_name = vinfo->maybe_make_full_name ())
    1427                 :             :           {
    1428                 :          79 :             driver_obj->set_string ("fullName", full_name);
    1429                 :          79 :             free (full_name);
    1430                 :             :           }
    1431                 :             : 
    1432                 :             :         /* "version" property (SARIF v2.1.0 section 3.19.13).  */
    1433                 :          79 :         if (const char *version = vinfo->get_version_string ())
    1434                 :          79 :           driver_obj->set_string ("version", version);
    1435                 :             : 
    1436                 :             :         /* "informationUri" property (SARIF v2.1.0 section 3.19.17).  */
    1437                 :          79 :         if (char *version_url =  vinfo->maybe_make_version_url ())
    1438                 :             :           {
    1439                 :          79 :             driver_obj->set_string ("informationUri", version_url);
    1440                 :          79 :             free (version_url);
    1441                 :             :           }
    1442                 :             :       }
    1443                 :             : 
    1444                 :             :   /* "rules" property (SARIF v2.1.0 section 3.19.23).  */
    1445                 :          79 :   driver_obj->set ("rules", m_rules_arr);
    1446                 :             : 
    1447                 :          79 :   return driver_obj;
    1448                 :             : }
    1449                 :             : 
    1450                 :             : /* If we've seen any CWE IDs, make an array for the "taxonomies" property
    1451                 :             :    (SARIF v2.1.0 section 3.14.8) of a run object, containting a singl
    1452                 :             :    toolComponent (3.19) as per 3.19.3, representing the CWE.
    1453                 :             : 
    1454                 :             :    Otherwise return NULL.  */
    1455                 :             : 
    1456                 :             : json::array *
    1457                 :          79 : sarif_builder::maybe_make_taxonomies_array () const
    1458                 :             : {
    1459                 :          79 :   json::object *cwe_obj = maybe_make_cwe_taxonomy_object ();
    1460                 :          79 :   if (!cwe_obj)
    1461                 :             :     return NULL;
    1462                 :             : 
    1463                 :             :   /* "taxonomies" property (SARIF v2.1.0 section 3.14.8).  */
    1464                 :          15 :   json::array *taxonomies_arr = new json::array ();
    1465                 :          15 :   taxonomies_arr->append (cwe_obj);
    1466                 :          15 :   return taxonomies_arr;
    1467                 :             : }
    1468                 :             : 
    1469                 :             : /* If we've seen any CWE IDs, make a toolComponent object
    1470                 :             :    (SARIF v2.1.0 section 3.19) representing the CWE taxonomy, as per 3.19.3.
    1471                 :             :    Populate the "taxa" property with all of the CWE IDs in m_cwe_id_set.
    1472                 :             : 
    1473                 :             :    Otherwise return NULL.  */
    1474                 :             : 
    1475                 :             : json::object *
    1476                 :          79 : sarif_builder::maybe_make_cwe_taxonomy_object () const
    1477                 :             : {
    1478                 :          79 :   if (m_cwe_id_set.is_empty ())
    1479                 :             :     return NULL;
    1480                 :             : 
    1481                 :          15 :   json::object *taxonomy_obj = new json::object ();
    1482                 :             : 
    1483                 :             :   /* "name" property (SARIF v2.1.0 section 3.19.8).  */
    1484                 :          15 :   taxonomy_obj->set_string ("name", "CWE");
    1485                 :             : 
    1486                 :             :   /* "version" property (SARIF v2.1.0 section 3.19.13).  */
    1487                 :          15 :   taxonomy_obj->set_string ("version", "4.7");
    1488                 :             : 
    1489                 :             :   /* "organization" property (SARIF v2.1.0 section 3.19.18).  */
    1490                 :          15 :   taxonomy_obj->set_string ("organization", "MITRE");
    1491                 :             : 
    1492                 :             :   /* "shortDescription" property (SARIF v2.1.0 section 3.19.19).  */
    1493                 :          15 :   json::object *short_desc
    1494                 :          15 :     = make_multiformat_message_string ("The MITRE"
    1495                 :             :                                        " Common Weakness Enumeration");
    1496                 :          15 :   taxonomy_obj->set ("shortDescription", short_desc);
    1497                 :             : 
    1498                 :             :   /* "taxa" property (SARIF v2.1.0 3.section 3.19.25).  */
    1499                 :          15 :   json::array *taxa_arr = new json::array ();
    1500                 :          45 :   for (auto cwe_id : m_cwe_id_set)
    1501                 :             :     {
    1502                 :          15 :       json::object *cwe_taxon
    1503                 :          15 :         = make_reporting_descriptor_object_for_cwe_id (cwe_id);
    1504                 :          15 :       taxa_arr->append (cwe_taxon);
    1505                 :             :     }
    1506                 :          15 :   taxonomy_obj->set ("taxa", taxa_arr);
    1507                 :             : 
    1508                 :          15 :   return taxonomy_obj;
    1509                 :             : }
    1510                 :             : 
    1511                 :             : /* Make an artifact object (SARIF v2.1.0 section 3.24).  */
    1512                 :             : 
    1513                 :             : json::object *
    1514                 :          79 : sarif_builder::make_artifact_object (const char *filename)
    1515                 :             : {
    1516                 :          79 :   json::object *artifact_obj = new json::object ();
    1517                 :             : 
    1518                 :             :   /* "location" property (SARIF v2.1.0 section 3.24.2).  */
    1519                 :          79 :   json::object *artifact_loc_obj = make_artifact_location_object (filename);
    1520                 :          79 :   artifact_obj->set ("location", artifact_loc_obj);
    1521                 :             : 
    1522                 :             :   /* "contents" property (SARIF v2.1.0 section 3.24.8).  */
    1523                 :         158 :   if (json::object *artifact_content_obj
    1524                 :          79 :         = maybe_make_artifact_content_object (filename))
    1525                 :          59 :     artifact_obj->set ("contents", artifact_content_obj);
    1526                 :             : 
    1527                 :             :   /* "sourceLanguage" property (SARIF v2.1.0 section 3.24.10).  */
    1528                 :          79 :   if (auto client_data_hooks = m_context->get_client_data_hooks ())
    1529                 :         158 :     if (const char *source_lang
    1530                 :          79 :         = client_data_hooks->maybe_get_sarif_source_language (filename))
    1531                 :          79 :       artifact_obj->set_string ("sourceLanguage", source_lang);
    1532                 :             : 
    1533                 :          79 :   return artifact_obj;
    1534                 :             : }
    1535                 :             : 
    1536                 :             : /* Make an artifactContent object (SARIF v2.1.0 section 3.3) for the
    1537                 :             :    full contents of FILENAME.  */
    1538                 :             : 
    1539                 :             : json::object *
    1540                 :          79 : sarif_builder::maybe_make_artifact_content_object (const char *filename) const
    1541                 :             : {
    1542                 :             :   /* Let input.cc handle any charset conversion.  */
    1543                 :          79 :   char_span utf8_content
    1544                 :          79 :     = m_context->get_file_cache ().get_source_file_content (filename);
    1545                 :          79 :   if (!utf8_content)
    1546                 :             :     return NULL;
    1547                 :             : 
    1548                 :             :   /* Don't add it if it's not valid UTF-8.  */
    1549                 :          74 :   if (!cpp_valid_utf8_p(utf8_content.get_buffer (), utf8_content.length ()))
    1550                 :             :     return NULL;
    1551                 :             : 
    1552                 :          59 :   json::object *artifact_content_obj = new json::object ();
    1553                 :         118 :   artifact_content_obj->set ("text",
    1554                 :             :                              new json::string (utf8_content.get_buffer (),
    1555                 :          59 :                                                utf8_content.length ()));
    1556                 :          59 :   return artifact_content_obj;
    1557                 :             : }
    1558                 :             : 
    1559                 :             : /* Attempt to read the given range of lines from FILENAME; return
    1560                 :             :    a freshly-allocated 0-terminated buffer containing them, or NULL.  */
    1561                 :             : 
    1562                 :             : char *
    1563                 :         361 : sarif_builder::get_source_lines (const char *filename,
    1564                 :             :                                  int start_line,
    1565                 :             :                                  int end_line) const
    1566                 :             : {
    1567                 :         361 :   auto_vec<char> result;
    1568                 :             : 
    1569                 :         717 :   for (int line = start_line; line <= end_line; line++)
    1570                 :             :     {
    1571                 :         361 :       char_span line_content
    1572                 :         361 :         = m_context->get_file_cache ().get_source_line (filename, line);
    1573                 :         361 :       if (!line_content.get_buffer ())
    1574                 :           5 :         return NULL;
    1575                 :         356 :       result.reserve (line_content.length () + 1);
    1576                 :        6467 :       for (size_t i = 0; i < line_content.length (); i++)
    1577                 :        6111 :         result.quick_push (line_content[i]);
    1578                 :         356 :       result.quick_push ('\n');
    1579                 :             :     }
    1580                 :         356 :   result.safe_push ('\0');
    1581                 :             : 
    1582                 :         712 :   return xstrdup (result.address ());
    1583                 :         361 : }
    1584                 :             : 
    1585                 :             : /* Make an artifactContent object (SARIF v2.1.0 section 3.3) for the given
    1586                 :             :    run of lines within FILENAME (including the endpoints).  */
    1587                 :             : 
    1588                 :             : json::object *
    1589                 :         361 : sarif_builder::maybe_make_artifact_content_object (const char *filename,
    1590                 :             :                                                    int start_line,
    1591                 :             :                                                    int end_line) const
    1592                 :             : {
    1593                 :         361 :   char *text_utf8 = get_source_lines (filename, start_line, end_line);
    1594                 :             : 
    1595                 :         361 :   if (!text_utf8)
    1596                 :             :     return NULL;
    1597                 :             : 
    1598                 :             :   /* Don't add it if it's not valid UTF-8.  */
    1599                 :         356 :   if (!cpp_valid_utf8_p(text_utf8, strlen(text_utf8)))
    1600                 :             :     {
    1601                 :         215 :       free (text_utf8);
    1602                 :         215 :       return NULL;
    1603                 :             :     }
    1604                 :             : 
    1605                 :         141 :   json::object *artifact_content_obj = new json::object ();
    1606                 :         141 :   artifact_content_obj->set_string ("text", text_utf8);
    1607                 :         141 :   free (text_utf8);
    1608                 :             : 
    1609                 :         141 :   return artifact_content_obj;
    1610                 :             : }
    1611                 :             : 
    1612                 :             : /* Make a fix object (SARIF v2.1.0 section 3.55) for RICHLOC.  */
    1613                 :             : 
    1614                 :             : json::object *
    1615                 :           5 : sarif_builder::make_fix_object (const rich_location &richloc)
    1616                 :             : {
    1617                 :           5 :   json::object *fix_obj = new json::object ();
    1618                 :             : 
    1619                 :             :   /* "artifactChanges" property (SARIF v2.1.0 section 3.55.3).  */
    1620                 :             :   /* We assume that all fix-it hints in RICHLOC affect the same file.  */
    1621                 :           5 :   json::array *artifact_change_arr = new json::array ();
    1622                 :           5 :   json::object *artifact_change_obj = make_artifact_change_object (richloc);
    1623                 :           5 :   artifact_change_arr->append (artifact_change_obj);
    1624                 :           5 :   fix_obj->set ("artifactChanges", artifact_change_arr);
    1625                 :             : 
    1626                 :           5 :   return fix_obj;
    1627                 :             : }
    1628                 :             : 
    1629                 :             : /* Make an artifactChange object (SARIF v2.1.0 section 3.56) for RICHLOC.  */
    1630                 :             : 
    1631                 :             : json::object *
    1632                 :           5 : sarif_builder::make_artifact_change_object (const rich_location &richloc)
    1633                 :             : {
    1634                 :           5 :   json::object *artifact_change_obj = new json::object ();
    1635                 :             : 
    1636                 :             :   /* "artifactLocation" property (SARIF v2.1.0 section 3.56.2).  */
    1637                 :           5 :   json::object *artifact_location_obj
    1638                 :           5 :     = make_artifact_location_object (richloc.get_loc ());
    1639                 :           5 :   artifact_change_obj->set ("artifactLocation", artifact_location_obj);
    1640                 :             : 
    1641                 :             :   /* "replacements" property (SARIF v2.1.0 section 3.56.3).  */
    1642                 :           5 :   json::array *replacement_arr = new json::array ();
    1643                 :          10 :   for (unsigned int i = 0; i < richloc.get_num_fixit_hints (); i++)
    1644                 :             :     {
    1645                 :           5 :       const fixit_hint *hint = richloc.get_fixit_hint (i);
    1646                 :           5 :       json::object *replacement_obj = make_replacement_object (*hint);
    1647                 :           5 :       replacement_arr->append (replacement_obj);
    1648                 :             :     }
    1649                 :           5 :   artifact_change_obj->set ("replacements", replacement_arr);
    1650                 :             : 
    1651                 :           5 :   return artifact_change_obj;
    1652                 :             : }
    1653                 :             : 
    1654                 :             : /* Make a replacement object (SARIF v2.1.0 section 3.57) for HINT.  */
    1655                 :             : 
    1656                 :             : json::object *
    1657                 :           5 : sarif_builder::make_replacement_object (const fixit_hint &hint) const
    1658                 :             : {
    1659                 :           5 :   json::object *replacement_obj = new json::object ();
    1660                 :             : 
    1661                 :             :   /* "deletedRegion" property (SARIF v2.1.0 section 3.57.3).  */
    1662                 :           5 :   json::object *region_obj = make_region_object_for_hint (hint);
    1663                 :           5 :   replacement_obj->set ("deletedRegion", region_obj);
    1664                 :             : 
    1665                 :             :   /* "insertedContent" property (SARIF v2.1.0 section 3.57.4).  */
    1666                 :           5 :   json::object *content_obj = make_artifact_content_object (hint.get_string ());
    1667                 :           5 :   replacement_obj->set ("insertedContent", content_obj);
    1668                 :             : 
    1669                 :           5 :   return replacement_obj;
    1670                 :             : }
    1671                 :             : 
    1672                 :             : /* Make an artifactContent object (SARIF v2.1.0 section 3.3) for TEXT.  */
    1673                 :             : 
    1674                 :             : json::object *
    1675                 :           5 : sarif_builder::make_artifact_content_object (const char *text) const
    1676                 :             : {
    1677                 :           5 :   json::object *content_obj = new json::object ();
    1678                 :             : 
    1679                 :             :   /* "text" property (SARIF v2.1.0 section 3.3.2).  */
    1680                 :           5 :   content_obj->set_string ("text", text);
    1681                 :             : 
    1682                 :           5 :   return content_obj;
    1683                 :             : }
    1684                 :             : 
    1685                 :             : /* Callback for diagnostic_context::ice_handler_cb for when an ICE
    1686                 :             :    occurs.  */
    1687                 :             : 
    1688                 :             : static void
    1689                 :           2 : sarif_ice_handler (diagnostic_context *context)
    1690                 :             : {
    1691                 :             :   /* Attempt to ensure that a .sarif file is written out.  */
    1692                 :           2 :   diagnostic_finish (context);
    1693                 :             : 
    1694                 :             :   /* Print a header for the remaining output to stderr, and
    1695                 :             :      return, attempting to print the usual ICE messages to
    1696                 :             :      stderr.  Hopefully this will be helpful to the user in
    1697                 :             :      indicating what's gone wrong (also for DejaGnu, for pruning
    1698                 :             :      those messages).   */
    1699                 :           2 :   fnotice (stderr, "Internal compiler error:\n");
    1700                 :           2 : }
    1701                 :             : 
    1702                 :          79 : class sarif_output_format : public diagnostic_output_format
    1703                 :             : {
    1704                 :             : public:
    1705                 :          84 :   void on_begin_group () final override
    1706                 :             :   {
    1707                 :             :     /* No-op,  */
    1708                 :          84 :   }
    1709                 :          56 :   void on_end_group () final override
    1710                 :             :   {
    1711                 :          56 :     m_builder.end_group ();
    1712                 :          56 :   }
    1713                 :             :   void
    1714                 :         304 :   on_begin_diagnostic (const diagnostic_info &) final override
    1715                 :             :   {
    1716                 :             :     /* No-op,  */
    1717                 :         304 :   }
    1718                 :             :   void
    1719                 :         304 :   on_end_diagnostic (const diagnostic_info &diagnostic,
    1720                 :             :                      diagnostic_t orig_diag_kind) final override
    1721                 :             :   {
    1722                 :         304 :     m_builder.end_diagnostic (&m_context, diagnostic, orig_diag_kind);
    1723                 :         304 :   }
    1724                 :           5 :   void on_diagram (const diagnostic_diagram &diagram) final override
    1725                 :             :   {
    1726                 :           5 :     m_builder.emit_diagram (&m_context, diagram);
    1727                 :           5 :   }
    1728                 :             : 
    1729                 :             : protected:
    1730                 :          79 :   sarif_output_format (diagnostic_context &context,
    1731                 :             :                        bool formatted)
    1732                 :          79 :   : diagnostic_output_format (context),
    1733                 :          79 :     m_builder (&context, formatted)
    1734                 :             :   {}
    1735                 :             : 
    1736                 :             :   sarif_builder m_builder;
    1737                 :             : };
    1738                 :             : 
    1739                 :             : class sarif_stream_output_format : public sarif_output_format
    1740                 :             : {
    1741                 :             : public:
    1742                 :           0 :   sarif_stream_output_format (diagnostic_context &context,
    1743                 :             :                               bool formatted,
    1744                 :             :                               FILE *stream)
    1745                 :           0 :   : sarif_output_format (context, formatted),
    1746                 :           0 :     m_stream (stream)
    1747                 :             :   {
    1748                 :             :   }
    1749                 :           0 :   ~sarif_stream_output_format ()
    1750                 :           0 :   {
    1751                 :           0 :     m_builder.flush_to_file (m_stream);
    1752                 :           0 :   }
    1753                 :           0 :   bool machine_readable_stderr_p () const final override
    1754                 :             :   {
    1755                 :           0 :     return m_stream == stderr;
    1756                 :             :   }
    1757                 :             : private:
    1758                 :             :   FILE *m_stream;
    1759                 :             : };
    1760                 :             : 
    1761                 :             : class sarif_file_output_format : public sarif_output_format
    1762                 :             : {
    1763                 :             : public:
    1764                 :          79 :   sarif_file_output_format (diagnostic_context &context,
    1765                 :             :                             bool formatted,
    1766                 :             :                             const char *base_file_name)
    1767                 :          79 :   : sarif_output_format (context, formatted),
    1768                 :          79 :     m_base_file_name (xstrdup (base_file_name))
    1769                 :             :   {
    1770                 :          79 :   }
    1771                 :         158 :   ~sarif_file_output_format ()
    1772                 :          79 :   {
    1773                 :          79 :     char *filename = concat (m_base_file_name, ".sarif", NULL);
    1774                 :          79 :     free (m_base_file_name);
    1775                 :          79 :     m_base_file_name = nullptr;
    1776                 :          79 :     FILE *outf = fopen (filename, "w");
    1777                 :          79 :     if (!outf)
    1778                 :             :       {
    1779                 :           0 :         const char *errstr = xstrerror (errno);
    1780                 :           0 :         fnotice (stderr, "error: unable to open '%s' for writing: %s\n",
    1781                 :             :                  filename, errstr);
    1782                 :           0 :         free (filename);
    1783                 :           0 :         return;
    1784                 :             :       }
    1785                 :          79 :     m_builder.flush_to_file (outf);
    1786                 :          79 :     fclose (outf);
    1787                 :          79 :     free (filename);
    1788                 :         158 :   }
    1789                 :           2 :   bool machine_readable_stderr_p () const final override
    1790                 :             :   {
    1791                 :           2 :     return false;
    1792                 :             :   }
    1793                 :             : 
    1794                 :             : private:
    1795                 :             :   char *m_base_file_name;
    1796                 :             : };
    1797                 :             : 
    1798                 :             : /* Populate CONTEXT in preparation for SARIF output (either to stderr, or
    1799                 :             :    to a file).  */
    1800                 :             : 
    1801                 :             : static void
    1802                 :          79 : diagnostic_output_format_init_sarif (diagnostic_context *context)
    1803                 :             : {
    1804                 :             :   /* Override callbacks.  */
    1805                 :          79 :   context->m_print_path = nullptr; /* handled in sarif_end_diagnostic.  */
    1806                 :          79 :   context->set_ice_handler_callback (sarif_ice_handler);
    1807                 :             : 
    1808                 :             :   /* The metadata is handled in SARIF format, rather than as text.  */
    1809                 :          79 :   context->set_show_cwe (false);
    1810                 :          79 :   context->set_show_rules (false);
    1811                 :             : 
    1812                 :             :   /* The option is handled in SARIF format, rather than as text.  */
    1813                 :          79 :   context->set_show_option_requested (false);
    1814                 :             : 
    1815                 :             :   /* Don't colorize the text.  */
    1816                 :          79 :   pp_show_color (context->printer) = false;
    1817                 :           0 : }
    1818                 :             : 
    1819                 :             : /* Populate CONTEXT in preparation for SARIF output to stderr.  */
    1820                 :             : 
    1821                 :             : void
    1822                 :           0 : diagnostic_output_format_init_sarif_stderr (diagnostic_context *context,
    1823                 :             :                                             bool formatted)
    1824                 :             : {
    1825                 :           0 :   diagnostic_output_format_init_sarif (context);
    1826                 :           0 :   context->set_output_format (new sarif_stream_output_format (*context,
    1827                 :             :                                                               formatted,
    1828                 :           0 :                                                               stderr));
    1829                 :           0 : }
    1830                 :             : 
    1831                 :             : /* Populate CONTEXT in preparation for SARIF output to a file named
    1832                 :             :    BASE_FILE_NAME.sarif.  */
    1833                 :             : 
    1834                 :             : void
    1835                 :          79 : diagnostic_output_format_init_sarif_file (diagnostic_context *context,
    1836                 :             :                                           bool formatted,
    1837                 :             :                                           const char *base_file_name)
    1838                 :             : {
    1839                 :          79 :   diagnostic_output_format_init_sarif (context);
    1840                 :          79 :   context->set_output_format (new sarif_file_output_format (*context,
    1841                 :             :                                                             formatted,
    1842                 :          79 :                                                             base_file_name));
    1843                 :          79 : }
    1844                 :             : 
    1845                 :             : /* Populate CONTEXT in preparation for SARIF output to STREAM.  */
    1846                 :             : 
    1847                 :             : void
    1848                 :           0 : diagnostic_output_format_init_sarif_stream (diagnostic_context *context,
    1849                 :             :                                             bool formatted,
    1850                 :             :                                             FILE *stream)
    1851                 :             : {
    1852                 :           0 :   diagnostic_output_format_init_sarif (context);
    1853                 :           0 :   context->set_output_format (new sarif_stream_output_format (*context,
    1854                 :             :                                                               formatted,
    1855                 :           0 :                                                               stream));
    1856                 :           0 : }
        

Generated by: LCOV version 2.0-1

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.