Skip to content

Commit acb58e7

Browse files
authored
Merge pull request #7051 from diffblue/shortcircuit2
Simplify goto-program generated for short-circuit operators
2 parents 23045d1 + 1570e0a commit acb58e7

File tree

15 files changed

+50
-43
lines changed

15 files changed

+50
-43
lines changed

regression/cbmc-cover/Quantifiers-not-exists/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
CORE
1+
KNOWNBUG
22
main.c
33
--cover location
44
^\*\* 1 of 46 covered \(2.2%\)

regression/cbmc/Quantifiers-not-exists/fixed.desc

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@ fixed.c
33

44
^\*\* Results:$
55
^\[main.assertion.5\] line 31 assertion a\[.*\]\[.*\] > 10: SUCCESS$
6-
^\[main.assertion.6\] line 33 assertion tmp_if_expr\$\d+: SUCCESS$
7-
^\[main.assertion.7\] line 34 assertion tmp_if_expr\$\d+: SUCCESS$
8-
^\[main.assertion.8\] line 36 assertion tmp_if_expr\$\d+: SUCCESS$
9-
^\[main.assertion.9\] line 38 assertion tmp_if_expr\$\d+: SUCCESS$
10-
^\[main.assertion.10\] line 39 assertion tmp_if_expr\$\d+: SUCCESS$
6+
^\[main.assertion.6\] line 33 assertion .*: SUCCESS$
7+
^\[main.assertion.7\] line 34 assertion .*: SUCCESS$
8+
^\[main.assertion.8\] line 36 assertion .*: SUCCESS$
9+
^\[main.assertion.9\] line 38 assertion .*: SUCCESS$
10+
^\[main.assertion.10\] line 39 assertion .*: SUCCESS$
1111
^\*\* 4 of 10 failed
1212
^VERIFICATION FAILED$
1313
^EXIT=10$

regression/cbmc/Quantifiers-two-dimension-array/fixed.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ fixed.c
66
^\[main.assertion.2\] line 15 assertion a\[.*\]\[.*\] == 1: SUCCESS$
77
^\[main.assertion.3\] line 16 assertion a\[.*\]\[.*\] == 1: SUCCESS$
88
^\[main.assertion.4\] line 17 assertion a\[.*\]\[.*\] == 2: SUCCESS$
9-
^\[main.assertion.5\] line 18 assertion tmp_if_expr\$\d+: SUCCESS$
9+
^\[main.assertion.5\] line 18 assertion .*: SUCCESS$
1010
^\*\* 0 of 5 failed
1111
^VERIFICATION SUCCESSFUL$
1212
^EXIT=0$

regression/cbmc/Quantifiers-two-dimension-array/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ main.c
66
^\[main.assertion.2\] line 13 assertion a\[.*\]\[.*\] == 1: SUCCESS$
77
^\[main.assertion.3\] line 14 assertion a\[.*\]\[.*\] == 1: SUCCESS$
88
^\[main.assertion.4\] line 15 assertion a\[.*\]\[.*\] == 2: SUCCESS$
9-
^\[main.assertion.5\] line 16 assertion tmp_if_expr\$\d+: FAILURE$
9+
^\[main.assertion.5\] line 16 assertion .*: FAILURE$
1010
^\*\* 1 of 5 failed
1111
^VERIFICATION FAILED$
1212
^EXIT=10$

regression/cbmc/Quantifiers-type2/test.desc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ CORE
22
main.c
33

44
^\*\* Results:$
5-
^\[main.assertion.1\] line 12 assertion tmp_if_expr(\$\d+)?: SUCCESS$
6-
^\[main.assertion.2\] line 13 assertion tmp_if_expr\$\d+: SUCCESS$
5+
^\[main.assertion.1\] line 12 assertion b\[.*0\] == 10 && b\[.*1\] == 10: SUCCESS$
6+
^\[main.assertion.2\] line 13 assertion c\[.*0\] == 10 && c\[.*1\] == 10: SUCCESS$
77
^VERIFICATION SUCCESSFUL$
88
^EXIT=0$
99
^SIGNAL=0$

