Skip to content

Commit 0b0d8dd

Browse files
committed
contract symbol changes
1 parent 34af14b commit 0b0d8dd

File tree

5 files changed

+71
-28
lines changed

5 files changed

+71
-28
lines changed

regression/cprover/function_calls/function_pointer1.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
CORE
1+
KNOWNBUG
22
function_pointer1.c
33
--safety
44
^EXIT=10$

regression/cprover/function_pointers/malloc_wrapper.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
CORE
1+
KNOWNBUG
22
malloc_wrapper.c
33

44
^EXIT=0$

src/cprover/instrument_contracts.cpp

Lines changed: 58 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ Author: Daniel Kroening, [email protected]
1313

1414
#include <util/c_types.h>
1515
#include <util/format_expr.h>
16+
#include <util/mathematical_expr.h>
1617
#include <util/pointer_predicates.h>
1718
#include <util/prefix.h>
1819
#include <util/replace_symbol.h>
@@ -26,6 +27,23 @@ Author: Daniel Kroening, [email protected]
2627

2728
#define MAX_TEXT 20
2829

30+
optionalt<code_with_contract_typet>
31+
get_contract(const irep_idt &function_identifier, const namespacet &ns)
32+
{
33+
// contracts are in a separate symbol, with prefix "contract::"
34+
auto contract_identifier = "contract::" + id2string(function_identifier);
35+
const symbolt *symbol_ptr;
36+
if(ns.lookup(contract_identifier, symbol_ptr))
37+
return {}; // symbol not found
38+
else
39+
return to_code_with_contract_type(symbol_ptr->type);
40+
}
41+
42+
bool has_contract(const irep_idt &function_identifier, const namespacet &ns)
43+
{
44+
return get_contract(function_identifier, ns).has_value();
45+
}
46+
2947
static std::string expr2text(const exprt &src, const namespacet &ns)
3048
{
3149
auto text = expr2c(src, ns);
@@ -120,15 +138,22 @@ exprt assigns_match(const exprt &assigns, const exprt &lhs)
120138
}
121139
}
122140

