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