From 6f24dbde5b5a1a92bf59ea1b595cbce6e9382777 Mon Sep 17 00:00:00 2001 From: Rui Ueyama Date: Tue, 13 Aug 2019 21:03:20 +0900 Subject: [PATCH] Add a notion of an incomplete array type --- chibi.h | 15 +++++++++------ parse.c | 44 +++++++++++++++++++++++++++++++++++++------- 2 files changed, 46 insertions(+), 13 deletions(-) diff --git a/chibi.h b/chibi.h index b4683c4..903789d 100644 --- a/chibi.h +++ b/chibi.h @@ -201,18 +201,21 @@ typedef enum { struct Type { TypeKind kind; - int size; // sizeof() value - int align; // alignment - Type *base; // pointer or array - int array_len; // array - Member *members; // struct - Type *return_ty; // function + int size; // sizeof() value + int align; // alignment + bool is_incomplete; // incomplete type + + Type *base; // pointer or array + int array_len; // array + Member *members; // struct + Type *return_ty; // function }; // Struct member struct Member { Member *next; Type *ty; + Token *tok; // for error message char *name; int offset; }; diff --git a/parse.c b/parse.c index 43b0b0e..1dfb4b3 100644 --- a/parse.c +++ b/parse.c @@ -372,14 +372,27 @@ static Type *abstract_declarator(Type *ty) { return type_suffix(ty); } -// type-suffix = ("[" num "]" type-suffix)? +// type-suffix = ("[" num? "]" type-suffix)? static Type *type_suffix(Type *ty) { if (!consume("[")) return ty; - int sz = expect_number(); - expect("]"); + + int sz = 0; + bool is_incomplete = true; + if (!consume("]")) { + sz = expect_number(); + is_incomplete = false; + expect("]"); + } + + Token *tok = token; ty = type_suffix(ty); - return array_of(ty, sz); + if (ty->is_incomplete) + error_tok(tok, "incomplete element type"); + + ty = array_of(ty, sz); + ty->is_incomplete = is_incomplete; + return ty; } // type-name = basetype abstract-declarator type-suffix @@ -430,6 +443,9 @@ static Type *struct_decl(void) { // Assign offsets within the struct to members. int offset = 0; for (Member *mem = ty->members; mem; mem = mem->next) { + if (mem->ty->is_incomplete) + error_tok(mem->tok, "incomplete struct member"); + offset = align_to(offset, mem->ty->align); mem->offset = offset; offset += mem->ty->size; @@ -501,6 +517,7 @@ static Type *enum_specifier(void) { // struct-member = basetype declarator type-suffix ";" static Member *struct_member(void) { Type *ty = basetype(NULL); + Token *tok = token; char *name = NULL; ty = declarator(ty, &name); ty = type_suffix(ty); @@ -509,6 +526,7 @@ static Member *struct_member(void) { Member *mem = calloc(1, sizeof(Member)); mem->name = name; mem->ty = ty; + mem->tok = tok; return mem; } @@ -587,14 +605,18 @@ static void global_var(void) { StorageClass sclass; Type *ty = basetype(&sclass); char *name = NULL; + Token *tok = token; ty = declarator(ty, &name); ty = type_suffix(ty); expect(";"); - if (sclass == TYPEDEF) + if (sclass == TYPEDEF) { push_scope(name)->type_def = ty; - else + } else { + if (ty->is_incomplete) + error_tok(tok, "incomplete type"); new_gvar(name, ty, true); + } } // declaration = basetype declarator type-suffix ("=" expr)? ";" @@ -603,9 +625,10 @@ static Node *declaration(void) { Token *tok = token; StorageClass sclass; Type *ty = basetype(&sclass); - if (consume(";")) + if (tok = consume(";")) return new_node(ND_NULL, tok); + tok = token; char *name = NULL; ty = declarator(ty, &name); ty = type_suffix(ty); @@ -620,6 +643,9 @@ static Node *declaration(void) { error_tok(tok, "variable declared void"); Var *var = new_lvar(name, ty); + if (ty->is_incomplete) + error_tok(tok, "incomplete type"); + if (consume(";")) return new_node(ND_NULL, tok); @@ -1081,6 +1107,8 @@ static Node *primary(void) { if (consume("(")) { if (is_typename()) { Type *ty = type_name(); + if (ty->is_incomplete) + error_tok(tok, "incomplete type"); expect(")"); return new_num(ty->size, tok); } @@ -1089,6 +1117,8 @@ static Node *primary(void) { Node *node = unary(); add_type(node); + if (node->ty->is_incomplete) + error_tok(node->tok, "incomplete type"); return new_num(node->ty->size, tok); } -- GitLab