Skip to content

Commit 31c40d8

Browse files
committed
Properly deals with ranges on assigns clauses
We expand assigns clause's support to also handle array ranges (e.g. `myArr[5 .. lastIdx]`) similarly to ACSL. Signed-off-by: Felipe R. Monteiro <[email protected]>
1 parent 0eed7fc commit 31c40d8

File tree

1 file changed

+100
-8
lines changed

1 file changed

+100
-8
lines changed

src/goto-instrument/code_contracts.cpp

Lines changed: 100 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1173,13 +1173,26 @@ assigns_clause_array_targett::assigns_clause_array_targett(
11731173
code_contractst &contract,
11741174
messaget &log_parameter,
11751175
const irep_idt &function_id)
1176-
: assigns_clause_targett(Array, object_ptr, contract, log_parameter),
1176+
: assigns_clause_targett(
1177+
Array,
1178+
to_range_exprt(object_ptr).lower(),
1179+
contract,
1180+
log_parameter),
11771181
lower_offset_object(),
11781182
upper_offset_object(),
11791183
array_standin_variable(typet()),
11801184
lower_offset_variable(typet()),
11811185
upper_offset_variable(typet())
11821186
{
1187+
const exprt &array = to_range_exprt(object_ptr).lower();
1188+
const exprt &range = to_range_exprt(object_ptr).upper();
1189+
1190+
// If the range doesn't have operands, it is just a single value
1191+
const exprt &lower_operand =
1192+
range.has_operands() ? to_range_exprt(range).lower() : range;
1193+
const exprt &upper_operand =
1194+
range.has_operands() ? to_range_exprt(range).upper() : range;
1195+
11831196
const symbolt &function_symbol = contract.ns.lookup(function_id);
11841197

11851198
// Declare a new symbol to stand in for the reference
@@ -1198,13 +1211,24 @@ assigns_clause_array_targett::assigns_clause_array_targett(
11981211
code_assignt(array_standin_variable, pointer_object),
11991212
function_symbol.location));
12001213

1201-
if(object_ptr.id() == ID_address_of)
1214+
if(lower_operand.id() == ID_constant)
12021215
{
1203-
exprt constant_size =
1204-
get_size(object_ptr.type().subtype(), contract.ns, log);
1216+
int lowerbase = std::stoi(
1217+
to_constant_expr(lower_operand).get(ID_C_base).c_str(), nullptr, 10);
1218+
lower_bound = std::stoi(
1219+
to_constant_expr(lower_operand).get_value().c_str(), nullptr, lowerbase);
1220+
1221+
irep_idt lower_const_string(
1222+
from_integer(lower_bound, integer_typet()).get_value());
1223+
irep_idt lower_const_irep(lower_const_string);
1224+
constant_exprt lower_val_const(lower_const_irep, lower_operand.type());
1225+
1226+
exprt lower_constant_size =
1227+
get_size(array.type().subtype(), contract.ns, log);
12051228
lower_offset_object = typecast_exprt(
12061229
mult_exprt(
1207-
typecast_exprt(object_ptr, unsigned_long_int_type()), constant_size),
1230+
typecast_exprt(lower_val_const, unsigned_long_int_type()),
1231+
lower_constant_size),
12081232
signed_int_type());
12091233

