Skip to content

Commit ea2f7fa

Browse files
committed
C front-end: ensure array type updates are consistent
We must not end up in a situation where the symbol's array type is different from the type applied to symbol expressions in code. With the previous approach, support-function generation would alter the type after typechecking of code had already been completed. Fixes: #7608
1 parent fd457d2 commit ea2f7fa

File tree

5 files changed

+36
-10
lines changed

5 files changed

+36
-10
lines changed

regression/cbmc/extern6/main.c

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
extern int stuff[];
2+
3+
extern int a[];
4+
int a[] = {1, 2, 3};
5+
6+
int main()
7+
{
8+
unsigned char idx;
9+
long val = *(long *)(stuff + idx);
10+
__CPROVER_assert(val == 13, "compare");
11+
return 0;
12+
}

regression/cbmc/extern6/test.desc

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CORE new-smt-backend
2+
main.c
3+
4+
^EXIT=10$
5+
^SIGNAL=0$
6+
^VERIFICATION FAILED$
7+
--
8+
^warning: ignoring
9+
^Invariant check failed

src/ansi-c/c_typecheck_base.cpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,7 @@ void c_typecheck_baset::typecheck_redefinition_non_type(
314314

315315
if(
316316
final_old.id() == ID_array &&
317-
to_array_type(final_old).size().is_not_nil() &&
317+
to_array_type(final_old).size().is_not_nil() && !old_symbol.is_weak &&
318318
initial_new.id() == ID_array &&
319319
to_array_type(initial_new).size().is_nil() &&
320320
to_array_type(final_old).element_type() ==
@@ -504,7 +504,8 @@ void c_typecheck_baset::typecheck_redefinition_non_type(
504504
if(final_old!=final_new)
505505
{
506506
if(
507-
final_old.id() == ID_array && to_array_type(final_old).size().is_nil() &&
507+
final_old.id() == ID_array &&
508+
(to_array_type(final_old).size().is_nil() || old_symbol.is_weak) &&
508509
final_new.id() == ID_array &&
509510
to_array_type(final_new).size().is_not_nil() &&
510511
to_array_type(final_old).element_type() ==

src/ansi-c/c_typecheck_initializer.cpp

+9
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,15 @@ void c_typecheck_baset::do_initializer(symbolt &symbol)
249249
if(!symbol.is_macro && symbol.type != symbol.value.type())
250250
symbol.type = symbol.value.type();
251251
}
252+
else if(
253+
symbol.type.id() == ID_array && to_array_type(symbol.type).size().is_nil())
254+
{
255+
// C standard 6.9.2, paragraph 5
256+
// adjust the type to an array of size 1, but mark as weak so that linking
257+
// can change that
258+
to_array_type(symbol.type).size() = from_integer(1, size_type());
259+
symbol.is_weak = true;
260+
}
252261

253262
if(symbol.is_macro)
254263
make_constant(symbol.value);

src/linking/static_lifetime_init.cpp

+3-8
Original file line numberDiff line numberDiff line change
@@ -50,14 +50,9 @@ static optionalt<codet> static_lifetime_init(
5050
if(type.id() == ID_code || type.id() == ID_empty)
5151
return {};
5252

53-
if(type.id() == ID_array && to_array_type(type).size().is_nil())
54-
{
55-
// C standard 6.9.2, paragraph 5
56-
// adjust the type to an array of size 1
57-
symbolt &writable_symbol = symbol_table.get_writeable_ref(identifier);
58-
writable_symbol.type = type;
59-
writable_symbol.type.set(ID_size, from_integer(1, size_type()));
60-
}
53+
DATA_INVARIANT(
54+
type.id() != ID_array || to_array_type(type).size().is_not_nil(),
55+
"arrays must have a size");
6156

6257
if(
6358
(type.id() == ID_struct || type.id() == ID_union) &&

0 commit comments

Comments
 (0)