Skip to content

Commit fee89cc

Browse files
authored
Merge pull request #6644 from tautschnig/feature/partial-loops
Unwinding options --unwinding-assertions and --partial-loops do not conflict
2 parents fb740f7 + 836f04b commit fee89cc

File tree

11 files changed

+46
-47
lines changed

11 files changed

+46
-47
lines changed

doc/cprover-manual/cbmc-unwinding.md

+3
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,9 @@ This option will allow paths that execute loops only partially, enabling
162162
a counterexample for the assertion above even for small unwinding
163163
bounds. The disadvantage of using this option is that the resulting path
164164
may be spurious, that is, it may not exist in the original program.
165+
If `--unwinding-assertions` is also used, and the particular counterexample
166+
trace does not include a report of a violated unwinding assertion, then that
167+
counterexample is not impacted by insufficient loop unwinding.
165168

166169
### Depth-based Unwinding
167170

jbmc/src/jbmc/jbmc_parse_options.cpp

-8
Original file line numberDiff line numberDiff line change
@@ -238,14 +238,6 @@ void jbmc_parse_optionst::get_command_line_options(optionst &options)
238238
"partial-loops",
239239
cmdline.isset("partial-loops"));
240240

241-
if(options.get_bool_option("partial-loops") &&
242-
options.get_bool_option("unwinding-assertions"))
243-
{
244-
log.error() << "--partial-loops and --unwinding-assertions "
245-
<< "must not be given together" << messaget::eom;
246-
exit(1); // should contemplate EX_USAGE from sysexits.h
247-
}
248-
249241
// remove unused equations
250242
options.set_option(
251243
"slice-formula",

regression/cbmc-concurrency/recursion1/test.desc

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
CORE
22
main.c
3-
--unwind 1 --partial-loops --depth 100
3+
--unwind 1 --partial-loops --unwinding-assertions --depth 100
44
^EXIT=10$
55
^SIGNAL=0$
66
^VERIFICATION FAILED$
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CORE
2+
main.c
3+
--unwind 9 --unwinding-assertions --partial-loops
4+
^\[main.assertion.1\] line 6 fails when fully unwinding the loop: FAILURE$
5+
^\*\* 2 of 2 failed
6+
^EXIT=10$
7+
^SIGNAL=0$
8+
^VERIFICATION FAILED$
9+
--
10+
^warning: ignoring

src/cbmc/cbmc_parse_options.cpp

-8
Original file line numberDiff line numberDiff line change
@@ -159,14 +159,6 @@ void cbmc_parse_optionst::get_command_line_options(optionst &options)
159159
options.set_option("no-array-field-sensitivity", true);
160160
}
161161

