Skip to content

Commit 3613ebc

Browse files
committed
When possible, update array types before typechecking initializer
This fixes a bug in compiling a Linux kernel driver.
1 parent 3273bf5 commit 3613ebc

File tree

3 files changed

+39
-29
lines changed

3 files changed

+39
-29
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#define STATIC_ASSERT_sizeof(condition) \
2+
int[(condition) ? 1 : -1]
3+
4+
int A[];
5+
int B[];
6+
7+
int A[1]={sizeof(A)};
8+
int B[1]={sizeof(STATIC_ASSERT_sizeof(sizeof(B)==sizeof(int)))};
9+
10+
int main()
11+
{
12+
return 0;
13+
}
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+
--
7+
^warning: ignoring
8+
^CONVERSION ERROR$

src/ansi-c/c_typecheck_base.cpp

+18-29
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ Author: Daniel Kroening, [email protected]
1111

1212
#include "c_typecheck_base.h"
1313

14+
#include <util/invariant.h>
1415
#include <util/std_types.h>
1516
#include <util/prefix.h>
1617
#include <util/config.h>
@@ -256,6 +257,16 @@ void c_typecheck_baset::typecheck_redefinition_non_type(
256257
// this is ok, just use old type
257258
new_symbol.type=old_symbol.type;
258259
}
260+
else if(final_old.id()==ID_array &&
261+
to_array_type(final_old).size().is_nil() &&
262+
initial_new.id()==ID_array &&
263+
to_array_type(initial_new).size().is_not_nil() &&
264+
final_old.subtype()==initial_new.subtype())
265+
{
266+
// update the type to enable the use of sizeof(x) on the
267+
// right-hand side of a definition of x
268+
old_symbol.type=new_symbol.type;
269+
}
259270

260271
// do initializer, this may change the type
261272
if(follow(new_symbol.type).id()!=ID_code &&
@@ -386,36 +397,14 @@ void c_typecheck_baset::typecheck_redefinition_non_type(
386397
if(final_old!=final_new)
387398
{
388399
if(final_old.id()==ID_array &&
389-
to_array_type(final_old).size().is_nil() &&
390-
final_new.id()==ID_array &&
391-
to_array_type(final_new).size().is_not_nil() &&
392-
final_old.subtype()==final_new.subtype())
400+
to_array_type(final_old).size().is_nil() &&
401+
final_new.id()==ID_array &&
402+
to_array_type(final_new).size().is_not_nil() &&
403+
final_old.subtype()==final_new.subtype())
393404
{
394-
// this is also ok
395-
if(old_symbol.type.id()==ID_symbol)
396-
{
397-
// fix the symbol, not just the type
398-
const irep_idt identifier=
399-
to_symbol_type(old_symbol.type).get_identifier();
400-
401-
symbol_tablet::symbolst::iterator s_it=
402-
symbol_table.symbols.find(identifier);
403-
404-
if(s_it==symbol_table.symbols.end())
405-
{
406-
error().source_location=old_symbol.location;
407-
error() << "typecheck_redefinition_non_type: "
408-
<< "failed to find symbol `" << identifier << "'"
409-
<< eom;
410-
throw 0;
411-
}
412-
413-
symbolt &symbol=s_it->second;
414-
415-
symbol.type=final_new;
416-
}
417-
else
418-
old_symbol.type=new_symbol.type;
405+
// we don't do symbol types for arrays anymore
406+
PRECONDITION(old_symbol.type.id()!=ID_symbol);
407+
old_symbol.type=new_symbol.type;
419408
}
420409
else if((final_old.id()==ID_incomplete_c_enum ||
421410
final_old.id()==ID_c_enum) &&

0 commit comments

Comments
 (0)