12101234
// Declare a new symbol to stand in for the reference
@@ -1222,10 +1246,78 @@ assigns_clause_array_targett::assigns_clause_array_targett(
12221246
init_block.add(goto_programt::make_assignment(
12231247
code_assignt(lower_offset_variable, lower_offset_object),
12241248
function_symbol.location));
1249+
}
1250+
else
1251+
{
1252+
exprt lower_constant_size =
1253+
get_size(array.type().subtype(), contract.ns, log);
1254+
lower_offset_object = typecast_exprt(
1255+
mult_exprt(
1256+
typecast_exprt(lower_operand, unsigned_long_int_type()),
1257+
lower_constant_size),
1258+
signed_int_type());
1259+
1260+
// Declare a new symbol to stand in for the reference
1261+
symbolt lower_standin_symbol = contract.new_tmp_symbol(
1262+
lower_offset_object.type(),
1263+
function_symbol.location,
1264+
function_id,
1265+
function_symbol.mode);
1266+
1267+
lower_offset_variable = lower_standin_symbol.symbol_expr();
12251268

1269+
// Add array temp to variable initialization block
1270+
init_block.add(goto_programt::make_decl(
1271+
lower_offset_variable, function_symbol.location));
1272+
init_block.add(goto_programt::make_assignment(
1273+
code_assignt(lower_offset_variable, lower_offset_object),
1274+
function_symbol.location));
1275+
}
1276+
1277+
if(upper_operand.id() == ID_constant)
1278+
{
1279+
int upperbase = std::stoi(
1280+
to_constant_expr(upper_operand).get(ID_C_base).c_str(), nullptr, 10);
1281+
upper_bound = std::stoi(
1282+
to_constant_expr(upper_operand).get_value().c_str(), nullptr, upperbase);
1283+
1284+
irep_idt upper_const_string(
1285+
from_integer(upper_bound, integer_typet()).get_value());
1286+
irep_idt upper_const_irep(upper_const_string);
1287+
constant_exprt upper_val_const(upper_const_irep, upper_operand.type());
1288+
1289+
exprt upper_constant_size =
1290+
get_size(array.type().subtype(), contract.ns, log);
1291+
upper_offset_object = typecast_exprt(
1292+
mult_exprt(
1293+
typecast_exprt(upper_val_const, unsigned_long_int_type()),
1294+
upper_constant_size),
1295+
signed_int_type());
1296+
1297+
// Declare a new symbol to stand in for the reference
1298+
symbolt upper_standin_symbol = contract.new_tmp_symbol(
1299+
upper_offset_object.type(),
1300+
function_symbol.location,
1301+
function_id,
1302+
function_symbol.mode);
1303+
1304+
upper_offset_variable = upper_standin_symbol.symbol_expr();
1305+
1306+
// Add array temp to variable initialization block
1307+
init_block.add(goto_programt::make_decl(
1308+
upper_offset_variable, function_symbol.location));
1309+
init_block.add(goto_programt::make_assignment(
1310+
code_assignt(upper_offset_variable, upper_offset_object),
1311+
function_symbol.location));
1312+
}
1313+
else
1314+
{
1315+
exprt upper_constant_size =
1316+
get_size(array.type().subtype(), contract.ns, log);
12261317
upper_offset_object = typecast_exprt(
12271318
mult_exprt(
1228-
typecast_exprt(object_ptr, unsigned_long_int_type()), constant_size),
1319+
typecast_exprt(upper_operand, unsigned_long_int_type()),
1320+
upper_constant_size),
12291321
signed_int_type());
12301322

12311323
// Declare a new symbol to stand in for the reference
@@ -1267,7 +1359,7 @@ assigns_clause_array_targett::havoc_code(source_locationt location) const
12671359
exprt array_type_size =
12681360
get_size(pointer_object.type().subtype(), contract.ns, log);
12691361

1270-
for(mp_integer i = lower_bound; i < upper_bound; ++i)
1362+
for(mp_integer i = lower_bound; i <= upper_bound; ++i)
12711363
{
12721364
irep_idt offset_string(from_integer(i, integer_typet()).get_value());
12731365
irep_idt offset_irep(offset_string);
@@ -1360,7 +1452,7 @@ assigns_clauset::~assigns_clauset()
13601452

13611453
assigns_clause_targett *assigns_clauset::add_target(exprt current_operation)
13621454
{
1363-
if(current_operation.id() == ID_address_of)
1455+
if(current_operation.id() == ID_range)
13641456
{
13651457
assigns_clause_array_targett *array_target =
13661458
new assigns_clause_array_targett(

0 commit comments

Comments
 (0)