]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/analyzer/region-model.h
analyzer: fix accessing wrong stack frame on interprocedural return [PR104979]
[thirdparty/gcc.git] / gcc / analyzer / region-model.h
1 /* Classes for modeling the state of memory.
2 Copyright (C) 2019-2022 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
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)
10 any later version.
11
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.
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_ANALYZER_REGION_MODEL_H
22 #define GCC_ANALYZER_REGION_MODEL_H
23
24 /* Implementation of the region-based ternary model described in:
25 "A Memory Model for Static Analysis of C Programs"
26 (Zhongxing Xu, Ted Kremenek, and Jian Zhang)
27 http://lcs.ios.ac.cn/~xuzb/canalyze/memmodel.pdf */
28
29 #include "analyzer/svalue.h"
30 #include "analyzer/region.h"
31
32 using namespace ana;
33
34 namespace inchash
35 {
36 extern void add_path_var (path_var pv, hash &hstate);
37 } // namespace inchash
38
39 namespace ana {
40
41 template <typename T>
42 class one_way_id_map
43 {
44 public:
45 one_way_id_map (int num_ids);
46 void put (T src, T dst);
47 T get_dst_for_src (T src) const;
48 void dump_to_pp (pretty_printer *pp) const;
49 void dump () const;
50 void update (T *) const;
51
52 private:
53 auto_vec<T> m_src_to_dst;
54 };
55
56 /* class one_way_id_map. */
57
58 /* one_way_id_map's ctor, which populates the map with dummy null values. */
59
60 template <typename T>
61 inline one_way_id_map<T>::one_way_id_map (int num_svalues)
62 : m_src_to_dst (num_svalues)
63 {
64 for (int i = 0; i < num_svalues; i++)
65 m_src_to_dst.quick_push (T::null ());
66 }
67
68 /* Record that SRC is to be mapped to DST. */
69
70 template <typename T>
71 inline void
72 one_way_id_map<T>::put (T src, T dst)
73 {
74 m_src_to_dst[src.as_int ()] = dst;
75 }
76
77 /* Get the new value for SRC within the map. */
78
79 template <typename T>
80 inline T
81 one_way_id_map<T>::get_dst_for_src (T src) const
82 {
83 if (src.null_p ())
84 return src;
85 return m_src_to_dst[src.as_int ()];
86 }
87
88 /* Dump this map to PP. */
89
90 template <typename T>
91 inline void
92 one_way_id_map<T>::dump_to_pp (pretty_printer *pp) const
93 {
94 pp_string (pp, "src to dst: {");
95 unsigned i;
96 T *dst;
97 FOR_EACH_VEC_ELT (m_src_to_dst, i, dst)
98 {
99 if (i > 0)
100 pp_string (pp, ", ");
101 T src (T::from_int (i));
102 src.print (pp);
103 pp_string (pp, " -> ");
104 dst->print (pp);
105 }
106 pp_string (pp, "}");
107 pp_newline (pp);
108 }
109
110 /* Dump this map to stderr. */
111
112 template <typename T>
113 DEBUG_FUNCTION inline void
114 one_way_id_map<T>::dump () const
115 {
116 pretty_printer pp;
117 pp.buffer->stream = stderr;
118 dump_to_pp (&pp);
119 pp_flush (&pp);
120 }
121
122 /* Update *ID from the old value to its new value in this map. */
123
124 template <typename T>
125 inline void
126 one_way_id_map<T>::update (T *id) const
127 {
128 *id = get_dst_for_src (*id);
129 }
130
131 /* A mapping from region to svalue for use when tracking state. */
132
133 class region_to_value_map
134 {
135 public:
136 typedef hash_map<const region *, const svalue *> hash_map_t;
137 typedef hash_map_t::iterator iterator;
138
139 region_to_value_map () : m_hash_map () {}
140 region_to_value_map (const region_to_value_map &other)
141 : m_hash_map (other.m_hash_map) {}
142 region_to_value_map &operator= (const region_to_value_map &other);
143
144 bool operator== (const region_to_value_map &other) const;
145 bool operator!= (const region_to_value_map &other) const
146 {
147 return !(*this == other);
148 }
149
150 iterator begin () const { return m_hash_map.begin (); }
151 iterator end () const { return m_hash_map.end (); }
152
153 const svalue * const *get (const region *reg) const
154 {
155 return const_cast <hash_map_t &> (m_hash_map).get (reg);
156 }
157 void put (const region *reg, const svalue *sval)
158 {
159 m_hash_map.put (reg, sval);
160 }
161 void remove (const region *reg)
162 {
163 m_hash_map.remove (reg);
164 }
165
166 bool is_empty () const { return m_hash_map.is_empty (); }
167
168 void dump_to_pp (pretty_printer *pp, bool simple, bool multiline) const;
169 void dump (bool simple) const;
170
171 bool can_merge_with_p (const region_to_value_map &other,
172 region_to_value_map *out) const;
173
174 void purge_state_involving (const svalue *sval);
175
176 private:
177 hash_map_t m_hash_map;
178 };
179
180 /* Various operations delete information from a region_model.
181
182 This struct tracks how many of each kind of entity were purged (e.g.
183 for selftests, and for debugging). */
184
185 struct purge_stats
186 {
187 purge_stats ()
188 : m_num_svalues (0),
189 m_num_regions (0),
190 m_num_equiv_classes (0),
191 m_num_constraints (0),
192 m_num_bounded_ranges_constraints (0),
193 m_num_client_items (0)
194 {}
195
196 int m_num_svalues;
197 int m_num_regions;
198 int m_num_equiv_classes;
199 int m_num_constraints;
200 int m_num_bounded_ranges_constraints;
201 int m_num_client_items;
202 };
203
204 /* A base class for visiting regions and svalues, with do-nothing
205 base implementations of the per-subclass vfuncs. */
206
207 class visitor
208 {
209 public:
210 virtual void visit_region_svalue (const region_svalue *) {}
211 virtual void visit_constant_svalue (const constant_svalue *) {}
212 virtual void visit_unknown_svalue (const unknown_svalue *) {}
213 virtual void visit_poisoned_svalue (const poisoned_svalue *) {}
214 virtual void visit_setjmp_svalue (const setjmp_svalue *) {}
215 virtual void visit_initial_svalue (const initial_svalue *) {}
216 virtual void visit_unaryop_svalue (const unaryop_svalue *) {}
217 virtual void visit_binop_svalue (const binop_svalue *) {}
218 virtual void visit_sub_svalue (const sub_svalue *) {}
219 virtual void visit_repeated_svalue (const repeated_svalue *) {}
220 virtual void visit_bits_within_svalue (const bits_within_svalue *) {}
221 virtual void visit_unmergeable_svalue (const unmergeable_svalue *) {}
222 virtual void visit_placeholder_svalue (const placeholder_svalue *) {}
223 virtual void visit_widening_svalue (const widening_svalue *) {}
224 virtual void visit_compound_svalue (const compound_svalue *) {}
225 virtual void visit_conjured_svalue (const conjured_svalue *) {}
226 virtual void visit_asm_output_svalue (const asm_output_svalue *) {}
227 virtual void visit_const_fn_result_svalue (const const_fn_result_svalue *) {}
228
229 virtual void visit_region (const region *) {}
230 };
231
232 } // namespace ana
233
234 namespace ana {
235
236 /* A class responsible for owning and consolidating region and svalue
237 instances.
238 region and svalue instances are immutable as far as clients are
239 concerned, so they are provided as "const" ptrs. */
240
241 class region_model_manager
242 {
243 public:
244 region_model_manager (logger *logger = NULL);
245 ~region_model_manager ();
246
247 /* svalue consolidation. */
248 const svalue *get_or_create_constant_svalue (tree cst_expr);
249 const svalue *get_or_create_int_cst (tree type, poly_int64);
250 const svalue *get_or_create_unknown_svalue (tree type);
251 const svalue *get_or_create_setjmp_svalue (const setjmp_record &r,
252 tree type);
253 const svalue *get_or_create_poisoned_svalue (enum poison_kind kind,
254 tree type);
255 const svalue *get_or_create_initial_value (const region *reg);
256 const svalue *get_ptr_svalue (tree ptr_type, const region *pointee);
257 const svalue *get_or_create_unaryop (tree type, enum tree_code op,
258 const svalue *arg);
259 const svalue *get_or_create_cast (tree type, const svalue *arg);
260 const svalue *get_or_create_binop (tree type,
261 enum tree_code op,
262 const svalue *arg0, const svalue *arg1);
263 const svalue *get_or_create_sub_svalue (tree type,
264 const svalue *parent_svalue,
265 const region *subregion);
266 const svalue *get_or_create_repeated_svalue (tree type,
267 const svalue *outer_size,
268 const svalue *inner_svalue);
269 const svalue *get_or_create_bits_within (tree type,
270 const bit_range &bits,
271 const svalue *inner_svalue);
272 const svalue *get_or_create_unmergeable (const svalue *arg);
273 const svalue *get_or_create_widening_svalue (tree type,
274 const program_point &point,
275 const svalue *base_svalue,
276 const svalue *iter_svalue);
277 const svalue *get_or_create_compound_svalue (tree type,
278 const binding_map &map);
279 const svalue *get_or_create_conjured_svalue (tree type, const gimple *stmt,
280 const region *id_reg);
281 const svalue *
282 get_or_create_asm_output_svalue (tree type,
283 const gasm *asm_stmt,
284 unsigned output_idx,
285 const vec<const svalue *> &inputs);
286 const svalue *
287 get_or_create_const_fn_result_svalue (tree type,
288 tree fndecl,
289 const vec<const svalue *> &inputs);
290
291 const svalue *maybe_get_char_from_string_cst (tree string_cst,
292 tree byte_offset_cst);
293
294 /* Dynamically-allocated svalue instances.
295 The number of these within the analysis can grow arbitrarily.
296 They are still owned by the manager. */
297 const svalue *create_unique_svalue (tree type);
298
299 /* region consolidation. */
300 const stack_region * get_stack_region () const { return &m_stack_region; }
301 const heap_region *get_heap_region () const { return &m_heap_region; }
302 const code_region *get_code_region () const { return &m_code_region; }
303 const globals_region *get_globals_region () const
304 {
305 return &m_globals_region;
306 }
307 const function_region *get_region_for_fndecl (tree fndecl);
308 const label_region *get_region_for_label (tree label);
309 const decl_region *get_region_for_global (tree expr);
310 const region *get_field_region (const region *parent, tree field);
311 const region *get_element_region (const region *parent,
312 tree element_type,
313 const svalue *index);
314 const region *get_offset_region (const region *parent,
315 tree type,
316 const svalue *byte_offset);
317 const region *get_sized_region (const region *parent,
318 tree type,
319 const svalue *byte_size_sval);
320 const region *get_cast_region (const region *original_region,
321 tree type);
322 const frame_region *get_frame_region (const frame_region *calling_frame,
323 function *fun);
324 const region *get_symbolic_region (const svalue *sval);
325 const string_region *get_region_for_string (tree string_cst);
326 const region *get_bit_range (const region *parent, tree type,
327 const bit_range &bits);
328
329 const region *
330 get_region_for_unexpected_tree_code (region_model_context *ctxt,
331 tree t,
332 const dump_location_t &loc);
333
334 unsigned alloc_region_id () { return m_next_region_id++; }
335
336 store_manager *get_store_manager () { return &m_store_mgr; }
337 bounded_ranges_manager *get_range_manager () const { return m_range_mgr; }
338
339 /* Dynamically-allocated region instances.
340 The number of these within the analysis can grow arbitrarily.
341 They are still owned by the manager. */
342 const region *create_region_for_heap_alloc ();
343 const region *create_region_for_alloca (const frame_region *frame);
344
345 void log_stats (logger *logger, bool show_objs) const;
346
347 void begin_checking_feasibility (void) { m_checking_feasibility = true; }
348 void end_checking_feasibility (void) { m_checking_feasibility = false; }
349
350 logger *get_logger () const { return m_logger; }
351
352 private:
353 bool too_complex_p (const complexity &c) const;
354 bool reject_if_too_complex (svalue *sval);
355
356 const svalue *maybe_fold_unaryop (tree type, enum tree_code op,
357 const svalue *arg);
358 const svalue *maybe_fold_binop (tree type, enum tree_code op,
359 const svalue *arg0, const svalue *arg1);
360 const svalue *maybe_fold_sub_svalue (tree type,
361 const svalue *parent_svalue,
362 const region *subregion);
363 const svalue *maybe_fold_repeated_svalue (tree type,
364 const svalue *outer_size,
365 const svalue *inner_svalue);
366 const svalue *maybe_fold_bits_within_svalue (tree type,
367 const bit_range &bits,
368 const svalue *inner_svalue);
369 const svalue *maybe_undo_optimize_bit_field_compare (tree type,
370 const compound_svalue *compound_sval,
371 tree cst, const svalue *arg1);
372 const svalue *maybe_fold_asm_output_svalue (tree type,
373 const vec<const svalue *> &inputs);
374
375 logger *m_logger;
376
377 unsigned m_next_region_id;
378 root_region m_root_region;
379 stack_region m_stack_region;
380 heap_region m_heap_region;
381
382 /* svalue consolidation. */
383 typedef hash_map<tree, constant_svalue *> constants_map_t;
384 constants_map_t m_constants_map;
385
386 typedef hash_map<tree, unknown_svalue *> unknowns_map_t;
387 unknowns_map_t m_unknowns_map;
388 const unknown_svalue *m_unknown_NULL;
389
390 typedef hash_map<poisoned_svalue::key_t,
391 poisoned_svalue *> poisoned_values_map_t;
392 poisoned_values_map_t m_poisoned_values_map;
393
394 typedef hash_map<setjmp_svalue::key_t,
395 setjmp_svalue *> setjmp_values_map_t;
396 setjmp_values_map_t m_setjmp_values_map;
397
398 typedef hash_map<const region *, initial_svalue *> initial_values_map_t;
399 initial_values_map_t m_initial_values_map;
400
401 typedef hash_map<region_svalue::key_t, region_svalue *> pointer_values_map_t;
402 pointer_values_map_t m_pointer_values_map;
403
404 typedef hash_map<unaryop_svalue::key_t,
405 unaryop_svalue *> unaryop_values_map_t;
406 unaryop_values_map_t m_unaryop_values_map;
407
408 typedef hash_map<binop_svalue::key_t, binop_svalue *> binop_values_map_t;
409 binop_values_map_t m_binop_values_map;
410
411 typedef hash_map<sub_svalue::key_t, sub_svalue *> sub_values_map_t;
412 sub_values_map_t m_sub_values_map;
413
414 typedef hash_map<repeated_svalue::key_t,
415 repeated_svalue *> repeated_values_map_t;
416 repeated_values_map_t m_repeated_values_map;
417
418 typedef hash_map<bits_within_svalue::key_t,
419 bits_within_svalue *> bits_within_values_map_t;
420 bits_within_values_map_t m_bits_within_values_map;
421
422 typedef hash_map<const svalue *,
423 unmergeable_svalue *> unmergeable_values_map_t;
424 unmergeable_values_map_t m_unmergeable_values_map;
425
426 typedef hash_map<widening_svalue::key_t,
427 widening_svalue */*,
428 widening_svalue::key_t::hash_map_traits*/>
429 widening_values_map_t;
430 widening_values_map_t m_widening_values_map;
431
432 typedef hash_map<compound_svalue::key_t,
433 compound_svalue *> compound_values_map_t;
434 compound_values_map_t m_compound_values_map;
435
436 typedef hash_map<conjured_svalue::key_t,
437 conjured_svalue *> conjured_values_map_t;
438 conjured_values_map_t m_conjured_values_map;
439
440 typedef hash_map<asm_output_svalue::key_t,
441 asm_output_svalue *> asm_output_values_map_t;
442 asm_output_values_map_t m_asm_output_values_map;
443
444 typedef hash_map<const_fn_result_svalue::key_t,
445 const_fn_result_svalue *> const_fn_result_values_map_t;
446 const_fn_result_values_map_t m_const_fn_result_values_map;
447
448 bool m_checking_feasibility;
449
450 /* "Dynamically-allocated" svalue instances.
451 The number of these within the analysis can grow arbitrarily.
452 They are still owned by the manager. */
453 auto_delete_vec<svalue> m_managed_dynamic_svalues;
454
455 /* Maximum complexity of svalues that weren't rejected. */
456 complexity m_max_complexity;
457
458 /* region consolidation. */
459
460 code_region m_code_region;
461 typedef hash_map<tree, function_region *> fndecls_map_t;
462 typedef fndecls_map_t::iterator fndecls_iterator_t;
463 fndecls_map_t m_fndecls_map;
464
465 typedef hash_map<tree, label_region *> labels_map_t;
466 typedef labels_map_t::iterator labels_iterator_t;
467 labels_map_t m_labels_map;
468
469 globals_region m_globals_region;
470 typedef hash_map<tree, decl_region *> globals_map_t;
471 typedef globals_map_t::iterator globals_iterator_t;
472 globals_map_t m_globals_map;
473
474 consolidation_map<field_region> m_field_regions;
475 consolidation_map<element_region> m_element_regions;
476 consolidation_map<offset_region> m_offset_regions;
477 consolidation_map<sized_region> m_sized_regions;
478 consolidation_map<cast_region> m_cast_regions;
479 consolidation_map<frame_region> m_frame_regions;
480 consolidation_map<symbolic_region> m_symbolic_regions;
481
482 typedef hash_map<tree, string_region *> string_map_t;
483 string_map_t m_string_map;
484
485 consolidation_map<bit_range_region> m_bit_range_regions;
486
487 store_manager m_store_mgr;
488
489 bounded_ranges_manager *m_range_mgr;
490
491 /* "Dynamically-allocated" region instances.
492 The number of these within the analysis can grow arbitrarily.
493 They are still owned by the manager. */
494 auto_delete_vec<region> m_managed_dynamic_regions;
495 };
496
497 struct append_regions_cb_data;
498
499 /* Helper class for handling calls to functions with known behavior.
500 Implemented in region-model-impl-calls.c. */
501
502 class call_details
503 {
504 public:
505 call_details (const gcall *call, region_model *model,
506 region_model_context *ctxt);
507
508 region_model_manager *get_manager () const;
509 region_model_context *get_ctxt () const { return m_ctxt; }
510 uncertainty_t *get_uncertainty () const;
511 tree get_lhs_type () const { return m_lhs_type; }
512 const region *get_lhs_region () const { return m_lhs_region; }
513
514 bool maybe_set_lhs (const svalue *result) const;
515
516 unsigned num_args () const;
517
518 const gcall *get_call_stmt () const { return m_call; }
519
520 tree get_arg_tree (unsigned idx) const;
521 tree get_arg_type (unsigned idx) const;
522 const svalue *get_arg_svalue (unsigned idx) const;
523 const char *get_arg_string_literal (unsigned idx) const;
524
525 tree get_fndecl_for_call () const;
526
527 void dump_to_pp (pretty_printer *pp, bool simple) const;
528 void dump (bool simple) const;
529
530 const svalue *get_or_create_conjured_svalue (const region *) const;
531
532 private:
533 const gcall *m_call;
534 region_model *m_model;
535 region_model_context *m_ctxt;
536 tree m_lhs_type;
537 const region *m_lhs_region;
538 };
539
540 /* A region_model encapsulates a representation of the state of memory, with
541 a tree of regions, along with their associated values.
542 The representation is graph-like because values can be pointers to
543 regions.
544 It also stores:
545 - a constraint_manager, capturing relationships between the values, and
546 - dynamic extents, mapping dynamically-allocated regions to svalues (their
547 capacities). */
548
549 class region_model
550 {
551 public:
552 typedef region_to_value_map dynamic_extents_t;
553
554 region_model (region_model_manager *mgr);
555 region_model (const region_model &other);
556 ~region_model ();
557 region_model &operator= (const region_model &other);
558
559 bool operator== (const region_model &other) const;
560 bool operator!= (const region_model &other) const
561 {
562 return !(*this == other);
563 }
564
565 hashval_t hash () const;
566
567 void print (pretty_printer *pp) const;
568
569 void dump_to_pp (pretty_printer *pp, bool simple, bool multiline) const;
570 void dump (FILE *fp, bool simple, bool multiline) const;
571 void dump (bool simple) const;
572
573 void debug () const;
574
575 void validate () const;
576
577 void canonicalize ();
578 bool canonicalized_p () const;
579
580 void
581 on_stmt_pre (const gimple *stmt,
582 bool *out_terminate_path,
583 bool *out_unknown_side_effects,
584 region_model_context *ctxt);
585
586 void on_assignment (const gassign *stmt, region_model_context *ctxt);
587 const svalue *get_gassign_result (const gassign *assign,
588 region_model_context *ctxt);
589 void on_asm_stmt (const gasm *asm_stmt, region_model_context *ctxt);
590 bool on_call_pre (const gcall *stmt, region_model_context *ctxt,
591 bool *out_terminate_path);
592 void on_call_post (const gcall *stmt,
593 bool unknown_side_effects,
594 region_model_context *ctxt);
595
596 void purge_state_involving (const svalue *sval, region_model_context *ctxt);
597
598 /* Specific handling for on_call_pre. */
599 void impl_call_alloca (const call_details &cd);
600 void impl_call_analyzer_describe (const gcall *call,
601 region_model_context *ctxt);
602 void impl_call_analyzer_dump_capacity (const gcall *call,
603 region_model_context *ctxt);
604 void impl_call_analyzer_dump_escaped (const gcall *call);
605 void impl_call_analyzer_eval (const gcall *call,
606 region_model_context *ctxt);
607 void impl_call_builtin_expect (const call_details &cd);
608 void impl_call_calloc (const call_details &cd);
609 bool impl_call_error (const call_details &cd, unsigned min_args,
610 bool *out_terminate_path);
611 void impl_call_fgets (const call_details &cd);
612 void impl_call_fread (const call_details &cd);
613 void impl_call_free (const call_details &cd);
614 void impl_call_malloc (const call_details &cd);
615 void impl_call_memcpy (const call_details &cd);
616 void impl_call_memset (const call_details &cd);
617 void impl_call_realloc (const call_details &cd);
618 void impl_call_strchr (const call_details &cd);
619 void impl_call_strcpy (const call_details &cd);
620 void impl_call_strlen (const call_details &cd);
621 void impl_call_operator_new (const call_details &cd);
622 void impl_call_operator_delete (const call_details &cd);
623 void impl_deallocation_call (const call_details &cd);
624
625 void handle_unrecognized_call (const gcall *call,
626 region_model_context *ctxt);
627 void get_reachable_svalues (svalue_set *out,
628 const svalue *extra_sval,
629 const uncertainty_t *uncertainty);
630
631 void on_return (const greturn *stmt, region_model_context *ctxt);
632 void on_setjmp (const gcall *stmt, const exploded_node *enode,
633 region_model_context *ctxt);
634 void on_longjmp (const gcall *longjmp_call, const gcall *setjmp_call,
635 int setjmp_stack_depth, region_model_context *ctxt);
636
637 void update_for_phis (const supernode *snode,
638 const cfg_superedge *last_cfg_superedge,
639 region_model_context *ctxt);
640
641 void handle_phi (const gphi *phi, tree lhs, tree rhs,
642 const region_model &old_state,
643 region_model_context *ctxt);
644
645 bool maybe_update_for_edge (const superedge &edge,
646 const gimple *last_stmt,
647 region_model_context *ctxt,
648 rejected_constraint **out);
649
650 void update_for_gcall (const gcall *call_stmt,
651 region_model_context *ctxt,
652 function *callee = NULL);
653
654 void update_for_return_gcall (const gcall *call_stmt,
655 region_model_context *ctxt);
656
657 const region *push_frame (function *fun, const vec<const svalue *> *arg_sids,
658 region_model_context *ctxt);
659 const frame_region *get_current_frame () const { return m_current_frame; }
660 function * get_current_function () const;
661 void pop_frame (tree result_lvalue,
662 const svalue **out_result,
663 region_model_context *ctxt);
664 int get_stack_depth () const;
665 const frame_region *get_frame_at_index (int index) const;
666
667 const region *get_lvalue (path_var pv, region_model_context *ctxt) const;
668 const region *get_lvalue (tree expr, region_model_context *ctxt) const;
669 const svalue *get_rvalue (path_var pv, region_model_context *ctxt) const;
670 const svalue *get_rvalue (tree expr, region_model_context *ctxt) const;
671
672 const region *deref_rvalue (const svalue *ptr_sval, tree ptr_tree,
673 region_model_context *ctxt) const;
674
675 const svalue *get_rvalue_for_bits (tree type,
676 const region *reg,
677 const bit_range &bits,
678 region_model_context *ctxt) const;
679
680 void set_value (const region *lhs_reg, const svalue *rhs_sval,
681 region_model_context *ctxt);
682 void set_value (tree lhs, tree rhs, region_model_context *ctxt);
683 void clobber_region (const region *reg);
684 void purge_region (const region *reg);
685 void fill_region (const region *reg, const svalue *sval);
686 void zero_fill_region (const region *reg);
687 void mark_region_as_unknown (const region *reg, uncertainty_t *uncertainty);
688
689 tristate eval_condition (const svalue *lhs,
690 enum tree_code op,
691 const svalue *rhs) const;
692 tristate eval_condition_without_cm (const svalue *lhs,
693 enum tree_code op,
694 const svalue *rhs) const;
695 tristate compare_initial_and_pointer (const initial_svalue *init,
696 const region_svalue *ptr) const;
697 tristate eval_condition (tree lhs,
698 enum tree_code op,
699 tree rhs,
700 region_model_context *ctxt);
701 bool add_constraint (tree lhs, enum tree_code op, tree rhs,
702 region_model_context *ctxt);
703 bool add_constraint (tree lhs, enum tree_code op, tree rhs,
704 region_model_context *ctxt,
705 rejected_constraint **out);
706
707 const region *create_region_for_heap_alloc (const svalue *size_in_bytes,
708 region_model_context *ctxt);
709 const region *create_region_for_alloca (const svalue *size_in_bytes,
710 region_model_context *ctxt);
711
712 tree get_representative_tree (const svalue *sval) const;
713 path_var
714 get_representative_path_var (const svalue *sval,
715 svalue_set *visited) const;
716 path_var
717 get_representative_path_var (const region *reg,
718 svalue_set *visited) const;
719
720 /* For selftests. */
721 constraint_manager *get_constraints ()
722 {
723 return m_constraints;
724 }
725
726 store *get_store () { return &m_store; }
727 const store *get_store () const { return &m_store; }
728
729 const dynamic_extents_t &
730 get_dynamic_extents () const
731 {
732 return m_dynamic_extents;
733 }
734 const svalue *get_dynamic_extents (const region *reg) const;
735 void set_dynamic_extents (const region *reg,
736 const svalue *size_in_bytes,
737 region_model_context *ctxt);
738 void unset_dynamic_extents (const region *reg);
739
740 region_model_manager *get_manager () const { return m_mgr; }
741 bounded_ranges_manager *get_range_manager () const
742 {
743 return m_mgr->get_range_manager ();
744 }
745
746 void unbind_region_and_descendents (const region *reg,
747 enum poison_kind pkind);
748
749 bool can_merge_with_p (const region_model &other_model,
750 const program_point &point,
751 region_model *out_model,
752 const extrinsic_state *ext_state = NULL,
753 const program_state *state_a = NULL,
754 const program_state *state_b = NULL) const;
755
756 tree get_fndecl_for_call (const gcall *call,
757 region_model_context *ctxt);
758
759 void get_regions_for_current_frame (auto_vec<const decl_region *> *out) const;
760 static void append_regions_cb (const region *base_reg,
761 struct append_regions_cb_data *data);
762
763 const svalue *get_store_value (const region *reg,
764 region_model_context *ctxt) const;
765
766 bool region_exists_p (const region *reg) const;
767
768 void loop_replay_fixup (const region_model *dst_state);
769
770 const svalue *get_capacity (const region *reg) const;
771
772 /* Implemented in sm-malloc.cc */
773 void on_realloc_with_move (const call_details &cd,
774 const svalue *old_ptr_sval,
775 const svalue *new_ptr_sval);
776
777 private:
778 const region *get_lvalue_1 (path_var pv, region_model_context *ctxt) const;
779 const svalue *get_rvalue_1 (path_var pv, region_model_context *ctxt) const;
780
781 path_var
782 get_representative_path_var_1 (const svalue *sval,
783 svalue_set *visited) const;
784 path_var
785 get_representative_path_var_1 (const region *reg,
786 svalue_set *visited) const;
787
788 bool add_constraint (const svalue *lhs,
789 enum tree_code op,
790 const svalue *rhs,
791 region_model_context *ctxt);
792 bool add_constraints_from_binop (const svalue *outer_lhs,
793 enum tree_code outer_op,
794 const svalue *outer_rhs,
795 bool *out,
796 region_model_context *ctxt);
797
798 void update_for_call_superedge (const call_superedge &call_edge,
799 region_model_context *ctxt);
800 void update_for_return_superedge (const return_superedge &return_edge,
801 region_model_context *ctxt);
802 void update_for_call_summary (const callgraph_superedge &cg_sedge,
803 region_model_context *ctxt);
804 bool apply_constraints_for_gcond (const cfg_superedge &edge,
805 const gcond *cond_stmt,
806 region_model_context *ctxt,
807 rejected_constraint **out);
808 bool apply_constraints_for_gswitch (const switch_cfg_superedge &edge,
809 const gswitch *switch_stmt,
810 region_model_context *ctxt,
811 rejected_constraint **out);
812 bool apply_constraints_for_exception (const gimple *last_stmt,
813 region_model_context *ctxt,
814 rejected_constraint **out);
815
816 int poison_any_pointers_to_descendents (const region *reg,
817 enum poison_kind pkind);
818
819 void on_top_level_param (tree param, region_model_context *ctxt);
820
821 bool called_from_main_p () const;
822 const svalue *get_initial_value_for_global (const region *reg) const;
823
824 const svalue *check_for_poison (const svalue *sval,
825 tree expr,
826 region_model_context *ctxt) const;
827 const region * get_region_for_poisoned_expr (tree expr) const;
828
829 void check_dynamic_size_for_taint (enum memory_space mem_space,
830 const svalue *size_in_bytes,
831 region_model_context *ctxt) const;
832
833 void check_region_for_taint (const region *reg,
834 enum access_direction dir,
835 region_model_context *ctxt) const;
836
837 void check_for_writable_region (const region* dest_reg,
838 region_model_context *ctxt) const;
839 void check_region_access (const region *reg,
840 enum access_direction dir,
841 region_model_context *ctxt) const;
842 void check_region_for_write (const region *dest_reg,
843 region_model_context *ctxt) const;
844 void check_region_for_read (const region *src_reg,
845 region_model_context *ctxt) const;
846
847 void check_call_args (const call_details &cd) const;
848 void check_external_function_for_access_attr (const gcall *call,
849 tree callee_fndecl,
850 region_model_context *ctxt) const;
851
852 /* Storing this here to avoid passing it around everywhere. */
853 region_model_manager *const m_mgr;
854
855 store m_store;
856
857 constraint_manager *m_constraints; // TODO: embed, rather than dynalloc?
858
859 const frame_region *m_current_frame;
860
861 /* Map from base region to size in bytes, for tracking the sizes of
862 dynamically-allocated regions.
863 This is part of the region_model rather than the region to allow for
864 memory regions to be resized (e.g. by realloc). */
865 dynamic_extents_t m_dynamic_extents;
866 };
867
868 /* Some region_model activity could lead to warnings (e.g. attempts to use an
869 uninitialized value). This abstract base class encapsulates an interface
870 for the region model to use when emitting such warnings.
871
872 Having this as an abstract base class allows us to support the various
873 operations needed by program_state in the analyzer within region_model,
874 whilst keeping them somewhat modularized. */
875
876 class region_model_context
877 {
878 public:
879 /* Hook for clients to store pending diagnostics.
880 Return true if the diagnostic was stored, or false if it was deleted. */
881 virtual bool warn (pending_diagnostic *d) = 0;
882
883 /* Hook for clients to add a note to the last previously stored pending diagnostic.
884 Takes ownership of the pending_node (or deletes it). */
885 virtual void add_note (pending_note *pn) = 0;
886
887 /* Hook for clients to be notified when an SVAL that was reachable
888 in a previous state is no longer live, so that clients can emit warnings
889 about leaks. */
890 virtual void on_svalue_leak (const svalue *sval) = 0;
891
892 /* Hook for clients to be notified when the set of explicitly live
893 svalues changes, so that they can purge state relating to dead
894 svalues. */
895 virtual void on_liveness_change (const svalue_set &live_svalues,
896 const region_model *model) = 0;
897
898 virtual logger *get_logger () = 0;
899
900 /* Hook for clients to be notified when the condition
901 "LHS OP RHS" is added to the region model.
902 This exists so that state machines can detect tests on edges,
903 and use them to trigger sm-state transitions (e.g. transitions due
904 to ptrs becoming known to be NULL or non-NULL, rather than just
905 "unchecked") */
906 virtual void on_condition (const svalue *lhs,
907 enum tree_code op,
908 const svalue *rhs) = 0;
909
910 /* Hooks for clients to be notified when an unknown change happens
911 to SVAL (in response to a call to an unknown function). */
912 virtual void on_unknown_change (const svalue *sval, bool is_mutable) = 0;
913
914 /* Hooks for clients to be notified when a phi node is handled,
915 where RHS is the pertinent argument. */
916 virtual void on_phi (const gphi *phi, tree rhs) = 0;
917
918 /* Hooks for clients to be notified when the region model doesn't
919 know how to handle the tree code of T at LOC. */
920 virtual void on_unexpected_tree_code (tree t,
921 const dump_location_t &loc) = 0;
922
923 /* Hook for clients to be notified when a function_decl escapes. */
924 virtual void on_escaped_function (tree fndecl) = 0;
925
926 virtual uncertainty_t *get_uncertainty () = 0;
927
928 /* Hook for clients to purge state involving SVAL. */
929 virtual void purge_state_involving (const svalue *sval) = 0;
930
931 /* Hook for clients to split state with a non-standard path.
932 Take ownership of INFO. */
933 virtual void bifurcate (custom_edge_info *info) = 0;
934
935 /* Hook for clients to terminate the standard path. */
936 virtual void terminate_path () = 0;
937
938 virtual const extrinsic_state *get_ext_state () const = 0;
939
940 /* Hook for clients to access the "malloc" state machine in
941 any underlying program_state. */
942 virtual bool get_malloc_map (sm_state_map **out_smap,
943 const state_machine **out_sm,
944 unsigned *out_sm_idx) = 0;
945 /* Likewise for the "taint" state machine. */
946 virtual bool get_taint_map (sm_state_map **out_smap,
947 const state_machine **out_sm,
948 unsigned *out_sm_idx) = 0;
949
950 /* Get the current statement, if any. */
951 virtual const gimple *get_stmt () const = 0;
952 };
953
954 /* A "do nothing" subclass of region_model_context. */
955
956 class noop_region_model_context : public region_model_context
957 {
958 public:
959 bool warn (pending_diagnostic *) OVERRIDE { return false; }
960 void add_note (pending_note *pn) OVERRIDE;
961 void on_svalue_leak (const svalue *) OVERRIDE {}
962 void on_liveness_change (const svalue_set &,
963 const region_model *) OVERRIDE {}
964 logger *get_logger () OVERRIDE { return NULL; }
965 void on_condition (const svalue *lhs ATTRIBUTE_UNUSED,
966 enum tree_code op ATTRIBUTE_UNUSED,
967 const svalue *rhs ATTRIBUTE_UNUSED) OVERRIDE
968 {
969 }
970 void on_unknown_change (const svalue *sval ATTRIBUTE_UNUSED,
971 bool is_mutable ATTRIBUTE_UNUSED) OVERRIDE
972 {
973 }
974 void on_phi (const gphi *phi ATTRIBUTE_UNUSED,
975 tree rhs ATTRIBUTE_UNUSED) OVERRIDE
976 {
977 }
978 void on_unexpected_tree_code (tree, const dump_location_t &) OVERRIDE {}
979
980 void on_escaped_function (tree) OVERRIDE {}
981
982 uncertainty_t *get_uncertainty () OVERRIDE { return NULL; }
983
984 void purge_state_involving (const svalue *sval ATTRIBUTE_UNUSED) OVERRIDE {}
985
986 void bifurcate (custom_edge_info *info) OVERRIDE;
987 void terminate_path () OVERRIDE;
988
989 const extrinsic_state *get_ext_state () const OVERRIDE { return NULL; }
990
991 bool get_malloc_map (sm_state_map **,
992 const state_machine **,
993 unsigned *) OVERRIDE
994 {
995 return false;
996 }
997 bool get_taint_map (sm_state_map **,
998 const state_machine **,
999 unsigned *) OVERRIDE
1000 {
1001 return false;
1002 }
1003
1004 const gimple *get_stmt () const OVERRIDE { return NULL; }
1005 };
1006
1007 /* A subclass of region_model_context for determining if operations fail
1008 e.g. "can we generate a region for the lvalue of EXPR?". */
1009
1010 class tentative_region_model_context : public noop_region_model_context
1011 {
1012 public:
1013 tentative_region_model_context () : m_num_unexpected_codes (0) {}
1014
1015 void on_unexpected_tree_code (tree, const dump_location_t &)
1016 FINAL OVERRIDE
1017 {
1018 m_num_unexpected_codes++;
1019 }
1020
1021 bool had_errors_p () const { return m_num_unexpected_codes > 0; }
1022
1023 private:
1024 int m_num_unexpected_codes;
1025 };
1026
1027 /* Subclass of region_model_context that wraps another context, allowing
1028 for extra code to be added to the various hooks. */
1029
1030 class region_model_context_decorator : public region_model_context
1031 {
1032 public:
1033 bool warn (pending_diagnostic *d) OVERRIDE
1034 {
1035 return m_inner->warn (d);
1036 }
1037
1038 void add_note (pending_note *pn) OVERRIDE
1039 {
1040 m_inner->add_note (pn);
1041 }
1042
1043 void on_svalue_leak (const svalue *sval) OVERRIDE
1044 {
1045 m_inner->on_svalue_leak (sval);
1046 }
1047
1048 void on_liveness_change (const svalue_set &live_svalues,
1049 const region_model *model) OVERRIDE
1050 {
1051 m_inner->on_liveness_change (live_svalues, model);
1052 }
1053
1054 logger *get_logger () OVERRIDE
1055 {
1056 return m_inner->get_logger ();
1057 }
1058
1059 void on_condition (const svalue *lhs,
1060 enum tree_code op,
1061 const svalue *rhs) OVERRIDE
1062 {
1063 m_inner->on_condition (lhs, op, rhs);
1064 }
1065
1066 void on_unknown_change (const svalue *sval, bool is_mutable) OVERRIDE
1067 {
1068 m_inner->on_unknown_change (sval, is_mutable);
1069 }
1070
1071 void on_phi (const gphi *phi, tree rhs) OVERRIDE
1072 {
1073 m_inner->on_phi (phi, rhs);
1074 }
1075
1076 void on_unexpected_tree_code (tree t,
1077 const dump_location_t &loc) OVERRIDE
1078 {
1079 m_inner->on_unexpected_tree_code (t, loc);
1080 }
1081
1082 void on_escaped_function (tree fndecl) OVERRIDE
1083 {
1084 m_inner->on_escaped_function (fndecl);
1085 }
1086
1087 uncertainty_t *get_uncertainty () OVERRIDE
1088 {
1089 return m_inner->get_uncertainty ();
1090 }
1091
1092 void purge_state_involving (const svalue *sval) OVERRIDE
1093 {
1094 m_inner->purge_state_involving (sval);
1095 }
1096
1097 void bifurcate (custom_edge_info *info) OVERRIDE
1098 {
1099 m_inner->bifurcate (info);
1100 }
1101
1102 void terminate_path () OVERRIDE
1103 {
1104 m_inner->terminate_path ();
1105 }
1106
1107 const extrinsic_state *get_ext_state () const OVERRIDE
1108 {
1109 return m_inner->get_ext_state ();
1110 }
1111
1112 bool get_malloc_map (sm_state_map **out_smap,
1113 const state_machine **out_sm,
1114 unsigned *out_sm_idx) OVERRIDE
1115 {
1116 return m_inner->get_malloc_map (out_smap, out_sm, out_sm_idx);
1117 }
1118
1119 bool get_taint_map (sm_state_map **out_smap,
1120 const state_machine **out_sm,
1121 unsigned *out_sm_idx) OVERRIDE
1122 {
1123 return m_inner->get_taint_map (out_smap, out_sm, out_sm_idx);
1124 }
1125
1126 const gimple *get_stmt () const OVERRIDE
1127 {
1128 return m_inner->get_stmt ();
1129 }
1130
1131 protected:
1132 region_model_context_decorator (region_model_context *inner)
1133 : m_inner (inner)
1134 {
1135 gcc_assert (m_inner);
1136 }
1137
1138 region_model_context *m_inner;
1139 };
1140
1141 /* Subclass of region_model_context_decorator that adds a note
1142 when saving diagnostics. */
1143
1144 class note_adding_context : public region_model_context_decorator
1145 {
1146 public:
1147 bool warn (pending_diagnostic *d) OVERRIDE
1148 {
1149 if (m_inner->warn (d))
1150 {
1151 add_note (make_note ());
1152 return true;
1153 }
1154 else
1155 return false;
1156 }
1157
1158 /* Hook to make the new note. */
1159 virtual pending_note *make_note () = 0;
1160
1161 protected:
1162 note_adding_context (region_model_context *inner)
1163 : region_model_context_decorator (inner)
1164 {
1165 }
1166 };
1167
1168 /* A bundle of data for use when attempting to merge two region_model
1169 instances to make a third. */
1170
1171 struct model_merger
1172 {
1173 model_merger (const region_model *model_a,
1174 const region_model *model_b,
1175 const program_point &point,
1176 region_model *merged_model,
1177 const extrinsic_state *ext_state,
1178 const program_state *state_a,
1179 const program_state *state_b)
1180 : m_model_a (model_a), m_model_b (model_b),
1181 m_point (point),
1182 m_merged_model (merged_model),
1183 m_ext_state (ext_state),
1184 m_state_a (state_a), m_state_b (state_b)
1185 {
1186 }
1187
1188 void dump_to_pp (pretty_printer *pp, bool simple) const;
1189 void dump (FILE *fp, bool simple) const;
1190 void dump (bool simple) const;
1191
1192 region_model_manager *get_manager () const
1193 {
1194 return m_model_a->get_manager ();
1195 }
1196
1197 bool mergeable_svalue_p (const svalue *) const;
1198
1199 const region_model *m_model_a;
1200 const region_model *m_model_b;
1201 const program_point &m_point;
1202 region_model *m_merged_model;
1203
1204 const extrinsic_state *m_ext_state;
1205 const program_state *m_state_a;
1206 const program_state *m_state_b;
1207 };
1208
1209 /* A record that can (optionally) be written out when
1210 region_model::add_constraint fails. */
1211
1212 class rejected_constraint
1213 {
1214 public:
1215 virtual ~rejected_constraint () {}
1216 virtual void dump_to_pp (pretty_printer *pp) const = 0;
1217
1218 const region_model &get_model () const { return m_model; }
1219
1220 protected:
1221 rejected_constraint (const region_model &model)
1222 : m_model (model)
1223 {}
1224
1225 region_model m_model;
1226 };
1227
1228 class rejected_op_constraint : public rejected_constraint
1229 {
1230 public:
1231 rejected_op_constraint (const region_model &model,
1232 tree lhs, enum tree_code op, tree rhs)
1233 : rejected_constraint (model),
1234 m_lhs (lhs), m_op (op), m_rhs (rhs)
1235 {}
1236
1237 void dump_to_pp (pretty_printer *pp) const FINAL OVERRIDE;
1238
1239 tree m_lhs;
1240 enum tree_code m_op;
1241 tree m_rhs;
1242 };
1243
1244 class rejected_ranges_constraint : public rejected_constraint
1245 {
1246 public:
1247 rejected_ranges_constraint (const region_model &model,
1248 tree expr, const bounded_ranges *ranges)
1249 : rejected_constraint (model),
1250 m_expr (expr), m_ranges (ranges)
1251 {}
1252
1253 void dump_to_pp (pretty_printer *pp) const FINAL OVERRIDE;
1254
1255 private:
1256 tree m_expr;
1257 const bounded_ranges *m_ranges;
1258 };
1259
1260 /* A bundle of state. */
1261
1262 class engine
1263 {
1264 public:
1265 engine (const supergraph *sg = NULL, logger *logger = NULL);
1266 const supergraph *get_supergraph () { return m_sg; }
1267 region_model_manager *get_model_manager () { return &m_mgr; }
1268
1269 void log_stats (logger *logger) const;
1270
1271 private:
1272 const supergraph *m_sg;
1273 region_model_manager m_mgr;
1274 };
1275
1276 } // namespace ana
1277
1278 extern void debug (const region_model &rmodel);
1279
1280 namespace ana {
1281
1282 #if CHECKING_P
1283
1284 namespace selftest {
1285
1286 using namespace ::selftest;
1287
1288 /* An implementation of region_model_context for use in selftests, which
1289 stores any pending_diagnostic instances passed to it. */
1290
1291 class test_region_model_context : public noop_region_model_context
1292 {
1293 public:
1294 bool warn (pending_diagnostic *d) FINAL OVERRIDE
1295 {
1296 m_diagnostics.safe_push (d);
1297 return true;
1298 }
1299
1300 unsigned get_num_diagnostics () const { return m_diagnostics.length (); }
1301
1302 void on_unexpected_tree_code (tree t, const dump_location_t &)
1303 FINAL OVERRIDE
1304 {
1305 internal_error ("unhandled tree code: %qs",
1306 get_tree_code_name (TREE_CODE (t)));
1307 }
1308
1309 private:
1310 /* Implicitly delete any diagnostics in the dtor. */
1311 auto_delete_vec<pending_diagnostic> m_diagnostics;
1312 };
1313
1314 /* Attempt to add the constraint (LHS OP RHS) to MODEL.
1315 Verify that MODEL remains satisfiable. */
1316
1317 #define ADD_SAT_CONSTRAINT(MODEL, LHS, OP, RHS) \
1318 SELFTEST_BEGIN_STMT \
1319 bool sat = (MODEL).add_constraint (LHS, OP, RHS, NULL); \
1320 ASSERT_TRUE (sat); \
1321 SELFTEST_END_STMT
1322
1323 /* Attempt to add the constraint (LHS OP RHS) to MODEL.
1324 Verify that the result is not satisfiable. */
1325
1326 #define ADD_UNSAT_CONSTRAINT(MODEL, LHS, OP, RHS) \
1327 SELFTEST_BEGIN_STMT \
1328 bool sat = (MODEL).add_constraint (LHS, OP, RHS, NULL); \
1329 ASSERT_FALSE (sat); \
1330 SELFTEST_END_STMT
1331
1332 /* Implementation detail of the ASSERT_CONDITION_* macros. */
1333
1334 void assert_condition (const location &loc,
1335 region_model &model,
1336 const svalue *lhs, tree_code op, const svalue *rhs,
1337 tristate expected);
1338
1339 void assert_condition (const location &loc,
1340 region_model &model,
1341 tree lhs, tree_code op, tree rhs,
1342 tristate expected);
1343
1344 /* Assert that REGION_MODEL evaluates the condition "LHS OP RHS"
1345 as "true". */
1346
1347 #define ASSERT_CONDITION_TRUE(REGION_MODEL, LHS, OP, RHS) \
1348 SELFTEST_BEGIN_STMT \
1349 assert_condition (SELFTEST_LOCATION, REGION_MODEL, LHS, OP, RHS, \
1350 tristate (tristate::TS_TRUE)); \
1351 SELFTEST_END_STMT
1352
1353 /* Assert that REGION_MODEL evaluates the condition "LHS OP RHS"
1354 as "false". */
1355
1356 #define ASSERT_CONDITION_FALSE(REGION_MODEL, LHS, OP, RHS) \
1357 SELFTEST_BEGIN_STMT \
1358 assert_condition (SELFTEST_LOCATION, REGION_MODEL, LHS, OP, RHS, \
1359 tristate (tristate::TS_FALSE)); \
1360 SELFTEST_END_STMT
1361
1362 /* Assert that REGION_MODEL evaluates the condition "LHS OP RHS"
1363 as "unknown". */
1364
1365 #define ASSERT_CONDITION_UNKNOWN(REGION_MODEL, LHS, OP, RHS) \
1366 SELFTEST_BEGIN_STMT \
1367 assert_condition (SELFTEST_LOCATION, REGION_MODEL, LHS, OP, RHS, \
1368 tristate (tristate::TS_UNKNOWN)); \
1369 SELFTEST_END_STMT
1370
1371 } /* end of namespace selftest. */
1372
1373 #endif /* #if CHECKING_P */
1374
1375 } // namespace ana
1376
1377 #endif /* GCC_ANALYZER_REGION_MODEL_H */