Skip to content

Commit 8f526b7

Browse files
committed
Implement GCC's switch-case ranges
1 parent 3082d9d commit 8f526b7

File tree

3 files changed

+66
-9
lines changed

3 files changed

+66
-9
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
int main()
2+
{
3+
int x;
4+
switch (x)
5+
{
6+
case 0:
7+
#ifdef __GNUC__
8+
// empty case - GCC emits a warning, but this is still reached via
9+
// fall-through
10+
case 13 ... 12:
11+
#endif
12+
__CPROVER_assert(0, "0 works");
13+
break;
14+
#ifdef __GNUC__
15+
case 1 ... 12:
16+
#else
17+
case 42:
18+
#endif
19+
__CPROVER_assert(0, "... works");
20+
break;
21+
case 13:
22+
__CPROVER_assert(0, "13 works");
23+
break;
24+
default:
25+
__CPROVER_assert(0, "default works");
26+
break;
27+
}
28+
29+
return 0;
30+
}
31+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CORE
2+
main.c
3+
4+
^EXIT=10$
5+
^SIGNAL=0$
6+
^VERIFICATION FAILED$
7+
^\*\* 4 of 4 failed
8+
--
9+
^warning: ignoring

src/goto-programs/goto_convert.cpp

+26-9
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ Author: Daniel Kroening, [email protected]
1313

1414
#include <cassert>
1515

16+
#include <util/arith_tools.h>
1617
#include <util/cprover_prefix.h>
1718
#include <util/expr_util.h>
1819
#include <util/fresh_symbol.h>
@@ -426,25 +427,41 @@ void goto_convertt::convert_gcc_switch_case_range(
426427
throw 0;
427428
}
428429

430+
const auto lb = numeric_cast<mp_integer>(code.op0());
431+
const auto ub = numeric_cast<mp_integer>(code.op1());
432+
433+
if(!lb.has_value() || !ub.has_value())
434+
{
435+
error().source_location = code.find_source_location();
436+
error() << "GCC's switch-case-range statement requires constant bounds"
437+
<< eom;
438+
throw 0;
439+
}
440+
else if(*lb > *ub)
441+
{
442+
warning().source_location = code.find_source_location();
443+
warning() << "GCC's switch-case-range statement with empty case range"
444+
<< eom;
445+
}
446+
429447
goto_programt tmp;
430448
convert(to_code(code.op2()), tmp, mode);
431449

432-
// goto_programt::targett target=tmp.instructions.begin();
450+
goto_programt::targett target = tmp.instructions.begin();
433451
dest.destructive_append(tmp);
434452

435-
#if 0
436-
cases_mapt::iterator cases_entry=targets.cases_map.find(target);
437-
if(cases_entry==targets.cases_map.end())
453+
cases_mapt::iterator cases_entry = targets.cases_map.find(target);
454+
if(cases_entry == targets.cases_map.end())
438455
{
439456
targets.cases.push_back(std::make_pair(target, caset()));
440-
cases_entry=targets.cases_map.insert(std::make_pair(
457+
cases_entry = targets.cases_map.insert(std::make_pair(
441458
target, --targets.cases.end())).first;
442459
}
443460

444-
// TODO
445-
exprt::operandst &case_op_dest=cases_entry->second->second;
446-
case_op_dest.push_back(code.case_op());
447-
#endif
461+
exprt::operandst &case_op_dest = cases_entry->second->second;
462+
463+
for(mp_integer i = *lb; i <= *ub; ++i)
464+
case_op_dest.push_back(from_integer(i, code.op0().type()));
448465
}
449466

450467
/// converts 'code' and appends the result to 'dest'

0 commit comments

Comments
 (0)