forked from Mirrors/tinycc
struct-init: Cleanup
Remove dead code and variables. Properly check for unions when skipping fields in initializers. Make tests2/*.expect depend on the .c files so they are automatically rebuilt when the latter change.master
parent
ed7d54651d
commit
7bf323843e
114
tccgen.c
114
tccgen.c
|
@ -3209,6 +3209,7 @@ static void struct_decl(CType *type, AttributeDef *ad, int u)
|
||||||
} else {
|
} else {
|
||||||
v = anon_sym++;
|
v = anon_sym++;
|
||||||
}
|
}
|
||||||
|
/* Record the original enum/struct/union token. */
|
||||||
type1.t = a;
|
type1.t = a;
|
||||||
type1.ref = NULL;
|
type1.ref = NULL;
|
||||||
/* we put an undefined size for struct/union */
|
/* we put an undefined size for struct/union */
|
||||||
|
@ -5650,7 +5651,6 @@ static void block(int *bsym, int *csym, int is_expr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define EXPR_VAL 0
|
|
||||||
#define EXPR_CONST 1
|
#define EXPR_CONST 1
|
||||||
#define EXPR_ANY 2
|
#define EXPR_ANY 2
|
||||||
|
|
||||||
|
@ -5795,8 +5795,7 @@ static void decl_designator(CType *type, Section *sec, unsigned long c,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* store a value or an expression directly in global data or in local array */
|
/* store a value or an expression directly in global data or in local array */
|
||||||
static void init_putv(CType *type, Section *sec, unsigned long c,
|
static void init_putv(CType *type, Section *sec, unsigned long c)
|
||||||
int v, int expr_type)
|
|
||||||
{
|
{
|
||||||
int bt, bit_pos, bit_size;
|
int bt, bit_pos, bit_size;
|
||||||
void *ptr;
|
void *ptr;
|
||||||
|
@ -6039,8 +6038,7 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c,
|
||||||
else
|
else
|
||||||
ch = ((nwchar_t *)tokc.str.data)[i];
|
ch = ((nwchar_t *)tokc.str.data)[i];
|
||||||
vpushi(ch);
|
vpushi(ch);
|
||||||
init_putv(t1, sec, c + (array_length + i) * size1,
|
init_putv(t1, sec, c + (array_length + i) * size1);
|
||||||
ch, EXPR_VAL);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6052,7 +6050,7 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c,
|
||||||
if (n < 0 || array_length < n) {
|
if (n < 0 || array_length < n) {
|
||||||
if (!size_only) {
|
if (!size_only) {
|
||||||
vpushi(0);
|
vpushi(0);
|
||||||
init_putv(t1, sec, c + (array_length * size1), 0, EXPR_VAL);
|
init_putv(t1, sec, c + (array_length * size1));
|
||||||
}
|
}
|
||||||
array_length++;
|
array_length++;
|
||||||
}
|
}
|
||||||
|
@ -6092,57 +6090,9 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c,
|
||||||
/* patch type size if needed */
|
/* patch type size if needed */
|
||||||
if (n < 0)
|
if (n < 0)
|
||||||
s->c = array_length;
|
s->c = array_length;
|
||||||
} else if (1 && have_elem && is_compatible_types(type, &vtop->type)) {
|
} else if (have_elem && is_compatible_types(type, &vtop->type)) {
|
||||||
/* currently, we always use constant expression for globals
|
init_putv(type, sec, c);
|
||||||
(may change for scripting case) */
|
} else if ((type->t & VT_BTYPE) == VT_STRUCT) {
|
||||||
expr_type = !sec ? EXPR_ANY : EXPR_CONST;
|
|
||||||
init_putv(type, sec, c, 0, expr_type);
|
|
||||||
} else if ((type->t & VT_BTYPE) == VT_STRUCT &&
|
|
||||||
(!first || tok == '{')) {
|
|
||||||
|
|
||||||
/* NOTE: the previous test is a specific case for automatic
|
|
||||||
struct/union init */
|
|
||||||
/* XXX: union needs only one init */
|
|
||||||
|
|
||||||
int par_count = 0;
|
|
||||||
if (0 && tok == '(') {
|
|
||||||
AttributeDef ad1;
|
|
||||||
CType type1;
|
|
||||||
next();
|
|
||||||
if (tcc_state->old_struct_init_code) {
|
|
||||||
/* an old version of struct initialization.
|
|
||||||
It have a problems. But with a new version
|
|
||||||
linux 2.4.26 can't load ramdisk.
|
|
||||||
*/
|
|
||||||
while (tok == '(') {
|
|
||||||
par_count++;
|
|
||||||
next();
|
|
||||||
}
|
|
||||||
if (!parse_btype(&type1, &ad1))
|
|
||||||
expect("cast");
|
|
||||||
type_decl(&type1, &ad1, &n, TYPE_ABSTRACT);
|
|
||||||
#if 0
|
|
||||||
if (!is_assignable_types(type, &type1))
|
|
||||||
tcc_error("invalid type for cast");
|
|
||||||
#endif
|
|
||||||
skip(')');
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (tok != '(') {
|
|
||||||
if (!parse_btype(&type1, &ad1))
|
|
||||||
expect("cast");
|
|
||||||
type_decl(&type1, &ad1, &n, TYPE_ABSTRACT);
|
|
||||||
#if 0
|
|
||||||
if (!is_assignable_types(type, &type1))
|
|
||||||
tcc_error("invalid type for cast");
|
|
||||||
#endif
|
|
||||||
skip(')');
|
|
||||||
} else
|
|
||||||
unget_tok(tok);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
no_oblock = 1;
|
no_oblock = 1;
|
||||||
if (first || tok == '{') {
|
if (first || tok == '{') {
|
||||||
skip('{');
|
skip('{');
|
||||||
|
@ -6165,44 +6115,10 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c,
|
||||||
if (index > array_length)
|
if (index > array_length)
|
||||||
array_length = index;
|
array_length = index;
|
||||||
|
|
||||||
/* gr: skip fields from same union - ugly. */
|
if (s->type.t == TOK_UNION)
|
||||||
while (f->next) {
|
f = NULL;
|
||||||
int align = 0;
|
else
|
||||||
int f_size = type_size(&f->type, &align);
|
f = f->next;
|
||||||
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;
|
|
||||||
int bit_pos_2 = (f->next->type.t >> VT_STRUCT_SHIFT) & 0x3f;
|
|
||||||
//printf("bitfield %d %d\n", bit_pos_1, bit_pos_2);
|
|
||||||
if (bit_pos_1 != bit_pos_2)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
f = f->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
f = f->next;
|
|
||||||
if (no_oblock && f == NULL)
|
if (no_oblock && f == NULL)
|
||||||
break;
|
break;
|
||||||
if (tok == '}')
|
if (tok == '}')
|
||||||
|
@ -6216,10 +6132,6 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c,
|
||||||
}
|
}
|
||||||
if (!no_oblock)
|
if (!no_oblock)
|
||||||
skip('}');
|
skip('}');
|
||||||
while (par_count) {
|
|
||||||
skip(')');
|
|
||||||
par_count--;
|
|
||||||
}
|
|
||||||
} else if (tok == '{') {
|
} else if (tok == '{') {
|
||||||
next();
|
next();
|
||||||
if (have_elem)
|
if (have_elem)
|
||||||
|
@ -6256,9 +6168,7 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c,
|
||||||
expect("string constant");
|
expect("string constant");
|
||||||
parse_init_elem(!sec ? EXPR_ANY : EXPR_CONST);
|
parse_init_elem(!sec ? EXPR_ANY : EXPR_CONST);
|
||||||
}
|
}
|
||||||
/* currently, we always use constant expression for globals
|
init_putv(type, sec, c);
|
||||||
(may change for scripting case) */
|
|
||||||
init_putv(type, sec, c, 0, expr_type);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -67,6 +67,16 @@ struct V gv3 = {((struct S){7,8,{9,10}}), {"hoho", 49}, 50};
|
||||||
/* Initialization of a flex array member (warns in GCC) */
|
/* Initialization of a flex array member (warns in GCC) */
|
||||||
struct W gw = {{1,2,3,4}, {1,2,3,4,5}};
|
struct W gw = {{1,2,3,4}, {1,2,3,4,5}};
|
||||||
|
|
||||||
|
union UU {
|
||||||
|
u8 a;
|
||||||
|
u8 b;
|
||||||
|
};
|
||||||
|
struct SU {
|
||||||
|
union UU u;
|
||||||
|
u8 c;
|
||||||
|
};
|
||||||
|
struct SU gsu = {5,6};
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
void print_ (const char *name, const u8 *p, long size)
|
void print_ (const char *name, const u8 *p, long size)
|
||||||
{
|
{
|
||||||
|
@ -133,6 +143,7 @@ int main()
|
||||||
print(gv3);
|
print(gv3);
|
||||||
print(sinit16);
|
print(sinit16);
|
||||||
print(gw);
|
print(gw);
|
||||||
|
print(gsu);
|
||||||
foo(&gw);
|
foo(&gw);
|
||||||
//printf("q: %s\n", q);
|
//printf("q: %s\n", q);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -12,6 +12,7 @@ gv2: 7 8 9 a 68 69 68 69 0 0 0 0 0 0 0 0 0 0 0 0 2f 30
|
||||||
gv3: 7 8 9 a 68 6f 68 6f 0 0 0 0 0 0 0 0 0 0 0 0 31 32
|
gv3: 7 8 9 a 68 6f 68 6f 0 0 0 0 0 0 0 0 0 0 0 0 31 32
|
||||||
sinit16: 1 0 0 0 2 0 0 0
|
sinit16: 1 0 0 0 2 0 0 0
|
||||||
gw: 1 2 3 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
gw: 1 2 3 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||||
|
gsu: 5 6
|
||||||
ls: 1 2 3 4
|
ls: 1 2 3 4
|
||||||
ls2: 1 2 3 4
|
ls2: 1 2 3 4
|
||||||
lt: 68 65 6c 6c 6f 0 0 0 0 0 0 0 0 0 0 0 2a
|
lt: 68 65 6c 6c 6f 0 0 0 0 0 0 0 0 0 0 0 2a
|
||||||
|
|
|
@ -53,7 +53,7 @@ all test: $(filter-out $(SKIP),$(TESTS))
|
||||||
@diff -Nbu $(SRC)/$*.expect $*.output && rm -f $*.output
|
@diff -Nbu $(SRC)/$*.expect $*.output && rm -f $*.output
|
||||||
|
|
||||||
# automatically generate .expect files with gcc:
|
# automatically generate .expect files with gcc:
|
||||||
%.expect :
|
%.expect : %.c
|
||||||
(gcc -w $*.c -o a.exe && ./a.exe $(ARGS)) >$*.expect 2>&1; rm -f a.exe
|
(gcc -w $*.c -o a.exe && ./a.exe $(ARGS)) >$*.expect 2>&1; rm -f a.exe
|
||||||
|
|
||||||
# tell make not to delete
|
# tell make not to delete
|
||||||
|
|
Loading…
Reference in New Issue