scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | Submodules | README | LICENSE

commit 4187be1a9dd2ee23522cd0dcd78deb046f8c3170
parent e04a52cc00199ad293774ad6b09d5a1d185109ee
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Tue, 25 Jul 2017 06:55:18 +0200

Rewrite initializers

Initializers had strong problems using recursd designated initializers.
This patch had rewrite the code to add recursivty between designator
and initlist.

Diffstat:
Mcc1/init.c | 285++++++++++++++++++++++++++++++++++++++++++-------------------------------------
1 file changed, 153 insertions(+), 132 deletions(-)

diff --git a/cc1/init.c b/cc1/init.c @@ -19,22 +19,19 @@ struct designator { }; struct init { - Type *type; - size_t pos; - size_t max; + TUINT pos; + TUINT max; struct designator *tail; struct designator *head; }; - static TINT -arydesig(Init *ip) +arydesig(Type *tp, Init *ip) { TINT npos; Node *np; - Type *tp = ip->type; - if (ip->type->op != ARY) + if (tp->op != ARY) errorp("array index in non-array initializer"); next(); np = constexpr(); @@ -49,11 +46,10 @@ arydesig(Init *ip) } static TINT -fielddesig(Init *ip) +fielddesig(Type *tp, Init *ip) { int ons; Symbol *sym, **p; - Type *tp = ip->type; if (!(tp->prop & TAGGREG)) errorp("field name not in record or union initializer"); @@ -64,6 +60,7 @@ fielddesig(Init *ip) if (yytoken != IDEN) unexpected(); sym = yylval.sym; + next(); if ((sym->flags & SDECLARED) == 0) { errorp("unknown field '%s' specified in initializer", sym->name); @@ -71,112 +68,119 @@ fielddesig(Init *ip) } for (p = tp->p.fields; *p != sym; ++p) /* nothing */; - next(); return p - tp->p.fields; } static Init * -designation(Init *ip) +init(Init *ip) { - TINT (*fun)(Init *); - - switch (yytoken) { - case '[': fun = arydesig; break; - case '.': fun = fielddesig; break; - default: return ip; - } - - ip->pos = (*fun)(ip); - expect('='); + ip->tail = ip->head = NULL; + ip->pos = ip->max = 0; return ip; } static Node * -initialize(Type *tp) +str2ary(Type *tp) { Node *np; + Type *btp = tp->type;; Symbol *sym; - Type *btp; size_t len; char *s; - int isstring; - if ((tp->op == ARY || tp->op == STRUCT) && - yytoken != '{' && yytoken != STRING) { - return initlist(tp); + np = assign(); + sym = np->left->sym; + if (btp != chartype && btp != uchartype && btp != schartype) { + errorp("array of inappropriate type initialized from string constant"); + return constnode(zero); } - isstring = yytoken == STRING; - np = (yytoken == '{') ? initlist(tp) : assign(); - - if (isstring && tp->op == ARY) { - sym = np->left->sym; - btp = tp->type; - if (btp != chartype && - btp != uchartype && - btp != schartype) { - errorp("array of inappropriate type initialized from string constant"); - goto return_zero; - } - len = sym->type->n.elem-1; - if (!(tp->prop & TDEFINED)) { - tp->n.elem = len+1; - deftype(tp); - } else if (tp->n.elem < len) { - warn("initializer-string for array of chars is too long"); - } - len = tp->n.elem; - s = sym->u.s; - sym = newstring(NULL, len); - strncpy(sym->u.s, s, len); - np->sym = sym; - np->type = sym->type; + len = sym->type->n.elem-1; + if (!(tp->prop & TDEFINED)) { + tp->n.elem = len+1; + deftype(tp); + } else if (tp->n.elem < len) { + warn("initializer-string for array of chars is too long"); + } + + len = tp->n.elem; + s = sym->u.s; + sym = newstring(NULL, len); + strncpy(sym->u.s, s, len); + np->sym = sym; + np->type = sym->type; + return np; +} + +static Node * +initialize(Type *tp) +{ + Node *np; + Symbol *sym; + + if (tp->op == ARY && yytoken == STRING) + return str2ary(tp); + + if (yytoken == '{' || tp->op == STRUCT || tp->op == ARY) + return initlist(tp); + + np = assign(); + if (eqtype(tp, np->type, 1)) return np; - } else { - if (eqtype(tp, np->type, 1)) - return np; - np = convert(decay(np), tp, 0); - if (!np) { - errorp("incorrect initializer"); - goto return_zero; - } + + np = convert(decay(np), tp, 0); + if (!np) { + errorp("incorrect initializer"); + return constnode(zero); } - return simplify(np); -return_zero: - return constnode(zero); + return simplify(np); } static Node * -mkcompound(Init *ip) +mkcompound(Init *ip, Type *tp) { Node **v, **p; size_t n; struct designator *dp, *next; Symbol *sym; - if ((n = ip->max) == 0) { - v = NULL; - } else if (n > SIZE_MAX / sizeof(*v)) { - errorp("compound literal too big"); - return constnode(zero); - } else { - n *= sizeof(*v); - v = memset(xmalloc(n), 0, n); + if (tp->op == UNION) { + Node *np = NULL; + v = xmalloc(sizeof(*v)); for (dp = ip->head; dp; dp = next) { - p = &v[dp->pos]; - freetree(*p); - *p = dp->expr; + freetree(np); + np = dp->expr; next = dp->next; free(dp); } + *v = np; + } else { + n = (tp->prop&TDEFINED) ? tp->n.elem : ip->max; + if (n == 0) { + v = NULL; + } else if (n > SIZE_MAX / sizeof(*v)) { + errorp("compound literal too big"); + return constnode(zero); + } else { + n *= sizeof(*v); + v = memset(xmalloc(n), 0, n); + + for (dp = ip->head; dp; dp = next) { + p = &v[dp->pos]; + freetree(*p); + *p = dp->expr; + next = dp->next; + free(dp); + } + } } sym = newsym(NS_IDEN, NULL); sym->u.init = v; - sym->type = ip->type; + sym->type = tp; sym->flags |= SINITLST; return constnode(sym); @@ -198,95 +202,114 @@ newdesig(Init *ip, Node *np) ip->tail->next = dp; ip->tail = dp; } + + if (ip->pos+1 > ip->max) + ip->max = ip->pos+1; } Node * initlist(Type *tp) { Init in; - int braces, scalar, toomany, outbound; - Type *newtp; Node *np; + Type *curtp; + int braces, scalar, toomany, outbound; + TINT nelem = tp->n.elem; + static int depth; - in.tail = in.head = NULL; - in.type = tp; - in.pos = 0; - in.max = 0; + if (depth == NR_SUBTYPE) + error("too many nested initializers"); + ++depth; + init(&in); braces = scalar = toomany = 0; if (accept('{')) braces = 1; do { - if (yytoken == '}') - break; - outbound = 0; - designation(&in); - switch (tp->op) { - case ARY: - newtp = tp->type; - if (!(tp->prop & TDEFINED) || in.pos < tp->n.elem) - break; - if (!toomany) - warn("excess elements in array initializer"); - outbound = 1; - toomany = 1; - break; - /* TODO: case UNION: */ - case STRUCT: - if (in.pos < tp->n.elem) { - newtp = tp->p.fields[in.pos]->type; - break; + curtp = inttype; + switch (yytoken) { + case '[': + in.pos = arydesig(tp, &in); + curtp = tp->type; + goto desig_list; + case '.': + in.pos = fielddesig(tp, &in); + if (in.pos < nelem) + curtp = tp->p.fields[in.pos]->type; + desig_list: + if (yytoken == '[' || yytoken == '.') { + np = initlist(curtp); + goto new_desig; } - newtp = inttype; - if (!toomany) - warn("excess elements in struct initializer"); - toomany = 1; - outbound = 1; - break; + expect('='); default: - newtp = tp; - if (!scalar) - warn("braces around scalar initializer"); - scalar = 1; - if (in.pos == 0) + outbound = 0; + + switch (tp->op) { + case ARY: + curtp = tp->type; + if (!(tp->prop & TDEFINED) || in.pos < tp->n.elem) + break; + if (!toomany) + warn("excess elements in array initializer"); + toomany = 1; + outbound = 1; break; - if (!toomany) - warn("excess elements in scalar initializer"); - toomany = 1; - outbound = 1; - break; + case UNION: + case STRUCT: + if (in.pos < nelem) { + curtp = tp->p.fields[in.pos]->type; + break; + } + if (!toomany) + warn("excess elements in struct initializer"); + toomany = 1; + outbound = 1; + break; + default: + curtp = tp; + if (!scalar) + warn("braces around scalar initializer"); + scalar = 1; + if (in.pos == 0) + break; + if (!toomany) + warn("excess elements in scalar initializer"); + toomany = 1; + outbound = 1; + break; + } + np = initialize(curtp); + if (outbound) { + freetree(np); + np = NULL; + } } - np = initialize(newtp); - if (outbound) - freetree(np); - else +new_desig: + if (np) newdesig(&in, np); - if (++in.pos == 0) errorp("compound literal too big"); - if (in.pos > in.max) - in.max = in.pos; - if (tp->n.elem == in.pos && !braces) + if (nelem == in.pos && !braces) break; } while (accept(',')); if (braces) expect('}'); + if (tp->op == ARY && !(tp->prop & TDEFINED)) { tp->n.elem = in.max; deftype(tp); } - if (tp->op == ARY || tp->op == STRUCT) - in.max = tp->n.elem; - else if (in.max == 0) { - errorp("empty scalar initializer"); + if (in.max == 0) { + errorp("empty braced initializer"); return constnode(zero); } - return mkcompound(&in); + return mkcompound(&in, tp); } static void @@ -294,8 +317,6 @@ autoinit(Symbol *sym, Node *np) { Symbol *hidden; Type *tp = sym->type; - size_t n; /* FIXME: It should be SIZET */ - repeat: switch (tp->op) {