141+
static exprt instantiate_contract_lambda(exprt src)
142+
{
143+
return src.id() == ID_lambda ? to_lambda_expr(src).where() : src;
144+
}
145+
123146
static exprt make_assigns_assertion(
124147
irep_idt function_identifier,
125148
const exprt::operandst &assigns,
126149
const exprt &lhs)
127150
{
128151
exprt::operandst disjuncts;
129152

130-
for(auto &a : assigns)
153+
for(auto &assigns_clause : assigns)
131154
{
155+
auto a = instantiate_contract_lambda(assigns_clause);
156+
132157
if(a.id() == ID_conditional_target_group)
133158
{
134159
auto &condition = to_binary_expr(a).op0();
@@ -247,8 +272,14 @@ void instrument_contract_checks(
247272
goto_functionst::function_mapt::value_type &f,
248273
const namespacet &ns)
249274
{
250-
auto &symbol = ns.lookup(f.first);
251-
auto &contract = to_code_with_contract_type(symbol.type);
275+
// contracts are in a separate symbol, with prefix "contract::"
276+
auto contract_identifier = "contract::" + id2string(f.first);
277+
const symbolt *symbol_ptr;
278+
if(ns.lookup(contract_identifier, symbol_ptr))
279+
return; // nothing to check
280+
281+
auto &contract = to_code_with_contract_type(symbol_ptr->type);
282+
252283
auto &body = f.second.body;
253284

254285
if(body.instructions.empty())
@@ -264,7 +295,8 @@ void instrument_contract_checks(
264295
goto_programt dest;
265296
for(auto &assumption : contract.requires())
266297
{
267-
auto fixed_assumption = add_function(f.first, assumption);
298+
exprt assumption_instance = instantiate_contract_lambda(assumption);
299+
auto fixed_assumption = add_function(f.first, assumption_instance);
268300
add_at_beginning.add(goto_programt::make_assumption(
269301
fixed_assumption, fixed_assumption.source_location()));
270302
}
@@ -284,16 +316,19 @@ void instrument_contract_checks(
284316

285317
for(auto &assertion : contract.ensures())
286318
{
319+
exprt assertion_instance = instantiate_contract_lambda(assertion);
320+
287321
std::string comment = "postcondition";
288322
if(contract.ensures().size() >= 2)
289-
comment += " " + expr2text(assertion, ns);
323+
comment += " " + expr2text(assertion_instance, ns);
290324

291325
auto location = assertion.source_location();
292326
location.set_function(f.first); // seems to be missing
293327
location.set_property_class(ID_postcondition);
294328
location.set_comment(comment);
295329

296-
auto replaced_assertion = replace_old(assertion, old_prefix, old_exprs);
330+
auto replaced_assertion =
331+
replace_old(assertion_instance, old_prefix, old_exprs);
297332

298333
auto fixed_assertion = add_function(f.first, replaced_assertion);
299334

@@ -319,7 +354,7 @@ void instrument_contract_checks(
319354
// Add assignments to 'old' symbols at the beginning of the function.
320355
{
321356
auto tmp =
322-
old_assignments(old_exprs, add_function(f.first, symbol.location));
357+
old_assignments(old_exprs, add_function(f.first, symbol_ptr->location));
323358
add_at_beginning.destructive_append(tmp);
324359
}
325360

@@ -377,14 +412,12 @@ void replace_function_calls_by_contracts(
377412
{
378413
const auto &symbol = ns.lookup(to_symbol_expr(function));
379414

380-
auto &contract = to_code_with_contract_type(symbol.type);
415+
const auto contract_opt = get_contract(symbol.name, ns);
381416

382-
if(
383-
contract.requires().empty() && contract.ensures().empty() &&
384-
contract.assigns().empty())
385-
{
417+
if(!contract_opt.has_value())
386418
continue;
387-
}
419+
420+
auto &contract = contract_opt.value();
388421

389422
// record "old(...)" expressions.
390423
std::vector<std::pair<symbol_exprt, exprt>> old_exprs;
@@ -394,6 +427,7 @@ void replace_function_calls_by_contracts(
394427
// need to substitute parameters
395428
const auto f_it =
396429
goto_model.goto_functions.function_map.find(symbol.name);
430+
397431
if(f_it == goto_model.goto_functions.function_map.end())
398432
DATA_INVARIANT(false, "failed to find function in function_map");
399433

@@ -419,24 +453,30 @@ void replace_function_calls_by_contracts(
419453
// assert the preconditions
420454
for(auto &precondition : contract.requires())
421455
{
456+
auto instantiated_precondition =
457+
instantiate_contract_lambda(precondition);
458+
422459
auto location = it->source_location();
423460
location.set_property_class(ID_precondition);
424461
location.set_comment(
425462
id2string(symbol.display_name()) + " precondition " +
426-
expr2text(precondition, ns));
463+
expr2text(instantiated_precondition, ns));
427464

428-
auto replaced_precondition = precondition;
465+
auto replaced_precondition = instantiated_precondition;
429466
replace_symbol(replaced_precondition);
430467

431468
dest.add(
432469
goto_programt::make_assertion(replaced_precondition, location));
433470
}
434471

435472
// havoc the 'assigned' variables
436-
for(auto &assigns_clause : contract.assigns())
473+
for(auto &assigns_clause_lambda : contract.assigns())
437474
{
438475
auto location = it->source_location();
439476

477+
auto assigns_clause =
478+
instantiate_contract_lambda(assigns_clause_lambda);
479+
440480
if(assigns_clause.id() == ID_conditional_target_group)
441481
{
442482
const auto &condition = to_binary_expr(assigns_clause).op0();
@@ -486,7 +526,8 @@ void replace_function_calls_by_contracts(
486526
{
487527
auto &location = it->source_location();
488528

489-
auto replaced_postcondition1 = postcondition;
529+
auto replaced_postcondition1 =
530+
instantiate_contract_lambda(postcondition);
490531
replace_symbol(replaced_postcondition1);
491532

492533
auto replaced_postcondition2 =

src/cprover/instrument_contracts.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,16 @@ Author: Daniel Kroening, [email protected]
1212
#ifndef CPROVER_CPROVER_INSTRUMENT_CONTRACTS_H
1313
#define CPROVER_CPROVER_INSTRUMENT_CONTRACTS_H
1414

15+
#include <util/irep.h>
16+
#include <util/optional.h>
17+
18+
class code_with_contract_typet;
1519
class goto_modelt;
20+
class namespacet;
1621

1722
void instrument_contracts(goto_modelt &);
1823

24+
optionalt<code_with_contract_typet>
25+
get_contract(const irep_idt &function_identifier, const namespacet &);
26+
1927
#endif // CPROVER_CPOVER_INSTRUMENT_CONTRACTS_H

src/cprover/state_encoding.cpp

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ Module: State Encoding
2020
#include <goto-programs/goto_model.h>
2121

2222
#include "equality_propagation.h"
23+
#include "instrument_contracts.h"
2324
#include "sentinel_dll.h"
2425
#include "solver.h"
2526
#include "state.h"
@@ -633,12 +634,6 @@ static exprt simplifying_not(exprt src)
633634
return not_exprt(src);
634635
}
635636

636-
static bool has_contract(const code_with_contract_typet &contract)
637-
{
638-
return !contract.assigns().empty() || !contract.requires().empty() ||
639-
!contract.ensures().empty();
640-
}
641-
642637
symbol_exprt state_encodingt::va_args(irep_idt function)
643638
{
644639
return symbol_exprt(
@@ -1142,7 +1137,7 @@ void state_encoding(
11421137
throw invalid_command_line_argument_exceptiont(
11431138
"The given function was not found", "contract");
11441139

1145-
if(!has_contract(to_code_with_contract_type(symbol->type)))
1140+
if(!get_contract(*contract, ns).has_value())
11461141
throw invalid_command_line_argument_exceptiont(
11471142
"The given function has no contract", "contract");
11481143

@@ -1161,10 +1156,9 @@ void state_encoding(
11611156
bool found = false;
11621157
for(auto &f : sorted)
11631158
{
1164-
const auto &symbol = ns.lookup(f->first);
11651159
if(
11661160
f->first == goto_functionst::entry_point() ||
1167-
has_contract(to_code_with_contract_type(symbol.type)))
1161+
get_contract(f->first, ns).has_value())
11681162
{
11691163
dest.annotation("");
11701164
dest.annotation("function " + id2string(f->first));

0 commit comments

Comments
 (0)