Skip to content

Commit b43753a

Browse files
authored
Merge pull request #3966 from tautschnig/reinstate-limited-symex-renaming
Reinstate limited symex renaming [blocks: #4164]
2 parents 3b7d59a + 94dacc5 commit b43753a

File tree

5 files changed

+119
-26
lines changed

5 files changed

+119
-26
lines changed

regression/cbmc/vla1/main.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#include <assert.h>
2+
3+
int main(int argc, char *argv[])
4+
{
5+
unsigned char x = argc;
6+
// make sure int multiplication below won't overflow - type casting to
7+
// unsigned long long would be possible, but puts yields a challenging problem
8+
// for the SAT solver
9+
__CPROVER_assume(x < 1ULL << (sizeof(int) * 8 / 2 - 1));
10+
11+
struct S
12+
{
13+
int a;
14+
int b[x];
15+
int c;
16+
};
17+
18+
if(x % 2 == 0)
19+
x = 3;
20+
21+
struct S s[x];
22+
23+
__CPROVER_assume(x < 255);
24+
++x;
25+
26+
assert(sizeof(struct S) == ((unsigned char)argc + 2) * sizeof(int));
27+
assert(sizeof(s) == (x - 1) * ((unsigned char)argc + 2) * sizeof(int));
28+
29+
return 0;
30+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
CORE
2+
main.c
3+
--program-only
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
--
7+
^warning: ignoring
8+
--
9+
\(__CPROVER_size_t\)x\$array_size
10+
--
11+
There should not be any type cast of x$array_size to __CPROVER_size_t, because
12+
it already is of that type.

regression/cbmc/vla1/test.desc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
main.c
3+
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^VERIFICATION SUCCESSFUL$
7+
--
8+
^warning: ignoring

src/ansi-c/c_typecheck_type.cpp

Lines changed: 11 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ Author: Daniel Kroening, [email protected]
1616
#include <util/arith_tools.h>
1717
#include <util/c_types.h>
1818
#include <util/config.h>
19+
#include <util/fresh_symbol.h>
1920
#include <util/mathematical_types.h>
2021
#include <util/pointer_offset_size.h>
2122
#include <util/simplify_expr.h>
@@ -614,41 +615,25 @@ void c_typecheck_baset::typecheck_array_type(array_typet &type)
614615
throw 0;
615616
}
616617

617-
// Need to pull out! We insert new symbol.
618-
unsigned count = 0;
619-
irep_idt temp_identifier;
620-
std::string suffix;
621-
622-
do
623-
{
624-
suffix = "$array_size" + std::to_string(count);
625-
temp_identifier = id2string(current_symbol.name) + suffix;
626-
count++;
627-
} while(symbol_table.symbols.find(temp_identifier) !=
628-
symbol_table.symbols.end());
629-
630-
// add the symbol to symbol table
631-
auxiliary_symbolt new_symbol;
632-
new_symbol.name = temp_identifier;
633-
new_symbol.pretty_name = id2string(current_symbol.pretty_name) + suffix;
634-
new_symbol.base_name = id2string(current_symbol.base_name) + suffix;
635-
new_symbol.type = size.type();
618+
symbolt &new_symbol = get_fresh_aux_symbol(
619+
size_type(),
620+
id2string(current_symbol.name) + "$array_size",
621+
id2string(current_symbol.base_name) + "$array_size",
622+
size_source_location,
623+
mode,
624+
symbol_table);
636625
new_symbol.type.set(ID_C_constant, true);
637-
new_symbol.value = size;
638-
new_symbol.location = size_source_location;
639-
new_symbol.mode = mode;
640-
641-
symbol_table.add(new_symbol);
626+
new_symbol.value = typecast_exprt::conditional_cast(size, size_type());
642627

643628
// produce the code that declares and initializes the symbol
644-
symbol_exprt symbol_expr(temp_identifier, new_symbol.type);
629+
symbol_exprt symbol_expr = new_symbol.symbol_expr();
645630

646631
code_declt declaration(symbol_expr);
647632
declaration.add_source_location() = size_source_location;
648633

649634
code_assignt assignment;
650635
assignment.lhs()=symbol_expr;
651-
assignment.rhs() = size;
636+
assignment.rhs() = new_symbol.value;
652637
assignment.add_source_location() = size_source_location;
653638

654639
// store the code

src/goto-symex/goto_symex_state.cpp

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -611,12 +611,70 @@ void goto_symex_statet::rename_address(
611611
}
612612
}
613613

614+
/// Return true if, and only if, the \p type or one of its subtypes requires SSA
615+
/// renaming. Renaming is necessary when symbol expressions occur within the
616+
/// type, which is the case for arrays of non-constant size.
617+
static bool requires_renaming(const typet &type, const namespacet &ns)
618+
{
619+
if(type.id() == ID_array)
620+
{
621+
const auto &array_type = to_array_type(type);
622+
return requires_renaming(array_type.subtype(), ns) ||
623+
!array_type.size().is_constant();
624+
}
625+
else if(
626+
type.id() == ID_struct || type.id() == ID_union || type.id() == ID_class)
627+
{
628+
const struct_union_typet &s_u_type = to_struct_union_type(type);
629+
const struct_union_typet::componentst &components = s_u_type.components();
630+
631+
for(auto &component : components)
632+
{
633+
// be careful, or it might get cyclic
634+
if(
635+
component.type().id() != ID_pointer &&
636+
requires_renaming(component.type(), ns))
637+
{
638+
return true;
639+
}
640+
}
641+
642+
return false;
643+
}
644+
else if(type.id() == ID_pointer)
645+
{
646+
return requires_renaming(to_pointer_type(type).subtype(), ns);
647+
}
648+
else if(type.id() == ID_symbol_type)
649+
{
650+
const symbolt &symbol = ns.lookup(to_symbol_type(type));
651+
return requires_renaming(symbol.type, ns);
652+
}
653+
else if(type.id() == ID_union_tag)
654+
{
655+
const symbolt &symbol = ns.lookup(to_union_tag_type(type));
656+
return requires_renaming(symbol.type, ns);
657+
}
658+
else if(type.id() == ID_struct_tag)
659+
{
660+
const symbolt &symbol = ns.lookup(to_struct_tag_type(type));
661+
return requires_renaming(symbol.type, ns);
662+
}
663+
664+
return false;
665+
}
666+
614667
void goto_symex_statet::rename(
615668
typet &type,
616669
const irep_idt &l1_identifier,
617670
const namespacet &ns,
618671
levelt level)
619672
{
673+
// check whether there are symbol expressions in the type; if not, there
674+
// is no need to expand the struct/union tags in the type
675+
if(!requires_renaming(type, ns))
676+
return; // no action
677+
620678
// rename all the symbols with their last known value
621679
// to the given level
622680

0 commit comments

Comments
 (0)