CBMC
Loading...
Searching...
No Matches
nondet_volatile.cpp
Go to the documentation of this file.
1/*******************************************************************\
2
3Module: Volatile Variables
4
5Author: Daniel Kroening
6
7Date: September 2011
8
9\*******************************************************************/
10
13
14#include "nondet_volatile.h"
15
16#include <util/c_types.h>
17#include <util/cmdline.h>
18#include <util/fresh_symbol.h>
19#include <util/options.h>
20#include <util/pointer_expr.h>
21#include <util/std_code.h>
22#include <util/std_expr.h>
23#include <util/string_utils.h>
24
26
28{
29public:
35
37 {
38 if(!all_nondet && nondet_variables.empty() && variable_models.empty())
39 {
40 return;
41 }
42
44 {
46 }
47
49 }
50
51private:
52 static bool is_volatile(const namespacet &ns, const typet &src);
53
55 exprt &expr,
56 const namespacet &ns,
58 goto_programt &post);
59
61 const symbol_table_baset &symbol_table,
62 exprt &expr,
64 goto_programt &post);
65
67 const symbol_table_baset &symbol_table,
68 exprt &expr,
70 goto_programt &post);
71
72 void nondet_volatile(
73 symbol_table_baset &symbol_table,
74 goto_programt &goto_program);
75
76 const symbolt &typecheck_variable(const irep_idt &id, const namespacet &ns);
77
78 void typecheck_model(
79 const irep_idt &id,
80 const symbolt &variable,
81 const namespacet &ns);
82
83 void typecheck_options(const optionst &options);
84
86
87 // configuration obtained from command line options
89 std::set<irep_idt> nondet_variables;
90 std::map<irep_idt, irep_idt> variable_models;
91};
92
94{
95 if(src.get_bool(ID_C_volatile))
96 return true;
97
99 return is_volatile(ns, ns.follow_tag(*struct_tag));
101 return is_volatile(ns, ns.follow_tag(*union_tag));
103 return is_volatile(ns, ns.follow_tag(*enum_tag));
104 else
105 return false;
106}
107
109 exprt &expr,
110 const namespacet &ns,
112 goto_programt &post)
113{
114 // Check if we should replace the variable by a nondet expression
115 if(
116 all_nondet ||
117 (expr.id() == ID_symbol &&
118 nondet_variables.count(to_symbol_expr(expr).get_identifier()) != 0))
119 {
120 typet t = expr.type();
122
124 expr.swap(nondet_expr);
125
126 return;
127 }
128
129 // Now check if we should replace the variable by a model
130
131 if(expr.id() != ID_symbol)
132 {
133 return;
134 }
135
136 const irep_idt &id = to_symbol_expr(expr).get_identifier();
137 const auto &it = variable_models.find(id);
138
139 if(it == variable_models.end())
140 {
141 return;
142 }
143
144 const auto &model_symbol = ns.lookup(it->second);
145
146 const auto &new_variable = get_fresh_aux_symbol(
147 to_code_type(model_symbol.type).return_type(),
148 "",
149 "modelled_volatile",
151 ID_C,
153 .symbol_expr();
154
155 pre.instructions.push_back(goto_programt::make_decl(new_variable));
156
157 code_function_callt call(new_variable, model_symbol.symbol_expr(), {});
158 pre.instructions.push_back(goto_programt::make_function_call(call));
159
160 post.instructions.push_back(goto_programt::make_dead(new_variable));
161
162 expr = new_variable;
163}
164
166 const symbol_table_baset &symbol_table,
167 exprt &expr,
169 goto_programt &post)
170{
171 Forall_operands(it, expr)
172 nondet_volatile_rhs(symbol_table, *it, pre, post);
173
174 if(expr.id()==ID_symbol ||
175 expr.id()==ID_dereference)
176 {
177 const namespacet ns(symbol_table);
178
179 if(is_volatile(ns, expr.type()))
180 {
181 handle_volatile_expression(expr, ns, pre, post);
182 }
183 }
184}
185
187 const symbol_table_baset &symbol_table,
188 exprt &expr,
190 goto_programt &post)
191{
192 if(expr.id()==ID_if)
193 {
194 nondet_volatile_rhs(symbol_table, to_if_expr(expr).cond(), pre, post);
195 nondet_volatile_lhs(symbol_table, to_if_expr(expr).true_case(), pre, post);
196 nondet_volatile_lhs(symbol_table, to_if_expr(expr).false_case(), pre, post);
197 }
198 else if(expr.id()==ID_index)
199 {
200 nondet_volatile_lhs(symbol_table, to_index_expr(expr).array(), pre, post);
201 nondet_volatile_rhs(symbol_table, to_index_expr(expr).index(), pre, post);
202 }
203 else if(expr.id()==ID_member)
204 {
206 symbol_table, to_member_expr(expr).struct_op(), pre, post);
207 }
208 else if(expr.id()==ID_dereference)
209 {
211 symbol_table, to_dereference_expr(expr).pointer(), pre, post);
212 }
213}
214
216 symbol_table_baset &symbol_table,
217 goto_programt &goto_program)
218{
219 namespacet ns(symbol_table);
220
221 for(auto i_it = goto_program.instructions.begin();
222 i_it != goto_program.instructions.end();
223 i_it++)
224 {
226 goto_programt post;
227
228 goto_programt::instructiont &instruction = *i_it;
229
230 if(instruction.is_assign())
231 {
233 symbol_table, instruction.assign_rhs_nonconst(), pre, post);
235 symbol_table, instruction.assign_lhs_nonconst(), pre, post);
236 }
237 else if(instruction.is_function_call())
238 {
239 // these have arguments and a return LHS
240
243
244 // do arguments
245 for(exprt::operandst::iterator
246 it=code_function_call.arguments().begin();
247 it!=code_function_call.arguments().end();
248 it++)
249 nondet_volatile_rhs(symbol_table, *it, pre, post);
250
251 // do return value
252 nondet_volatile_lhs(symbol_table, code_function_call.lhs(), pre, post);
253 }
254 else if(instruction.has_condition())
255 {
256 // do condition
258 symbol_table, instruction.condition_nonconst(), pre, post);
259 }
260
261 const auto pre_size = pre.instructions.size();
262 goto_program.insert_before_swap(i_it, pre);
263 std::advance(i_it, pre_size);
264
265 const auto post_size = post.instructions.size();
266 goto_program.destructive_insert(std::next(i_it), post);
267 std::advance(i_it, post_size);
268 }
269}
270
271const symbolt &
273{
274 const symbolt *symbol;
275
276 if(ns.lookup(id, symbol))
277 {
279 "given symbol `" + id2string(id) + "` not found in symbol table",
281 }
282
283 if(!symbol->is_static_lifetime || !symbol->type.get_bool(ID_C_volatile))
284 {
286 "symbol `" + id2string(id) +
287 "` does not represent a volatile variable "
288 "with static lifetime",
290 }
291
292 INVARIANT(!symbol->is_type, "symbol must not represent a type");
293
294 INVARIANT(!symbol->is_function(), "symbol must not represent a function");
295
296 return *symbol;
297}
298
300 const irep_idt &id,
301 const symbolt &variable,
302 const namespacet &ns)
303{
304 const symbolt *symbol;
305
306 if(ns.lookup(id, symbol))
307 {
309 "given model name " + id2string(id) + " not found in symbol table",
311 }
312
313 if(!symbol->is_function())
314 {
316 "symbol `" + id2string(id) + "` is not a function",
318 }
319
320 const auto &code_type = to_code_type(symbol->type);
321
322 if(variable.type != code_type.return_type())
323 {
325 "return type of model `" + id2string(id) +
326 "` is not compatible with the "
327 "type of the modelled variable " +
328 id2string(variable.name),
330 }
331
332 if(!code_type.parameters().empty())
333 {
335 "model `" + id2string(id) + "` must not take parameters ",
337 }
338}
339
341{
345
347 {
348 all_nondet = true;
349 return;
350 }
351
353
355 {
356 const auto &variable_list =
358
359 nondet_variables.insert(variable_list.begin(), variable_list.end());
360
361 for(const auto &id : nondet_variables)
362 {
363 typecheck_variable(id, ns);
364 }
365 }
366
368 {
370
371 for(const auto &s : model_list)
372 {
373 std::string variable;
374 std::string model;
375
376 try
377 {
378 split_string(s, ':', variable, model, true);
379 }
380 catch(const deserialization_exceptiont &e)
381 {
383 "cannot split argument `" + s + "` into variable name and model name",
385 }
386
387 const auto &variable_symbol = typecheck_variable(variable, ns);
388
389 if(nondet_variables.count(variable) != 0)
390 {
392 "conflicting options for variable `" + variable + "`",
394 }
395
397
398 const auto p = variable_models.insert(std::make_pair(variable, model));
399
400 if(!p.second && p.first->second != model)
401 {
403 "conflicting models for variable `" + variable + "`",
405 }
406 }
407 }
408}
409
455
456void nondet_volatile(goto_modelt &goto_model, const optionst &options)
457{
458 nondet_volatilet nv(goto_model, options);
459 nv();
460}
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
Definition ai.h:562
virtual bool isset(char option) const
Definition cmdline.cpp:30
const std::list< std::string > & get_values(const std::string &option) const
Definition cmdline.cpp:119
goto_instruction_codet representation of a function call statement.
Thrown when failing to deserialize a value from some low level format, like JSON or raw bytes.
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition dstring.h:38
Base class for all expressions.
Definition expr.h:56
typet & type()
Return the type of the expression.
Definition expr.h:84
const source_locationt & source_location() const
Definition expr.h:231
function_mapt function_map
symbol_tablet symbol_table
Symbol table.
Definition goto_model.h:31
goto_functionst goto_functions
GOTO functions.
Definition goto_model.h:34
This class represents an instruction in the GOTO intermediate representation.
bool has_condition() const
Does this instruction have a condition?
exprt & assign_lhs_nonconst()
Get the lhs of the assignment for ASSIGN.
goto_instruction_codet & code_nonconst()
Set the code represented by this instruction.
exprt & condition_nonconst()
Get the condition of gotos, assume, assert.
exprt & assign_rhs_nonconst()
Get the rhs of the assignment for ASSIGN.
A generic container class for the GOTO intermediate representation of one function.
instructionst instructions
The list of instructions in the goto program.
static instructiont make_dead(const symbol_exprt &symbol, const source_locationt &l=source_locationt::nil())
void insert_before_swap(targett target)
Insertion that preserves jumps to "target".
void destructive_insert(const_targett target, goto_programt &p)
Inserts the given program p before target.
static instructiont make_function_call(const code_function_callt &_code, const source_locationt &l=source_locationt::nil())
Create a function call instruction.
static instructiont make_decl(const symbol_exprt &symbol, const source_locationt &l=source_locationt::nil())
Thrown when users pass incorrect command line arguments, for example passing no files to analysis or ...
bool get_bool(const irep_idt &name) const
Definition irep.cpp:57
void remove(const irep_idt &name)
Definition irep.cpp:87
void swap(irept &irep)
Definition irep.h:434
const irep_idt & id() const
Definition irep.h:388
const union_typet & follow_tag(const union_tag_typet &) const
Follow type tag of union type.
Definition namespace.cpp:49
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
Definition namespace.h:91
bool lookup(const irep_idt &name, const symbolt *&symbol) const override
See documentation for namespace_baset::lookup().
goto_modelt & goto_model
void nondet_volatile(symbol_table_baset &symbol_table, goto_programt &goto_program)
void typecheck_model(const irep_idt &id, const symbolt &variable, const namespacet &ns)
std::set< irep_idt > nondet_variables
static bool is_volatile(const namespacet &ns, const typet &src)
nondet_volatilet(goto_modelt &goto_model, const optionst &options)
void handle_volatile_expression(exprt &expr, const namespacet &ns, goto_programt &pre, goto_programt &post)
std::map< irep_idt, irep_idt > variable_models
const symbolt & typecheck_variable(const irep_idt &id, const namespacet &ns)
void nondet_volatile_rhs(const symbol_table_baset &symbol_table, exprt &expr, goto_programt &pre, goto_programt &post)
void typecheck_options(const optionst &options)
void nondet_volatile_lhs(const symbol_table_baset &symbol_table, exprt &expr, goto_programt &pre, goto_programt &post)
bool is_set(const std::string &option) const
N.B. opts.is_set("foo") does not imply opts.get_bool_option("foo")
Definition options.cpp:62
bool get_bool_option(const std::string &option) const
Definition options.cpp:44
void set_option(const std::string &option, const bool value)
Definition options.cpp:28
const value_listt & get_list_option(const std::string &option) const
Definition options.cpp:80
A side_effect_exprt that returns a non-deterministically chosen value.
Definition std_code.h:1520
The symbol table base class interface.
Symbol table entry.
Definition symbol.h:28
bool is_static_lifetime
Definition symbol.h:70
bool is_type
Definition symbol.h:61
class symbol_exprt symbol_expr() const
Produces a symbol_exprt for a symbol.
Definition symbol.cpp:121
bool is_function() const
Definition symbol.h:106
typet type
Type of symbol.
Definition symbol.h:31
irep_idt name
The unique identifier.
Definition symbol.h:40
The type of an expression, extends irept.
Definition type.h:29
#define Forall_operands(it, expr)
Definition expr.h:27
symbolt & get_fresh_aux_symbol(const typet &type, const std::string &name_prefix, const std::string &basename_prefix, const source_locationt &source_location, const irep_idt &symbol_mode, const namespacet &ns, symbol_table_baset &symbol_table)
Installs a fresh-named symbol with respect to the given namespace ns with the requested name pattern ...
Fresh auxiliary symbol creation.
const code_function_callt & to_code_function_call(const goto_instruction_codet &code)
Symbol Table + CFG.
const std::string & id2string(const irep_idt &d)
Definition irep.h:44
void parse_nondet_volatile_options(const cmdlinet &cmdline, optionst &options)
void nondet_volatile(goto_modelt &goto_model, const optionst &options)
Havoc reads from volatile expressions, if enabled in the options.
Volatile Variables.
#define NONDET_VOLATILE_MODEL_OPT
#define NONDET_VOLATILE_OPT
#define NONDET_VOLATILE_VARIABLE_OPT
Options.
API to expression classes for Pointers.
const dereference_exprt & to_dereference_expr(const exprt &expr)
Cast an exprt to a dereference_exprt.
#define PRECONDITION(CONDITION)
Definition invariant.h:463
#define INVARIANT(CONDITION, REASON)
This macro uses the wrapper function 'invariant_violated_string'.
Definition invariant.h:423
API to expression classes.
const index_exprt & to_index_expr(const exprt &expr)
Cast an exprt to an index_exprt.
Definition std_expr.h:1538
const if_exprt & to_if_expr(const exprt &expr)
Cast an exprt to an if_exprt.
Definition std_expr.h:2577
const member_exprt & to_member_expr(const exprt &expr)
Cast an exprt to a member_exprt.
Definition std_expr.h:3063
const symbol_exprt & to_symbol_expr(const exprt &expr)
Cast an exprt to a symbol_exprt.
Definition std_expr.h:272
const code_typet & to_code_type(const typet &type)
Cast a typet to a code_typet.
Definition std_types.h:788
void split_string(const std::string &s, char delim, std::vector< std::string > &result, bool strip, bool remove_empty)