commit ce562ff3330645d192da9223cdfc3b87c5319123 Author: Jiang Date: Wed Aug 6 21:05:37 2014 +0800 Improved algorithms struct ('->' and '.') diff --git a/tccgen.c b/tccgen.c index 1a89d4a..1c0adeb 100644 --- a/tccgen.c +++ b/tccgen.c @@ -3835,7 +3835,6 @@ ST_FUNC void unary(void) case TOK_builtin_frame_address: { int level; - CType type; next(); skip('('); if (tok != TOK_CINT || tokc.i < 0) { @@ -3873,7 +3872,6 @@ ST_FUNC void unary(void) #else case TOK_builtin_va_arg_types: { - CType type; next(); skip('('); parse_type(&type); @@ -3997,43 +3995,51 @@ ST_FUNC void unary(void) inc(1, tok); next(); } else if (tok == '.' || tok == TOK_ARROW) { - int qualifiers; - /* field */ - if (tok == TOK_ARROW) - indir(); + int qualifiers, add; + /* field */ qualifiers = vtop->type.t & (VT_CONSTANT | VT_VOLATILE); + add = 0; + if (tok == TOK_ARROW) + indir(); + + type = vtop->type; test_lvalue(); gaddrof(); - next(); - /* expect pointer on structure */ - if ((vtop->type.t & VT_BTYPE) != VT_STRUCT) - expect("struct or union"); - s = vtop->type.ref; - /* find field */ - tok |= SYM_FIELD; - while ((s = s->next) != NULL) { - if (s->v == tok) - break; - } - if (!s) - tcc_error("field not found: %s", get_tok_str(tok & ~SYM_FIELD, NULL)); - /* add field offset to pointer */ vtop->type = char_pointer_type; /* change type to 'char *' */ - vpushi(s->c); + do{ + next(); + /* expect pointer on structure */ + if ((type.t & VT_BTYPE) != VT_STRUCT) + expect("struct or union"); + s = type.ref; + /* find field */ + tok |= SYM_FIELD; + while ((s = s->next) != NULL) { + if (s->v == tok) + break; + } + if (!s) + tcc_error("field not found: %s", get_tok_str(tok & ~SYM_FIELD, NULL)); + /* add bit */ + add += s->c; + /* change type to field type, and set to lvalue */ + type = s->type; + next(); + }while(tok == '.'); + + type.t |= qualifiers; + vpushi(add); gen_op('+'); - /* change type to field type, and set to lvalue */ - vtop->type = s->type; - vtop->type.t |= qualifiers; /* an array is never an lvalue */ - if (!(vtop->type.t & VT_ARRAY)) { - vtop->r |= lvalue_type(vtop->type.t); + if (!(type.t & (VT_ARRAY|VT_VLA))) { + vtop->r |= lvalue_type(type.t); #ifdef CONFIG_TCC_BCHECK /* if bound checking, the referenced pointer must be checked */ if (tcc_state->do_bounds_check) vtop->r |= VT_MUSTBOUND; #endif } - next(); + vtop->type = type; } else if (tok == '[') { next(); gexpr();