Skip to content

Commit f0fad5e

Browse files
authored
Merge pull request #7395 from tautschnig/feature/rw_ok-back-end
Move CPROVER_{r,w,rw}_ok processing to back-end
2 parents 671e46a + e261217 commit f0fad5e

22 files changed

+620
-61
lines changed

src/ansi-c/expr2c.cpp

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3572,6 +3572,26 @@ std::string expr2ct::convert_r_or_w_ok(const r_or_w_ok_exprt &src)
35723572
return dest;
35733573
}
35743574

3575+
std::string
3576+
expr2ct::convert_prophecy_r_or_w_ok(const prophecy_r_or_w_ok_exprt &src)
3577+
{
3578+
// we hide prophecy expressions in C-style output
3579+
std::string dest = src.id() == ID_prophecy_r_ok ? "R_OK"
3580+
: src.id() == ID_prophecy_w_ok ? "W_OK"
3581+
: "RW_OK";
3582+
3583+
dest += '(';
3584+
3585+
unsigned p;
3586+
dest += convert_with_precedence(src.pointer(), p);
3587+
dest += ", ";
3588+
dest += convert_with_precedence(src.size(), p);
3589+
3590+
dest += ')';
3591+
3592+
return dest;
3593+
}
3594+
35753595
std::string expr2ct::convert_pointer_in_range(const pointer_in_range_exprt &src)
35763596
{
35773597
std::string dest = CPROVER_PREFIX "pointer_in_range";
@@ -3590,6 +3610,26 @@ std::string expr2ct::convert_pointer_in_range(const pointer_in_range_exprt &src)
35903610
return dest;
35913611
}
35923612

3613+
std::string expr2ct::convert_prophecy_pointer_in_range(
3614+
const prophecy_pointer_in_range_exprt &src)
3615+
{
3616+
// we hide prophecy expressions in C-style output
3617+
std::string dest = CPROVER_PREFIX "pointer_in_range";
3618+
3619+
dest += '(';
3620+
3621+
unsigned p;
3622+
dest += convert_with_precedence(src.lower_bound(), p);
3623+
dest += ", ";
3624+
dest += convert_with_precedence(src.pointer(), p);
3625+
dest += ", ";
3626+
dest += convert_with_precedence(src.upper_bound(), p);
3627+
3628+
dest += ')';
3629+
3630+
return dest;
3631+
}
3632+
35933633
std::string expr2ct::convert_with_precedence(
35943634
const exprt &src,
35953635
unsigned &precedence)
@@ -4002,9 +4042,22 @@ std::string expr2ct::convert_with_precedence(
40024042
else if(src.id() == ID_r_ok || src.id() == ID_w_ok || src.id() == ID_rw_ok)
40034043
return convert_r_or_w_ok(to_r_or_w_ok_expr(src));
40044044

4045+
else if(
4046+
auto prophecy_r_or_w_ok =
4047+
expr_try_dynamic_cast<prophecy_r_or_w_ok_exprt>(src))
4048+
{
4049+
return convert_prophecy_r_or_w_ok(*prophecy_r_or_w_ok);
4050+
}
4051+
40054052
else if(src.id() == ID_pointer_in_range)
40064053
return convert_pointer_in_range(to_pointer_in_range_expr(src));
40074054

4055+
else if(src.id() == ID_prophecy_pointer_in_range)
4056+
{
4057+
return convert_prophecy_pointer_in_range(
4058+
to_prophecy_pointer_in_range_expr(src));
4059+
}
4060+
40084061
auto function_string_opt = convert_function(src);
40094062
if(function_string_opt.has_value())
40104063
return *function_string_opt;

src/ansi-c/expr2c_class.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ class qualifierst;
2828
class namespacet;
2929
class r_or_w_ok_exprt;
3030
class pointer_in_range_exprt;
31+
class prophecy_r_or_w_ok_exprt;
32+
class prophecy_pointer_in_range_exprt;
3133

3234
class expr2ct
3335
{
@@ -285,7 +287,10 @@ class expr2ct
285287
std::string convert_bitreverse(const bitreverse_exprt &src);
286288

287289
std::string convert_r_or_w_ok(const r_or_w_ok_exprt &src);
290+
std::string convert_prophecy_r_or_w_ok(const prophecy_r_or_w_ok_exprt &src);
288291
std::string convert_pointer_in_range(const pointer_in_range_exprt &src);
292+
std::string
293+
convert_prophecy_pointer_in_range(const prophecy_pointer_in_range_exprt &src);
289294
};
290295

291296
#endif // CPROVER_ANSI_C_EXPR2C_CLASS_H

src/ansi-c/goto_check_c.cpp

Lines changed: 3 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,6 @@ class goto_check_ct
228228
void conversion_check(const exprt &, const guardt &);
229229
void float_overflow_check(const exprt &, const guardt &);
230230
void nan_check(const exprt &, const guardt &);
231-
optionalt<exprt> expand_pointer_checks(exprt);
232231

233232
std::string array_name(const exprt &);
234233

@@ -1444,6 +1443,8 @@ void goto_check_ct::pointer_primitive_check(
14441443
const exprt pointer =
14451444
(expr.id() == ID_r_ok || expr.id() == ID_w_ok || expr.id() == ID_rw_ok)
14461445
? to_r_or_w_ok_expr(expr).pointer()
1446+
: can_cast_expr<prophecy_r_or_w_ok_exprt>(expr)
1447+
? to_prophecy_r_or_w_ok_expr(expr).pointer()
14471448
: to_unary_expr(expr).op();
14481449

14491450
CHECK_RETURN(pointer.type().id() == ID_pointer);
@@ -1484,6 +1485,7 @@ bool goto_check_ct::requires_pointer_primitive_check(const exprt &expr)
14841485
// will equally be non-deterministic.
14851486
return can_cast_expr<object_size_exprt>(expr) || expr.id() == ID_r_ok ||
14861487
expr.id() == ID_w_ok || expr.id() == ID_rw_ok ||
1488+
can_cast_expr<prophecy_r_or_w_ok_exprt>(expr) ||
14871489
expr.id() == ID_is_dynamic_object;
14881490
}
14891491

@@ -1992,62 +1994,6 @@ void goto_check_ct::check(const exprt &expr)
19921994
check_rec(expr, identity);
19931995
}
19941996

