ESBMC
Efficient SMT-based Context-Bounded Model Checker
Loading...
Searching...
No Matches
context.h
Go to the documentation of this file.
1#ifndef CPROVER_CONTEXT_H
2#define CPROVER_CONTEXT_H
3
4#include <functional>
5
6#include <boost/multi_index/hashed_index.hpp>
7#include <boost/multi_index/member.hpp>
8#include <boost/multi_index/sequenced_index.hpp>
9#include <boost/multi_index_container.hpp>
10
11#include <util/config/config.h>
12#include <util/symtab/symbol.h>
13#include <util/irep/type.h>
14
15/* Symbol table.
16 *
17 * A single boost::multi_index_container of symbolt holds every symbol and
18 * exposes the two views the codebase needs, kept in sync automatically:
19 *
20 * - by_id: hashed_unique on symbolt::id — O(1) lookup by id
21 * - by_order: sequenced — insertion order (init order)
22 *
23 * multi_index is node-based, so element references/pointers stay valid across
24 * insert and erase (only the erased element is invalidated). This replaces the
25 * former hand-synced trio (unordered_map + vector<symbolt*> + multimap), which
26 * leaked base-name entries on erase, did an O(n) scan to erase from the order
27 * vector, and stored raw symbolt* into the map (a documented use-after-free
28 * hazard on erase). Same pattern already used by smt_solver_baset::smt_cache.
29 *
30 * There is no base-name index: the only base-name lookup is the one-shot
31 * entry-point search (find `main`) done once per run, served by a linear scan
32 * (foreach_named_symbol_with_base) — not worth a third index maintained on
33 * every insert/erase.
34 */
35
37{
38struct by_id
39{
40};
42{
43};
44
45typedef boost::multi_index_container<
46 symbolt,
47 boost::multi_index::indexed_by<
48 boost::multi_index::hashed_unique<
49 boost::multi_index::tag<by_id>,
50 BOOST_MULTI_INDEX_MEMBER(symbolt, irep_idt, id),
52 boost::multi_index::sequenced<boost::multi_index::tag<by_order>>>>
54} // namespace contextt_detail
55
57{
58 typedef std::function<void(const symbolt &symbol)> const_symbol_delegate;
59 typedef std::function<void(symbolt &symbol)> symbol_delegate;
60
61public:
62 explicit contextt()
63 {
64 }
65 ~contextt() = default;
66 contextt(const contextt &obj) = delete;
67 contextt(contextt &&) noexcept = default;
68
69#ifdef ENABLE_OLD_FRONTEND
70 contextt &operator=(const contextt &rhs)
71 {
72 // copy assignment operator for old frontend typechecking
73 if (&rhs == this) // check self assignment
74 {
75 log_error("Context is copying itself");
76 }
77
78 // Since the const messaget& member breaks default copy assignment operation
79 // in this class, this no-op copy assignment operator aims to restore the
80 // functionality of ansic_c_typecheck function in
81 // src/ansi-c/ansi_c_typecheck.cpp prior to commit 4dc8478. However, using a
82 // no-op copy assignment operator is quite hacky. We do not recomment it in
83 // other places of ESBMC.
84 return *this;
85 }
86#else
87 contextt &operator=(const contextt &rhs) = delete;
88#endif
89
90 contextt &operator=(contextt &&) noexcept = default;
91
92 bool add(const symbolt &symbol);
93 bool move(symbolt &symbol, symbolt *&new_symbol);
94
95 bool move(symbolt &symbol)
96 {
97 symbolt *new_symbol;
98 return move(symbol, new_symbol);
99 }
101
102 void clear()
103 {
104 symbols.clear();
105 }
106
107 DUMP_METHOD void dump() const;
108
110 {
111 symbols.swap(other.symbols);
112 }
113
114 symbolt *find_symbol(const char *name)
115 {
116 return find_symbol(irep_idt(name));
117 }
119 const symbolt *find_symbol(irep_idt name) const;
120
121 void erase_symbol(irep_idt name);
122
127 irep_idt mark() const;
128
131 void erase_since(irep_idt point);
132
141
147 template <typename T>
148 void foreach_named_symbol_with_base(irep_idt base_name, T &&t) const
149 {
150 for (const symbolt &s : symbols.get<contextt_detail::by_order>())
151 if (s.name == base_name)
152 if (!t(s.id))
153 break;
154 }
155
156 template <typename T>
158 {
159 const_symbol_delegate wrapped(std::cref(t));
160 foreach_operand_impl_in_order_const(wrapped);
161 }
162
163 template <typename T>
165 {
166 symbol_delegate wrapped(std::ref(t));
167 foreach_operand_impl_in_order(wrapped);
168 }
169
170 template <typename T>
171 void foreach_operand(T &&t) const
172 {
173 const_symbol_delegate wrapped(std::cref(t));
174 foreach_operand_impl_const(wrapped);
175 }
176
177 template <typename T>
179 {
180 symbol_delegate wrapped(std::ref(t));
181 foreach_operand_impl(wrapped);
182 }
183
184 unsigned int size() const
185 {
186 return symbols.size();
187 }
188
189private:
191
192 void foreach_operand_impl_const(const_symbol_delegate &expr) const;
193 void foreach_operand_impl(symbol_delegate &expr);
194
195 void foreach_operand_impl_in_order_const(const_symbol_delegate &expr) const;
196 void foreach_operand_impl_in_order(symbol_delegate &expr);
197};
198
199#endif
void Foreach_operand(T &&t)
Definition context.h:178
symbolt * find_symbol(const char *name)
Definition context.h:114
contextt()
Definition context.h:62
contextt & operator=(const contextt &rhs)=delete
DUMP_METHOD void dump() const
Definition context.cpp:40
~contextt()=default
void Foreach_operand_in_order(T &&t)
Definition context.h:164
symbolt * reorder_symbol_to_back(irep_idt name)
Move the symbol with id name to the end of the insertion-order view, keeping it in the table.
Definition context.cpp:107
bool add(const symbolt &symbol)
Definition context.cpp:10
bool move(symbolt &symbol, symbolt *&new_symbol)
Definition context.cpp:18
void erase_since(irep_idt point)
Erase every symbol added after point (in insertion order, as returned by mark()).
Definition context.cpp:85
void erase_symbol(irep_idt name)
Definition context.cpp:65
contextt & operator=(contextt &&) noexcept=default
void foreach_operand(T &&t) const
Definition context.h:171
contextt(contextt &&) noexcept=default
contextt(const contextt &obj)=delete
void clear()
Definition context.h:102
unsigned int size() const
Definition context.h:184
void foreach_operand_in_order(T &&t) const
Definition context.h:157
symbolt * move_symbol_to_context(symbolt &symbol)
Definition context.cpp:158
void swap(contextt &other)
Definition context.h:109
irep_idt mark() const
Id of the most-recently-added symbol, or a nil id if the table is empty.
Definition context.cpp:79
void foreach_named_symbol_with_base(irep_idt base_name, T &&t) const
Invoke t(id) for every symbol whose base name equals base_name, in insertion order (the former forall...
Definition context.h:148
Definition irep_idt.h:12
Definition symbol.h:12
#define DUMP_METHOD
Definition compiler_defs.h:97
@ other
Definition converter_compare.cpp:887
#define T
Definition exp2f.c:24
std::hash< irep_idt > irep_id_hash
Definition irep.h:15
#define log_error(fmt,...)
Definition message.h:83
Definition context.h:37
boost::multi_index_container< symbolt, boost::multi_index::indexed_by< boost::multi_index::hashed_unique< boost::multi_index::tag< by_id >, BOOST_MULTI_INDEX_MEMBER(symbolt, irep_idt, id), irep_id_hash >, boost::multi_index::sequenced< boost::multi_index::tag< by_order > > > > symbol_containert
Definition context.h:53
Definition context.h:39
Definition context.h:42