LCOV - code coverage report
Current view: top level - gcc/diagnostics - digraphs.h (source / functions) Coverage Total Hit
Test: gcc.info Lines: 93.8 % 81 76
Test Date: 2025-09-20 13:40:47 Functions: 100.0 % 17 17
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : /* Directed graphs associated with a diagnostic.
       2                 :             :    Copyright (C) 2025 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                 :             : #ifndef GCC_DIAGNOSTICS_DIGRAPHS_H
      22                 :             : #define GCC_DIAGNOSTICS_DIGRAPHS_H
      23                 :             : 
      24                 :             : #include "json.h"
      25                 :             : #include "diagnostics/logical-locations.h"
      26                 :             : 
      27                 :             : class graphviz_out;
      28                 :             : 
      29                 :             : class sarif_graph;
      30                 :             : class sarif_node;
      31                 :             : class sarif_edge;
      32                 :             : 
      33                 :             : namespace dot { class graph; }
      34                 :             : 
      35                 :             : namespace diagnostics {
      36                 :             : namespace digraphs {
      37                 :             : 
      38                 :             : /* A family of classes: digraph, node, and edge, closely related to
      39                 :             :    SARIF's graph, node, and edge types (SARIF v2.1.0 sections 3.39-3.41).
      40                 :             : 
      41                 :             :    Nodes can have child nodes, allowing for arbitrarily deep nesting.
      42                 :             :    Edges can be between any pair of nodes (potentially at different
      43                 :             :    nesting levels).
      44                 :             : 
      45                 :             :    Digraphs, nodes, and edges also optionally have a JSON property bag,
      46                 :             :    allowing round-tripping of arbitrary key/value pairs through SARIF.  */
      47                 :             : 
      48                 :             : class digraph;
      49                 :             : class node;
      50                 :             : class edge;
      51                 :             : 
      52                 :             : /* A base class for digraph, node, and edge to allow them to have
      53                 :             :    an optional JSON property bag.  */
      54                 :             : 
      55                 :        4488 : class object
      56                 :             : {
      57                 :             : public:
      58                 :             :   const char *
      59                 :             :   get_attr (const char *key_prefix,
      60                 :             :             const char *key) const;
      61                 :             : 
      62                 :             :   void
      63                 :             :   set_attr (const char *key_prefix,
      64                 :             :             const char *key,
      65                 :             :             const char *value);
      66                 :             : 
      67                 :             :   void
      68                 :             :   set_json_attr (const char *key_prefix,
      69                 :             :                  const char *key,
      70                 :             :                  std::unique_ptr<json::value> value);
      71                 :             : 
      72                 :             :   json::object *
      73                 :        1427 :   get_property_bag () const { return m_property_bag.get (); }
      74                 :             : 
      75                 :             :   void
      76                 :           0 :   set_property_bag (std::unique_ptr<json::object> property_bag)
      77                 :             :   {
      78                 :           0 :     m_property_bag = std::move (property_bag);
      79                 :             :   }
      80                 :             : 
      81                 :             : private:
      82                 :             :   std::unique_ptr<json::object> m_property_bag;
      83                 :             : };
      84                 :             : 
      85                 :             : // A directed graph, corresponding to SARIF v2.1.0 section 3.39.
      86                 :             : 
      87                 :             : class digraph : public object
      88                 :             : {
      89                 :             :  public:
      90                 :             :   friend class node;
      91                 :             :   friend class edge;
      92                 :             : 
      93                 :          40 :   digraph () : m_next_edge_id_index (0) {}
      94                 :          56 :   virtual ~digraph () {}
      95                 :             : 
      96                 :             :   const char *
      97                 :          52 :   get_description () const
      98                 :             :   {
      99                 :          52 :     if (!m_description)
     100                 :             :       return nullptr;
     101                 :          17 :     return m_description->c_str ();
     102                 :             :   }
     103                 :             : 
     104                 :             :   void
     105                 :           4 :   set_description (const char *desc)
     106                 :             :   {
     107                 :           4 :     if (desc)
     108                 :           4 :       m_description = std::make_unique<std::string> (desc);
     109                 :             :     else
     110                 :           0 :       m_description = nullptr;
     111                 :           4 :   }
     112                 :             :   void
     113                 :             :   set_description (std::string desc)
     114                 :             :   {
     115                 :             :     m_description = std::make_unique<std::string> (std::move (desc));
     116                 :             :   }
     117                 :             : 
     118                 :             :   node *
     119                 :             :   get_node_by_id (const char *id) const
     120                 :             :   {
     121                 :             :     auto iter = m_id_to_node_map.find (id);
     122                 :             :     if (iter == m_id_to_node_map.end ())
     123                 :             :       return nullptr;
     124                 :             :     return iter->second;
     125                 :             :   }
     126                 :             : 
     127                 :             :   edge *
     128                 :             :   get_edge_by_id (const char *id) const
     129                 :             :   {
     130                 :             :     auto iter = m_id_to_edge_map.find (id);
     131                 :             :     if (iter == m_id_to_edge_map.end ())
     132                 :             :       return nullptr;
     133                 :             :     return iter->second;
     134                 :             :   }
     135                 :             : 
     136                 :             :   size_t
     137                 :          51 :   get_num_nodes () const
     138                 :             :   {
     139                 :          51 :     return m_nodes.size ();
     140                 :             :   }
     141                 :             : 
     142                 :             :   node &
     143                 :         104 :   get_node (size_t idx) const
     144                 :             :   {
     145                 :         104 :     return *m_nodes[idx].get ();
     146                 :             :   }
     147                 :             : 
     148                 :             :   size_t
     149                 :          51 :   get_num_edges () const
     150                 :             :   {
     151                 :          51 :     return m_edges.size ();
     152                 :             :   }
     153                 :             : 
     154                 :             :   edge &
     155                 :        1232 :   get_edge (size_t idx) const
     156                 :             :   {
     157                 :        1232 :     return *m_edges[idx].get ();
     158                 :             :   }
     159                 :             : 
     160                 :             :   void
     161                 :             :   dump () const;
     162                 :             : 
     163                 :             :   std::unique_ptr<json::object>
     164                 :             :   make_json_sarif_graph () const;
     165                 :             : 
     166                 :             :   std::unique_ptr<dot::graph>
     167                 :             :   make_dot_graph () const;
     168                 :             : 
     169                 :             :   void
     170                 :          78 :   add_node (std::unique_ptr<node> n)
     171                 :             :   {
     172                 :          78 :     gcc_assert (n);
     173                 :          78 :     m_nodes.push_back (std::move (n));
     174                 :          78 :   }
     175                 :             : 
     176                 :             :   void
     177                 :         829 :   add_edge (std::unique_ptr<edge> e)
     178                 :             :   {
     179                 :         829 :     gcc_assert (e);
     180                 :         829 :     m_edges.push_back (std::move (e));
     181                 :         829 :   }
     182                 :             : 
     183                 :             :   void
     184                 :             :   add_edge (const char *id,
     185                 :             :             node &src_node,
     186                 :             :             node &dst_node,
     187                 :             :             const char *label = nullptr);
     188                 :             : 
     189                 :             :   std::unique_ptr<digraph> clone () const;
     190                 :             : 
     191                 :             :  private:
     192                 :             :   void
     193                 :        1368 :   add_node_id (std::string node_id, node &new_node)
     194                 :             :   {
     195                 :        1368 :     m_id_to_node_map.insert ({std::move (node_id), &new_node});
     196                 :        1368 :   }
     197                 :             :   void
     198                 :         833 :   add_edge_id (std::string edge_id, edge &new_edge)
     199                 :             :   {
     200                 :         833 :     m_id_to_edge_map.insert ({std::move (edge_id), &new_edge});
     201                 :         833 :   }
     202                 :             : 
     203                 :             :   std::string
     204                 :             :   make_edge_id (const char *edge_id);
     205                 :             : 
     206                 :             :   std::unique_ptr<std::string> m_description;
     207                 :             :   std::map<std::string, node *> m_id_to_node_map;
     208                 :             :   std::map<std::string, edge *> m_id_to_edge_map;
     209                 :             :   std::vector<std::unique_ptr<node>> m_nodes;
     210                 :             :   std::vector<std::unique_ptr<edge>> m_edges;
     211                 :             :   size_t m_next_edge_id_index;
     212                 :             : };
     213                 :             : 
     214                 :             : // A node in a directed graph, corresponding to SARIF v2.1.0 section 3.40.
     215                 :             : 
     216                 :             : class node : public object
     217                 :             : {
     218                 :             :  public:
     219                 :        2732 :   virtual ~node () {}
     220                 :             : 
     221                 :        1368 :   node (digraph &g, std::string id)
     222                 :        2736 :   : m_id (id),
     223                 :        2736 :     m_physical_loc (UNKNOWN_LOCATION)
     224                 :             :   {
     225                 :        1368 :     g.add_node_id (std::move (id), *this);
     226                 :        1368 :   }
     227                 :             :   node (const node &) = delete;
     228                 :             : 
     229                 :             :   std::string
     230                 :        5196 :   get_id () const { return m_id; }
     231                 :             : 
     232                 :             :   const char *
     233                 :        1364 :   get_label () const
     234                 :             :   {
     235                 :        1364 :     if (!m_label)
     236                 :             :       return nullptr;
     237                 :         810 :     return m_label->c_str ();
     238                 :             :   }
     239                 :             : 
     240                 :             :   void
     241                 :           4 :   set_label (const char *label)
     242                 :             :   {
     243                 :           4 :     if (label)
     244                 :           4 :       m_label = std::make_unique<std::string> (label);
     245                 :             :     else
     246                 :           0 :       m_label = nullptr;
     247                 :           4 :   }
     248                 :             :   void
     249                 :             :   set_label (std::string label)
     250                 :             :   {
     251                 :             :     m_label = std::make_unique<std::string> (std::move (label));
     252                 :             :   }
     253                 :             : 
     254                 :             :   size_t
     255                 :        1000 :   get_num_children () const { return m_children.size (); }
     256                 :             : 
     257                 :             :   node &
     258                 :        1282 :   get_child (size_t idx) const { return *m_children[idx].get (); }
     259                 :             : 
     260                 :             :   void
     261                 :         476 :   add_child (std::unique_ptr<node> child)
     262                 :             :   {
     263                 :         476 :     gcc_assert (child);
     264                 :         476 :     m_children.push_back (std::move (child));
     265                 :         476 :   }
     266                 :             : 
     267                 :             :   location_t
     268                 :         947 :   get_physical_loc () const
     269                 :             :   {
     270                 :         947 :     return m_physical_loc;
     271                 :             :   }
     272                 :             : 
     273                 :             :   void
     274                 :             :   set_physical_loc (location_t physical_loc)
     275                 :             :   {
     276                 :             :     m_physical_loc = physical_loc;
     277                 :             :   }
     278                 :             : 
     279                 :             :   logical_locations::key
     280                 :         986 :   get_logical_loc () const
     281                 :             :   {
     282                 :         986 :     return m_logical_loc;
     283                 :             :   }
     284                 :             : 
     285                 :             :   void
     286                 :          39 :   set_logical_loc (logical_locations::key logical_loc)
     287                 :             :   {
     288                 :          39 :     m_logical_loc = logical_loc;
     289                 :             :   }
     290                 :             : 
     291                 :             :   void print (graphviz_out &gv) const;
     292                 :             : 
     293                 :             :   void
     294                 :             :   dump () const;
     295                 :             : 
     296                 :             :   std::unique_ptr<json::object>
     297                 :             :   to_json_sarif_node () const;
     298                 :             : 
     299                 :             :   std::unique_ptr<node>
     300                 :             :   clone (digraph &new_graph,
     301                 :             :          std::map<node *, node *> &node_mapping) const;
     302                 :             : 
     303                 :             :  private:
     304                 :             :   std::string m_id;
     305                 :             :   std::unique_ptr<std::string> m_label;
     306                 :             :   std::vector<std::unique_ptr<node>> m_children;
     307                 :             :   location_t m_physical_loc;
     308                 :             :   logical_locations::key m_logical_loc;
     309                 :             : };
     310                 :             : 
     311                 :             : // An edge in a directed graph, corresponding to SARIF v2.1.0 section 3.41.
     312                 :             : 
     313                 :             : class edge : public object
     314                 :             : {
     315                 :             :  public:
     316                 :        1666 :   virtual ~edge () {}
     317                 :             : 
     318                 :             :   /* SARIF requires us to provide unique edge IDs within a graph,
     319                 :             :      but otherwise we don't need them.
     320                 :             :      Pass in nullptr for the id to get the graph to generate a unique
     321                 :             :      edge id for us.  */
     322                 :         833 :   edge (digraph &g,
     323                 :             :         const char *id,
     324                 :             :         node &src_node,
     325                 :             :         node &dst_node)
     326                 :         833 :   : m_id (g.make_edge_id (id)),
     327                 :         833 :     m_src_node (src_node),
     328                 :         833 :     m_dst_node (dst_node)
     329                 :             :   {
     330                 :        1666 :     g.add_edge_id (m_id, *this);
     331                 :         833 :   }
     332                 :             : 
     333                 :             :   std::string
     334                 :         884 :   get_id () const { return m_id; }
     335                 :             : 
     336                 :             :   const char *
     337                 :         837 :   get_label () const
     338                 :             :   {
     339                 :         837 :     if (!m_label)
     340                 :             :       return nullptr;
     341                 :         790 :     return m_label->c_str ();
     342                 :             :   }
     343                 :             : 
     344                 :             :   void
     345                 :         782 :   set_label (const char *label)
     346                 :             :   {
     347                 :         782 :     if (label)
     348                 :         782 :       m_label = std::make_unique<std::string> (label);
     349                 :             :     else
     350                 :           0 :       m_label = nullptr;
     351                 :         782 :   }
     352                 :             : 
     353                 :             :   node &
     354                 :        1232 :   get_src_node () const { return m_src_node; }
     355                 :             : 
     356                 :             :   node &
     357                 :        1232 :   get_dst_node () const { return m_dst_node; }
     358                 :             : 
     359                 :             :   void
     360                 :             :   dump () const;
     361                 :             : 
     362                 :             :   std::unique_ptr<json::object>
     363                 :             :   to_json_sarif_edge () const;
     364                 :             : 
     365                 :             :   std::unique_ptr<edge>
     366                 :             :   clone (digraph &new_graph,
     367                 :             :          const std::map<diagnostics::digraphs::node *, diagnostics::digraphs::node *> &node_mapping) const;
     368                 :             : 
     369                 :             : private:
     370                 :             :   std::string m_id;
     371                 :             :   std::unique_ptr<std::string> m_label;
     372                 :             :   node &m_src_node;
     373                 :             :   node &m_dst_node;
     374                 :             : };
     375                 :             : 
     376                 :             : } // namespace digraphs
     377                 :             : } // namespace diagnostics
     378                 :             : 
     379                 :             : #endif /* ! GCC_DIAGNOSTICS_DIGRAPHS_H */
        

Generated by: LCOV version 2.1-beta

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.