regression/contracts/assigns_validity_pointer_01/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
CORE
1+
KNOWNBUG
22
main.c
33
--enforce-contract foo --replace-call-with-contract bar --replace-call-with-contract baz
44
^EXIT=0$

regression/contracts/assigns_validity_pointer_04/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
CORE
1+
KNOWNBUG
22
main.c
33
--enforce-contract foo --replace-call-with-contract bar --replace-call-with-contract baz _ --pointer-primitive-check
44
^EXIT=10$

regression/contracts/history-pointer-enforce-03/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
CORE
1+
KNOWNBUG
22
main.c
33
--enforce-contract foo
44
^EXIT=0$

regression/contracts/history-pointer-enforce-04/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
CORE
1+
KNOWNBUG
22
main.c
33
--enforce-contract foo
44
^EXIT=0$

regression/contracts/history-pointer-enforce-05/test.desc

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

regression/goto-analyzer/constant_propagation_08/test-vsd.desc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ main.c
33
--variable-sensitivity --vsd-arrays every-element --simplify out.gb
44
^EXIT=0$
55
^SIGNAL=0$
6-
^Simplified: assert: 1, assume: 0, goto: 2, assigns: 8, function calls: 0$
7-
^Unmodified: assert: 0, assume: 0, goto: 3, assigns: 14, function calls: 2$
6+
^Simplified: assert: 1, assume: 0, goto: 1, assigns: 8, function calls: 0$
7+
^Unmodified: assert: 0, assume: 0, goto: 2, assigns: 12, function calls: 2$
88
--
99
^warning: ignoring

regression/goto-analyzer/pointer-comparison-same-target-non-det/test-value-set.desc

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,20 @@ main.c
44
^EXIT=0$
55
^SIGNAL=0$
66
^\[main.assertion.1\] .* assertion p == q: FAILURE
7-
^\[main.assertion.2\] .* assertion p == r: FAILURE
7+
^\[main.assertion.2\] .* assertion p == r: UNKNOWN
88
^\[main.assertion.3\] .* assertion q == r: UNKNOWN
99
^\[main.assertion.4\] .* assertion p != q: SUCCESS
10-
^\[main.assertion.5\] .* assertion p != r: SUCCESS
10+
^\[main.assertion.5\] .* assertion p != r: UNKNOWN
1111
^\[main.assertion.6\] .* assertion q != r: UNKNOWN
1212
^\[main.assertion.7\] .* assertion p < q: SUCCESS
13-
^\[main.assertion.8\] .* assertion p < r: SUCCESS
13+
^\[main.assertion.8\] .* assertion p < r: UNKNOWN
1414
^\[main.assertion.9\] .* assertion q < r: UNKNOWN
1515
^\[main.assertion.10\] .* assertion p <= q: SUCCESS
16-
^\[main.assertion.11\] .* assertion p <= r: SUCCESS
17-
^\[main.assertion.12\] .* assertion q <= r: SUCCESS
16+
^\[main.assertion.11\] .* assertion p <= r: UNKNOWN
17+
^\[main.assertion.12\] .* assertion q <= r: UNKNOWN
1818
^\[main.assertion.13\] .* assertion p > q: FAILURE
19-
^\[main.assertion.14\] .* assertion p > r: FAILURE
20-
^\[main.assertion.15\] .* assertion q > r: FAILURE
19+
^\[main.assertion.14\] .* assertion p > r: UNKNOWN
20+
^\[main.assertion.15\] .* assertion q > r: UNKNOWN
2121
^\[main.assertion.16\] .* assertion p >= q: FAILURE
22-
^\[main.assertion.17\] .* assertion p >= r: FAILURE
22+
^\[main.assertion.17\] .* assertion p >= r: UNKNOWN
2323
^\[main.assertion.18\] .* assertion q >= r: UNKNOWN

