scc

Simple C99 Compiler
Log | Files | Refs | README | LICENSE

commit ca4dc0e4231ef4fa8cd322fd21beb4a99e6a0fac
parent 4598b8d587aacaf1df6ff34ee6985061b1303de2
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Mon, 14 Sep 2015 13:59:00 +0200

Add semantic analysis of initializers

Diffstat:
cc1/cc1.h | 2+-
cc1/decl.c | 2+-
cc1/expr.c | 79++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------
3 files changed, 60 insertions(+), 23 deletions(-)

diff --git a/cc1/cc1.h b/cc1/cc1.h @@ -375,7 +375,7 @@ extern bool isnodecmp(int op); extern int negop(int op); extern bool cmpnode(Node *np, TUINT val); extern Node *decay(Node *np); -extern void initializer(Symbol *sym); +extern void initializer(Symbol *sym, Type *tp, int nelem); /* cpp.c */ extern void icpp(void); diff --git a/cc1/decl.c b/cc1/decl.c @@ -674,7 +674,7 @@ identifier(struct decl *dcl) if (sym->token == IDEN && sym->type->op != FTN) emit(ODECL, sym); if (accept('=')) - initializer(sym); + initializer(sym, sym->type, -1); return sym; redeclaration: diff --git a/cc1/expr.c b/cc1/expr.c @@ -978,37 +978,74 @@ condexpr(void) return np; } -/* TODO: check correctness of the initializator */ -/* TODO: emit initializer */ +static void +initlist(Symbol *sym, Type *tp) +{ + int n, toomany = 0; + Type *newtp; + + for (n = 0; ; ++n) { + switch (tp->op) { + case ARY: + if (tp->defined && n >= tp->n.elem && !toomany) { + toomany = 1; + warn("excess elements in array initializer"); + sym = NULL; + } + newtp = tp->type; + break; + case STRUCT: + if (n >= tp->n.elem && !toomany) { + toomany = 1; + warn("excess elements in struct initializer"); + sym = NULL; + } else { + sym = tp->p.fields[n]; + newtp = sym->type; + } + break; + default: + newtp = tp; + warn("braces around scalar initializer"); + if (n > 0 && !toomany) { + toomany = 1; + warn("excess elements in scalar initializer"); + } + break; + } + initializer(sym, newtp, n); + if (!accept(',')) + break; + } + expect('}'); + + if (tp->op == ARY && !tp->defined) { + tp->n.elem = n + 1; + tp->defined = 1; + } +} + void -initializer(Symbol *sym) +initializer(Symbol *sym, Type *tp, int nelem) { Node *np; - Type *tp = sym->type; - int flags = sym->flags, scalar; + int flags = sym->flags; - switch (tp->op) { - case FTN: + if (tp->op == FTN) error("function '%s' is initialized like a variable", sym->name); - case PTR: - case INT: - scalar = 1; - break; - default: - scalar = 0; - break; - } if (accept('{')) { - do { - initializer(sym); - } while (accept(',')); - expect('}'); + initlist(sym, tp); return; } - np = assignop(OINIT, varnode(sym), assign()); + np = assign(); + + /* if !sym it means there are too much initializers */ + if (!sym) + return; + np = assignop(OINIT, varnode(sym), np); - if ((flags & (ISLOCAL|ISPRIVATE|ISGLOBAL)) != 0) { + if ((flags & (ISEXTERN|ISTYPEDEF)) != 0) { if (!np->right->constant) errorp("initializer element is not constant"); emit(OINIT, np);