1995-
/// expand the r_ok, w_ok, rw_ok, pointer_in_range predicates
1996-
optionalt<exprt> goto_check_ct::expand_pointer_checks(exprt expr)
1997-
{
1998-
bool modified = false;
1999-
2000-
for(auto &op : expr.operands())
2001-
{
2002-
auto op_result = expand_pointer_checks(op);
2003-
if(op_result.has_value())
2004-
{
2005-
op = *op_result;
2006-
modified = true;
2007-
}
2008-
}
2009-
2010-
if(expr.id() == ID_r_ok || expr.id() == ID_w_ok || expr.id() == ID_rw_ok)
2011-
{
2012-
// these get an address as first argument and a size as second
2013-
DATA_INVARIANT(
2014-
expr.operands().size() == 2, "r/w_ok must have two operands");
2015-
2016-
const auto conditions = get_pointer_dereferenceable_conditions(
2017-
to_r_or_w_ok_expr(expr).pointer(), to_r_or_w_ok_expr(expr).size());
2018-
2019-
exprt::operandst conjuncts;
2020-
2021-
for(const auto &c : conditions)
2022-
conjuncts.push_back(c.assertion);
2023-
2024-
exprt c = conjunction(conjuncts);
2025-
if(enable_simplify)
2026-
simplify(c, ns);
2027-
return c;
2028-
}
2029-
else if(expr.id() == ID_pointer_in_range)
2030-
{
2031-
const auto &pointer_in_range_expr = to_pointer_in_range_expr(expr);
2032-
2033-
auto expanded = pointer_in_range_expr.lower();
2034-
2035-
// rec. call
2036-
auto expanded_rec_opt = expand_pointer_checks(expanded);
2037-
if(expanded_rec_opt.has_value())
2038-
expanded = *expanded_rec_opt;
2039-
2040-
if(enable_simplify)
2041-
simplify(expanded, ns);
2042-
2043-
return expanded;
2044-
}
2045-
else if(modified)
2046-
return std::move(expr);
2047-
else
2048-
return {};
2049-
}
2050-
20511997
void goto_check_ct::memory_leak_check(const irep_idt &function_id)
20521998
{
20531999
const symbolt &leak = ns.lookup(CPROVER_PREFIX "memory_leak");
@@ -2267,8 +2213,6 @@ void goto_check_ct::goto_check(
22672213
}
22682214
}
22692215

