GCC Middle and Back End API Reference
digraphs.h
Go to the documentation of this file.
1/* Directed graphs associated with a diagnostic.
2 Copyright (C) 2025 Free Software Foundation, Inc.
3 Contributed by David Malcolm <dmalcolm@redhat.com>
4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify it under
8the terms of the GNU General Public License as published by the Free
9Software Foundation; either version 3, or (at your option) any later
10version.
11
12GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13WARRANTY; without even the implied warranty of MERCHANTABILITY or
14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15for more details.
16
17You should have received a copy of the GNU General Public License
18along 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"
26
27class graphviz_out;
28
29class sarif_graph;
30class sarif_node;
31class sarif_edge;
32
33namespace dot { class graph; }
34
35namespace diagnostics {
36namespace 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
48class digraph;
49class node;
50class edge;
51
52/* A base class for digraph, node, and edge to allow them to have
53 an optional JSON property bag. */
54
55class object
56{
57public:
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
73 get_property_bag () const { return m_property_bag.get (); }
74
75 void
76 set_property_bag (std::unique_ptr<json::object> property_bag)
77 {
78 m_property_bag = std::move (property_bag);
79 }
80
81private:
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
87class digraph : public object
88{
89 public:
90 friend class node;
91 friend class edge;
92
94 virtual ~digraph () {}
95
96 const char *
98 {
99 if (!m_description)
100 return nullptr;
101 return m_description->c_str ();
102 }
103
104 void
105 set_description (const char *desc)
106 {
107 if (desc)
108 m_description = std::make_unique<std::string> (desc);
109 else
110 m_description = nullptr;
111 }
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
138 {
139 return m_nodes.size ();
140 }
141
142 node &
143 get_node (size_t idx) const
144 {
145 return *m_nodes[idx].get ();
146 }
147
148 size_t
150 {
151 return m_edges.size ();
152 }
153
154 edge &
155 get_edge (size_t idx) const
156 {
157 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 add_node (std::unique_ptr<node> n)
171 {
172 gcc_assert (n);
173 m_nodes.push_back (std::move (n));
174 }
175
176 void
177 add_edge (std::unique_ptr<edge> e)
178 {
179 gcc_assert (e);
180 m_edges.push_back (std::move (e));
181 }
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 add_node_id (std::string node_id, node &new_node)
194 {
195 m_id_to_node_map.insert ({std::move (node_id), &new_node});
196 }
197 void
198 add_edge_id (std::string edge_id, edge &new_edge)
199 {
200 m_id_to_edge_map.insert ({std::move (edge_id), &new_edge});
201 }
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;
212};
213
214// A node in a directed graph, corresponding to SARIF v2.1.0 section 3.40.
215
216class node : public object
217{
218 public:
219 virtual ~node () {}
220
221 node (digraph &g, std::string id)
222 : m_id (id),
224 {
225 g.add_node_id (std::move (id), *this);
226 }
227 node (const node &) = delete;
228
229 std::string
230 get_id () const { return m_id; }
231
232 const char *
233 get_label () const
234 {
235 if (!m_label)
236 return nullptr;
237 return m_label->c_str ();
238 }
239
240 void
241 set_label (const char *label)
242 {
243 if (label)
244 m_label = std::make_unique<std::string> (label);
245 else
246 m_label = nullptr;
247 }
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 get_num_children () const { return m_children.size (); }
256
257 node &
258 get_child (size_t idx) const { return *m_children[idx].get (); }
259
260 void
261 add_child (std::unique_ptr<node> child)
262 {
263 gcc_assert (child);
264 m_children.push_back (std::move (child));
265 }
266
267 location_t
269 {
270 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
281 {
282 return m_logical_loc;
283 }
284
285 void
287 {
288 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>
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;
309};
310
311// An edge in a directed graph, corresponding to SARIF v2.1.0 section 3.41.
312
313class edge : public object
314{
315 public:
316 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. */
323 const char *id,
324 node &src_node,
325 node &dst_node)
326 : m_id (g.make_edge_id (id)),
327 m_src_node (src_node),
328 m_dst_node (dst_node)
329 {
330 g.add_edge_id (m_id, *this);
331 }
332
333 std::string
334 get_id () const { return m_id; }
335
336 const char *
337 get_label () const
338 {
339 if (!m_label)
340 return nullptr;
341 return m_label->c_str ();
342 }
343
344 void
345 set_label (const char *label)
346 {
347 if (label)
348 m_label = std::make_unique<std::string> (label);
349 else
350 m_label = nullptr;
351 }
352
353 node &
354 get_src_node () const { return m_src_node; }
355
356 node &
357 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>
367 const std::map<diagnostics::digraphs::node *, diagnostics::digraphs::node *> &node_mapping) const;
368
369private:
370 std::string m_id;
371 std::unique_ptr<std::string> m_label;
374};
375
376} // namespace digraphs
377} // namespace diagnostics
378
379#endif /* ! GCC_DIAGNOSTICS_DIGRAPHS_H */
Definition digraphs.h:88
std::unique_ptr< std::string > m_description
Definition digraphs.h:206
digraph()
Definition digraphs.h:93
friend class node
Definition digraphs.h:90
size_t get_num_edges() const
Definition digraphs.h:149
edge * get_edge_by_id(const char *id) const
Definition digraphs.h:128
friend class edge
Definition digraphs.h:91
std::vector< std::unique_ptr< edge > > m_edges
Definition digraphs.h:210
size_t m_next_edge_id_index
Definition digraphs.h:211
void set_description(std::string desc)
Definition digraphs.h:113
void add_node_id(std::string node_id, node &new_node)
Definition digraphs.h:193
std::unique_ptr< json::object > make_json_sarif_graph() const
Definition digraphs.cc:213
std::unique_ptr< dot::graph > make_dot_graph() const
Definition digraphs.cc:219
node * get_node_by_id(const char *id) const
Definition digraphs.h:119
void add_node(std::unique_ptr< node > n)
Definition digraphs.h:170
void dump() const
Definition digraphs.cc:207
void add_edge_id(std::string edge_id, edge &new_edge)
Definition digraphs.h:198
std::map< std::string, node * > m_id_to_node_map
Definition digraphs.h:207
std::string make_edge_id(const char *edge_id)
Definition digraphs.cc:266
const char * get_description() const
Definition digraphs.h:97
std::unique_ptr< digraph > clone() const
Definition digraphs.cc:226
edge & get_edge(size_t idx) const
Definition digraphs.h:155
size_t get_num_nodes() const
Definition digraphs.h:137
virtual ~digraph()
Definition digraphs.h:94
std::vector< std::unique_ptr< node > > m_nodes
Definition digraphs.h:209
void add_edge(std::unique_ptr< edge > e)
Definition digraphs.h:177
std::map< std::string, edge * > m_id_to_edge_map
Definition digraphs.h:208
node & get_node(size_t idx) const
Definition digraphs.h:143
void set_description(const char *desc)
Definition digraphs.h:105
Definition digraphs.h:314
edge(digraph &g, const char *id, node &src_node, node &dst_node)
Definition digraphs.h:322
std::string get_id() const
Definition digraphs.h:334
node & m_src_node
Definition digraphs.h:372
virtual ~edge()
Definition digraphs.h:316
std::string m_id
Definition digraphs.h:370
void dump() const
Definition digraphs.cc:343
node & get_dst_node() const
Definition digraphs.h:357
node & m_dst_node
Definition digraphs.h:373
std::unique_ptr< edge > clone(digraph &new_graph, const std::map< diagnostics::digraphs::node *, diagnostics::digraphs::node * > &node_mapping) const
std::unique_ptr< json::object > to_json_sarif_edge() const
Definition digraphs.cc:349
std::unique_ptr< std::string > m_label
Definition digraphs.h:371
void set_label(const char *label)
Definition digraphs.h:345
const char * get_label() const
Definition digraphs.h:337
node & get_src_node() const
Definition digraphs.h:354
Definition digraphs.h:217
std::unique_ptr< json::object > to_json_sarif_node() const
Definition digraphs.cc:296
std::string get_id() const
Definition digraphs.h:230
void add_child(std::unique_ptr< node > child)
Definition digraphs.h:261
std::unique_ptr< node > clone(digraph &new_graph, std::map< node *, node * > &node_mapping) const
Definition digraphs.cc:302
void set_label(std::string label)
Definition digraphs.h:249
std::unique_ptr< std::string > m_label
Definition digraphs.h:305
node(const node &)=delete
std::vector< std::unique_ptr< node > > m_children
Definition digraphs.h:306
location_t get_physical_loc() const
Definition digraphs.h:268
void dump() const
Definition digraphs.cc:290
logical_locations::key get_logical_loc() const
Definition digraphs.h:280
std::string m_id
Definition digraphs.h:304
void set_physical_loc(location_t physical_loc)
Definition digraphs.h:274
void set_label(const char *label)
Definition digraphs.h:241
size_t get_num_children() const
Definition digraphs.h:255
void print(graphviz_out &gv) const
const char * get_label() const
Definition digraphs.h:233
node(digraph &g, std::string id)
Definition digraphs.h:221
virtual ~node()
Definition digraphs.h:219
node & get_child(size_t idx) const
Definition digraphs.h:258
location_t m_physical_loc
Definition digraphs.h:307
logical_locations::key m_logical_loc
Definition digraphs.h:308
void set_logical_loc(logical_locations::key logical_loc)
Definition digraphs.h:286
Definition digraphs.h:56
void set_attr(const char *key_prefix, const char *key, const char *value)
Definition digraphs.cc:189
const char * get_attr(const char *key_prefix, const char *key) const
Definition digraphs.cc:176
void set_property_bag(std::unique_ptr< json::object > property_bag)
Definition digraphs.h:76
json::object * get_property_bag() const
Definition digraphs.h:73
void set_json_attr(const char *key_prefix, const char *key, std::unique_ptr< json::value > value)
Definition digraphs.cc:196
std::unique_ptr< json::object > m_property_bag
Definition digraphs.h:82
Definition logical-locations.h:101
Definition graphviz.h:385
Definition json.h:149
gcc::context * g
Definition context.cc:29
struct graph * new_graph(int n_vertices)
Definition graphds.cc:50
#define UNKNOWN_LOCATION
Definition input.h:32
Definition diagnostics/context.h:39
Definition coretypes.h:167
Definition graphviz.cc:147
Definition graphviz.h:160
Definition collect2.cc:168
#define gcc_assert(EXPR)
Definition system.h:814