@@ -11,6 +11,7 @@ Date: February 2016
11
11
// / \file
12
12
// / Verify and use annotated invariants and pre/post-conditions
13
13
14
+ #include " contracts_assigns.h"
14
15
#include " contracts_memory_predicates.h"
15
16
16
17
#include < algorithm>
@@ -24,15 +25,13 @@ Date: February 2016
24
25
25
26
#include < goto-programs/remove_skip.h>
26
27
27
- #include < util/arith_tools.h>
28
28
#include < util/c_types.h>
29
29
#include < util/expr_util.h>
30
30
#include < util/fresh_symbol.h>
31
31
#include < util/mathematical_expr.h>
32
32
#include < util/mathematical_types.h>
33
33
#include < util/message.h>
34
34
#include < util/pointer_offset_size.h>
35
- #include < util/pointer_predicates.h>
36
35
#include < util/replace_symbol.h>
37
36
38
37
exprt get_size (const typet &type, const namespacet &ns, messaget &log)
@@ -163,8 +162,8 @@ void code_contractst::check_apply_loop_contracts(
163
162
164
163
// Generate: an assignment to store the decreases clause's value before the
165
164
// loop
166
- code_assignt old_decreases_assignment{old_decreases_symbol,
167
- decreases_clause};
165
+ code_assignt old_decreases_assignment{
166
+ old_decreases_symbol, decreases_clause};
168
167
old_decreases_assignment.add_source_location () = loop_head->source_location ;
169
168
converter.goto_convert (old_decreases_assignment, havoc_code, mode);
170
169
}
@@ -201,8 +200,8 @@ void code_contractst::check_apply_loop_contracts(
201
200
202
201
// Generate: an assignment to store the decreases clause's value after one
203
202
// iteration of the loop
204
- code_assignt new_decreases_assignment{new_decreases_symbol,
205
- decreases_clause};
203
+ code_assignt new_decreases_assignment{
204
+ new_decreases_symbol, decreases_clause};
206
205
new_decreases_assignment.add_source_location () = loop_head->source_location ;
207
206
converter.goto_convert (new_decreases_assignment, havoc_code, mode);
208
207
@@ -1258,317 +1257,4 @@ bool code_contractst::enforce_contracts(
1258
1257
fail = enforce_contract (fun);
1259
1258
}
1260
1259
return fail;
1261
- }
1262
-
1263
- assigns_clause_targett::assigns_clause_targett (
1264
- const exprt &object_ptr,
1265
- code_contractst &contract,
1266
- messaget &log_parameter,
1267
- const irep_idt &function_id)
1268
- : pointer_object(pointer_for(object_ptr)),
1269
- contract(contract),
1270
- init_block(),
1271
- log(log_parameter),
1272
- local_target(typet())
1273
- {
1274
- INVARIANT (
1275
- pointer_object.type ().id () == ID_pointer,
1276
- " Assigns clause targets should be stored as pointer expressions." );
1277
-
1278
- const symbolt &function_symbol = contract.ns .lookup (function_id);
1279
-
1280
- // Declare a new symbol to stand in for the reference
1281
- symbolt standin_symbol = contract.new_tmp_symbol (
1282
- pointer_object.type (),
1283
- function_symbol.location ,
1284
- function_id,
1285
- function_symbol.mode );
1286
-
1287
- local_target = standin_symbol.symbol_expr ();
1288
-
1289
- // Build standin variable initialization block
1290
- init_block.add (
1291
- goto_programt::make_decl (local_target, function_symbol.location ));
1292
- init_block.add (goto_programt::make_assignment (
1293
- code_assignt (local_target, pointer_object), function_symbol.location ));
1294
- }
1295
-
1296
- assigns_clause_targett::~assigns_clause_targett ()
1297
- {
1298
- }
1299
-
1300
- std::vector<symbol_exprt> assigns_clause_targett::temporary_declarations () const
1301
- {
1302
- std::vector<symbol_exprt> result;
1303
- result.push_back (local_target);
1304
- return result;
1305
- }
1306
-
1307
- exprt assigns_clause_targett::alias_expression (const exprt &ptr)
1308
- {
1309
- return same_object (ptr, local_target);
1310
- }
1311
-
1312
- exprt assigns_clause_targett::compatible_expression (
1313
- const assigns_clause_targett &called_target)
1314
- {
1315
- return alias_expression (called_target.get_direct_pointer ());
1316
- }
1317
-
1318
- goto_programt
1319
- assigns_clause_targett::havoc_code (source_locationt location) const
1320
- {
1321
- goto_programt assigns_havoc;
1322
-
1323
- exprt lhs = dereference_exprt (pointer_object);
1324
- side_effect_expr_nondett rhs (lhs.type (), location);
1325
-
1326
- goto_programt::targett target =
1327
- assigns_havoc.add (goto_programt::make_assignment (
1328
- code_assignt (std::move (lhs), std::move (rhs)), location));
1329
- target->code_nonconst ().add_source_location () = location;
1330
-
1331
- return assigns_havoc;
1332
- }
1333
-
1334
- const exprt &assigns_clause_targett::get_direct_pointer () const
1335
- {
1336
- return pointer_object;
1337
- }
1338
-
1339
- goto_programt &assigns_clause_targett::get_init_block ()
1340
- {
1341
- return init_block;
1342
- }
1343
-
1344
- assigns_clauset::assigns_clauset (
1345
- const exprt &assigns,
1346
- code_contractst &contract,
1347
- const irep_idt function_id,
1348
- messaget log_parameter)
1349
- : assigns_expr(assigns),
1350
- parent(contract),
1351
- function_id(function_id),
1352
- log(log_parameter)
1353
- {
1354
- for (exprt current_operation : assigns_expr.operands ())
1355
- {
1356
- add_target (current_operation);
1357
- }
1358
- }
1359
-
1360
- assigns_clauset::~assigns_clauset ()
1361
- {
1362
- for (assigns_clause_targett *target : targets)
1363
- {
1364
- delete target;
1365
- }
1366
- }
1367
-
1368
- assigns_clause_targett *assigns_clauset::add_target (exprt current_operation)
1369
- {
1370
- assigns_clause_targett *target = new assigns_clause_targett (
1371
- (current_operation.id () == ID_address_of)
1372
- ? to_index_expr (to_address_of_expr (current_operation).object ()).array ()
1373
- : current_operation,
1374
- parent,
1375
- log ,
1376
- function_id);
1377
- targets.push_back (target);
1378
- return target;
1379
- }
1380
-
1381
- assigns_clause_targett *
1382
- assigns_clauset::add_pointer_target (exprt current_operation)
1383
- {
1384
- return add_target (dereference_exprt (current_operation));
1385
- }
1386
-
1387
- goto_programt assigns_clauset::init_block (source_locationt location)
1388
- {
1389
- goto_programt result;
1390
- for (assigns_clause_targett *target : targets)
1391
- {
1392
- for (goto_programt::instructiont inst :
1393
- target->get_init_block ().instructions )
1394
- {
1395
- result.add (goto_programt::instructiont (inst));
1396
- }
1397
- }
1398
- return result;
1399
- }
1400
-
1401
- goto_programt &assigns_clauset::temporary_declarations (
1402
- source_locationt location,
1403
- irep_idt function_name,
1404
- irep_idt language_mode)
1405
- {
1406
- if (standin_declarations.empty ())
1407
- {
1408
- for (assigns_clause_targett *target : targets)
1409
- {
1410
- for (symbol_exprt symbol : target->temporary_declarations ())
1411
- {
1412
- standin_declarations.add (
1413
- goto_programt::make_decl (symbol, symbol.source_location ()));
1414
- }
1415
- }
1416
- }
1417
- return standin_declarations;
1418
- }
1419
-
1420
- goto_programt assigns_clauset::dead_stmts (
1421
- source_locationt location,
1422
- irep_idt function_name,
1423
- irep_idt language_mode)
1424
- {
1425
- goto_programt dead_statements;
1426
- for (assigns_clause_targett *target : targets)
1427
- {
1428
- for (symbol_exprt symbol : target->temporary_declarations ())
1429
- {
1430
- dead_statements.add (
1431
- goto_programt::make_dead (symbol, symbol.source_location ()));
1432
- }
1433
- }
1434
- return dead_statements;
1435
- }
1436
-
1437
- goto_programt assigns_clauset::havoc_code (
1438
- source_locationt location,
1439
- irep_idt function_name,
1440
- irep_idt language_mode)
1441
- {
1442
- goto_programt havoc_statements;
1443
- for (assigns_clause_targett *target : targets)
1444
- {
1445
- // (1) If the assigned target is not a dereference,
1446
- // only include the havoc_statement
1447
-
1448
- // (2) If the assigned target is a dereference, do the following:
1449
-
1450
- // if(!__CPROVER_w_ok(target, 0)) goto z;
1451
- // havoc_statements
1452
- // z: skip
1453
-
1454
- // create the z label
1455
- goto_programt tmp_z;
1456
- goto_programt::targett z = tmp_z.add (goto_programt::make_skip (location));
1457
-
1458
- const auto &target_ptr = target->get_direct_pointer ();
1459
-
1460
- if (to_address_of_expr (target_ptr).object ().id () == ID_dereference)
1461
- {
1462
- // create the condition
1463
- exprt condition =
1464
- not_exprt (w_ok_exprt (target_ptr, from_integer (0 , unsigned_int_type ())));
1465
- havoc_statements.add (goto_programt::make_goto (z, condition, location));
1466
- }
1467
-
1468
- // create havoc_statements
1469
- for (goto_programt::instructiont instruction :
1470
- target->havoc_code (location).instructions )
1471
- {
1472
- havoc_statements.add (std::move (instruction));
1473
- }
1474
-
1475
- if (to_address_of_expr (target_ptr).object ().id () == ID_dereference)
1476
- {
1477
- // add the z label instruction
1478
- havoc_statements.destructive_append (tmp_z);
1479
- }
1480
- }
1481
- return havoc_statements;
1482
- }
1483
-
1484
- exprt assigns_clauset::alias_expression (const exprt &lhs)
1485
- {
1486
- if (targets.empty ())
1487
- {
1488
- return false_exprt ();
1489
- }
1490
-
1491
- exprt left_ptr = assigns_clause_targett::pointer_for (lhs);
1492
-
1493
- bool first_iter = true ;
1494
- exprt result = false_exprt ();
1495
- for (assigns_clause_targett *target : targets)
1496
- {
1497
- if (first_iter)
1498
- {
1499
- result = target->alias_expression (left_ptr);
1500
- first_iter = false ;
1501
- }
1502
- else
1503
- {
1504
- result = or_exprt (result, target->alias_expression (left_ptr));
1505
- }
1506
- }
1507
- return result;
1508
- }
1509
-
1510
- exprt assigns_clauset::compatible_expression (
1511
- const assigns_clauset &called_assigns)
1512
- {
1513
- if (called_assigns.targets .empty ())
1514
- {
1515
- return true_exprt ();
1516
- }
1517
-
1518
- bool first_clause = true ;
1519
- exprt result = true_exprt ();
1520
- for (assigns_clause_targett *called_target : called_assigns.targets )
1521
- {
1522
- bool first_iter = true ;
1523
- exprt current_target_compatible = false_exprt ();
1524
- for (assigns_clause_targett *target : targets)
1525
- {
1526
- if (first_iter)
1527
- {
1528
- // TODO: Optimize the validation below and remove code duplication
1529
- // See GitHub issue #6105 for further details
1530
-
1531
- // Validating the called target through __CPROVER_w_ok() is
1532
- // only useful when the called target is a dereference
1533
- const auto &called_target_ptr = called_target->get_direct_pointer ();
1534
- if (
1535
- to_address_of_expr (called_target_ptr).object ().id () == ID_dereference)
1536
- {
1537
- // or_exprt is short-circuited, therefore
1538
- // target->compatible_expression(*called_target) would not be
1539
- // checked on invalid called_targets.
1540
- current_target_compatible = or_exprt (
1541
- not_exprt (w_ok_exprt (
1542
- called_target_ptr, from_integer (0 , unsigned_int_type ()))),
1543
- target->compatible_expression (*called_target));
1544
- }
1545
- else
1546
- {
1547
- current_target_compatible =
1548
- target->compatible_expression (*called_target);
1549
- }
1550
- first_iter = false ;
1551
- }
1552
- else
1553
- {
1554
- current_target_compatible = or_exprt (
1555
- current_target_compatible,
1556
- target->compatible_expression (*called_target));
1557
- }
1558
- }
1559
- if (first_clause)
1560
- {
1561
- result = current_target_compatible;
1562
- first_clause = false ;
1563
- }
1564
- else
1565
- {
1566
- exprt::operandst conjuncts;
1567
- conjuncts.push_back (result);
1568
- conjuncts.push_back (current_target_compatible);
1569
- result = conjunction (conjuncts);
1570
- }
1571
- }
1572
-
1573
- return result;
1574
1260
}
0 commit comments