1 /* Classes for representing the state of interest at a given path of analysis.
2 Copyright (C) 2019-2021 Free Software Foundation, Inc.
3 Contributed by David Malcolm <dmalcolm@redhat.com>.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
12 GCC is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
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/>. */
21 #ifndef GCC_ANALYZER_PROGRAM_STATE_H
22 #define GCC_ANALYZER_PROGRAM_STATE_H
26 /* Data shared by all program_state instances. */
31 extrinsic_state (auto_delete_vec
<state_machine
> &checkers
,
33 logger
*logger
= NULL
)
34 : m_checkers (checkers
), m_logger (logger
), m_engine (eng
)
38 const state_machine
&get_sm (int idx
) const
40 return *m_checkers
[idx
];
43 const char *get_name (int idx
) const
45 return m_checkers
[idx
]->get_name ();
48 unsigned get_num_checkers () const { return m_checkers
.length (); }
50 logger
*get_logger () const { return m_logger
; }
52 void dump_to_pp (pretty_printer
*pp
) const;
53 void dump_to_file (FILE *outf
) const;
56 json::object
*to_json () const;
58 engine
*get_engine () const { return m_engine
; }
59 region_model_manager
*get_model_manager () const;
62 /* The state machines. */
63 auto_delete_vec
<state_machine
> &m_checkers
;
69 /* Map from svalue * to state machine state, also capturing the origin of
75 /* An entry in the hash_map. */
78 /* Default ctor needed by hash_map::empty. */
80 : m_state (0), m_origin (NULL
)
84 entry_t (state_machine::state_t state
,
86 : m_state (state
), m_origin (origin
)
89 bool operator== (const entry_t
&other
) const
91 return (m_state
== other
.m_state
92 && m_origin
== other
.m_origin
);
94 bool operator!= (const entry_t
&other
) const
96 return !(*this == other
);
99 static int cmp (const entry_t
&entry_a
, const entry_t
&entry_b
);
101 state_machine::state_t m_state
;
102 const svalue
*m_origin
;
104 typedef hash_map
<const svalue
*, entry_t
> map_t
;
105 typedef map_t::iterator iterator_t
;
107 sm_state_map (const state_machine
&sm
);
109 sm_state_map
*clone () const;
111 void print (const region_model
*model
,
112 bool simple
, bool multiline
,
113 pretty_printer
*pp
) const;
114 void dump (bool simple
) const;
116 json::object
*to_json () const;
118 bool is_empty_p () const;
120 hashval_t
hash () const;
122 bool operator== (const sm_state_map
&other
) const;
123 bool operator!= (const sm_state_map
&other
) const
125 return !(*this == other
);
128 state_machine::state_t
get_state (const svalue
*sval
,
129 const extrinsic_state
&ext_state
) const;
130 const svalue
*get_origin (const svalue
*sval
,
131 const extrinsic_state
&ext_state
) const;
133 void set_state (region_model
*model
,
135 state_machine::state_t state
,
136 const svalue
*origin
,
137 const extrinsic_state
&ext_state
);
138 bool set_state (const equiv_class
&ec
,
139 state_machine::state_t state
,
140 const svalue
*origin
,
141 const extrinsic_state
&ext_state
);
142 bool impl_set_state (const svalue
*sval
,
143 state_machine::state_t state
,
144 const svalue
*origin
,
145 const extrinsic_state
&ext_state
);
147 void set_global_state (state_machine::state_t state
);
148 state_machine::state_t
get_global_state () const;
150 void on_svalue_leak (const svalue
*sval
,
151 impl_region_model_context
*ctxt
);
152 void on_liveness_change (const svalue_set
&live_svalues
,
153 const region_model
*model
,
154 impl_region_model_context
*ctxt
);
156 void on_unknown_change (const svalue
*sval
,
158 const extrinsic_state
&ext_state
);
160 iterator_t
begin () const { return m_map
.begin (); }
161 iterator_t
end () const { return m_map
.end (); }
162 size_t elements () const { return m_map
.elements (); }
164 static int cmp (const sm_state_map
&smap_a
, const sm_state_map
&smap_b
);
166 static const svalue
*
167 canonicalize_svalue (const svalue
*sval
, const extrinsic_state
&ext_state
);
170 const state_machine
&m_sm
;
172 state_machine::state_t m_global_state
;
175 /* A class for representing the state of interest at a given path of
178 Currently this is a combination of:
179 (a) a region_model, giving:
180 (a.1) a hierarchy of memory regions
181 (a.2) values for the regions
182 (a.3) inequalities between values
183 (b) sm_state_maps per state machine, giving a sparse mapping of
189 program_state (const extrinsic_state
&ext_state
);
190 program_state (const program_state
&other
);
191 program_state
& operator= (const program_state
&other
);
193 #if __cplusplus >= 201103
194 program_state (program_state
&&other
);
199 hashval_t
hash () const;
200 bool operator== (const program_state
&other
) const;
201 bool operator!= (const program_state
&other
) const
203 return !(*this == other
);
206 void print (const extrinsic_state
&ext_state
,
207 pretty_printer
*pp
) const;
209 void dump_to_pp (const extrinsic_state
&ext_state
, bool simple
,
210 bool multiline
, pretty_printer
*pp
) const;
211 void dump_to_file (const extrinsic_state
&ext_state
, bool simple
,
212 bool multiline
, FILE *outf
) const;
213 void dump (const extrinsic_state
&ext_state
, bool simple
) const;
215 json::object
*to_json (const extrinsic_state
&ext_state
) const;
217 void push_frame (const extrinsic_state
&ext_state
, function
*fun
);
218 function
* get_current_function () const;
220 bool on_edge (exploded_graph
&eg
,
221 const exploded_node
&enode
,
222 const superedge
*succ
);
224 program_state
prune_for_point (exploded_graph
&eg
,
225 const program_point
&point
,
226 const exploded_node
*enode_for_diag
) const;
228 tree
get_representative_tree (const svalue
*sval
) const;
230 bool can_purge_p (const extrinsic_state
&ext_state
,
233 /* Don't purge vars that have non-purgeable sm state, to avoid
234 generating false "leak" complaints. */
237 FOR_EACH_VEC_ELT (m_checker_states
, i
, smap
)
239 const state_machine
&sm
= ext_state
.get_sm (i
);
240 if (!sm
.can_purge_p (smap
->get_state (sval
, ext_state
)))
246 bool can_merge_with_p (const program_state
&other
,
247 const program_point
&point
,
248 program_state
*out
) const;
250 void validate (const extrinsic_state
&ext_state
) const;
252 static void detect_leaks (const program_state
&src_state
,
253 const program_state
&dest_state
,
254 const svalue
*extra_sval
,
255 const extrinsic_state
&ext_state
,
256 region_model_context
*ctxt
);
258 /* TODO: lose the pointer here (const-correctness issues?). */
259 region_model
*m_region_model
;
260 auto_delete_vec
<sm_state_map
> m_checker_states
;
262 /* If false, then don't attempt to explore further states along this path.
263 For use in "handling" lvalues for tree codes we haven't yet
268 /* An abstract base class for use with for_each_state_change. */
270 class state_change_visitor
273 virtual ~state_change_visitor () {}
275 /* Return true for early exit, false to keep iterating. */
276 virtual bool on_global_state_change (const state_machine
&sm
,
277 state_machine::state_t src_sm_val
,
278 state_machine::state_t dst_sm_val
) = 0;
280 /* Return true for early exit, false to keep iterating. */
281 virtual bool on_state_change (const state_machine
&sm
,
282 state_machine::state_t src_sm_val
,
283 state_machine::state_t dst_sm_val
,
284 const svalue
*dst_sval
,
285 const svalue
*dst_origin_sval
) = 0;
288 extern bool for_each_state_change (const program_state
&src_state
,
289 const program_state
&dst_state
,
290 const extrinsic_state
&ext_state
,
291 state_change_visitor
*visitor
);
295 #endif /* GCC_ANALYZER_PROGRAM_STATE_H */