@@ -13,9 +13,13 @@ Date: September 2011
13
13
14
14
#include " nondet_volatile.h"
15
15
16
+ #include < util/cmdline.h>
17
+ #include < util/options.h>
16
18
#include < util/std_expr.h>
17
19
#include < util/symbol_table.h>
18
20
21
+ using havoc_predicatet = std::function<bool (const exprt &)>;
22
+
19
23
static bool is_volatile (const namespacet &ns, const typet &src)
20
24
{
21
25
if (src.get_bool (ID_C_volatile))
@@ -31,16 +35,19 @@ static bool is_volatile(const namespacet &ns, const typet &src)
31
35
return false ;
32
36
}
33
37
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)
35
42
{
36
43
Forall_operands (it, expr)
37
- nondet_volatile_rhs (symbol_table, *it);
44
+ nondet_volatile_rhs (symbol_table, *it, should_havoc );
38
45
39
46
if (expr.id ()==ID_symbol ||
40
47
expr.id ()==ID_dereference)
41
48
{
42
49
const namespacet ns (symbol_table);
43
- if (is_volatile (ns, expr.type ()))
50
+ if (is_volatile (ns, expr.type ()) && should_havoc (expr) )
44
51
{
45
52
typet t=expr.type ();
46
53
t.remove (ID_C_volatile);
@@ -52,31 +59,42 @@ static void nondet_volatile_rhs(const symbol_tablet &symbol_table, exprt &expr)
52
59
}
53
60
}
54
61
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)
56
66
{
57
67
if (expr.id ()==ID_if)
58
68
{
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);
62
74
}
63
75
else if (expr.id ()==ID_index)
64
76
{
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);
67
81
}
68
82
else if (expr.id ()==ID_member)
69
83
{
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);
71
86
}
72
87
else if (expr.id ()==ID_dereference)
73
88
{
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);
75
91
}
76
92
}
77
93
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)
80
98
{
81
99
namespacet ns (symbol_table);
82
100
@@ -86,8 +104,10 @@ nondet_volatile(symbol_tablet &symbol_table, goto_programt &goto_program)
86
104
87
105
if (instruction.is_assign ())
88
106
{
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);
91
111
}
92
112
else if (instruction.is_function_call ())
93
113
{
@@ -101,25 +121,105 @@ nondet_volatile(symbol_tablet &symbol_table, goto_programt &goto_program)
101
121
it=code_function_call.arguments ().begin ();
102
122
it!=code_function_call.arguments ().end ();
103
123
it++)
104
- nondet_volatile_rhs (symbol_table, *it);
124
+ nondet_volatile_rhs (symbol_table, *it, should_havoc );
105
125
106
126
// 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 );
108
128
}
109
129
else if (instruction.has_condition ())
110
130
{
111
131
// do condition
112
132
exprt cond = instruction.get_condition ();
113
- nondet_volatile_rhs (symbol_table, cond);
133
+ nondet_volatile_rhs (symbol_table, cond, should_havoc );
114
134
instruction.set_condition (cond);
115
135
}
116
136
}
117
137
}
118
138
119
- void nondet_volatile (goto_modelt &goto_model)
139
+ void nondet_volatile (goto_modelt &goto_model, havoc_predicatet should_havoc )
120
140
{
121
141
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 );
123
143
124
144
goto_model.goto_functions .update ();
125
145
}
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