162-
if(cmdline.isset("partial-loops") && cmdline.isset("unwinding-assertions"))
163-
{
164-
log.error()
165-
<< "--partial-loops and --unwinding-assertions must not be given "
166-
<< "together" << messaget::eom;
167-
exit(CPROVER_EXIT_USAGE_ERROR);
168-
}
169-
170162
if(cmdline.isset("reachability-slice") &&
171163
cmdline.isset("reachability-slice-fb"))
172164
{

src/goto-checker/bmc_util.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ void run_property_decider(
234234
" --show-vcc show the verification conditions\n" \
235235
" --slice-formula remove assignments unrelated to property\n" \
236236
" --unwinding-assertions generate unwinding assertions (cannot be\n" \
237-
" used with --cover or --partial-loops)\n" \
237+
" used with --cover)\n" \
238238
" --partial-loops permit paths with partial loops\n" \
239239
" --no-self-loops-to-assumptions\n" \
240240
" do not simplify while(1){} to assume(0)\n" \

src/goto-instrument/goto_instrument_parse_options.cpp

+14-5
Original file line numberDiff line numberDiff line change
@@ -182,17 +182,26 @@ int goto_instrument_parse_optionst::doit()
182182
bool unwinding_assertions=cmdline.isset("unwinding-assertions");
183183
bool partial_loops=cmdline.isset("partial-loops");
184184
bool continue_as_loops=cmdline.isset("continue-as-loops");
185-
186-
if(unwinding_assertions+partial_loops+continue_as_loops>1)
187-
throw "more than one of --unwinding-assertions,--partial-loops,"
188-
"--continue-as-loops selected";
185+
if(continue_as_loops)
186+
{
187+
if(unwinding_assertions)
188+
{
189+
throw "unwinding assertions cannot be used with "
190+
"--continue-as-loops";
191+
}
192+
else if(partial_loops)
193+
throw "partial loops cannot be used with --continue-as-loops";
194+
}
189195

190196
goto_unwindt::unwind_strategyt unwind_strategy=
191197
goto_unwindt::unwind_strategyt::ASSUME;
192198

193199
if(unwinding_assertions)
194200
{
195-
unwind_strategy = goto_unwindt::unwind_strategyt::ASSERT_ASSUME;
201+
if(partial_loops)
202+
unwind_strategy = goto_unwindt::unwind_strategyt::ASSERT_PARTIAL;
203+
else
204+
unwind_strategy = goto_unwindt::unwind_strategyt::ASSERT_ASSUME;
196205
}
197206
else if(partial_loops)
198207
{

src/goto-instrument/unwind.cpp

+4-1
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ void goto_unwindt::unwind(
130130
{
131131
PRECONDITION(
132132
unwind_strategy == unwind_strategyt::ASSERT_ASSUME ||
133+
unwind_strategy == unwind_strategyt::ASSERT_PARTIAL ||
133134
unwind_strategy == unwind_strategyt::ASSUME);
134135

135136
goto_programt::const_targett t=loop_exit;
@@ -148,7 +149,9 @@ void goto_unwindt::unwind(
148149
exit_cond = loop_head->get_condition();
149150
}
150151

151-
if(unwind_strategy == unwind_strategyt::ASSERT_ASSUME)
152+
if(
153+
unwind_strategy == unwind_strategyt::ASSERT_ASSUME ||
154+
unwind_strategy == unwind_strategyt::ASSERT_PARTIAL)
152155
{
153156
goto_programt::targett assertion = rest_program.add(
154157
goto_programt::make_assertion(exit_cond, loop_head->source_location()));

src/goto-instrument/unwind.h

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ class goto_unwindt
2626
CONTINUE,
2727
PARTIAL,
2828
ASSERT_ASSUME,
29+
ASSERT_PARTIAL,
2930
ASSUME
3031
};
3132

src/goto-symex/symex_function_call.cpp

+3-8
Original file line numberDiff line numberDiff line change
@@ -245,15 +245,10 @@ void goto_symext::symex_function_call_post_clean(
245245
// see if it's too much
246246
if(stop_recursing)
247247
{
248-
if(symex_config.partial_loops)
248+
if(symex_config.unwinding_assertions)
249+
vcc(false_exprt(), "recursion unwinding assertion", state);
250+
if(!symex_config.partial_loops)
249251
{
250-
// it's ok, ignore
251-
}
252-
else
253-
{
254-
if(symex_config.unwinding_assertions)
255-
vcc(false_exprt(), "recursion unwinding assertion", state);
256-
257252
// Rule out this path:
258253
symex_assume_l2(state, false_exprt());
259254
}

src/goto-symex/symex_goto.cpp

+9-15
Original file line numberDiff line numberDiff line change
@@ -932,25 +932,19 @@ void goto_symext::loop_bound_exceeded(
932932
else
933933
negated_cond=not_exprt(guard);
934934

935-
if(!symex_config.partial_loops)
935+
if(symex_config.unwinding_assertions)
936936
{
937-
if(symex_config.unwinding_assertions)
938-
{
939-
// Generate VCC for unwinding assertion.
940-
vcc(
941-
negated_cond,
942-
"unwinding assertion loop " + std::to_string(loop_number),
943-
state);
944-
}
937+
// Generate VCC for unwinding assertion.
938+
vcc(
939+
negated_cond,
940+
"unwinding assertion loop " + std::to_string(loop_number),
941+
state);
942+
}
945943

944+
if(!symex_config.partial_loops)
945+
{
946946
// generate unwinding assumption, unless we permit partial loops
947947
symex_assume_l2(state, negated_cond);
948-
949-
if(symex_config.unwinding_assertions)
950-
{
951-
// add to state guard to prevent further assignments
952-
state.guard.add(negated_cond);
953-
}
954948
}
955949
}
956950

0 commit comments

Comments
 (0)