src/goto-programs/goto_clean_expr.cpp

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -59,23 +59,17 @@ symbol_exprt goto_convertt::make_compound_literal(
5959
return result;
6060
}
6161

62+
/// Returns 'true' for expressions that may change the program
63+
/// state.
64+
/// Expressions that may trigger undefined behavior
65+
/// (e.g., dereference, index, division) are deliberately not
66+
/// included.
6267
bool goto_convertt::needs_cleaning(const exprt &expr)
6368
{
64-
if(expr.id()==ID_dereference ||
65-
expr.id()==ID_side_effect ||
66-
expr.id()==ID_compound_literal ||
67-
expr.id()==ID_comma)
68-
return true;
69-
70-
if(expr.id()==ID_index)
69+
if(
70+
expr.id() == ID_side_effect || expr.id() == ID_compound_literal ||
71+
expr.id() == ID_comma)
7172
{
72-
// Will usually clean index expressions because of possible
73-
// memory violation in case of out-of-bounds indices.
74-
// We do an exception for "string-lit"[0], which is safe.
75-
if(to_index_expr(expr).array().id()==ID_string_constant &&
76-
to_index_expr(expr).index().is_zero())
77-
return false;
78-
7973
return true;
8074
}
8175

@@ -384,7 +378,7 @@ void goto_convertt::clean_expr(
384378
clean_expr(side_effect_assign.lhs(), dest, mode);
385379
exprt lhs = side_effect_assign.lhs();
386380

387-
const bool must_use_rhs = needs_cleaning(lhs);
381+
const bool must_use_rhs = assignment_lhs_needs_temporary(lhs);
388382
if(must_use_rhs)
389383
{
390384
remove_function_call(

src/goto-programs/goto_convert_class.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,15 @@ class goto_convertt:public messaget
8989

9090
static bool needs_cleaning(const exprt &expr);
9191

92+
// Do we need to introduce a temporary for the value of an assignment
93+
// to the given lhs? E.g., a[i] needs a temporary as its value may change
94+
// when i is changed; likewise, *p needs a temporary as its value may change
95+
// when p is changed.
96+
static bool assignment_lhs_needs_temporary(const exprt &lhs)
97+
{
98+
return lhs.id() != ID_symbol;
99+
}
100+
92101
void make_temp_symbol(
93102
exprt &expr,
94103
const std::string &suffix,

src/goto-programs/goto_convert_side_effect.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,9 @@ void goto_convertt::remove_assignment(
5050
{
5151
auto &old_assignment = to_side_effect_expr_assign(expr);
5252

53-
if(result_is_used && !address_taken && needs_cleaning(old_assignment.lhs()))
53+
if(
54+
result_is_used && !address_taken &&
55+
assignment_lhs_needs_temporary(old_assignment.lhs()))
5456
{
5557
if(!old_assignment.rhs().is_constant())
5658
make_temp_symbol(old_assignment.rhs(), "assign", dest, mode);
@@ -122,7 +124,9 @@ void goto_convertt::remove_assignment(
122124
exprt rhs = binary_exprt{binary_expr.op0(), new_id, binary_expr.op1()};
123125
rhs.add_source_location() = expr.source_location();
124126

125-
if(result_is_used && !address_taken && needs_cleaning(binary_expr.op0()))
127+
if(
128+
result_is_used && !address_taken &&
129+
assignment_lhs_needs_temporary(binary_expr.op0()))
126130
{
127131
make_temp_symbol(rhs, "assign", dest, mode);
128132
replacement_expr_opt = rhs;
@@ -237,7 +241,7 @@ void goto_convertt::remove_pre(
237241
}
238242

239243
const bool cannot_use_lhs =
240-
result_is_used && !address_taken && needs_cleaning(lhs);
244+
result_is_used && !address_taken && assignment_lhs_needs_temporary(lhs);
241245
if(cannot_use_lhs)
242246
make_temp_symbol(rhs, "pre", dest, mode);
243247

0 commit comments

Comments
 (0)