Skip to content

Commit fc4df55

Browse files
author
Remi Delmas
committed
CONTRACTS: avoid circular dependency between classes
Do not instrument code in `dfcc_spec_functionst` but rather one layer above in `dfcc_contract_functionst`. This allows to avoid creating a circular depedency on `dfcc_instrumentt` later.
1 parent 9e14d8a commit fc4df55

File tree

4 files changed

+53
-42
lines changed

4 files changed

+53
-42
lines changed

src/goto-instrument/contracts/dynamic-frames/dfcc_contract_functions.cpp

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ Date: August 2022
2323
#include <langapi/language_util.h>
2424

2525
#include "dfcc_contract_clauses_codegen.h"
26+
#include "dfcc_instrument.h"
2627
#include "dfcc_library.h"
2728
#include "dfcc_spec_functions.h"
2829
#include "dfcc_utils.h"
@@ -34,7 +35,8 @@ dfcc_contract_functionst::dfcc_contract_functionst(
3435
dfcc_utilst &utils,
3536
dfcc_libraryt &library,
3637
dfcc_spec_functionst &spec_functions,
37-
dfcc_contract_clauses_codegent &contract_clauses_codegen)
38+
dfcc_contract_clauses_codegent &contract_clauses_codegen,
39+
dfcc_instrumentt &instrument)
3840
: pure_contract_symbol(pure_contract_symbol),
3941
code_with_contract(to_code_with_contract_type(pure_contract_symbol.type)),
4042
spec_assigns_function_id(
@@ -50,6 +52,7 @@ dfcc_contract_functionst::dfcc_contract_functionst(
5052
library(library),
5153
spec_functions(spec_functions),
5254
contract_clauses_codegen(contract_clauses_codegen),
55+
instrument(instrument),
5356
ns(goto_model.symbol_table)
5457
{
5558
gen_spec_assigns_function();
@@ -66,6 +69,28 @@ dfcc_contract_functionst::dfcc_contract_functionst(
6669

6770
spec_functions.to_spec_frees_function(
6871
spec_frees_function_id, nof_frees_targets);
72+
73+
instrument_without_loop_contracts_check_no_pointer_contracts(
74+
spec_assigns_function_id);
75+
76+
instrument_without_loop_contracts_check_no_pointer_contracts(
77+
spec_frees_function_id);
78+
}
79+
80+
void dfcc_contract_functionst::
81+
instrument_without_loop_contracts_check_no_pointer_contracts(
82+
const irep_idt &spec_function_id)
83+
{
84+
std::set<irep_idt> function_pointer_contracts;
85+
instrument.instrument_function(
86+
spec_function_id,
87+
dfcc_loop_contract_modet::NONE,
88+
function_pointer_contracts);
89+
90+
INVARIANT(
91+
function_pointer_contracts.empty(),
92+
id2string(spec_function_id) + " shall not contain calls to " CPROVER_PREFIX
93+
"obeys_contract");
6994
}
7095

7196
const symbolt &

src/goto-instrument/contracts/dynamic-frames/dfcc_contract_functions.h

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,31 +29,34 @@ class goto_modelt;
2929
class message_handlert;
3030
class dfcc_libraryt;
3131
class dfcc_utilst;
32+
class dfcc_instrumentt;
3233
class dfcc_spec_functionst;
3334
class dfcc_contract_clauses_codegent;
3435
class code_with_contract_typet;
3536
class conditional_target_group_exprt;
3637

3738
/// Generates GOTO functions modelling a contract assigns and frees clauses.
3839
///
39-
/// The generated functions are the following.
40+
/// The generated functions are the following:
4041
///
41-
/// Populates write_set_to_fill with targets of the assigns clause
42-
/// checks its own body against write_set_to_check:
4342
/// ```c
43+
/// // Populates write_set_to_fill with targets of the assigns clause
44+
/// // checks its own body against write_set_to_check:
4445
/// void contract_id::assigns(
4546
/// function-params,
4647
/// write_set_to_fill,
4748
/// write_set_to_check);
4849
/// ```
49-
/// Havocs the targets specified in the assigns clause, assuming
50-
/// write_set_to_havoc is a snapshot created using contract_id::assigns:
50+
///
5151
/// ```c
52+
/// // Havocs the targets specified in the assigns clause, assuming
53+
/// // write_set_to_havoc is a snapshot created using contract_id::assigns
5254
/// void contract_id::assigns::havoc(write_set_to_havoc);
5355
/// ```
54-
/// Populates write_set_to_fill with targets of the frees clause
55-
/// checks its own body against write_set_to_check:
56+
///
5657
/// ```c
58+
/// // Populates write_set_to_fill with targets of the frees clause
59+
/// // checks its own body against write_set_to_check:
5760
/// void contract_id::frees(
5861
/// function-params,
5962
/// write_set_to_fill,
@@ -70,14 +73,21 @@ class dfcc_contract_functionst
7073
/// \param spec_functions provides translation methods for assignable set
7174
/// \param contract_clauses_codegen provides GOTO code generation methods
7275
/// for assigns and free clauses.
76+
/// \param instrument Used to instrument generated functions for side effects
7377
dfcc_contract_functionst(
7478
const symbolt &pure_contract_symbol,
7579
goto_modelt &goto_model,
7680
message_handlert &message_handler,
7781
dfcc_utilst &utils,
7882
dfcc_libraryt &library,
7983
dfcc_spec_functionst &spec_functions,
80-
dfcc_contract_clauses_codegent &contract_clauses_codegen);
84+
dfcc_contract_clauses_codegent &contract_clauses_codegen,
85+
dfcc_instrumentt &instrument);
86+
87+
/// Instruments the given function without loop contracts and checks that no
88+
/// function pointer contracts were discovered.
89+
void instrument_without_loop_contracts_check_no_pointer_contracts(
90+
const irep_idt &spec_function_id);
8191

8292
/// Returns the contract::assigns function symbol
8393
const symbolt &get_spec_assigns_function_symbol() const;
@@ -120,6 +130,7 @@ class dfcc_contract_functionst
120130
dfcc_libraryt &library;
121131
dfcc_spec_functionst &spec_functions;
122132
dfcc_contract_clauses_codegent &contract_clauses_codegen;
133+
dfcc_instrumentt &instrument;
123134
namespacet ns;
124135
std::size_t nof_assigns_targets;
125136
std::size_t nof_frees_targets;

src/goto-instrument/contracts/dynamic-frames/dfcc_spec_functions.cpp

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,19 @@ Author: Remi Delmas, [email protected]
1717
#include <langapi/language_util.h>
1818

1919
#include "dfcc_library.h"
20+
#include "dfcc_loop_contract_mode.h"
2021
#include "dfcc_utils.h"
2122

2223
dfcc_spec_functionst::dfcc_spec_functionst(
2324
goto_modelt &goto_model,
2425
message_handlert &message_handler,
2526
dfcc_utilst &utils,
26-
dfcc_libraryt &library,
27-
dfcc_instrumentt &instrument)
27+
dfcc_libraryt &library)
2828
: goto_model(goto_model),
2929
message_handler(message_handler),
3030
log(message_handler),
3131
utils(utils),
3232
library(library),
33-
instrument(instrument),
3433
ns(goto_model.symbol_table)
3534
{
3635
}
@@ -111,6 +110,8 @@ void dfcc_spec_functionst::generate_havoc_function(
111110
havoc_program,
112111
nof_targets);
113112

113+
havoc_program.add(goto_programt::make_end_function());
114+
114115
goto_model.goto_functions.update();
115116

116117
std::set<irep_idt> no_body;
@@ -246,7 +247,6 @@ void dfcc_spec_functionst::generate_havoc_instructions(
246247
}
247248
}
248249
nof_targets = next_idx;
249-
havoc_program.add(goto_programt::make_end_function());
250250
}
251251

