@@ -13,9 +13,13 @@ Date: September 2011
1313
1414#include " nondet_volatile.h"
1515
16+ #include < util/cmdline.h>
17+ #include < util/options.h>
1618#include < util/std_expr.h>
1719#include < util/symbol_table.h>
1820
21+ using havoc_predicatet = std::function<bool (const exprt &)>;
22+
1923static bool is_volatile (const namespacet &ns, const typet &src)
2024{
2125 if (src.get_bool (ID_C_volatile))
@@ -31,16 +35,19 @@ static bool is_volatile(const namespacet &ns, const typet &src)
3135 return false ;
3236}
3337
34- static void nondet_volatile_rhs (const symbol_tablet &symbol_table, exprt &expr)
38+ static void nondet_volatile_rhs (
39+ const symbol_tablet &symbol_table,
40+ exprt &expr,
41+ havoc_predicatet should_havoc)
3542{
3643 Forall_operands (it, expr)
37- nondet_volatile_rhs (symbol_table, *it);
44+ nondet_volatile_rhs (symbol_table, *it, should_havoc );
3845
3946 if (expr.id ()==ID_symbol ||
4047 expr.id ()==ID_dereference)
4148 {
4249 const namespacet ns (symbol_table);
43- if (is_volatile (ns, expr.type ()))
50+ if (is_volatile (ns, expr.type ()) && should_havoc (expr) )
4451 {
4552 typet t=expr.type ();
4653 t.remove (ID_C_volatile);
@@ -52,31 +59,42 @@ static void nondet_volatile_rhs(const symbol_tablet &symbol_table, exprt &expr)
5259 }
5360}
5461
55- static void nondet_volatile_lhs (const symbol_tablet &symbol_table, exprt &expr)
62+ static void nondet_volatile_lhs (
63+ const symbol_tablet &symbol_table,
64+ exprt &expr,
65+ havoc_predicatet should_havoc)
5666{
5767 if (expr.id ()==ID_if)
5868 {
59- nondet_volatile_rhs (symbol_table, to_if_expr (expr).cond ());
60- nondet_volatile_lhs (symbol_table, to_if_expr (expr).true_case ());
61- nondet_volatile_lhs (symbol_table, to_if_expr (expr).false_case ());
69+ nondet_volatile_rhs (symbol_table, to_if_expr (expr).cond (), should_havoc);
70+ nondet_volatile_lhs (
71+ symbol_table, to_if_expr (expr).true_case (), should_havoc);
72+ nondet_volatile_lhs (
73+ symbol_table, to_if_expr (expr).false_case (), should_havoc);
6274 }
6375 else if (expr.id ()==ID_index)
6476 {
65- nondet_volatile_lhs (symbol_table, to_index_expr (expr).array ());
66- nondet_volatile_rhs (symbol_table, to_index_expr (expr).index ());
77+ nondet_volatile_lhs (
78+ symbol_table, to_index_expr (expr).array (), should_havoc);
79+ nondet_volatile_rhs (
80+ symbol_table, to_index_expr (expr).index (), should_havoc);
6781 }
6882 else if (expr.id ()==ID_member)
6983 {
70- nondet_volatile_lhs (symbol_table, to_member_expr (expr).struct_op ());
84+ nondet_volatile_lhs (
85+ symbol_table, to_member_expr (expr).struct_op (), should_havoc);
7186 }
7287 else if (expr.id ()==ID_dereference)
7388 {
74- nondet_volatile_rhs (symbol_table, to_dereference_expr (expr).pointer ());
89+ nondet_volatile_rhs (
90+ symbol_table, to_dereference_expr (expr).pointer (), should_havoc);
7591 }
7692}
7793
78- static void
79- nondet_volatile (symbol_tablet &symbol_table, goto_programt &goto_program)
94+ static void nondet_volatile (
95+ symbol_tablet &symbol_table,
96+ goto_programt &goto_program,
97+ havoc_predicatet should_havoc)
8098{
8199 namespacet ns (symbol_table);
82100
@@ -86,8 +104,10 @@ nondet_volatile(symbol_tablet &symbol_table, goto_programt &goto_program)
86104
87105 if (instruction.is_assign ())
88106 {
89- nondet_volatile_rhs (symbol_table, to_code_assign (instruction.code ).rhs ());
90- nondet_volatile_lhs (symbol_table, to_code_assign (instruction.code ).lhs ());
107+ nondet_volatile_rhs (
108+ symbol_table, to_code_assign (instruction.code ).rhs (), should_havoc);
109+ nondet_volatile_lhs (
110+ symbol_table, to_code_assign (instruction.code ).lhs (), should_havoc);
91111 }
92112 else if (instruction.is_function_call ())
93113 {
@@ -101,25 +121,105 @@ nondet_volatile(symbol_tablet &symbol_table, goto_programt &goto_program)
101121 it=code_function_call.arguments ().begin ();
102122 it!=code_function_call.arguments ().end ();
103123 it++)
104- nondet_volatile_rhs (symbol_table, *it);
124+ nondet_volatile_rhs (symbol_table, *it, should_havoc );
105125
106126 // do return value
107- nondet_volatile_lhs (symbol_table, code_function_call.lhs ());
127+ nondet_volatile_lhs (symbol_table, code_function_call.lhs (), should_havoc );
108128 }
109129 else if (instruction.has_condition ())
110130 {
111131 // do condition
112132 exprt cond = instruction.get_condition ();
113- nondet_volatile_rhs (symbol_table, cond);
133+ nondet_volatile_rhs (symbol_table, cond, should_havoc );
114134 instruction.set_condition (cond);
115135 }
116136 }
117137}
118138
119- void nondet_volatile (goto_modelt &goto_model)
139+ void nondet_volatile (goto_modelt &goto_model, havoc_predicatet should_havoc )
120140{
121141 Forall_goto_functions (f_it, goto_model.goto_functions )
122- nondet_volatile (goto_model.symbol_table , f_it->second .body );
142+ nondet_volatile (goto_model.symbol_table , f_it->second .body , should_havoc );
123143
124144 goto_model.goto_functions .update ();
125145}
146+
147+ void parse_nondet_volatile_options (const cmdlinet &cmdline, optionst &options)
148+ {
149+ PRECONDITION (!options.is_set (NONDET_VOLATILE_OPT));
150+ PRECONDITION (!options.is_set (NONDET_VOLATILE_VARIABLE_OPT));
151+
152+ const bool nondet_volatile_opt = cmdline.isset (NONDET_VOLATILE_OPT);
153+ const bool nondet_volatile_variable_opt =
154+ cmdline.isset (NONDET_VOLATILE_VARIABLE_OPT);
155+
156+ if (nondet_volatile_opt && nondet_volatile_variable_opt)
157+ {
158+ throw invalid_command_line_argument_exceptiont (
159+ " only one of " NONDET_VOLATILE_OPT " /" NONDET_VOLATILE_VARIABLE_OPT
160+ " can "
161+ " be given at a time" ,
162+ NONDET_VOLATILE_OPT " /" NONDET_VOLATILE_VARIABLE_OPT);
163+ }
164+
165+ if (nondet_volatile_opt)
166+ {
167+ options.set_option (NONDET_VOLATILE_OPT, true );
168+ }
169+ else if (cmdline.isset (NONDET_VOLATILE_VARIABLE_OPT))
170+ {
171+ options.set_option (
172+ NONDET_VOLATILE_VARIABLE_OPT,
173+ cmdline.get_values (NONDET_VOLATILE_VARIABLE_OPT));
174+ }
175+ }
176+
177+ void nondet_volatile (goto_modelt &goto_model, const optionst &options)
178+ {
179+ if (options.get_bool_option (NONDET_VOLATILE_OPT))
180+ {
181+ nondet_volatile (goto_model);
182+ }
183+ else if (options.is_set (NONDET_VOLATILE_VARIABLE_OPT))
184+ {
185+ const auto &variable_list =
186+ options.get_list_option (NONDET_VOLATILE_VARIABLE_OPT);
187+
188+ std::set<irep_idt> variables (variable_list.begin (), variable_list.end ());
189+ const namespacet ns (goto_model.symbol_table );
190+
191+ // typecheck given variables
192+ for (const auto &id : variables)
193+ {
194+ const symbolt *symbol;
195+
196+ if (ns.lookup (id, symbol))
197+ {
198+ throw invalid_command_line_argument_exceptiont (
199+ " given name " + id2string (id) + " not found in symbol table" ,
200+ NONDET_VOLATILE_VARIABLE_OPT);
201+ }
202+
203+ if (!symbol->is_static_lifetime || !symbol->type .get_bool (ID_C_volatile))
204+ {
205+ throw invalid_command_line_argument_exceptiont (
206+ " given name " + id2string (id) +
207+ " does not represent a volatile "
208+ " variable with static lifetime" ,
209+ NONDET_VOLATILE_VARIABLE_OPT);
210+ }
211+
212+ INVARIANT (!symbol->is_type , " symbol must not represent a type" );
213+
214+ INVARIANT (
215+ symbol->type .id () != ID_code, " symbol must not represent a function" );
216+ }
217+
218+ auto should_havoc = [&variables](const exprt &expr) {
219+ return expr.id () == ID_symbol &&
220+ variables.count (to_symbol_expr (expr).get_identifier ()) != 0 ;
221+ };
222+
223+ nondet_volatile (goto_model, should_havoc);
224+ }
225+ }
0 commit comments