commit ca4dc0e4231ef4fa8cd322fd21beb4a99e6a0fac
Author:     Roberto E. Vargas Caballero <[email protected]>
AuthorDate: Mon Sep 14 13:59:00 2015 +0200
Commit:     Roberto E. Vargas Caballero <[email protected]>
CommitDate: Mon Sep 14 14:02:39 2015 +0200

    Add semantic analysis of initializers

diff --git a/cc1/cc1.h b/cc1/cc1.h
index da438c6..addbea9 100644
--- 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
index 000c290..13b328b 100644
--- 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
index 7c405b7..6d3ed17 100644
--- 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);

Reply via email to