Skip to content

Commit 248fec3

Browse files
committed
nondet_initializer to build deep non-deterministic expressions
Create a side_effect_expr_nondett for all PODs or types of unknown/unbounded size, and arrays/structs/vectors/unions of non-deterministic expressions. For example, struct { int; float; } will yield a struct{nondet(int), nondet(float)}.
1 parent 8ac06a4 commit 248fec3

File tree

2 files changed

+106
-11
lines changed

2 files changed

+106
-11
lines changed

src/util/expr_initializer.cpp

Lines changed: 95 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,10 @@ Author: Daniel Kroening, [email protected]
1818
#include "message.h"
1919
#include "namespace.h"
2020
#include "pointer_offset_size.h"
21+
#include "std_code.h"
2122
#include "std_expr.h"
2223

24+
template <bool nondet>
2325
class zero_initializert:public messaget
2426
{
2527
public:
@@ -46,7 +48,8 @@ class zero_initializert:public messaget
4648
const source_locationt &source_location);
4749
};
4850

49-
exprt zero_initializert::zero_initializer_rec(
51+
template <bool nondet>
52+
exprt zero_initializert<nondet>::zero_initializer_rec(
5053
const typet &type,
5154
const source_locationt &source_location)
5255
{
@@ -63,31 +66,55 @@ exprt zero_initializert::zero_initializer_rec(
6366
type_id==ID_floatbv ||
6467
type_id==ID_fixedbv)
6568
{
66-
exprt result=from_integer(0, type);
69+
exprt result;
70+
if(nondet)
71+
result = side_effect_expr_nondett(type);
72+
else
73+
result = from_integer(0, type);
74+
6775
result.add_source_location()=source_location;
6876
return result;
6977
}
7078
else if(type_id==ID_rational ||
7179
type_id==ID_real)
7280
{
73-
constant_exprt result(ID_0, type);
81+
exprt result;
82+
if(nondet)
83+
result = side_effect_expr_nondett(type);
84+
else
85+
result = constant_exprt(ID_0, type);
86+
7487
result.add_source_location()=source_location;
7588
return result;
7689
}
7790
else if(type_id==ID_verilog_signedbv ||
7891
type_id==ID_verilog_unsignedbv)
7992
{
80-
std::size_t width=to_bitvector_type(type).get_width();
81-
std::string value(width, '0');
93+
exprt result;
94+
if(nondet)
95+
result = side_effect_expr_nondett(type);
96+
else
97+
{
98+
const std::size_t width = to_bitvector_type(type).get_width();
99+
std::string value(width, '0');
100+
101+
result = constant_exprt(value, type);
102+
}
82103

83-
constant_exprt result(value, type);
84104
result.add_source_location()=source_location;
85105
return result;
86106
}
87107
else if(type_id==ID_complex)
88108
{
89-
exprt sub_zero=zero_initializer_rec(type.subtype(), source_location);
90-
complex_exprt result(sub_zero, sub_zero, to_complex_type(type));
109+
exprt result;
110+
if(nondet)
111+
result = side_effect_expr_nondett(type);
112+
else
113+
{
114+
exprt sub_zero = zero_initializer_rec(type.subtype(), source_location);
115+
result = complex_exprt(sub_zero, sub_zero, to_complex_type(type));
116+
}
117+
91118
result.add_source_location()=source_location;
92119
return result;
93120
}
@@ -119,12 +146,26 @@ exprt zero_initializert::zero_initializer_rec(
119146

120147
if(array_type.size().id()==ID_infinity)
121148
{
149+
if(nondet)
150+
{
151+
side_effect_expr_nondett result(type);
152+
result.add_source_location() = source_location;
153+
return result;
154+
}
155+
122156
array_of_exprt value(tmpval, array_type);
123157
value.add_source_location()=source_location;
124158
return value;
125159
}
126160
else if(to_integer(array_type.size(), array_size))
127161
{
162+
if(nondet)
163+
{
164+
side_effect_expr_nondett result(type);
165+
result.add_source_location() = source_location;
166+
return result;
167+
}
168+
128169
error().source_location=source_location;
129170
error() << "failed to zero-initialize array of non-fixed size `"
130171
<< format(array_type.size()) << "'" << eom;
@@ -154,6 +195,13 @@ exprt zero_initializert::zero_initializer_rec(
154195

155196
if(to_integer(vector_type.size(), vector_size))
156197
{
198+
if(nondet)
199+
{
200+
side_effect_expr_nondett result(type);
201+
result.add_source_location() = source_location;
202+
return result;
203+
}
204+
157205
error().source_location=source_location;
158206
error() << "failed to zero-initialize vector of non-fixed size `"
159207
<< format(vector_type.size()) << "'" << eom;
@@ -282,7 +330,14 @@ exprt zero_initializert::zero_initializer_rec(
282330
}
283331
else if(type_id==ID_string)
284332
{
285-
return constant_exprt(irep_idt(), type);
333+
exprt result;
334+
if(nondet)
335+
result = side_effect_expr_nondett(type);
336+
else
337+
result = constant_exprt(irep_idt(), type);
338+
339+
result.add_source_location()=source_location;
340+
return result;
286341
}
287342
else
288343
{
@@ -298,7 +353,17 @@ exprt zero_initializer(
298353
const namespacet &ns,
299354
message_handlert &message_handler)
300355
{
301-
zero_initializert z_i(ns, message_handler);
356+
zero_initializert<false> z_i(ns, message_handler);
357+
return z_i(type, source_location);
358+
}
359+
360+
exprt nondet_initializer(
361+
const typet &type,
362+
const source_locationt &source_location,
363+
const namespacet &ns,
364+
message_handlert &message_handler)
365+
{
366+
zero_initializert<true> z_i(ns, message_handler);
302367
return z_i(type, source_location);
303368
}
304369

@@ -312,7 +377,26 @@ exprt zero_initializer(
312377

313378
try
314379
{
315-
zero_initializert z_i(ns, mh);
380+
zero_initializert<false> z_i(ns, mh);
381+
return z_i(type, source_location);
382+
}
383+
catch(int)
384+
{
385+
throw oss.str();
386+
}
387+
}
388+
389+
exprt nondet_initializer(
390+
const typet &type,
391+
const source_locationt &source_location,
392+
const namespacet &ns)
393+
{
394+
std::ostringstream oss;
395+
stream_message_handlert mh(oss);
396+
397+
try
398+
{
399+
zero_initializert<true> z_i(ns, mh);
316400
return z_i(type, source_location);
317401
}
318402
catch(int)

src/util/expr_initializer.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,21 @@ exprt zero_initializer(
2424
const namespacet &,
2525
message_handlert &);
2626

27+
exprt nondet_initializer(
28+
const typet &,
29+
const source_locationt &,
30+
const namespacet &,
31+
message_handlert &);
32+
2733
// throws a char* in case of failure
2834
exprt zero_initializer(
2935
const typet &,
3036
const source_locationt &,
3137
const namespacet &);
3238

39+
exprt nondet_initializer(
40+
const typet &type,
41+
const source_locationt &source_location,
42+
const namespacet &ns);
43+
3344
#endif // CPROVER_UTIL_EXPR_INITIALIZER_H

0 commit comments

Comments
 (0)