2270-
i.transform([this](exprt expr) { return expand_pointer_checks(expr); });
2271-
22722216
for(auto &instruction : new_code.instructions)
22732217
{
22742218
if(instruction.source_location().is_nil())

src/cbmc/cbmc_parse_options.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,7 @@ void cbmc_parse_optionst::get_command_line_options(optionst &options)
406406
PARSE_OPTIONS_GOTO_TRACE(cmdline, options);
407407

408408
// Options for process_goto_program
409+
options.set_option("rewrite-rw-ok", true);
409410
options.set_option("rewrite-union", true);
410411

411412
if(cmdline.isset("smt1"))

src/goto-analyzer/goto_analyzer_parse_options.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,7 @@ int goto_analyzer_parse_optionst::doit()
393393

394394
// Preserve backwards compatibility in processing
395395
options.set_option("partial-inline", true);
396+
options.set_option("rewrite-rw-ok", false);
396397
options.set_option("rewrite-union", false);
397398
options.set_option("remove-returns", true);
398399

src/goto-diff/goto_diff_parse_options.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ void goto_diff_parse_optionst::get_command_line_options(optionst &options)
6565
options.set_option("show-properties", cmdline.isset("show-properties"));
6666

6767
// Options for process_goto_program
68+
options.set_option("rewrite-rw-ok", false);
6869
options.set_option("rewrite-union", true);
6970
}
7071

