Let init_putz one-time generation.
authorjiang <30155751@qq.com>
Wed, 28 May 2014 14:09:49 +0000 (28 22:09 +0800)
committerjiang <30155751@qq.com>
Wed, 28 May 2014 14:09:49 +0000 (28 22:09 +0800)
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

tccgen.c

index d286dd4..b2a7717 100644 (file)
--- 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;
-
-            /* 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)
+            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)
+                            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) {