diff --git a/ccc.h b/ccc.h index 2c491d6..cb7f735 100644 --- a/ccc.h +++ b/ccc.h @@ -188,6 +188,7 @@ struct Type { struct Member { Member *next; Type *ty; + Token *tok; char *name; int offset; }; diff --git a/codegen.c b/codegen.c index 1977929..921e9e1 100644 --- a/codegen.c +++ b/codegen.c @@ -305,7 +305,7 @@ void gen(Node *node) { load(node->ty); inc(node); store(node->ty); - dec(node->ty); + dec(node); return; case ND_POST_DEC: gen_lval(node->lhs); @@ -313,7 +313,7 @@ void gen(Node *node) { load(node->ty); dec(node); store(node->ty); - inc(node->ty); + inc(node); return; case ND_A_ADD: case ND_A_SUB: diff --git a/parse.c b/parse.c index a476306..5e5fe4f 100644 --- a/parse.c +++ b/parse.c @@ -102,7 +102,7 @@ VarScope *push_scope(char *name) { return sc; } -Var *push_var(char *name, Type *ty, bool is_local, Token* tok) { +Var *push_var(char *name, Type *ty, bool is_local, Token *tok) { Var *var = calloc(1, sizeof(Var)); var->name = name; var->ty = ty; @@ -348,11 +348,18 @@ Type *type_suffix(Type *ty) { if (!consume("[")) { return ty; } - + int sz = 0; bool is_incomplete = true; + if (!consume("]")) { + sz = expect_number(); + is_incomplete = false; + expect("]"); + } ty = type_suffix(ty); - return array_of(ty, sz); + ty = array_of(ty, sz); + ty->is_incomplete = is_incomplete; + return ty; } // type-name = type-specifier abstract-declarator type-suffix @@ -408,7 +415,7 @@ Type *struct_decl() { for (Member *mem = ty->members; mem; mem = mem->next) { offset = align_to(offset, mem->ty->align); mem->offset = offset; - offset += size_of(mem->ty); + offset += size_of(mem->ty, mem->tok); if (ty->align < mem->ty->align) { ty->align = mem->ty->align; } @@ -472,6 +479,7 @@ Type *enum_specifier() { // struct-member = type-specifier declarator type-suffix ";" Member *struct_member() { Type *ty = type_specifier(); + Token *tok = token; char *name = NULL; ty = declarator(ty, &name); ty = type_suffix(ty); @@ -480,16 +488,18 @@ Member *struct_member() { Member *mem = calloc(1, sizeof(Member)); mem->name = name; mem->ty = ty; + mem->tok = tok; return mem; } VarList *read_func_param() { Type *ty = type_specifier(); char *name = NULL; + Token *tok = token; ty = declarator(ty, &name); ty = type_suffix(ty); - Var *var = push_var(name, ty, true); + Var *var = push_var(name, ty, true, tok); push_scope(name)->var = var; VarList *vl = calloc(1, sizeof(VarList)); @@ -520,10 +530,11 @@ Function *function() { Type *ty = type_specifier(); char *name = NULL; + Token *tok = token; ty = declarator(ty, &name); // Add a function type to the scope - Var *var = push_var(name, func_type(ty), false); + Var *var = push_var(name, func_type(ty), false, tok); push_scope(name)->var = var; // construct a function object @@ -555,22 +566,24 @@ Function *function() { void global_var() { Type *ty = type_specifier(); char *name = NULL; + Token *tok = token; ty = declarator(ty, &name); ty = type_suffix(ty); expect(";"); - Var *var = push_var(name, ty, false); + Var *var = push_var(name, ty, false, tok); push_scope(name)->var = var; } // declaration = type-specifier declarator type-suffix ("=" expr)? ";" // = type-specifier ";" Node *declaration() { - Token *tok = token; + Token *tok = tok; Type *ty = type_specifier(); - if (consume(";")) { + if (tok = consume(";")) { return new_node(ND_NULL, tok); } + tok = token; char *name = NULL; ty = declarator(ty, &name); ty = type_suffix(ty); @@ -588,9 +601,9 @@ Node *declaration() { Var *var; if (ty->is_static) { - var = push_var(new_label(), ty, false); + var = push_var(new_label(), ty, false, tok); } else { - var = push_var(name, ty, true); + var = push_var(name, ty, true, tok); } push_scope(name)->var = var; if (consume(";")) { @@ -651,8 +664,7 @@ Node *stmt() { Node *node = new_node(ND_FOR, tok); expect("("); - VarScope *sc1 = var_scope; - TagScope *sc2 = tag_scope; + Scope *sc = enter_scope(); if (!consume(";")) { if (is_typename()) { @@ -672,8 +684,7 @@ Node *stmt() { } node->then = stmt(); - var_scope = sc1; - tag_scope = sc2; + leave_scope(sc); return node; } if (tok = consume("{")) { @@ -681,14 +692,12 @@ Node *stmt() { head.next = NULL; Node *cur = &head; - VarScope *sc1 = var_scope; - TagScope *sc2 = tag_scope; + Scope *sc = enter_scope(); while (!consume("}")) { cur->next = stmt(); cur = cur->next; } - var_scope = sc1; - tag_scope = sc2; + leave_scope(sc); Node *node = new_node(ND_BLOCK, tok); node->body = head.next; return node; @@ -936,8 +945,7 @@ Node *postfix() { // // statement expression is a GNU C extension Node *stmt_expr(Token *tok) { - VarScope *sc1 = var_scope; - TagScope *sc2 = tag_scope; + Scope *sc = enter_scope(); Node *node = new_node(ND_STMT_EXPR, tok); node->body = stmt(); Node *cur = node->body; @@ -948,8 +956,7 @@ Node *stmt_expr(Token *tok) { } expect(")"); - var_scope = sc1; - tag_scope = sc2; + leave_scope(sc); if (cur->kind != ND_EXPR_STMT) { error_tok(cur->tok, "stmt expr returning void is not supporsed"); @@ -993,7 +1000,7 @@ Node *primary() { if (is_typename()) { Type *ty = type_name(); expect(")"); - return new_num(size_of(ty), tok); + return new_num(size_of(ty, tok), tok); } token = tok->next; } @@ -1032,7 +1039,7 @@ Node *primary() { token = token->next; Type *ty = array_of(char_type(), tok->cont_len); - Var *var = push_var(new_label(), ty, false); + Var *var = push_var(new_label(), ty, false, NULL); var->contents = tok->contents; var->cont_len = tok->cont_len; return new_var(var, tok); diff --git a/type.c b/type.c index 861fa06..697c96c 100644 --- a/type.c +++ b/type.c @@ -41,8 +41,11 @@ Type* array_of(Type* base, int size) { return ty; } -int size_of(Type* ty) { +int size_of(Type* ty, Token* tok) { assert(ty->kind != TY_VOID); + if (ty->is_incomplete) { + error_tok(tok, "incomplete type"); + } switch (ty->kind) { case TY_BOOL: case TY_CHAR: @@ -58,14 +61,14 @@ int size_of(Type* ty) { return 8; case TY_ARRAY: assert(ty->kind == TY_ARRAY); - return size_of(ty->base) * ty->array_size; + return size_of(ty->base, tok) * ty->array_size; default: assert(ty->kind == TY_STRUCT); Member* mem = ty->members; while (mem->next) { mem = mem->next; } - int end = mem->offset + size_of(mem->ty); + int end = mem->offset + size_of(mem->ty, mem->tok); return align_to(end, ty->align); } } @@ -186,7 +189,7 @@ void visit(Node* node) { case ND_SIZEOF: node->kind = ND_NUM; node->ty = int_type(); - node->val = size_of(node->lhs->ty); + node->val = size_of(node->lhs->ty, node->tok); node->lhs = NULL; return; case ND_STMT_EXPR: {