252252
void dfcc_spec_functionst::to_spec_assigns_function(
@@ -272,13 +272,6 @@ void dfcc_spec_functionst::to_spec_assigns_function(
272272

273273
goto_model.goto_functions.update();
274274

275-
// instrument for side-effects checking
276-
std::set<irep_idt> function_pointer_contracts;
277-
instrument.instrument_function(function_id, function_pointer_contracts);
278-
INVARIANT(
279-
function_pointer_contracts.empty(),
280-
"discovered function pointer contracts unexpectedly");
281-
282275
goto_model.goto_functions.function_map.at(function_id).make_hidden();
283276
}
284277

@@ -362,13 +355,6 @@ void dfcc_spec_functionst::to_spec_frees_function(
362355

363356
goto_model.goto_functions.update();
364357

365-
// instrument for side-effects checking
366-
std::set<irep_idt> function_pointer_contracts;
367-
instrument.instrument_function(function_id, function_pointer_contracts);
368-
INVARIANT(
369-
function_pointer_contracts.empty(),
370-
"discovered function pointer contracts unexpectedly");
371-
372358
goto_model.goto_functions.function_map.at(function_id).make_hidden();
373359
}
374360

src/goto-instrument/contracts/dynamic-frames/dfcc_spec_functions.h

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ Author: Remi Delmas, [email protected]
2121
#include <util/std_expr.h>
2222
#include <util/std_types.h>
2323

24-
#include "dfcc_instrument.h"
2524
#include "dfcc_library.h"
2625
#include "dfcc_utils.h"
2726

@@ -32,28 +31,23 @@ class goto_modelt;
3231
class message_handlert;
3332
class symbolt;
3433
class conditional_target_group_exprt;
35-
class cfg_infot;
3634

37-
/// This class transforms (in place) declarative assigns clause and frees clause
38-
/// specification functions expressed in terms of the builtins:
35+
/// This class rewrites GOTO functions that use the built-ins:
3936
/// - `__CPROVER_assignable`,
4037
/// - `__CPROVER_object_whole`,
4138
/// - `__CRPOVER_object_from`,
4239
/// - `__CPROVER_object_upto`,
4340
/// - `__CPROVER_freeable`
44-
/// into active functions by transforming the builtin calls into calls to
45-
/// dfcc library functions that actually built frame descriptions.
46-
/// The resulting function is then itself instrumented for frame condition
47-
/// checking to be able to prove the absence of side effects.
41+
/// into GOTO functions that populate a write set instance or havoc a write set
42+
/// by calling the library implementation of these built-ins.
4843
class dfcc_spec_functionst
4944
{
5045
public:
5146
dfcc_spec_functionst(
5247
goto_modelt &goto_model,
5348
message_handlert &message_handler,
5449
dfcc_utilst &utils,
55-
dfcc_libraryt &library,
56-
dfcc_instrumentt &instrument);
50+
dfcc_libraryt &library);
5751

5852
/// From a function:
5953
///
@@ -122,13 +116,11 @@ class dfcc_spec_functionst
122116
/// void function_id(
123117
/// params,
124118
/// __CPROVER_assignable_set_t write_set_to_fill,
125-
/// __CPROVER_assignable_set_t write_set_to_check
126119
/// )
127120
/// ```
128121
///
129122
/// Where:
130123
/// - `write_set_to_fill` is the write set to populate.
131-
/// - `write_set_to_check` is the write set to use for checking side effects.
132124
///
133125
/// \param function_id function to transform in place
134126
/// \param nof_targets receives the estimated size of the write set
@@ -174,13 +166,11 @@ class dfcc_spec_functionst
174166
/// void function_id(
175167
/// params,
176168
/// __CPROVER_assignable_set_t write_set_to_fill,
177-
/// __CPROVER_assignable_set_t write_set_to_check
178169
/// )
179170
/// ```
180171
///
181172
/// Where:
182173
/// - `write_set_to_fill` is the write set to populate.
183-
/// - `write_set_to_check` is the write set to use for checking side effects.
184174
///
185175
/// The function must be fully inlined and loop free.
186176
///
@@ -219,7 +209,6 @@ class dfcc_spec_functionst
219209
messaget log;
220210
dfcc_utilst &utils;
221211
dfcc_libraryt &library;
222-
dfcc_instrumentt &instrument;
223212
namespacet ns;
224213

225214
/// Extracts the type of an assigns clause target expression

0 commit comments

Comments
 (0)