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:
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);