commit 0c67ef96bc161927ea6562f6ba0fa3578132de38 Author: Jiang Date: Mon Aug 18 19:38:23 2014 +0800 Let the following be compiled: struct buffered_lines_head { int *slh_first; }; static int eval_rept() { struct buffered_lines_head { int *slh_first; } lines; return 0; } int main() { struct buffered_lines_head ppp; ppp.slh_first = 0; return 0; } diff --git a/tccgen.c b/tccgen.c index 5fd127f..639ad64 100644 --- a/tccgen.c +++ b/tccgen.c @@ -317,7 +317,7 @@ static void apply_visibility(Sym *sym, CType *type) ElfW(Sym) *esym; esym = &((ElfW(Sym) *)symtab_section->data)[sym->c]; - vis >>= VT_VIS_SHIFT; + vis >>= VT_VIS_SHIFT; esym->st_other = (esym->st_other & ~ELFW(ST_VISIBILITY)(-1)) | vis; } } @@ -2851,15 +2851,17 @@ static void struct_decl(CType *type, int u, int tdef) /* we put an undefined size for struct/union */ s = sym_push(v | SYM_STRUCT, &type1, 0, -1); s->r = 0; /* default alignment is zero as gcc */ - /* put struct/union/enum name in type */ do_decl: - type->t = u; - type->ref = s; - if (tok == '{') { + if (s->c != -1){ + if(local_stack){ + s = sym_push(v | SYM_STRUCT, &type1, 0, -1); + s->r = 0; /* default alignment is zero as gcc */ + }else{ + tcc_error("struct/union/enum already defined"); + } + } next(); - if (s->c != -1) - tcc_error("struct/union/enum already defined"); /* cannot be empty */ c = 0; /* non empty enums are not allowed */ @@ -2900,9 +2902,9 @@ static void struct_decl(CType *type, int u, int tdef) while (tok != '}') { parse_btype(&btype, &ad); while (1) { - if (flexible) - tcc_error("flexible array member '%s' not at the end of struct", - get_tok_str(v, NULL)); + if (flexible) + tcc_error("flexible array member '%s' not at the end of struct", + get_tok_str(v, NULL)); bit_size = -1; v = 0; type1 = btype; @@ -3035,6 +3037,9 @@ static void struct_decl(CType *type, int u, int tdef) s->r = maxalign; } } + /* put struct/union/enum name in type */ + type->t = u; + type->ref = s; } /* return 1 if basic type is a type size (short, long, long long) */ @@ -5704,12 +5709,12 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, } else { /* push global reference */ sym = get_sym_ref(type, sec, addr, size); - vpushsym(type, sym); + vpushsym(type, sym); } /* patch symbol weakness */ if (type->t & VT_WEAK) weaken_symbol(sym); - apply_visibility(sym, type); + apply_visibility(sym, type); #ifdef CONFIG_TCC_BCHECK /* handles bounds now because the symbol must be defined before for the relocation */ @@ -6027,10 +6032,10 @@ static int decl0(int l, int is_for_loop_init) if (sym->type.t & VT_STATIC) type.t = (type.t & ~VT_EXTERN) | VT_STATIC; - /* If the definition has no visibility use the - one from prototype. */ - if (! (type.t & VT_VIS_MASK)) - type.t |= sym->type.t & VT_VIS_MASK; + /* If the definition has no visibility use the + one from prototype. */ + if (! (type.t & VT_VIS_MASK)) + type.t |= sym->type.t & VT_VIS_MASK; if (!is_compatible_types(&sym->type, &type)) { func_error1: diff --git a/tests/tests2/03_struct.c b/tests/tests2/03_struct.c index c5d48c5..3b99e30 100644 --- a/tests/tests2/03_struct.c +++ b/tests/tests2/03_struct.c @@ -1,5 +1,18 @@ #include +truct buffered_lines_head { + int *slh_first; +}; + +static int eval_rept() +{ + /* Test locally defined */ + struct buffered_lines_head { + int *slh_first; + } lines; + return 0; +} + struct fred { int boris; @@ -8,24 +21,27 @@ struct fred int main() { - struct fred bloggs; + struct fred bloggs; + struct buffered_lines_head tst; + /* Test locally defined */ + tst.slh_first = 0; - bloggs.boris = 12; - bloggs.natasha = 34; + bloggs.boris = 12; + bloggs.natasha = 34; - printf("%d\n", bloggs.boris); - printf("%d\n", bloggs.natasha); + printf("%d\n", bloggs.boris); + printf("%d\n", bloggs.natasha); - struct fred jones[2]; - jones[0].boris = 12; - jones[0].natasha = 34; - jones[1].boris = 56; - jones[1].natasha = 78; + struct fred jones[2]; + jones[0].boris = 12; + jones[0].natasha = 34; + jones[1].boris = 56; + jones[1].natasha = 78; - printf("%d\n", jones[0].boris); - printf("%d\n", jones[0].natasha); - printf("%d\n", jones[1].boris); - printf("%d\n", jones[1].natasha); + printf("%d\n", jones[0].boris); + printf("%d\n", jones[0].natasha); + printf("%d\n", jones[1].boris); + printf("%d\n", jones[1].natasha); return 0; }