diff options
| author | seyko <seyko2@gmail.com> | 2015-03-03 15:15:48 +0300 |
|---|---|---|
| committer | seyko <seyko2@gmail.com> | 2015-03-03 15:15:48 +0300 |
| commit | 1a1e9548fba67d321da10dc9f9df858278f5d5ca (patch) | |
| tree | 2bc1386197f9decf9785254bbd61e5462ee96235 | |
| parent | bbf8221ec35d6197c8b717940fd0a24d1956e507 (diff) | |
| download | tinycc-1a1e9548fba67d321da10dc9f9df858278f5d5ca.tar.gz tinycc-1a1e9548fba67d321da10dc9f9df858278f5d5ca.tar.bz2 | |
iitialisation of the empty struct
Current tcc don't understand an initialization of the empty struct
This problem was found trying to compile a linux kernel 2.4.26
which can be compiled by tcc 0.9.23
A test program:
////////////////////
// ./tcc -c test_3.c
// test_3.c:31: error: too many field init
#undef __GNUC__
#undef __GNUC_MINOR__
#define __GNUC__ 2
#define __GNUC_MINOR__ 95
typedef struct { } rwlock_t;
struct fs_struct {
int count;
rwlock_t lock;
int umask;
};
#define INIT_FS { \
1, \
RW_LOCK_UNLOCKED, \
0022, \
}
#if (__GNUC__ > 2 || __GNUC_MINOR__ > 91)
typedef struct { } rwlock_t;
#define RW_LOCK_UNLOCKED (rwlock_t) { }
#else
typedef struct { int gcc_is_buggy; } rwlock_t;
#define RW_LOCK_UNLOCKED (rwlock_t) { 0 }
#endif
static struct fs_struct init_fs = INIT_FS;
// static struct fs_struct init_fs = { { (1) }, (rwlock_t) { 0 }, 0022, };
// ^ with this all Ok
// static struct fs_struct init_fs = { { (1) }, (rwlock_t) { }, 0022, };
// ^ current tcc don't understand, but tcc 0.9.23 can
int main()
{
return 0;
}
////////////////////
A regression is detected after a patch 69fdb57eddd00c592828605819f0678522d346c6
////////////////////
// A test for patch 69fdb57eddd00c592828605819f0678522d346c6
// Author: grischka <grischka>
// Date: Wed Jun 17 02:09:07 2009 +0200
// unions: initzialize only one field
// struct {
// union {
// int a,b;
// };
// int c;
// } sss = { 1,2 };
// This had previously assigned 1,2 to a,b and 0 to c which is wrong.
//
// Expected: sss.a=1 sss.b=1 sss.c=2
int main()
{
struct {
union {
int a,b;
};
int c;
} sss = { 1, 2 };
printf ("sss.a=%d sss.b=%d sss.c=%d\n", sss.a, sss.b, sss.c);
return 0;
}
////////////////////
| -rw-r--r-- | tccgen.c | 20 |
1 files changed, 20 insertions, 0 deletions
@@ -5525,10 +5525,30 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c, /* gr: skip fields from same union - ugly. */ while (f->next) { + int align = 0; + int f_size = type_size(&f->type, &align); + int f_type = (f->type.t & VT_BTYPE); + ///printf("index: %2d %08x -- %2d %08x\n", f->c, f->type.t, f->next->c, f->next->type.t); /* test for same offset */ if (f->next->c != f->c) break; + if ((f_type == VT_STRUCT) && (f_size == 0)) { + /* + Lets assume a structure of size 0 can't be a member of the union. + This allow to compile the following code from a linux kernel v2.4.26 + typedef struct { } rwlock_t; + struct fs_struct { + int count; + rwlock_t lock; + int umask; + }; + struct fs_struct init_fs = { { (1) }, (rwlock_t) {}, 0022, }; + tcc-0.9.23 can succesfully compile this version of the kernel. + gcc don't have problems with this code too. + */ + break; + } /* if yes, test for bitfield shift */ if ((f->type.t & VT_BITFIELD) && (f->next->type.t & VT_BITFIELD)) { int bit_pos_1 = (f->type.t >> VT_STRUCT_SHIFT) & 0x3f; |