src/goto-instrument/goto_instrument_parse_options.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ Author: Daniel Kroening, [email protected]
4545
#include <goto-programs/remove_unused_functions.h>
4646
#include <goto-programs/remove_virtual_functions.h>
4747
#include <goto-programs/restrict_function_pointers.h>
48+
#include <goto-programs/rewrite_rw_ok.h>
4849
#include <goto-programs/rewrite_union.h>
4950
#include <goto-programs/set_properties.h>
5051
#include <goto-programs/show_properties.h>
@@ -569,6 +570,7 @@ int goto_instrument_parse_optionst::doit()
569570
if(cmdline.isset("show-reaching-definitions"))
570571
{
571572
do_indirect_call_and_rtti_removal();
573+
rewrite_rw_ok(goto_model);
572574

573575
const namespacet ns(goto_model.symbol_table);
574576
reaching_definitions_analysist rd_analysis(ns);
@@ -581,6 +583,7 @@ int goto_instrument_parse_optionst::doit()
581583
if(cmdline.isset("show-dependence-graph"))
582584
{
583585
do_indirect_call_and_rtti_removal();
586+
rewrite_rw_ok(goto_model);
584587

585588
const namespacet ns(goto_model.symbol_table);
586589
dependence_grapht dependence_graph(ns);
@@ -1767,6 +1770,7 @@ void goto_instrument_parse_optionst::instrument_goto_program()
17671770
{
17681771
do_indirect_call_and_rtti_removal();
17691772
do_remove_returns();
1773+
rewrite_rw_ok(goto_model);
17701774

17711775
log.warning() << "**** WARNING: Experimental option --full-slice, "
17721776
<< "analysis results may be unsound. See "

src/goto-programs/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ SRC = allocate_objects.cpp \
5656
remove_vector.cpp \
5757
remove_virtual_functions.cpp \
5858
restrict_function_pointers.cpp \
59+
rewrite_rw_ok.cpp \
5960
rewrite_union.cpp \
6061
resolve_inherited_component.cpp \
6162
safety_checker.cpp \

src/goto-programs/process_goto_program.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ Author: Martin Brain, [email protected]
2323
#include <goto-programs/remove_function_pointers.h>
2424
#include <goto-programs/remove_returns.h>
2525
#include <goto-programs/remove_vector.h>
26+
#include <goto-programs/rewrite_rw_ok.h>
2627
#include <goto-programs/rewrite_union.h>
2728
#include <goto-programs/string_abstraction.h>
2829
#include <goto-programs/string_instrumentation.h>
@@ -70,6 +71,9 @@ bool process_goto_program(
7071
if(options.get_bool_option("rewrite-union"))
7172
rewrite_union(goto_model);
7273

74+
if(options.get_bool_option("rewrite-rw-ok"))
75+
rewrite_rw_ok(goto_model);
76+
7377
// add generic checks
7478
log.status() << "Generic Property Instrumentation" << messaget::eom;
7579
goto_check_c(options, goto_model, log.get_message_handler());

src/goto-programs/rewrite_rw_ok.cpp

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/*******************************************************************\
2+
3+
Module: Rewrite {r,w,rw}_ok expressions as required by symbolic execution
4+
5+
Author: Michael Tautschnig
6+
7+
\*******************************************************************/
8+
9+
#include "rewrite_rw_ok.h"
10+
11+
#include <util/expr_iterator.h>
12+
#include <util/pointer_expr.h>
13+
14+
#include <goto-programs/goto_model.h>
15+
16+
static optionalt<exprt> rewrite_rw_ok(exprt expr, const namespacet &ns)
17+
{
18+
bool unchanged = true;
19+
20+
for(auto it = expr.depth_begin(), itend = expr.depth_end();
21+
it != itend;) // no ++it
22+
{
23+
if(auto r_or_w_ok = expr_try_dynamic_cast<r_or_w_ok_exprt>(*it))
24+
{
25+
const auto &id = it->id();
26+
exprt replacement =
27+
prophecy_r_or_w_ok_exprt{
28+
id == ID_r_ok ? ID_prophecy_r_ok
29+
: id == ID_w_ok ? ID_prophecy_w_ok
30+
: ID_prophecy_rw_ok,
31+
r_or_w_ok->pointer(),
32+
r_or_w_ok->size(),
33+
ns.lookup(CPROVER_PREFIX "deallocated").symbol_expr(),
34+
ns.lookup(CPROVER_PREFIX "dead_object").symbol_expr()}
35+
.with_source_location<exprt>(*it);
36+
37+
it.mutate() = std::move(replacement);
38+
unchanged = false;
39+
it.next_sibling_or_parent();
40+
}
41+
else if(
42+
auto pointer_in_range =
43+
expr_try_dynamic_cast<pointer_in_range_exprt>(*it))
44+
{
45+
exprt replacement =
46+
prophecy_pointer_in_range_exprt{
47+
pointer_in_range->lower_bound(),
48+
pointer_in_range->pointer(),
49+
pointer_in_range->upper_bound(),
50+
ns.lookup(CPROVER_PREFIX "deallocated").symbol_expr(),
51+
ns.lookup(CPROVER_PREFIX "dead_object").symbol_expr()}
52+
.with_source_location<exprt>(*it);
53+
54+
it.mutate() = std::move(replacement);
55+
unchanged = false;
56+
it.next_sibling_or_parent();
57+
}
58+
else
59+
++it;
60+
}
61+
62+
if(unchanged)
63+
return {};
64+
else
65+
return std::move(expr);
66+
}
67+
68+
static void rewrite_rw_ok(
69+
goto_functionst::goto_functiont &goto_function,
70+
const namespacet &ns)
71+
{
72+
for(auto &instruction : goto_function.body.instructions)
73+
instruction.transform(
74+
[&ns](exprt expr) { return rewrite_rw_ok(expr, ns); });
75+
}
76+
77+
void rewrite_rw_ok(goto_modelt &goto_model)
78+
{
79+
const namespacet ns(goto_model.symbol_table);
80+
81+
for(auto &gf_entry : goto_model.goto_functions.function_map)
82+
rewrite_rw_ok(gf_entry.second, ns);
83+
}

0 commit comments

Comments
 (0)