aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tccgen.c114
1 files changed, 63 insertions, 51 deletions
diff --git a/tccgen.c b/tccgen.c
index d286dd4..b2a7717 100644
--- a/tccgen.c
+++ b/tccgen.c
@@ -90,6 +90,7 @@ static void vla_runtime_type_size(CType *type, int *a);
static void vla_sp_save(void);
static int is_compatible_parameter_types(CType *type1, CType *type2);
static void expr_type(CType *type);
+static int is_putz;
static int is_force;
ST_FUNC void vpush64(int ty, unsigned long long v);
@@ -5039,11 +5040,11 @@ static void decl_designator(CType *type, Section *sec, unsigned long c,
nb_elems = 1;
if (gnu_ext && (l = is_label()) != 0)
goto struct_field;
+ s = type->ref;
while (tok == '[' || tok == '.') {
if (tok == '[') {
if (!(type->t & VT_ARRAY))
expect("array type");
- s = type->ref;
next();
index = expr_const();
if (index < 0 || (s->c >= 0 && index >= s->c))
@@ -5077,7 +5078,6 @@ static void decl_designator(CType *type, Section *sec, unsigned long c,
struct_field:
if ((type->t & VT_BTYPE) != VT_STRUCT)
expect("struct/union type");
- s = type->ref;
l |= SYM_FIELD;
f = s->next;
while (f) {
@@ -5107,17 +5107,30 @@ static void decl_designator(CType *type, Section *sec, unsigned long c,
} else {
if (type->t & VT_ARRAY) {
index = *cur_index;
- type = pointed_type(type);
- c += index * type_size(type, &align);
+ if (s->c >= 0 && index >= s->c){
+ if(!size_only)
+ tcc_warning("excess elements in array initializer");
+ type = NULL;
+ size_only = 1;
+ }else{
+ type = pointed_type(type);
+ c += index * type_size(type, &align);
+ }
} else {
f = *cur_field;
- if (!f)
- tcc_error("too many field init");
- /* XXX: fix this mess by using explicit storage field */
- type1 = f->type;
- type1.t |= (type->t & ~VT_TYPE);
- type = &type1;
- c += f->c;
+ if (f){
+ /* XXX: fix this mess by using explicit storage field */
+ type1 = f->type;
+ type1.t |= (type->t & ~VT_TYPE);
+ type = &type1;
+ c += f->c;
+ }else{
+ if(!size_only)
+ tcc_warning("excess elements in %s initializer",
+ get_tok_str(s->type.t, NULL));
+ type = NULL;
+ size_only = 1;
+ }
}
}
decl_initializer(type, sec, c, 0, size_only);
@@ -5277,6 +5290,8 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c,
Sym *s, *f;
CType *t1;
+ if(!type)
+ goto Ignore;
if (type->t & VT_VLA) {
int a;
@@ -5367,14 +5382,10 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c,
index = 0;
while (tok != '}') {
decl_designator(type, sec, c, &index, NULL, size_only);
- if (n >= 0 && index >= n)
- tcc_error("index too large");
/* must put zero in holes (note that doing it that way
ensures that it even works with designators) */
- if (!size_only && array_length < index) {
- init_putz(t1, sec, c + array_length * size1,
- (index - array_length) * size1);
- }
+ if (!is_putz && array_length < index)
+ is_putz = 1;
index++;
if (index > array_length)
array_length = index;
@@ -5391,10 +5402,8 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c,
if (!no_oblock)
skip('}');
/* put zeros at the end */
- if (!size_only && n >= 0 && array_length < n) {
- init_putz(t1, sec, c + array_length * size1,
- (n - array_length) * size1);
- }
+ if (!is_putz && n >= 0 && array_length < n)
+ is_putz = 1;
/* patch type size if needed */
if (n < 0)
s->c = array_length;
@@ -5440,46 +5449,44 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c,
n = s->c;
while (tok != '}') {
decl_designator(type, sec, c, NULL, &f, size_only);
- index = f->c;
- if (!size_only && array_length < index) {
- init_putz(type, sec, c + array_length,
- index - array_length);
- }
- index = index + type_size(&f->type, &align1);
- if (index > array_length)
- array_length = index;
+ if(f){
+ index = f->c;
+ if (!is_putz && array_length < index)
+ is_putz = 1;
+ index = index + type_size(&f->type, &align1);
+ if (index > array_length)
+ array_length = index;
- /* gr: skip fields from same union - ugly. */
- while (f->next) {
- ///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 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)
+ /* gr: skip fields from same union - ugly. */
+ while (f->next) {
+ ///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 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)
+ break;
}
-
- f = f->next;
- if (no_oblock && f == NULL)
- break;
if (tok == '}')
break;
skip(',');
}
- /* put zeros at the end */
- if (!size_only && array_length < n) {
- init_putz(type, sec, c + array_length,
- n - array_length);
- }
if (!no_oblock)
skip('}');
+ /* put zeros at the end */
+ if (!is_putz && array_length < n)
+ is_putz = 1;
while (par_count) {
skip(')');
par_count--;
@@ -5489,6 +5496,7 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c,
decl_initializer(type, sec, c, first, size_only);
skip('}');
} else if (size_only) {
+Ignore:
/* just skip expression */
parlevel = parlevel1 = 0;
while ((parlevel > 0 || parlevel1 > 0 ||
@@ -5533,6 +5541,7 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
Sym *flexible_array;
flexible_array = NULL;
+ is_putz = 0;
if ((type->t & VT_BTYPE) == VT_STRUCT) {
Sym *field = type->ref->next;
if (field) {
@@ -5551,7 +5560,8 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
literals). It also simplifies local
initializers handling */
tok_str_new(&init_str);
- if (size < 0 || (flexible_array && has_init)) {
+ if (size < 0 || ((((type->t & VT_BTYPE) == VT_STRUCT) || (type->t & VT_ARRAY)) &&
+ has_init && (tok < TOK_IDENT))){
if (!has_init)
tcc_error("unknown type size");
/* get all init string */
@@ -5742,6 +5752,8 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
#endif
}
if (has_init || (type->t & VT_VLA)) {
+ if(is_putz)
+ init_putz(type, sec, addr, size);
decl_initializer(type, sec, addr, 1, 0);
/* restore parse state if needed */
if (init_str.str) {