Skip to content

Commit dca1a9f

Browse files
authored
Merge pull request #3918 from tautschnig/fix-requires-renaming
Check all struct members for possible need for renaming
2 parents 03e4dbc + e98554b commit dca1a9f

File tree

9 files changed

+157
-31
lines changed

9 files changed

+157
-31
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

regression/cbmc/vla2/main.c

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
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+
if((unsigned char)argc > 0)
24+
{
25+
s[0].b[0] = 42;
26+
assert(s[0].b[0] == 42);
27+
}
28+
29+
__CPROVER_assume(x < 255);
30+
++x;
31+
32+
assert(sizeof(struct S) == ((unsigned char)argc + 2) * sizeof(int));
33+
assert(sizeof(s) == (x - 1) * ((unsigned char)argc + 2) * sizeof(int));
34+
35+
return 0;
36+
}

regression/cbmc/vla2/test.desc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
KNOWNBUG
2+
main.c
3+
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^VERIFICATION SUCCESSFUL$
7+
--
8+
^warning: ignoring
9+
--
10+
The array decision procedure does not yet handle member expressions.

regression/cbmc/vla3/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+
7+
for(int i = 0; i < 3; ++i)
8+
{
9+
struct S
10+
{
11+
int a;
12+
int b[x + i + 1];
13+
int *c;
14+
} __attribute((packed));
15+
16+
struct S s;
17+
18+
for(int j = 0; j < i; ++j)
19+
s.b[x + j] = j;
20+
21+
for(int j = 0; j < i; ++j)
22+
assert(s.b[x + j] == j);
23+
24+
assert(
25+
sizeof(struct S) ==
26+
sizeof(int *) + ((unsigned char)argc + i + 2) * sizeof(int));
27+
}
28+
29+
return 0;
30+
}

regression/cbmc/vla3/test.desc

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
KNOWNBUG
2+
main.c
3+
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^VERIFICATION SUCCESSFUL$
7+
--
8+
^warning: ignoring
9+
--
10+
Renaming is inconsistent across loop iterations as we map L1 names to types, but
11+
do not actually introduce new L1 ids each time we declare an object.

src/ansi-c/c_typecheck_type.cpp

Lines changed: 11 additions & 29 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>
@@ -608,44 +609,25 @@ void c_typecheck_baset::typecheck_array_type(array_typet &type)
608609
throw 0;
609610
}
610611

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

638622
// produce the code that declares and initializes the symbol
639-
symbol_exprt symbol_expr;
640-
symbol_expr.set_identifier(temp_identifier);
641-
symbol_expr.type()=new_symbol.type;
623+
symbol_exprt symbol_expr = new_symbol.symbol_expr();
642624

643625
code_declt declaration(symbol_expr);
644626
declaration.add_source_location() = size_source_location;
645627

646628
code_assignt assignment;
647629
assignment.lhs()=symbol_expr;
648-
assignment.rhs()=size;
630+
assignment.rhs() = new_symbol.value;
649631
assignment.add_source_location() = size_source_location;
650632

651633
// store the code

src/goto-symex/goto_symex_state.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -618,6 +618,9 @@ void goto_symex_statet::rename_address(
618618
}
619619
}
620620

621+
/// Return true if, and only if, the \p type or one of its subtypes requires SSA
622+
/// renaming. Renaming is necessary when symbol expressions occur within the
623+
/// type, which is the case for arrays of non-constant size.
621624
static bool requires_renaming(const typet &type, const namespacet &ns)
622625
{
623626
if(type.id() == ID_array)
@@ -635,8 +638,12 @@ static bool requires_renaming(const typet &type, const namespacet &ns)
635638
for(auto &component : components)
636639
{
637640
// be careful, or it might get cyclic
638-
if(component.type().id() != ID_pointer)
639-
return requires_renaming(component.type(), ns);
641+
if(
642+
component.type().id() != ID_pointer &&
643+
requires_renaming(component.type(), ns))
644+
{
645+
return true;
646+
}
640647
}
641648

642649
return false;

0 commit comments

Comments
 (0)