Skip to content

Commit f28f7ba

Browse files
author
Remi Delmas
committed
CONTRACTS: Move code to utils
- Move havoc_assigns_clauset from contract/assigns to utils - Moving functions for tracking assigns clause replacement to utils to break circular dependency - Unified interface for adding "disable:check" pragmas on locations, instructions and programs
1 parent a61b669 commit f28f7ba

File tree

4 files changed

+141
-57
lines changed

4 files changed

+141
-57
lines changed

src/goto-instrument/contracts/havoc_assigns_clause_targets.cpp

Lines changed: 5 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,6 @@ Author: Remi Delmas, [email protected]
1313

1414
#include <map>
1515

16-
#include <langapi/language_util.h>
17-
18-
#include <ansi-c/c_expr.h>
19-
2016
#include <util/c_types.h>
2117
#include <util/format_expr.h>
2218
#include <util/format_type.h>
@@ -26,27 +22,12 @@ Author: Remi Delmas, [email protected]
2622
#include <util/pointer_predicates.h>
2723
#include <util/std_code.h>
2824

25+
#include <ansi-c/c_expr.h>
26+
#include <langapi/language_util.h>
27+
2928
#include "instrument_spec_assigns.h"
3029
#include "utils.h"
3130

32-
static const char ASSIGNS_CLAUSE_REPLACEMENT_TRACKING[] =
33-
" (assigned by the contract of ";
34-
35-
static irep_idt make_tracking_comment(
36-
const exprt &target,
37-
const irep_idt &function_id,
38-
const namespacet &ns)
39-
{
40-
return from_expr(ns, target.id(), target) +
41-
ASSIGNS_CLAUSE_REPLACEMENT_TRACKING + id2string(function_id) + ")";
42-
}
43-
44-
bool is_assigns_clause_replacement_tracking_comment(const irep_idt &comment)
45-
{
46-
return id2string(comment).find(ASSIGNS_CLAUSE_REPLACEMENT_TRACKING) !=
47-
std::string::npos;
48-
}
49-
5031
void havoc_assigns_clause_targetst::get_instructions(goto_programt &dest)
5132
{
5233
// snapshotting instructions and well-definedness checks
@@ -80,7 +61,8 @@ void havoc_assigns_clause_targetst::havoc_if_valid(
8061
goto_programt &dest)
8162
{
8263
const irep_idt &tracking_comment =
83-
make_tracking_comment(car.target(), function_id, ns);
64+
make_assigns_clause_replacement_tracking_comment(
65+
car.target(), function_id, ns);
8466

8567
source_locationt source_location_no_checks(source_location);
8668
add_pragma_disable_pointer_checks(source_location_no_checks);

src/goto-instrument/contracts/havoc_assigns_clause_targets.h

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,6 @@ class goto_programt;
2121
class goto_functionst;
2222
class message_handlert;
2323

24-
bool is_assigns_clause_replacement_tracking_comment(const irep_idt &comment);
25-
2624
/// Class to generate havocking instructions for target expressions of a
2725
/// function contract's assign clause (replacement).
2826
///
@@ -73,8 +71,11 @@ class havoc_assigns_clause_targetst : public instrument_spec_assignst
7371
void get_instructions(goto_programt &dest);
7472

7573
private:
76-
/// \brief Generates instructions to conditionally havoc
77-
/// the given `car_exprt`.
74+
/// \brief Generates instructions to conditionally havoc the given conditional
75+
/// address range expression `car`, adding results to `dest`.
76+
///
77+
/// Adds a special comment on the havoc instructions in order to trace back
78+
/// the origin of the havoc expressions to the function being replaced.
7879
///
7980
/// Generates these instructions for a `__CPROVER_POINTER_OBJECT(...)` target:
8081
///
@@ -91,14 +92,13 @@ class havoc_assigns_clause_targetst : public instrument_spec_assignst
9192
///
9293
/// ```
9394
/// IF !__car_writable GOTO skip_target
94-
/// ASSIGN * ((<target.type()> *)_car_lb) = nondet_<target.type()>;
95+
/// ASSIGN *((target_type *) _car_lb) = nondet(target_type);
9596
/// skip_target: SKIP
9697
/// DEAD __car_writable
9798
/// DEAD __car_lb
9899
/// DEAD __car_ub
99100
/// ```
100-
/// Adds a special comment on the havoc instructions in order to trace back
101-
/// the havoc to the replaced function.
101+
/// Where `target_type` is the type of the target expression.
102102
void havoc_if_valid(car_exprt car, goto_programt &dest);
103103

104104
const std::vector<exprt> &targets;

src/goto-instrument/contracts/utils.cpp

Lines changed: 78 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -11,27 +11,15 @@ Date: September 2021
1111
#include "utils.h"
1212

1313
#include <goto-programs/cfg.h>
14+
1415
#include <util/fresh_symbol.h>
1516
#include <util/graph.h>
1617
#include <util/message.h>
1718
#include <util/pointer_expr.h>
1819
#include <util/pointer_predicates.h>
1920
#include <util/simplify_expr.h>
2021

21-
goto_programt::instructiont &
22-
add_pragma_disable_assigns_check(goto_programt::instructiont &instr)
23-
{
24-
instr.source_location_nonconst().add_pragma(
25-
CONTRACT_PRAGMA_DISABLE_ASSIGNS_CHECK);
26-
return instr;
27-
}
28-
29-
goto_programt &add_pragma_disable_assigns_check(goto_programt &prog)
30-
{
31-
Forall_goto_program_instructions(it, prog)
32-
add_pragma_disable_assigns_check(*it);
33-
return prog;
34-
}
22+
#include <langapi/language_util.h>
3523

3624
static void append_safe_havoc_code_for_expr(
3725
const source_locationt location,
@@ -74,6 +62,63 @@ void havoc_if_validt::append_scalar_havoc_code_for_expr(
7462
});
7563
}
7664

65+
void havoc_assigns_targetst::append_havoc_code_for_expr(
66+
const source_locationt location,
67+
const exprt &expr,
68+
goto_programt &dest) const
69+
{
70+
if(expr.id() == ID_pointer_object)
71+
{
72+
append_object_havoc_code_for_expr(location, expr.operands().front(), dest);
73+
return;
74+
}
75+
76+
havoc_utilst::append_havoc_code_for_expr(location, expr, dest);
77+
}
78+
79+
void add_pragma_disable_pointer_checks(source_locationt &location)
80+
{
81+
location.add_pragma("disable:pointer-check");
82+
location.add_pragma("disable:pointer-primitive-check");
83+
location.add_pragma("disable:pointer-overflow-check");
84+
location.add_pragma("disable:signed-overflow-check");
85+
location.add_pragma("disable:unsigned-overflow-check");
86+
location.add_pragma("disable:conversion-check");
87+
}
88+
89+
goto_programt::instructiont &
90+
add_pragma_disable_pointer_checks(goto_programt::instructiont &instr)
91+
{
92+
add_pragma_disable_pointer_checks(instr.source_location_nonconst());
93+
return instr;
94+
}
95+
96+
goto_programt &add_pragma_disable_pointer_checks(goto_programt &prog)
97+
{
98+
Forall_goto_program_instructions(it, prog)
99+
add_pragma_disable_pointer_checks(*it);
100+
return prog;
101+
}
102+
103+
void add_pragma_disable_assigns_check(source_locationt &location)
104+
{
105+
location.add_pragma(CONTRACT_PRAGMA_DISABLE_ASSIGNS_CHECK);
106+
}
107+
108+
goto_programt::instructiont &
109+
add_pragma_disable_assigns_check(goto_programt::instructiont &instr)
110+
{
111+
add_pragma_disable_assigns_check(instr.source_location_nonconst());
112+
return instr;
113+
}
114+
115+
goto_programt &add_pragma_disable_assigns_check(goto_programt &prog)
116+
{
117+
Forall_goto_program_instructions(it, prog)
118+
add_pragma_disable_assigns_check(*it);
119+
return prog;
120+
}
121+
77122
exprt all_dereferences_are_valid(const exprt &expr, const namespacet &ns)
78123
{
79124
exprt::operandst validity_checks;
@@ -156,16 +201,6 @@ const symbolt &new_tmp_symbol(
156201
return new_symbol;
157202
}
158203

159-
void disable_pointer_checks(source_locationt &source_location)
160-
{
161-
source_location.add_pragma("disable:pointer-check");
162-
source_location.add_pragma("disable:pointer-primitive-check");
163-
source_location.add_pragma("disable:pointer-overflow-check");
164-
source_location.add_pragma("disable:signed-overflow-check");
165-
source_location.add_pragma("disable:unsigned-overflow-check");
166-
source_location.add_pragma("disable:conversion-check");
167-
}
168-
169204
void simplify_gotos(goto_programt &goto_program, namespacet &ns)
170205
{
171206
for(auto &instruction : goto_program.instructions)
@@ -226,3 +261,22 @@ bool is_loop_free(
226261
}
227262
return true;
228263
}
264+
265+
/// Prefix for comments added to track assigns clause replacement.
266+
static const char ASSIGNS_CLAUSE_REPLACEMENT_TRACKING[] =
267+
" (assigned by the contract of ";
268+
269+
irep_idt make_assigns_clause_replacement_tracking_comment(
270+
const exprt &target,
271+
const irep_idt &function_id,
272+
const namespacet &ns)
273+
{
274+
return from_expr(ns, target.id(), target) +
275+
ASSIGNS_CLAUSE_REPLACEMENT_TRACKING + id2string(function_id) + ")";
276+
}
277+
278+
bool is_assigns_clause_replacement_tracking_comment(const irep_idt &comment)
279+
{
280+
return id2string(comment).find(ASSIGNS_CLAUSE_REPLACEMENT_TRACKING) !=
281+
std::string::npos;
282+
}

src/goto-instrument/contracts/utils.h

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,46 @@ class havoc_if_validt : public havoc_utilst
5151
const namespacet &ns;
5252
};
5353

54+
/// \brief A class that further overrides the "safe" havoc utilities,
55+
/// and adds support for havocing pointer_object expressions.
56+
class havoc_assigns_targetst : public havoc_if_validt
57+
{
58+
public:
59+
havoc_assigns_targetst(const assignst &mod, const namespacet &ns)
60+
: havoc_if_validt(mod, ns)
61+
{
62+
}
63+
64+
void append_havoc_code_for_expr(
65+
const source_locationt location,
66+
const exprt &expr,
67+
goto_programt &dest) const override;
68+
};
69+
70+
/// \brief Adds a pragma on a source location disable all pointer checks.
71+
///
72+
/// The disabled checks are: "pointer-check", "pointer-primitive-check",
73+
/// "pointer-overflow-check", "signed-overflow-check",
74+
// "unsigned-overflow-check", "conversion-check".
75+
void add_pragma_disable_pointer_checks(source_locationt &source_location);
76+
77+
/// \brief Adds pragmas on a GOTO instruction to disable all pointer checks.
78+
///
79+
/// \param instr: A mutable reference to the GOTO instruction.
80+
/// \return The same reference after mutation (i.e., adding the pragma).
81+
goto_programt::instructiont &
82+
add_pragma_disable_pointer_checks(goto_programt::instructiont &instr);
83+
84+
/// \brief Adds pragmas on all instructions in a GOTO program
85+
/// to disable all pointer checks.
86+
///
87+
/// \param prog: A mutable reference to the GOTO program.
88+
/// \return The same reference after mutation (i.e., adding the pragmas).
89+
goto_programt &add_pragma_disable_pointer_checks(goto_programt &prog);
90+
91+
/// \brief Adds a pragma on a source_locationt to disable inclusion checking.
92+
void add_pragma_disable_assigns_check(source_locationt &source_location);
93+
5494
/// \brief Adds a pragma on a GOTO instruction to disable inclusion checking.
5595
///
5696
/// \param instr: A mutable reference to the GOTO instruction.
@@ -129,9 +169,6 @@ const symbolt &new_tmp_symbol(
129169
std::string suffix = "tmp_cc",
130170
bool is_auxiliary = true);
131171

132-
/// Add disable pragmas for all pointer checks on the given location
133-
void disable_pointer_checks(source_locationt &source_location);
134-
135172
/// Turns goto instructions `IF cond GOTO label` where the condition
136173
/// statically simplifies to `false` into SKIP instructions.
137174
void simplify_gotos(goto_programt &goto_program, namespacet &ns);
@@ -224,4 +261,15 @@ class cleanert : public goto_convertt
224261
}
225262
};
226263

264+
/// Returns an \ref irep_idt that essentially says that
265+
/// `target` was assigned by the contract of `function_id`.
266+
irep_idt make_assigns_clause_replacement_tracking_comment(
267+
const exprt &target,
268+
const irep_idt &function_id,
269+
const namespacet &ns);
270+
271+
/// Returns true if the given comment matches the type of comments created by
272+
/// \ref make_assigns_clause_replacement_tracking_comment.
273+
bool is_assigns_clause_replacement_tracking_comment(const irep_idt &comment);
274+
227275
#endif // CPROVER_GOTO_INSTRUMENT_CONTRACTS_UTILS_H

0 commit comments

Comments
 (0)