Skip to content

Commit cf41a88

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 626fb98 commit cf41a88

File tree

2 files changed

+110
-15
lines changed

2 files changed

+110
-15
lines changed

src/util/expr_initializer.cpp

+99-15
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 expr_initializert : public messaget
2426
{
2527
public:
@@ -46,7 +48,8 @@ class expr_initializert : public messaget
4648
const source_locationt &source_location);
4749
};
4850

49-
exprt expr_initializert::expr_initializer_rec(
51+
template <bool nondet>
52+
exprt expr_initializert<nondet>::expr_initializer_rec(
5053
const typet &type,
5154
const source_locationt &source_location)
5255
{
@@ -63,38 +66,62 @@ exprt expr_initializert::expr_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 = expr_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 = expr_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
}
94121
else if(type_id==ID_code)
95122
{
96123
error().source_location=source_location;
97-
error() << "cannot zero-initialize code-type" << eom;
124+
error() << "cannot initialize code-type" << eom;
98125
throw 0;
99126
}
100127
else if(type_id==ID_array)
@@ -120,12 +147,26 @@ exprt expr_initializert::expr_initializer_rec(
120147

121148
if(array_type.size().id()==ID_infinity)
122149
{
150+
if(nondet)
151+
{
152+
side_effect_expr_nondett result(type);
153+
result.add_source_location() = source_location;
154+
return result;
155+
}
156+
123157
array_of_exprt value(tmpval, array_type);
124158
value.add_source_location()=source_location;
125159
return value;
126160
}
127161
else if(to_integer(array_type.size(), array_size))
128162
{
163+
if(nondet)
164+
{
165+
side_effect_expr_nondett result(type);
166+
result.add_source_location() = source_location;
167+
return result;
168+
}
169+
129170
error().source_location=source_location;
130171
error() << "failed to zero-initialize array of non-fixed size `"
131172
<< format(array_type.size()) << "'" << eom;
@@ -135,7 +176,7 @@ exprt expr_initializert::expr_initializer_rec(
135176
if(array_size<0)
136177
{
137178
error().source_location=source_location;
138-
error() << "failed to zero-initialize array with negative size" << eom;
179+
error() << "failed to initialize array with negative size" << eom;
139180
throw 0;
140181
}
141182

@@ -155,6 +196,13 @@ exprt expr_initializert::expr_initializer_rec(
155196

156197
if(to_integer(vector_type.size(), vector_size))
157198
{
199+
if(nondet)
200+
{
201+
side_effect_expr_nondett result(type);
202+
result.add_source_location() = source_location;
203+
return result;
204+
}
205+
158206
error().source_location=source_location;
159207
error() << "failed to zero-initialize vector of non-fixed size `"
160208
<< format(vector_type.size()) << "'" << eom;
@@ -164,7 +212,7 @@ exprt expr_initializert::expr_initializer_rec(
164212
if(vector_size<0)
165213
{
166214
error().source_location=source_location;
167-
error() << "failed to zero-initialize vector with negative size" << eom;
215+
error() << "failed to initialize vector with negative size" << eom;
168216
throw 0;
169217
}
170218

@@ -283,12 +331,19 @@ exprt expr_initializert::expr_initializer_rec(
283331
}
284332
else if(type_id==ID_string)
285333
{
286-
return constant_exprt(irep_idt(), type);
334+
exprt result;
335+
if(nondet)
336+
result = side_effect_expr_nondett(type);
337+
else
338+
result = constant_exprt(irep_idt(), type);
339+
340+
result.add_source_location()=source_location;
341+
return result;
287342
}
288343
else
289344
{
290345
error().source_location=source_location;
291-
error() << "failed to zero-initialize `" << format(type) << "'" << eom;
346+
error() << "failed to initialize `" << format(type) << "'" << eom;
292347
throw 0;
293348
}
294349
}
@@ -299,7 +354,17 @@ exprt zero_initializer(
299354
const namespacet &ns,
300355
message_handlert &message_handler)
301356
{
302-
expr_initializert z_i(ns, message_handler);
357+
expr_initializert<false> z_i(ns, message_handler);
358+
return z_i(type, source_location);
359+
}
360+
361+
exprt nondet_initializer(
362+
const typet &type,
363+
const source_locationt &source_location,
364+
const namespacet &ns,
365+
message_handlert &message_handler)
366+
{
367+
expr_initializert<true> z_i(ns, message_handler);
303368
return z_i(type, source_location);
304369
}
305370

@@ -313,7 +378,26 @@ exprt zero_initializer(
313378

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

src/util/expr_initializer.h

+11
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)