Let init_putz one-time generation.

At the same time, increase the GCC style warning
---------------------------------------------------------------------------
int main()
{
	int a[10] = {[5]=5};
	return 0;
}

Disassembly of section .text:

0000000000000000 <main>:
   0:	55                   	push   %rbp
   1:	48 89 e5             	mov    %rsp,%rbp
   4:	48 81 ec 30 00 00 00 	sub    $0x30,%rsp
   b:	b8 05 00 00 00       	mov    $0x5,%eax
  10:	89 45 ec             	mov    %eax,-0x14(%rbp)
  13:	48 b8 14 00 00 00 00 	movabs $0x14,%rax
  1a:	00 00 00
  1d:	49 89 c2             	mov    %rax,%r10
  20:	b8 00 00 00 00       	mov    $0x0,%eax
  25:	48 89 c6             	mov    %rax,%rsi
  28:	48 8d 45 d8          	lea    -0x28(%rbp),%rax
  2c:	48 89 c7             	mov    %rax,%rdi
  2f:	4c 89 d2             	mov    %r10,%rdx
  32:	b8 00 00 00 00       	mov    $0x0,%eax
  37:	e8 fc ff ff ff       	callq  38 <main+0x38>
  3c:	48 b8 10 00 00 00 00 	movabs $0x10,%rax
  43:	00 00 00
  46:	49 89 c2             	mov    %rax,%r10
  49:	b8 00 00 00 00       	mov    $0x0,%eax
  4e:	48 89 c6             	mov    %rax,%rsi
  51:	48 8d 45 f0          	lea    -0x10(%rbp),%rax
  55:	48 89 c7             	mov    %rax,%rdi
  58:	4c 89 d2             	mov    %r10,%rdx
  5b:	b8 00 00 00 00       	mov    $0x0,%eax
  60:	e8 fc ff ff ff       	callq  61 <main+0x61>
  65:	b8 00 00 00 00       	mov    $0x0,%eax
  6a:	e9 00 00 00 00       	jmpq   6f <main+0x6f>
  6f:	c9                   	leaveq
  70:	c3                   	retq

After the patch

0000000000000000 <main>:
   0:	55                   	push   %rbp
   1:	48 89 e5             	mov    %rsp,%rbp
   4:	48 81 ec 30 00 00 00 	sub    $0x30,%rsp
   b:	48 b8 28 00 00 00 00 	movabs $0x28,%rax
  12:	00 00 00
  15:	49 89 c2             	mov    %rax,%r10
  18:	b8 00 00 00 00       	mov    $0x0,%eax
  1d:	48 89 c6             	mov    %rax,%rsi
  20:	48 8d 45 d8          	lea    -0x28(%rbp),%rax
  24:	48 89 c7             	mov    %rax,%rdi
  27:	4c 89 d2             	mov    %r10,%rdx
  2a:	b8 00 00 00 00       	mov    $0x0,%eax
  2f:	e8 fc ff ff ff       	callq  30 <main+0x30>
  34:	b8 05 00 00 00       	mov    $0x5,%eax
  39:	89 45 ec             	mov    %eax,-0x14(%rbp)
  3c:	b8 00 00 00 00       	mov    $0x0,%eax
  41:	e9 00 00 00 00       	jmpq   46 <main+0x46>
  46:	c9                   	leaveq
  47:	c3                   	retq
 -----------------------------------------------------------------------------------
"c5.c"
int main()
{
  // union st
   struct st
   {
    char c;
    short s;
   // char cc[];
    };
   // union st
  struct st
    ss = { 1, 2, 3};
   // int a = ss;
    char cb[1] = {1,2,3};
    return 0;
}

c5.c:12: warning: excess elements in struct initializer
c5.c:14: warning: excess elements in array initializer
c5.c:14: warning: excess elements in array initializer
master
jiang 2014-05-28 22:09:49 +08:00
parent 89134dd7b0
commit d316836008
1 changed files with 64 additions and 52 deletions

116
tccgen.c
View File

@ -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;
}
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) {