Skip to content

Commit 254a484

Browse files
committed
Implement GCC's switch-case ranges
1 parent 1a4fc92 commit 254a484

File tree

3 files changed

+55
-9
lines changed

3 files changed

+55
-9
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
int main()
2+
{
3+
int x;
4+
switch (x)
5+
{
6+
case 0:
7+
__CPROVER_assert(0, "0 works");
8+
break;
9+
#ifdef __GNUC__
10+
case 1 ... 12:
11+
#else
12+
case 42:
13+
#endif
14+
__CPROVER_assert(0, "... works");
15+
break;
16+
case 13:
17+
__CPROVER_assert(0, "13 works");
18+
break;
19+
default:
20+
__CPROVER_assert(0, "default works");
21+
break;
22+
}
23+
24+
return 0;
25+
}
26+
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

+20-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>
@@ -429,22 +430,32 @@ void goto_convertt::convert_gcc_switch_case_range(
429430
goto_programt tmp;
430431
convert(to_code(code.op2()), tmp, mode);
431432

432-
// goto_programt::targett target=tmp.instructions.begin();
433+
goto_programt::targett target = tmp.instructions.begin();
433434
dest.destructive_append(tmp);
434435

435-
#if 0
436-
cases_mapt::iterator cases_entry=targets.cases_map.find(target);
437-
if(cases_entry==targets.cases_map.end())
436+
cases_mapt::iterator cases_entry = targets.cases_map.find(target);
437+
if(cases_entry == targets.cases_map.end())
438438
{
439439
targets.cases.push_back(std::make_pair(target, caset()));
440-
cases_entry=targets.cases_map.insert(std::make_pair(
440+
cases_entry = targets.cases_map.insert(std::make_pair(
441441
target, --targets.cases.end())).first;
442442
}
443443

444-
// TODO
445-
exprt::operandst &case_op_dest=cases_entry->second->second;
446-
case_op_dest.push_back(code.case_op());
447-
#endif
444+
const auto lb = numeric_cast<mp_integer>(code.op0());
445+
const auto ub = numeric_cast<mp_integer>(code.op1());
446+
447+
if(!lb.has_value() || !ub.has_value())
448+
{
449+
error().source_location = code.find_source_location();
450+
error() << "GCC's switch-case-range statement requires integer bounds"
451+
<< eom;
452+
throw 0;
453+
}
454+
455+
exprt::operandst &case_op_dest = cases_entry->second->second;
456+
457+
for(mp_integer i = *lb; i <= *ub; ++i)
458+
case_op_dest.push_back(from_integer(i, code.op0().type()));
448459
}
449460

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

0 commit comments

Comments
 (0)