aboutsummaryrefslogtreecommitdiff
path: root/gcc/diagnostics/state-graphs.h
blob: ad18f82b5b73a43f78c6380e121752596282627c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
/* Extensions to diagnostics::digraphs to support state graphs.
   Copyright (C) 2025 Free Software Foundation, Inc.
   Contributed by David Malcolm <dmalcolm@redhat.com>

This file is part of GCC.

GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.

GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.

You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3.  If not see
<http://www.gnu.org/licenses/>.  */

#ifndef GCC_DIAGNOSTICS_STATE_GRAPHS_H
#define GCC_DIAGNOSTICS_STATE_GRAPHS_H

#include "diagnostics/digraphs.h"
#include "diagnostics/logical-locations.h"

/* diagnostics::digraphs provides support for directed graphs.

   diagnostics::state_graphs provides a way to extend these graphs
   for representing "state graphs" i.e. a representation of the state
   of memory inside a program, for use e.g. by -fanalyzer.

   Specifically, nodes represent memory regions, and we use property bags
   in these nodes to stash extra properties (e.g. what kind of memory region
   a node is e.g. stack vs heap).  */

class sarif_graph;
namespace dot { class graph; }

namespace diagnostics {
namespace state_graphs {

enum class node_kind
{
  // Memory regions
  globals,
  code,
  function, // code within a particular function
  stack,
  stack_frame,
  heap_,
  thread_local_,

  /* Dynamically-allocated buffer,
     on heap or stack (depending on parent).  */
  dynalloc_buffer,

  variable,

  field, // field within a struct or union
  padding, // padding bits in a struct or union
  element, // element within an array

  other // anything else
};

extern const char *
node_kind_to_str (enum node_kind);

enum class node_dynalloc_state
{
  unknown,
  nonnull,
  unchecked,
  freed
};

/* Prefixes to use in SARIF property bags.  */
#define STATE_GRAPH_PREFIX "gcc/diagnostic_state_graph/"
#define STATE_NODE_PREFIX "gcc/diagnostic_state_node/"
#define STATE_EDGE_PREFIX "gcc/diagnostic_state_edge/"

/* A wrapper around a node that gets/sets attributes, using
   the node's property bag for storage, so that the data roundtrips
   through SARIF.  */

struct state_node_ref
{
  state_node_ref (diagnostics::digraphs::node &node)
  : m_node (node)
  {}

  enum node_kind
  get_node_kind () const;
  void
  set_node_kind (enum node_kind);

  // For node_kind::stack_frame, this will be the function
  logical_locations::key
  get_logical_loc () const
  {
    return m_node.get_logical_loc ();
  }

  // For node_kind::dynalloc_buffer
  enum node_dynalloc_state
  get_dynalloc_state () const;

  void
  set_dynalloc_state (enum node_dynalloc_state) const;

  const char *
  get_dynamic_extents () const;

  const char *
  get_name () const { return get_attr ("name"); }
  void
  set_name (const char *name) const { set_attr ("name", name); }

  const char *
  get_type () const { return get_attr ("type"); }
  void
  set_type (const char *type) const { set_attr ("type", type); }

  const char *
  get_value () const { return get_attr ("value"); }

  const char *
  get_index () const { return get_attr ("index"); }

  const char *
  get_attr (const char *key) const
  {
    return m_node.get_attr (STATE_NODE_PREFIX, key);
  }

  void
  set_attr (const char *key, const char *value) const
  {
    return m_node.set_attr (STATE_NODE_PREFIX, key, value);
  }

  void
  set_json_attr (const char *key, std::unique_ptr<json::value> value) const;

  diagnostics::digraphs::node &m_node;
};

extern std::unique_ptr<dot::graph>
make_dot_graph (const diagnostics::digraphs::digraph &state_graph,
		const logical_locations::manager &logical_loc_mgr);

} // namespace state_graphs
} // namespace diagnostics

#endif /* ! GCC_DIAGNOSTICS_STATE_GRAPHS_H */