ref: ca4dc0e4231ef4fa8cd322fd21beb4a99e6a0fac
parent: 4598b8d587aacaf1df6ff34ee6985061b1303de2
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Mon Sep 14 09:59:00 EDT 2015
Add semantic analysis of initializers
--- a/cc1/cc1.h
+++ b/cc1/cc1.h
@@ -375,7 +375,7 @@
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);
--- a/cc1/decl.c
+++ b/cc1/decl.c
@@ -674,7 +674,7 @@
if (sym->token == IDEN && sym->type->op != FTN)
emit(ODECL, sym);
if (accept('='))- initializer(sym);
+ initializer(sym, sym->type, -1);
return sym;
redeclaration:
--- a/cc1/expr.c
+++ b/cc1/expr.c
@@ -978,37 +978,74 @@
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 ((flags & (ISLOCAL|ISPRIVATE|ISGLOBAL)) != 0) {+ /* if !sym it means there are too much initializers */
+ if (!sym)
+ return;
+ np = assignop(OINIT, varnode(sym), np);
+
+ if ((flags & (ISEXTERN|ISTYPEDEF)) != 0) {if (!np->right->constant)
errorp("initializer element is not constant");emit(OINIT, np);
--
⑨