Skip to content

Commit c2a5d79

Browse files
committed
Adds a assigns clause module in contracts
Signed-off-by: Felipe R. Monteiro <[email protected]>
1 parent e8777aa commit c2a5d79

File tree

7 files changed

+430
-393
lines changed

7 files changed

+430
-393
lines changed

src/goto-instrument/Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,9 @@ SRC = accelerate/accelerate.cpp \
1616
alignment_checks.cpp \
1717
branch.cpp \
1818
call_sequences.cpp \
19-
code_contracts.cpp \
19+
contracts_assigns.cpp \
2020
contracts_memory_predicates.cpp \
21+
contracts.cpp \
2122
concurrency.cpp \
2223
count_eloc.cpp \
2324
cover.cpp \

src/goto-instrument/code_contracts.cpp renamed to src/goto-instrument/contracts.cpp

Lines changed: 5 additions & 319 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ Date: February 2016
1111
/// \file
1212
/// Verify and use annotated invariants and pre/post-conditions
1313

14+
#include "contracts_assigns.h"
1415
#include "contracts_memory_predicates.h"
1516

1617
#include <algorithm>
@@ -24,15 +25,13 @@ Date: February 2016
2425

2526
#include <goto-programs/remove_skip.h>
2627

27-
#include <util/arith_tools.h>
2828
#include <util/c_types.h>
2929
#include <util/expr_util.h>
3030
#include <util/fresh_symbol.h>
3131
#include <util/mathematical_expr.h>
3232
#include <util/mathematical_types.h>
3333
#include <util/message.h>
3434
#include <util/pointer_offset_size.h>
35-
#include <util/pointer_predicates.h>
3635
#include <util/replace_symbol.h>
3736

3837
exprt get_size(const typet &type, const namespacet &ns, messaget &log)
@@ -163,8 +162,8 @@ void code_contractst::check_apply_loop_contracts(
163162

164163
// Generate: an assignment to store the decreases clause's value before the
165164
// 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};
168167
old_decreases_assignment.add_source_location() = loop_head->source_location;
169168
converter.goto_convert(old_decreases_assignment, havoc_code, mode);
170169
}
@@ -201,8 +200,8 @@ void code_contractst::check_apply_loop_contracts(
201200

202201
// Generate: an assignment to store the decreases clause's value after one
203202
// 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};
206205
new_decreases_assignment.add_source_location() = loop_head->source_location;
207206
converter.goto_convert(new_decreases_assignment, havoc_code, mode);
208207

@@ -1258,317 +1257,4 @@ bool code_contractst::enforce_contracts(
12581257
fail = enforce_contract(fun);
12591258
}
12601259
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;
15741260
}

0 commit comments

Comments
 (0)