GCC Middle and Back End API Reference
store.h
Go to the documentation of this file.
1/* Classes for modeling the state of memory.
2 Copyright (C) 2020-2026 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
8under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 3, or (at your option)
10any later version.
11
12GCC is distributed in the hope that it will be useful, but
13WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15General Public License for 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_ANALYZER_STORE_H
22#define GCC_ANALYZER_STORE_H
23
25
26/* Implementation of the region-based ternary model described in:
27 "A Memory Model for Static Analysis of C Programs"
28 (Zhongxing Xu, Ted Kremenek, and Jian Zhang)
29 http://lcs.ios.ac.cn/~xuzb/canalyze/memmodel.pdf */
30
31/* The store models memory as a collection of "clusters", where regions
32 are partitioned into clusters via their base region.
33
34 For example, given:
35 int a, b, c;
36 struct coord { double x; double y; } verts[3];
37 then "verts[0].y" and "verts[1].x" both have "verts" as their base region.
38 Each of a, b, c, and verts will have their own clusters, so that we
39 know that writes to e.g. "verts[1].x".don't affect e.g. "a".
40
41 Within each cluster we store a map of bindings to values, where the
42 binding keys can be either concrete or symbolic.
43
44 Concrete bindings affect a specific range of bits relative to the start
45 of the base region of the cluster, whereas symbolic bindings affect
46 a specific subregion within the cluster.
47
48 Consider (from the symbolic-1.c testcase):
49
50 char arr[1024];
51 arr[2] = a; (1)
52 arr[3] = b; (2)
53 After (1) and (2), the cluster for "arr" has concrete bindings
54 for bits 16-23 and for bits 24-31, with svalues "INIT_VAL(a)"
55 and "INIT_VAL(b)" respectively:
56 cluster: {bits 16-23: "INIT_VAL(a)",
57 bits 24-31: "INIT_VAL(b)";
58 flags: {}}
59 Attempting to query unbound subregions e.g. arr[4] will
60 return "UNINITIALIZED".
61 "a" and "b" are each in their own clusters, with no explicit
62 bindings, and thus implicitly have value INIT_VAL(a) and INIT_VAL(b).
63
64 arr[3] = c; (3)
65 After (3), the concrete binding for bits 24-31 is replaced with the
66 svalue "INIT_VAL(c)":
67 cluster: {bits 16-23: "INIT_VAL(a)", (from before)
68 bits 24-31: "INIT_VAL(c)"; (updated)
69 flags: {}}
70
71 arr[i] = d; (4)
72 After (4), we lose the concrete bindings and replace them with a
73 symbolic binding for "arr[i]", with svalue "INIT_VAL(d)". We also
74 mark the cluster as having been "symbolically touched": future
75 attempts to query the values of subregions other than "arr[i]",
76 such as "arr[3]" are "UNKNOWN", since we don't know if the write
77 to arr[i] affected them.
78 cluster: {symbolic_key(arr[i]): "INIT_VAL(d)";
79 flags: {TOUCHED}}
80
81 arr[j] = e; (5)
82 After (5), we lose the symbolic binding for "arr[i]" since we could
83 have overwritten it, and add a symbolic binding for "arr[j]".
84 cluster: {symbolic_key(arr[j]): "INIT_VAL(d)"; (different symbolic
85 flags: {TOUCHED}} binding)
86
87 arr[3] = f; (6)
88 After (6), we lose the symbolic binding for "arr[j]" since we could
89 have overwritten it, and gain a concrete binding for bits 24-31
90 again, this time with svalue "INIT_VAL(e)":
91 cluster: {bits 24-31: "INIT_VAL(d)";
92 flags: {TOUCHED}}
93 The cluster is still flagged as touched, so that we know that
94 accesses to other elements are "UNKNOWN" rather than
95 "UNINITIALIZED".
96
97 Handling symbolic regions requires us to handle aliasing.
98
99 In the first example above, each of a, b, c and verts are non-symbolic
100 base regions and so their clusters are "concrete clusters", whereas given:
101 struct coord *p, *q;
102 then "*p" and "*q" are symbolic base regions, and thus "*p" and "*q"
103 have "symbolic clusters".
104
105 In the above, "verts[i].x" will have a symbolic *binding* within a
106 concrete cluster for "verts", whereas "*p" is a symbolic *cluster*.
107
108 Writes to concrete clusters can't affect other concrete clusters,
109 but can affect symbolic clusters; e.g. after:
110 verts[0].x = 42;
111 we bind 42 in the cluster for "verts", but the clusters for "b" and "c"
112 can't be affected. Any symbolic clusters for *p and for *q can be
113 affected, *p and *q could alias verts.
114
115 Writes to a symbolic cluster can affect other clusters, both
116 concrete and symbolic; e.g. after:
117 p->x = 17;
118 we bind 17 within the cluster for "*p". The concrete clusters for a, b,
119 c, and verts could be affected, depending on whether *p aliases them.
120 Similarly, the symbolic cluster to *q could be affected. */
121
122namespace ana {
123
124/* A class for keeping track of aspects of a program_state that we don't
125 know about, to avoid false positives about leaks.
126
127 Consider:
128
129 p->field = malloc (1024);
130 q->field = NULL;
131
132 where we don't know whether or not p and q point to the same memory,
133 and:
134
135 p->field = malloc (1024);
136 unknown_fn (p);
137
138 In both cases, the svalue for the address of the allocated buffer
139 goes from being bound to p->field to not having anything explicitly bound
140 to it.
141
142 Given that we conservatively discard bindings due to possible aliasing or
143 calls to unknown function, the store loses references to svalues,
144 but these svalues could still be live. We don't want to warn about
145 them leaking - they're effectively in a "maybe live" state.
146
147 This "maybe live" information is somewhat transient.
148
149 We don't want to store this "maybe live" information in the program_state,
150 region_model, or store, since we don't want to bloat these objects (and
151 potentially bloat the exploded_graph with more nodes).
152 However, we can't store it in the region_model_context, as these context
153 objects sometimes don't last long enough to be around when comparing the
154 old vs the new state.
155
156 This class is a way to track a set of such svalues, so that we can
157 temporarily capture that they are in a "maybe live" state whilst
158 comparing old and new states. */
159
161{
162public:
164
165 void on_maybe_bound_sval (const svalue *sval)
166 {
167 m_maybe_bound_svals.add (sval);
168 }
170 {
172 }
173
174 bool unknown_sm_state_p (const svalue *sval)
175 {
176 return (m_maybe_bound_svals.contains (sval)
177 || m_mutable_at_unknown_call_svals.contains (sval));
178 }
179
180 void dump_to_pp (pretty_printer *pp, bool simple) const;
181 void dump (bool simple) const;
182
184 {
185 return m_maybe_bound_svals.begin ();
186 }
188 {
189 return m_maybe_bound_svals.end ();
190 }
191
192private:
193
194 /* svalues that might or might not still be bound. */
196
197 /* svalues that have mutable sm-state at unknown calls. */
199};
200
201class byte_range;
202class concrete_binding;
203class symbolic_binding;
204
205/* Abstract base class for describing ranges of bits within a binding_map
206 that can have svalues bound to them. */
207
209{
210public:
211 virtual ~binding_key () {}
212 virtual bool concrete_p () const = 0;
213 bool symbolic_p () const { return !concrete_p (); }
214
215 static const binding_key *make (store_manager *mgr, const region *r);
216
217 virtual void dump_to_pp (pretty_printer *pp, bool simple) const = 0;
218 void dump (bool simple) const;
219 label_text get_desc (bool simple=true) const;
220
221 static int cmp_ptrs (const void *, const void *);
222 static int cmp (const binding_key *, const binding_key *);
223
225 { return nullptr; }
227 { return nullptr; }
228};
229
230/* A concrete range of bits. */
231
233{
234 bit_range (bit_offset_t start_bit_offset, bit_size_t size_in_bits)
235 : m_start_bit_offset (start_bit_offset),
236 m_size_in_bits (size_in_bits)
237 {}
238
239 void dump_to_pp (pretty_printer *pp) const;
240 void dump () const;
241
242 std::unique_ptr<json::object> to_json () const;
243
244 bool empty_p () const
245 {
246 return m_size_in_bits == 0;
247 }
248
250 {
251 return m_start_bit_offset;
252 }
258 {
259 gcc_assert (!empty_p ());
260 return get_next_bit_offset () - 1;
261 }
262
263 bool contains_p (bit_offset_t offset) const
264 {
265 return (offset >= get_start_bit_offset ()
266 && offset < get_next_bit_offset ());
267 }
268
269 bool contains_p (const bit_range &other, bit_range *out) const;
270
271 bool operator== (const bit_range &other) const
272 {
273 return (m_start_bit_offset == other.m_start_bit_offset
274 && m_size_in_bits == other.m_size_in_bits);
275 }
276
277 bool intersects_p (const bit_range &other) const
278 {
279 return (get_start_bit_offset () < other.get_next_bit_offset ()
280 && other.get_start_bit_offset () < get_next_bit_offset ());
281 }
282 bool intersects_p (const bit_range &other,
283 bit_size_t *out_num_overlap_bits) const;
284 bool intersects_p (const bit_range &other,
285 bit_range *out_this,
286 bit_range *out_other) const;
287
288 bool exceeds_p (const bit_range &other,
289 bit_range *out_overhanging_bit_range) const;
290
292 bit_range *out_fall_short_bits) const;
293
294 static int cmp (const bit_range &br1, const bit_range &br2);
295
297
298 static bool from_mask (unsigned HOST_WIDE_INT mask, bit_range *out);
299
300 bool as_byte_range (byte_range *out) const;
301
302 bool
303 operator< (const bit_range &other) const
304 {
305 if (m_start_bit_offset < other.m_start_bit_offset)
306 return true;
307 if (m_start_bit_offset > other.m_start_bit_offset)
308 return false;
309 return (m_size_in_bits < other.m_size_in_bits);
310 }
311
312 hashval_t hash () const
313 {
314 inchash::hash hstate;
317 return hstate.end ();
318 }
319
322};
323
324/* A concrete range of bytes. */
325
327{
329 : m_start_byte_offset (start_byte_offset),
331 {}
332
333 void dump_to_pp (pretty_printer *pp) const;
334 void dump () const;
335
336 std::unique_ptr<json::object> to_json () const;
337
338 bool empty_p () const
339 {
340 return m_size_in_bytes == 0;
341 }
342
343 bool contains_p (byte_offset_t offset) const
344 {
345 return (offset >= get_start_byte_offset ()
346 && offset < get_next_byte_offset ());
347 }
348 bool contains_p (const byte_range &other, byte_range *out) const;
349
350 bool operator== (const byte_range &other) const
351 {
352 return (m_start_byte_offset == other.m_start_byte_offset
353 && m_size_in_bytes == other.m_size_in_bytes);
354 }
355
369
371 {
372 return bit_range (m_start_byte_offset * BITS_PER_UNIT,
373 m_size_in_bytes * BITS_PER_UNIT);
374 }
375
377 {
378 return m_start_byte_offset * BITS_PER_UNIT;
379 }
381 {
382 return get_next_byte_offset () * BITS_PER_UNIT;
383 }
384
385 static int cmp (const byte_range &br1, const byte_range &br2);
386
389};
390
391/* Concrete subclass of binding_key, for describing a non-empty
392 concrete range of bits within the binding_map (e.g. "bits 8-15"). */
393
395{
396public:
397 /* This class is its own key for the purposes of consolidation. */
399
400 concrete_binding (bit_offset_t start_bit_offset, bit_size_t size_in_bits)
401 : m_bit_range (start_bit_offset, size_in_bits)
402 {
403 gcc_assert (m_bit_range.m_size_in_bits > 0);
404 }
405 bool concrete_p () const final override { return true; }
406
407 hashval_t hash () const { return m_bit_range.hash (); }
408 bool operator== (const concrete_binding &other) const
409 {
410 return m_bit_range == other.m_bit_range;
411 }
412
413 void dump_to_pp (pretty_printer *pp, bool simple) const final override;
414
416 { return this; }
417
418 const bit_range &get_bit_range () const { return m_bit_range; }
419 bool get_byte_range (byte_range *out) const;
420
422 {
423 return m_bit_range.m_start_bit_offset;
424 }
426 {
427 return m_bit_range.m_size_in_bits;
428 }
429 /* Return the next bit offset after the end of this binding. */
431 {
432 return m_bit_range.get_next_bit_offset ();
433 }
434
435 bool overlaps_p (const concrete_binding &other) const;
436
437 static int cmp_ptr_ptr (const void *, const void *);
438
439 void mark_deleted () { m_bit_range.m_size_in_bits = -1; }
440 void mark_empty () { m_bit_range.m_size_in_bits = -2; }
441 bool is_deleted () const { return m_bit_range.m_size_in_bits == -1; }
442 bool is_empty () const { return m_bit_range.m_size_in_bits == -2; }
443
444private:
446};
447
448} // namespace ana
449
450template <>
451template <>
452inline bool
454{
455 return key->concrete_p ();
456}
457
459: public member_function_hash_traits<ana::concrete_binding>
460{
461 static const bool empty_zero_p = false;
462};
463
464namespace ana {
465
466/* Concrete subclass of binding_key, for describing a symbolic set of
467 bits within the binding_map in terms of a region (e.g. "arr[i]"). */
468
470{
471public:
472 /* This class is its own key for the purposes of consolidation. */
474
476 bool concrete_p () const final override { return false; }
477
478 hashval_t hash () const
479 {
480 return (intptr_t)m_region;
481 }
482 bool operator== (const symbolic_binding &other) const
483 {
484 return m_region == other.m_region;
485 }
486
487 void dump_to_pp (pretty_printer *pp, bool simple) const final override;
488
490 { return this; }
491
492 const region *get_region () const { return m_region; }
493
494 static int cmp_ptr_ptr (const void *, const void *);
495
496 void mark_deleted () { m_region = reinterpret_cast<const region *> (1); }
497 void mark_empty () { m_region = nullptr; }
498 bool is_deleted () const
499 { return m_region == reinterpret_cast<const region *> (1); }
500 bool is_empty () const { return m_region == nullptr; }
501
502private:
504};
505
506} // namespace ana
507
509: public member_function_hash_traits<ana::symbolic_binding>
510{
511 static const bool empty_zero_p = true;
512};
513
514namespace ana {
515
516/* A mapping from binding_keys to svalues, for use by binding_cluster
517 and compound_svalue.
518 We store a map from concrete keys to svalues, which is ordered by
519 the start offset.
520 We also store a vector of (symbolic key, svalue) pairs, but for now
521 this has maximum length of 1. */
522
524{
525public:
527 {
528 bool operator== (const symbolic_binding &other) const
529 {
530 return (m_region == other.m_region
531 && m_sval == other.m_sval);
532 }
533
536 };
537 using concrete_bindings_t = std::map<bit_range, const svalue *>;
538 using symbolic_bindings_t = std::vector<symbolic_binding>;
539
541 {
543 const svalue *sval)
544 : m_key (key),
545 m_sval (sval)
546 {
547 }
548
551 };
552
553 typedef class const_iterator
554 {
555 public:
557 concrete_bindings_t::const_iterator concrete_iter,
558 symbolic_bindings_t::const_iterator symbolic_iter)
559 : m_map (map),
560 m_concrete (concrete_iter),
561 m_symbolic (symbolic_iter)
562 {
563 }
564 bool operator== (const const_iterator &other) const;
565 bool operator!= (const const_iterator &other) const
566 {
567 return !(*this == other);
568 }
570
572 const svalue *get_svalue () const;
573
574 private:
576 concrete_bindings_t::const_iterator m_concrete;
577 symbolic_bindings_t::const_iterator m_symbolic;
579
580 typedef class iterator
581 {
582 public:
583 friend class binding_map;
584
586 concrete_bindings_t::iterator concrete_iter,
587 symbolic_bindings_t::iterator symbolic_iter)
588 : m_map (map),
589 m_concrete (concrete_iter),
590 m_symbolic (symbolic_iter)
591 {
592 }
593 bool operator== (const iterator &other) const;
594 bool operator!= (const iterator &other) const
595 {
596 return !(*this == other);
597 }
599
601
602 const binding_key *get_key () const;
603
604 private:
606 concrete_bindings_t::iterator m_concrete;
607 symbolic_bindings_t::iterator m_symbolic;
609
611 binding_map (const binding_map &other);
613
614 bool operator== (const binding_map &other) const;
615 bool operator!= (const binding_map &other) const
616 {
617 return !(*this == other);
618 }
619
620 hashval_t hash () const;
621
622 const svalue *get (const binding_key *key) const;
623 void put (const binding_key *k, const svalue *v);
624 void overwrite (iterator_t &pos, const svalue *v);
625
626 void remove (const binding_key *k);
627 void clear ()
628 {
629 m_concrete.clear ();
630 m_symbolic.clear ();
631 }
632
633 bool empty_p () const
634 {
635 return m_concrete.empty () && m_symbolic.empty ();
636 }
637
642 size_t elements () const;
643
644 void dump_to_pp (pretty_printer *pp, bool simple, bool multiline) const;
645 void dump (bool simple) const;
646
647 void validate () const;
648
649 std::unique_ptr<json::object> to_json () const;
650
652 const text_art::dump_widget_info &dwi) const;
653
654 bool apply_ctor_to_region (const region *parent_reg, tree ctor,
656
657 static int cmp (const binding_map &map1, const binding_map &map2);
658
660 const binding_key *drop_key,
661 uncertainty_t *uncertainty,
662 svalue_set *maybe_live_values,
663 bool always_overlap);
664
665 const concrete_bindings_t &
667
668 const symbolic_bindings_t &
670
671private:
674 bool apply_ctor_val_to_range (const region *parent_reg,
676 tree min_index, tree max_index,
677 tree val);
680 tree index, tree val);
681
685};
686
687/* All of the bindings within a store for regions that share the same
688 base region. */
689
691{
692public:
693 friend class store;
694
697
698 binding_cluster (store_manager &store_mgr, const region *base_region);
701
702 bool operator== (const binding_cluster &other) const;
703 bool operator!= (const binding_cluster &other) const
704 {
705 return !(*this == other);
706 }
707
708 hashval_t hash () const;
709
710 bool symbolic_p () const;
711
712 const region *get_base_region () const { return m_base_region; }
713
714 void dump_to_pp (pretty_printer *pp, bool simple, bool multiline) const;
715 void dump (bool simple) const;
716
717 void validate () const;
718
719 std::unique_ptr<json::object> to_json () const;
720
721 std::unique_ptr<text_art::tree_widget>
723 store_manager *mgr) const;
724
725 void bind (store_manager *mgr, const region *, const svalue *);
726
727 void clobber_region (store_manager *mgr, const region *reg);
728 void purge_region (store_manager *mgr, const region *reg);
729 void fill_region (store_manager *mgr, const region *reg, const svalue *sval);
730 void zero_fill_region (store_manager *mgr, const region *reg);
732 const region *reg_to_bind,
733 const region *reg_for_overlap,
734 uncertainty_t *uncertainty,
735 svalue_set *maybe_live_values);
736 void purge_state_involving (const svalue *sval,
737 region_model_manager *sval_mgr);
738
739 const svalue *get_binding (store_manager *mgr, const region *reg) const;
741 const region *reg) const;
743 const region *reg) const;
745 const region *reg) const;
746
748 uncertainty_t *uncertainty,
749 svalue_set *maybe_live_values);
750
751 template <typename T>
752 void for_each_value (void (*cb) (const svalue *sval, T user_data),
753 T user_data) const
754 {
755 for (auto iter = m_map.begin (); iter != m_map.end (); ++iter)
756 cb (iter.get_svalue (), user_data);
757 }
758
759 static bool can_merge_p (const binding_cluster *cluster_a,
760 const binding_cluster *cluster_b,
761 binding_cluster *out_cluster,
762 store *out_store,
763 store_manager *mgr,
764 model_merger *merger);
765 void make_unknown_relative_to (const binding_cluster *other_cluster,
766 store *out_store,
767 store_manager *mgr);
768
770 void on_unknown_fncall (const gcall &call, store_manager *mgr,
771 const conjured_purge &p);
772 void on_asm (const gasm *stmt, store_manager *mgr,
773 const conjured_purge &p);
774
775 bool escaped_p () const;
776 bool touched_p () const { return m_touched; }
777
778 bool redundant_p () const;
779 bool empty_p () const { return m_map.empty_p (); }
780
783 const region *base_reg,
784 const svalue *sval,
785 logger *logger,
786 auto_vec<path_var> *out_pvs) const;
787
789
790 const_iterator_t begin () const { return m_map.begin (); }
791 const_iterator_t end () const { return m_map.end (); }
792
793 iterator_t begin () { return m_map.begin (); }
794 iterator_t end () { return m_map.end (); }
795
796 const binding_map &get_map () const { return m_map; }
797 binding_map &get_map () { return m_map; }
798
799private:
800 const svalue *get_any_value (const binding_key *key) const;
802 const region *reg,
803 const compound_svalue *compound_sval);
804 void bind_key (const binding_key *key, const svalue *sval);
805
807
809
810 /* Has a pointer to this cluster "escaped" into a part of the program
811 we don't know about (via a call to a function with an unknown body,
812 or by being passed in as a pointer param of a "top-level" function call).
813 Such regions could be overwritten when other such functions are called,
814 even if the region is no longer reachable by pointers that we are
815 tracking. */
817
818 /* Has this cluster been written to via a symbolic binding?
819 If so, then we don't know anything about unbound subregions,
820 so we can't use initial_svalue, treat them as uninitialized, or
821 inherit values from a parent region. */
823};
824
825/* The mapping from regions to svalues.
826 This is actually expressed by subdividing into clusters, to better
827 handle aliasing. */
828
829class store
830{
831public:
832 typedef hash_map <const region *, binding_cluster *> cluster_map_t;
833
835 store (const store &other);
837
838 store &operator= (const store &other);
839
840 bool operator== (const store &other) const;
841 bool operator!= (const store &other) const
842 {
843 return !(*this == other);
844 }
845
846 hashval_t hash () const;
847
848 void dump_to_pp (pretty_printer *pp, bool summarize, bool multiline,
849 store_manager *mgr) const;
850 void dump (bool simple) const;
851 void summarize_to_pp (pretty_printer *pp, bool simple) const;
852
853 void validate () const;
854
855 std::unique_ptr<json::object> to_json () const;
856
857 std::unique_ptr<text_art::tree_widget>
859 store_manager *mgr) const;
860
861 const svalue *get_any_binding (store_manager *mgr, const region *reg) const;
862
863 bool called_unknown_fn_p () const { return m_called_unknown_fn; }
864
865 void set_value (store_manager *mgr, const region *lhs_reg,
866 const svalue *rhs_sval,
867 uncertainty_t *uncertainty);
868 void clobber_region (store_manager *mgr, const region *reg);
869 void purge_region (store_manager *mgr, const region *reg);
870 void fill_region (store_manager *mgr, const region *reg, const svalue *sval);
871 void zero_fill_region (store_manager *mgr, const region *reg);
873 uncertainty_t *uncertainty,
874 svalue_set *maybe_live_values);
875 void purge_state_involving (const svalue *sval,
876 region_model_manager *sval_mgr);
877
878 const binding_cluster *get_cluster (const region *base_reg) const;
881 const region *base_reg);
882 void purge_cluster (const region *base_reg);
883
884 template <typename T>
885 void for_each_cluster (void (*cb) (const region *base_reg, T user_data),
886 T user_data) const
887 {
888 for (cluster_map_t::iterator iter = m_cluster_map.begin ();
889 iter != m_cluster_map.end (); ++iter)
890 cb ((*iter).first, user_data);
891 }
892
893 static bool can_merge_p (const store *store_a, const store *store_b,
894 store *out_store, store_manager *mgr,
895 model_merger *merger);
896
897 void mark_as_escaped (store_manager &mgr, const region *base_reg);
898 void on_unknown_fncall (const gcall &call, store_manager *mgr,
899 const conjured_purge &p);
900 bool escaped_p (const region *reg) const;
901
904 const svalue *sval,
905 logger *logger,
906 auto_vec<path_var> *out_pvs) const;
907
908 cluster_map_t::iterator begin () const { return m_cluster_map.begin (); }
909 cluster_map_t::iterator end () const { return m_cluster_map.end (); }
910
911 tristate eval_alias (const region *base_reg_a,
912 const region *base_reg_b) const;
913
915 void loop_replay_fixup (const store *other_store,
917
919 const store &summary);
921 const store &summary,
922 const region *base_reg);
924 const svalue_set &maybe_live_values);
925
926private:
928 uncertainty_t *uncertainty);
929 tristate eval_alias_1 (const region *base_reg_a,
930 const region *base_reg_b) const;
931
933
934 /* If this is true, then unknown code has been called, and so
935 any global variable that isn't currently modelled by the store
936 has unknown state, rather than being in an "initial state".
937 This is to avoid having to mark (and thus explicitly track)
938 every global when an unknown function is called; instead, they
939 can be tracked implicitly. */
941};
942
943/* A class responsible for owning and consolidating binding keys
944 (both concrete and symbolic).
945 Key instances are immutable as far as clients are concerned, so they
946 are provided as "const" ptrs. */
947
949{
950public:
952
954
955 /* binding consolidation. */
956 const concrete_binding *
958 bit_offset_t size_in_bits);
959 const concrete_binding *
961 {
962 return get_concrete_binding (bits.get_start_bit_offset (),
963 bits.m_size_in_bits);
964 }
965 const concrete_binding *
967 {
968 bit_range bits = bytes.as_bit_range ();
969 return get_concrete_binding (bits);
970 }
971 const symbolic_binding *
973
975 {
976 return m_mgr;
977 }
978
979 void log_stats (logger *logger, bool show_objs) const;
980
981private:
985};
986
987} // namespace ana
988
989#endif /* GCC_ANALYZER_STORE_H */
Definition store.h:691
binding_map m_map
Definition store.h:808
const_iterator_t end() const
Definition store.h:791
void bind(store_manager *mgr, const region *, const svalue *)
void dump(bool simple) const
void get_representative_path_vars(const region_model *model, svalue_set *visited, const region *base_reg, const svalue *sval, logger *logger, auto_vec< path_var > *out_pvs) const
void fill_region(store_manager *mgr, const region *reg, const svalue *sval)
binding_cluster(store_manager &store_mgr, const region *base_region)
void on_asm(const gasm *stmt, store_manager *mgr, const conjured_purge &p)
const svalue * get_binding_recursive(store_manager *mgr, const region *reg) const
void for_each_value(void(*cb)(const svalue *sval, T user_data), T user_data) const
Definition store.h:752
binding_map & get_map()
Definition store.h:797
void bind_compound_sval(store_manager *mgr, const region *reg, const compound_svalue *compound_sval)
std::unique_ptr< text_art::tree_widget > make_dump_widget(const text_art::dump_widget_info &dwi, store_manager *mgr) const
bool m_escaped
Definition store.h:816
friend class store
Definition store.h:693
void mark_region_as_unknown(store_manager *mgr, const region *reg_to_bind, const region *reg_for_overlap, uncertainty_t *uncertainty, svalue_set *maybe_live_values)
binding_cluster(const binding_cluster &other)
hashval_t hash() const
void validate() const
bool symbolic_p() const
void purge_region(store_manager *mgr, const region *reg)
void clobber_region(store_manager *mgr, const region *reg)
void make_unknown_relative_to(const binding_cluster *other_cluster, store *out_store, store_manager *mgr)
bool operator==(const binding_cluster &other) const
binding_map::iterator iterator_t
Definition store.h:696
iterator_t begin()
Definition store.h:793
const_iterator_t begin() const
Definition store.h:790
void bind_key(const binding_key *key, const svalue *sval)
bool empty_p() const
Definition store.h:779
const svalue * get_any_binding(store_manager *mgr, const region *reg) const
bool operator!=(const binding_cluster &other) const
Definition store.h:703
binding_cluster & operator=(const binding_cluster &other)
void purge_state_involving(const svalue *sval, region_model_manager *sval_mgr)
const svalue * get_any_value(const binding_key *key) const
void dump_to_pp(pretty_printer *pp, bool simple, bool multiline) const
const region * get_base_region() const
Definition store.h:712
const region * m_base_region
Definition store.h:806
const svalue * maybe_get_compound_binding(store_manager *mgr, const region *reg) const
bool touched_p() const
Definition store.h:776
const binding_map & get_map() const
Definition store.h:796
bool escaped_p() const
iterator_t end()
Definition store.h:794
binding_map::const_iterator const_iterator_t
Definition store.h:695
std::unique_ptr< json::object > to_json() const
void remove_overlapping_bindings(store_manager *mgr, const region *reg, uncertainty_t *uncertainty, svalue_set *maybe_live_values)
void zero_fill_region(store_manager *mgr, const region *reg)
const svalue * get_binding(store_manager *mgr, const region *reg) const
static bool can_merge_p(const binding_cluster *cluster_a, const binding_cluster *cluster_b, binding_cluster *out_cluster, store *out_store, store_manager *mgr, model_merger *merger)
void on_unknown_fncall(const gcall &call, store_manager *mgr, const conjured_purge &p)
bool redundant_p() const
bool m_touched
Definition store.h:822
const svalue * maybe_get_simple_value(store_manager *mgr) const
Definition store.h:209
void dump(bool simple) const
static const binding_key * make(store_manager *mgr, const region *r)
static int cmp_ptrs(const void *, const void *)
virtual const symbolic_binding * dyn_cast_symbolic_binding() const
Definition store.h:226
virtual bool concrete_p() const =0
virtual void dump_to_pp(pretty_printer *pp, bool simple) const =0
virtual ~binding_key()
Definition store.h:211
bool symbolic_p() const
Definition store.h:213
static int cmp(const binding_key *, const binding_key *)
label_text get_desc(bool simple=true) const
virtual const concrete_binding * dyn_cast_concrete_binding() const
Definition store.h:224
Definition store.h:554
const svalue * get_svalue() const
bool operator==(const const_iterator &other) const
bool operator!=(const const_iterator &other) const
Definition store.h:565
concrete_bindings_t::const_iterator m_concrete
Definition store.h:576
const binding_map & m_map
Definition store.h:575
symbolic_bindings_t::const_iterator m_symbolic
Definition store.h:577
const_iterator(const binding_map &map, concrete_bindings_t::const_iterator concrete_iter, symbolic_bindings_t::const_iterator symbolic_iter)
Definition store.h:556
Definition store.h:581
bool operator!=(const iterator &other) const
Definition store.h:594
bool operator==(const iterator &other) const
symbolic_bindings_t::iterator m_symbolic
Definition store.h:607
const binding_map & m_map
Definition store.h:605
iterator(const binding_map &map, concrete_bindings_t::iterator concrete_iter, symbolic_bindings_t::iterator symbolic_iter)
Definition store.h:585
const binding_key * get_key() const
friend class binding_map
Definition store.h:583
concrete_bindings_t::iterator m_concrete
Definition store.h:606
Definition store.h:524
size_t elements() const
binding_map & operator=(const binding_map &other)
static int cmp(const binding_map &map1, const binding_map &map2)
const_iterator_t end() const
void validate() const
void dump_to_pp(pretty_printer *pp, bool simple, bool multiline) const
void get_overlapping_bindings(const binding_key *key, auto_vec< const binding_key * > *out)
bool operator==(const binding_map &other) const
bool apply_ctor_pair_to_child_region(const region *parent_reg, region_model_manager *mgr, tree index, tree val)
iterator_t end()
bool empty_p() const
Definition store.h:633
std::map< bit_range, const svalue * > concrete_bindings_t
Definition store.h:537
void dump(bool simple) const
hashval_t hash() const
class ana::binding_map::iterator iterator_t
store_manager & m_store_mgr
Definition store.h:682
void clear()
Definition store.h:627
binding_map(store_manager &store_mgr)
const symbolic_bindings_t & get_symbolic_bindings() const
Definition store.h:669
symbolic_bindings_t m_symbolic
Definition store.h:684
iterator_t begin()
const_iterator_t begin() const
const svalue * get(const binding_key *key) const
std::unique_ptr< json::object > to_json() const
bool apply_ctor_val_to_range(const region *parent_reg, region_model_manager *mgr, tree min_index, tree max_index, tree val)
const concrete_bindings_t & get_concrete_bindings() const
Definition store.h:666
bool apply_ctor_to_region(const region *parent_reg, tree ctor, region_model_manager *mgr)
void add_to_tree_widget(text_art::tree_widget &parent_widget, const text_art::dump_widget_info &dwi) const
void put(const binding_key *k, const svalue *v)
class ana::binding_map::const_iterator const_iterator_t
std::vector< symbolic_binding > symbolic_bindings_t
Definition store.h:538
concrete_bindings_t m_concrete
Definition store.h:683
bool operator!=(const binding_map &other) const
Definition store.h:615
void remove_overlapping_bindings(store_manager *mgr, const binding_key *drop_key, uncertainty_t *uncertainty, svalue_set *maybe_live_values, bool always_overlap)
void remove(const binding_key *k)
void overwrite(iterator_t &pos, const svalue *v)
binding_map(const binding_map &other)
Definition call-summary.h:68
Definition svalue.h:1396
Definition store.h:395
bit_size_t get_size_in_bits() const
Definition store.h:425
bool get_byte_range(byte_range *out) const
void mark_empty()
Definition store.h:440
concrete_binding(bit_offset_t start_bit_offset, bit_size_t size_in_bits)
Definition store.h:400
concrete_binding key_t
Definition store.h:398
const bit_range & get_bit_range() const
Definition store.h:418
void dump_to_pp(pretty_printer *pp, bool simple) const final override
bit_offset_t get_next_bit_offset() const
Definition store.h:430
bool operator==(const concrete_binding &other) const
Definition store.h:408
bool concrete_p() const final override
Definition store.h:405
bit_range m_bit_range
Definition store.h:445
bool is_empty() const
Definition store.h:442
bit_offset_t get_start_bit_offset() const
Definition store.h:421
bool is_deleted() const
Definition store.h:441
void mark_deleted()
Definition store.h:439
bool overlaps_p(const concrete_binding &other) const
hashval_t hash() const
Definition store.h:407
const concrete_binding * dyn_cast_concrete_binding() const final override
Definition store.h:415
static int cmp_ptr_ptr(const void *, const void *)
Definition svalue.h:1500
Definition analyzer-logging.h:34
Definition region-model-manager.h:32
Definition region-model.h:294
Definition region.h:126
Definition store.h:949
consolidation_map< symbolic_binding > m_symbolic_binding_key_mgr
Definition store.h:984
const concrete_binding * get_concrete_binding(const bit_range &bits)
Definition store.h:960
const concrete_binding * get_concrete_binding(bit_offset_t start_bit_offset, bit_offset_t size_in_bits)
const concrete_binding * get_concrete_binding(const byte_range &bytes)
Definition store.h:966
region_model_manager * m_mgr
Definition store.h:982
logger * get_logger() const
region_model_manager * get_svalue_manager() const
Definition store.h:974
store_manager(region_model_manager *mgr)
Definition store.h:951
consolidation_map< concrete_binding > m_concrete_binding_key_mgr
Definition store.h:983
void log_stats(logger *logger, bool show_objs) const
const symbolic_binding * get_symbolic_binding(const region *region)
std::unique_ptr< json::object > to_json() const
void purge_state_involving(const svalue *sval, region_model_manager *sval_mgr)
void dump(bool simple) const
bool escaped_p(const region *reg) const
store(const store &other)
void fill_region(store_manager *mgr, const region *reg, const svalue *sval)
void purge_region(store_manager *mgr, const region *reg)
tristate eval_alias(const region *base_reg_a, const region *base_reg_b) const
void summarize_to_pp(pretty_printer *pp, bool simple) const
void mark_as_escaped(store_manager &mgr, const region *base_reg)
bool operator==(const store &other) const
store & operator=(const store &other)
void on_maybe_live_values(store_manager &mgr, const svalue_set &maybe_live_values)
hash_map< const region *, binding_cluster * > cluster_map_t
Definition store.h:832
void replay_call_summary_cluster(call_summary_replay &r, const store &summary, const region *base_reg)
cluster_map_t::iterator end() const
Definition store.h:909
std::unique_ptr< text_art::tree_widget > make_dump_widget(const text_art::dump_widget_info &dwi, store_manager *mgr) const
void get_representative_path_vars(const region_model *model, svalue_set *visited, const svalue *sval, logger *logger, auto_vec< path_var > *out_pvs) const
bool m_called_unknown_fn
Definition store.h:940
void loop_replay_fixup(const store *other_store, region_model_manager *mgr)
static bool can_merge_p(const store *store_a, const store *store_b, store *out_store, store_manager *mgr, model_merger *merger)
bool operator!=(const store &other) const
Definition store.h:841
bool called_unknown_fn_p() const
Definition store.h:863
void set_value(store_manager *mgr, const region *lhs_reg, const svalue *rhs_sval, uncertainty_t *uncertainty)
cluster_map_t m_cluster_map
Definition store.h:932
const binding_cluster * get_cluster(const region *base_reg) const
void zero_fill_region(store_manager *mgr, const region *reg)
binding_cluster * get_or_create_cluster(store_manager &store_mgr, const region *base_reg)
tristate eval_alias_1(const region *base_reg_a, const region *base_reg_b) const
void validate() const
void mark_region_as_unknown(store_manager *mgr, const region *reg, uncertainty_t *uncertainty, svalue_set *maybe_live_values)
void canonicalize(store_manager *mgr)
cluster_map_t::iterator begin() const
Definition store.h:908
const svalue * get_any_binding(store_manager *mgr, const region *reg) const
hashval_t hash() const
binding_cluster * get_cluster(const region *base_reg)
void replay_call_summary(call_summary_replay &r, const store &summary)
void dump_to_pp(pretty_printer *pp, bool summarize, bool multiline, store_manager *mgr) const
void purge_cluster(const region *base_reg)
void for_each_cluster(void(*cb)(const region *base_reg, T user_data), T user_data) const
Definition store.h:885
void remove_overlapping_bindings(store_manager *mgr, const region *reg, uncertainty_t *uncertainty)
void clobber_region(store_manager *mgr, const region *reg)
void on_unknown_fncall(const gcall &call, store_manager *mgr, const conjured_purge &p)
Definition svalue.h:92
Definition store.h:470
void dump_to_pp(pretty_printer *pp, bool simple) const final override
bool is_empty() const
Definition store.h:500
void mark_empty()
Definition store.h:497
bool operator==(const symbolic_binding &other) const
Definition store.h:482
bool concrete_p() const final override
Definition store.h:476
symbolic_binding(const region *region)
Definition store.h:475
symbolic_binding key_t
Definition store.h:473
const symbolic_binding * dyn_cast_symbolic_binding() const final override
Definition store.h:489
const region * get_region() const
Definition store.h:492
bool is_deleted() const
Definition store.h:498
hashval_t hash() const
Definition store.h:478
const region * m_region
Definition store.h:503
static int cmp_ptr_ptr(const void *, const void *)
void mark_deleted()
Definition store.h:496
Definition store.h:161
bool unknown_sm_state_p(const svalue *sval)
Definition store.h:174
void dump(bool simple) const
void dump_to_pp(pretty_printer *pp, bool simple) const
void on_mutable_sval_at_unknown_call(const svalue *sval)
Definition store.h:169
iterator end_maybe_bound_svals() const
Definition store.h:187
hash_set< const svalue * > m_mutable_at_unknown_call_svals
Definition store.h:198
void on_maybe_bound_sval(const svalue *sval)
Definition store.h:165
hash_set< constsvalue * >::iterator iterator
Definition store.h:163
iterator begin_maybe_bound_svals() const
Definition store.h:183
hash_set< const svalue * > m_maybe_bound_svals
Definition store.h:195
Definition vec.h:1667
Definition common.h:560
Definition hash-set.h:110
Definition hash-set.h:37
Definition inchash.h:38
hashval_t end() const
Definition inchash.h:49
void add_wide_int(const generic_wide_int< T > &x)
Definition inchash.h:84
Definition pretty-print.h:241
Definition tree-widget.h:32
Definition tristate.h:26
union tree_node * tree
Definition coretypes.h:97
static struct string2counter_map map[debug_counter_number_of_counters]
Definition dbgcnt.cc:39
void final(rtx_insn *first, FILE *file, int optimize_p)
Definition final.cc:2009
static struct token T
Definition gengtype-parse.cc:45
Definition access-diagram.h:30
offset_int byte_size_t
Definition common.h:201
@ stmt
Definition checker-event.h:38
offset_int bit_offset_t
Definition common.h:198
offset_int byte_offset_t
Definition common.h:200
offset_int bit_size_t
Definition common.h:199
hash_set< const svalue * > svalue_set
Definition common.h:74
poly_int< N, C > r
Definition poly-int.h:774
Definition store.h:541
const binding_key * m_key
Definition store.h:549
binding_pair(const binding_key *key, const svalue *sval)
Definition store.h:542
const svalue * m_sval
Definition store.h:550
const region * m_region
Definition store.h:534
bool operator==(const symbolic_binding &other) const
Definition store.h:528
const svalue * m_sval
Definition store.h:535
Definition store.h:233
bit_range operator-(bit_offset_t offset) const
bool operator==(const bit_range &other) const
Definition store.h:271
std::unique_ptr< json::object > to_json() const
bool exceeds_p(const bit_range &other, bit_range *out_overhanging_bit_range) const
bool empty_p() const
Definition store.h:244
bool intersects_p(const bit_range &other) const
Definition store.h:277
static bool from_mask(unsigned HOST_WIDE_INT mask, bit_range *out)
bool falls_short_of_p(bit_offset_t offset, bit_range *out_fall_short_bits) const
bool operator<(const bit_range &other) const
Definition store.h:303
bool intersects_p(const bit_range &other, bit_range *out_this, bit_range *out_other) const
bit_size_t m_size_in_bits
Definition store.h:321
bool contains_p(bit_offset_t offset) const
Definition store.h:263
bit_offset_t get_next_bit_offset() const
Definition store.h:253
bit_offset_t m_start_bit_offset
Definition store.h:320
bool intersects_p(const bit_range &other, bit_size_t *out_num_overlap_bits) const
void dump_to_pp(pretty_printer *pp) const
bit_range(bit_offset_t start_bit_offset, bit_size_t size_in_bits)
Definition store.h:234
hashval_t hash() const
Definition store.h:312
bool as_byte_range(byte_range *out) const
void dump() const
static int cmp(const bit_range &br1, const bit_range &br2)
bool contains_p(const bit_range &other, bit_range *out) const
bit_offset_t get_start_bit_offset() const
Definition store.h:249
bit_offset_t get_last_bit_offset() const
Definition store.h:257
Definition store.h:327
bool operator==(const byte_range &other) const
Definition store.h:350
byte_offset_t get_next_byte_offset() const
Definition store.h:360
byte_size_t m_size_in_bytes
Definition store.h:388
byte_offset_t get_last_byte_offset() const
Definition store.h:364
bool contains_p(byte_offset_t offset) const
Definition store.h:343
byte_offset_t get_start_byte_offset() const
Definition store.h:356
void dump_to_pp(pretty_printer *pp) const
void dump() const
byte_range(byte_offset_t start_byte_offset, byte_size_t size_in_bytes)
Definition store.h:328
static int cmp(const byte_range &br1, const byte_range &br2)
bit_offset_t get_start_bit_offset() const
Definition store.h:376
byte_offset_t m_start_byte_offset
Definition store.h:387
bool contains_p(const byte_range &other, byte_range *out) const
bool empty_p() const
Definition store.h:338
bit_offset_t get_next_bit_offset() const
Definition store.h:380
std::unique_ptr< json::object > to_json() const
bit_range as_bit_range() const
Definition store.h:370
Definition region-model.h:1202
static const bool empty_zero_p
Definition store.h:461
static const bool empty_zero_p
Definition store.h:511
Definition hash-traits.h:466
Definition gimple.h:549
Definition gimple.h:352
static bool test(U *p)
Definition common.h:539
Definition dump-widget-info.h:31
#define gcc_assert(EXPR)
Definition system.h:817
static bitmap visited
Definition tree-ssa-dce.cc:640
tree size_in_bytes(const_tree t)
Definition tree.h:5266