Skip to content

Commit

Permalink
When possible, update array types before typechecking initializer
Browse files Browse the repository at this point in the history
This fixes a bug in compiling a Linux kernel driver.
  • Loading branch information
tautschnig committed Sep 7, 2017
1 parent 3273bf5 commit 3613ebc
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 29 deletions.
13 changes: 13 additions & 0 deletions regression/ansi-c/array_initialization3/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#define STATIC_ASSERT_sizeof(condition) \
int[(condition) ? 1 : -1]

int A[];
int B[];

int A[1]={sizeof(A)};
int B[1]={sizeof(STATIC_ASSERT_sizeof(sizeof(B)==sizeof(int)))};

int main()
{
return 0;
}
8 changes: 8 additions & 0 deletions regression/ansi-c/array_initialization3/test.desc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
CORE
main.c

^EXIT=0$
^SIGNAL=0$
--
^warning: ignoring
^CONVERSION ERROR$
47 changes: 18 additions & 29 deletions src/ansi-c/c_typecheck_base.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Author: Daniel Kroening, [email protected]

#include "c_typecheck_base.h"

#include <util/invariant.h>
#include <util/std_types.h>
#include <util/prefix.h>
#include <util/config.h>
Expand Down Expand Up @@ -256,6 +257,16 @@ void c_typecheck_baset::typecheck_redefinition_non_type(
// this is ok, just use old type
new_symbol.type=old_symbol.type;
}
else if(final_old.id()==ID_array &&
to_array_type(final_old).size().is_nil() &&
initial_new.id()==ID_array &&
to_array_type(initial_new).size().is_not_nil() &&
final_old.subtype()==initial_new.subtype())
{
// update the type to enable the use of sizeof(x) on the
// right-hand side of a definition of x
old_symbol.type=new_symbol.type;
}

// do initializer, this may change the type
if(follow(new_symbol.type).id()!=ID_code &&
Expand Down Expand Up @@ -386,36 +397,14 @@ void c_typecheck_baset::typecheck_redefinition_non_type(
if(final_old!=final_new)
{
if(final_old.id()==ID_array &&
to_array_type(final_old).size().is_nil() &&
final_new.id()==ID_array &&
to_array_type(final_new).size().is_not_nil() &&
final_old.subtype()==final_new.subtype())
to_array_type(final_old).size().is_nil() &&
final_new.id()==ID_array &&
to_array_type(final_new).size().is_not_nil() &&
final_old.subtype()==final_new.subtype())
{
// this is also ok
if(old_symbol.type.id()==ID_symbol)
{
// fix the symbol, not just the type
const irep_idt identifier=
to_symbol_type(old_symbol.type).get_identifier();

symbol_tablet::symbolst::iterator s_it=
symbol_table.symbols.find(identifier);

if(s_it==symbol_table.symbols.end())
{
error().source_location=old_symbol.location;
error() << "typecheck_redefinition_non_type: "
<< "failed to find symbol `" << identifier << "'"
<< eom;
throw 0;
}

symbolt &symbol=s_it->second;

symbol.type=final_new;
}
else
old_symbol.type=new_symbol.type;
// we don't do symbol types for arrays anymore
PRECONDITION(old_symbol.type.id()!=ID_symbol);
old_symbol.type=new_symbol.type;
}
else if((final_old.id()==ID_incomplete_c_enum ||
final_old.id()==ID_c_enum) &&
Expand Down

0 comments on commit 3613ebc

Please sign in to comment.