diff --git a/chibicc.h b/chibicc.h index 509d595b39c7f1e3aed77d0516b291a93fb7d0a8..30a26fd7f11eb2fc654ee1b5754ef1a758c3be7c 100644 --- a/chibicc.h +++ b/chibicc.h @@ -164,6 +164,7 @@ Program *program(); // typedef enum { + TY_VOID, TY_CHAR, TY_SHORT, TY_INT, @@ -192,6 +193,7 @@ struct Member { }; int align_to(int n, int align); +Type *void_type(); Type *char_type(); Type *short_type(); Type *int_type(); diff --git a/parse.c b/parse.c index 7557efddf1e0a4db26c1ecf28aaa2ccfc3ffbb93..03e8eebe1cdc900a5ff3f5bba109554f4ea4b9c2 100644 --- a/parse.c +++ b/parse.c @@ -170,11 +170,13 @@ Program *program() { } // type-specifier = builtin-type | struct-decl | typedef-name -// builtin-type = "char" | "short" | "int" | "long" +// builtin-type = "void" | "char" | "short" | "int" | "long" Type *type_specifier() { if (!is_typename(token)) error_tok(token, "typename expected"); + if (consume("void")) + return void_type(); if (consume("char")) return char_type(); if (consume("short")) @@ -364,8 +366,11 @@ Node *declaration() { char *name = NULL; ty = declarator(ty, &name); ty = type_suffix(ty); - Var *var = push_var(name, ty, true); + if (ty->kind == TY_VOID) + error_tok(tok, "variable declared void"); + + Var *var = push_var(name, ty, true); if (consume(";")) return new_node(ND_NULL, tok); @@ -383,8 +388,8 @@ Node *read_expr_stmt() { } bool is_typename() { - return peek("char") || peek("short") || peek("int") || peek("long") || - peek("struct") || find_typedef(token); + return peek("void") || peek("char") || peek("short") || peek("int") || + peek("long") || peek("struct") || find_typedef(token); } // stmt = "return" expr ";" diff --git a/tests b/tests index 6aec64fa39793e2cec95206b4462c88495facf8f..bb0073a7922739ebf85e38cd1ddec37c4bf0dcaf 100644 --- a/tests +++ b/tests @@ -273,6 +273,8 @@ int main() { assert(3, *g1_ptr(), "*g1_ptr()"); + { void *x; } + printf("OK\n"); return 0; } diff --git a/tokenize.c b/tokenize.c index 3eae8c50d1435b32faf42eea5a2c0c123d35c6ad..8acdfdfa901478b40b618f682c77bdb06fe967ad 100644 --- a/tokenize.c +++ b/tokenize.c @@ -153,7 +153,7 @@ char *starts_with_reserved(char *p) { // Keyword static char *kw[] = {"return", "if", "else", "while", "for", "int", "char", "sizeof", "struct", "typedef", "short", - "long"}; + "long", "void"}; for (int i = 0; i < sizeof(kw) / sizeof(*kw); i++) { int len = strlen(kw[i]); diff --git a/type.c b/type.c index 5c6bb8b237ebf1cd434f31cc8b5a665595fe2b63..403cfbc1722e7f85cd1a2750a221623f05f6d4ba 100644 --- a/type.c +++ b/type.c @@ -11,6 +11,10 @@ Type *new_type(TypeKind kind, int align) { return ty; } +Type *void_type() { + return new_type(TY_VOID, 1); +} + Type *char_type() { return new_type(TY_CHAR, 1); } @@ -47,6 +51,8 @@ Type *array_of(Type *base, int size) { } int size_of(Type *ty) { + assert(ty->kind != TY_VOID); + switch (ty->kind) { case TY_CHAR: return 1; @@ -144,6 +150,8 @@ void visit(Node *node) { if (!node->lhs->ty->base) error_tok(node->tok, "invalid pointer dereference"); node->ty = node->lhs->ty->base; + if (node->ty->kind == TY_VOID) + error_tok(node->tok, "dereferencing a void pointer"); return; case ND_SIZEOF: node->kind = ND_NUM;