Skip to content

Commit 4ec7d9b

Browse files
authored
Merge pull request #6521 from tautschnig/switch-eval-once
Evaluate any non-trivial switch condition just once
2 parents 47c1c7e + 52d7e3c commit 4ec7d9b

File tree

3 files changed

+55
-0
lines changed

3 files changed

+55
-0
lines changed

regression/cbmc/switch9/main.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#include <stdlib.h>
2+
3+
int main()
4+
{
5+
int *p = malloc(sizeof(int));
6+
7+
if(!p)
8+
return 1;
9+
10+
switch(*p)
11+
{
12+
case 1:
13+
case 2:
14+
case 3:
15+
return 0;
16+
case 4:
17+
default:
18+
return -1;
19+
}
20+
}

regression/cbmc/switch9/test.desc

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
CORE
2+
main.c
3+
--pointer-check --malloc-may-fail --malloc-fail-null
4+
activate-multi-line-match
5+
^\[main.pointer_dereference.\d+\] line 10 dereference failure: pointer NULL in \*p: SUCCESS$
6+
^VERIFICATION SUCCESSFUL$
7+
^EXIT=0$
8+
^SIGNAL=0$
9+
--
10+
^warning: ignoring
11+
\[main.pointer_dereference.\d+\] line 10 dereference failure: pointer NULL in \*p: SUCCESS\n.*\[main.pointer_dereference.\d+\] line 10 dereference failure: pointer NULL in \*p: SUCCESS\n
12+
--
13+
A pointer check for the switch value should be generated, but there should only
14+
be one such check.

src/goto-programs/goto_convert.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1184,6 +1184,27 @@ void goto_convertt::convert_switch(
11841184
goto_programt sideeffects;
11851185
clean_expr(argument, sideeffects, mode);
11861186

1187+
// Avoid potential performance penalties caused by evaluating the value
1188+
// multiple times (as the below chain-of-ifs does). "needs_cleaning" isn't
1189+
// necessarily the right check here, and we may need to introduce a different
1190+
// way of identifying the class of non-trivial expressions that warrant
1191+
// introduction of a temporary.
1192+
if(needs_cleaning(argument))
1193+
{
1194+
symbolt &new_symbol = new_tmp_symbol(
1195+
argument.type(),
1196+
"switch_value",
1197+
sideeffects,
1198+
code.source_location(),
1199+
mode);
1200+
1201+
code_assignt copy_value{
1202+
new_symbol.symbol_expr(), argument, code.source_location()};
1203+
convert(copy_value, sideeffects, mode);
1204+
1205+
argument = new_symbol.symbol_expr();
1206+
}
1207+
11871208
// save break/default/cases targets
11881209
break_switch_targetst old_targets(targets);
11891210

0 commit comments

Comments
 (0)