From 476103724ed8524edb78fe2c2b5cbc5a821169dc Mon Sep 17 00:00:00 2001 From: Rui Ueyama Date: Sun, 11 Aug 2019 15:04:35 +0900 Subject: [PATCH] Make sizeof to accept not only an expression but also a typename Previously, chibicc's sizeof accepted only an expression, so you couldn't write something like `sizeof(int)`. Now it accepts that. --- parse.c | 34 ++++++++++++++++++++++++++++++++++ tests | 18 ++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/parse.c b/parse.c index 7bbf61d..3c0af8a 100644 --- a/parse.c +++ b/parse.c @@ -154,7 +154,9 @@ static char *new_label(void) { static Function *function(void); static Type *basetype(bool *is_typedef); static Type *declarator(Type *ty, char **name); +static Type *abstract_declarator(Type *ty); static Type *type_suffix(Type *ty); +static Type *type_name(void); static Type *struct_decl(void); static Member *struct_member(void); static void global_var(void); @@ -330,6 +332,21 @@ static Type *declarator(Type *ty, char **name) { return type_suffix(ty); } +// abstract-declarator = "*"* ("(" abstract-declarator ")")? type-suffix +static Type *abstract_declarator(Type *ty) { + while (consume("*")) + ty = pointer_to(ty); + + if (consume("(")) { + Type *placeholder = calloc(1, sizeof(Type)); + Type *new_ty = abstract_declarator(placeholder); + expect(")"); + memcpy(placeholder, type_suffix(ty), sizeof(Type)); + return new_ty; + } + return type_suffix(ty); +} + // type-suffix = ("[" num "]" type-suffix)? static Type *type_suffix(Type *ty) { if (!consume("[")) @@ -340,6 +357,13 @@ static Type *type_suffix(Type *ty) { return array_of(ty, sz); } +// type-name = basetype abstract-declarator type-suffix +static Type *type_name(void) { + Type *ty = basetype(NULL); + ty = abstract_declarator(ty); + return type_suffix(ty); +} + static void push_tag_scope(Token *tok, Type *ty) { TagScope *sc = calloc(1, sizeof(TagScope)); sc->next = tag_scope; @@ -831,6 +855,7 @@ static Node *func_args(void) { // primary = "(" "{" stmt-expr-tail // | "(" expr ")" +// | "sizeof" "(" type-name ")" // | "sizeof" unary // | ident func-args? // | str @@ -848,6 +873,15 @@ static Node *primary(void) { } if (tok = consume("sizeof")) { + if (consume("(")) { + if (is_typename()) { + Type *ty = type_name(); + expect(")"); + return new_num(ty->size, tok); + } + token = tok->next; + } + Node *node = unary(); add_type(node); return new_num(node->ty->size, tok); diff --git a/tests b/tests index dc1a4ff..5ce818a 100644 --- a/tests +++ b/tests @@ -301,6 +301,24 @@ int main() { assert(3, ({ MyInt x=3; x; }), "MyInt x=3; x;"); + assert(1, sizeof(char), "sizeof(char)"); + assert(2, sizeof(short), "sizeof(short)"); + assert(2, sizeof(short int), "sizeof(short int)"); + assert(2, sizeof(int short), "sizeof(int short)"); + assert(4, sizeof(int), "sizeof(int)"); + assert(8, sizeof(long), "sizeof(long)"); + assert(8, sizeof(long int), "sizeof(long int)"); + assert(8, sizeof(long int), "sizeof(long int)"); + assert(8, sizeof(char *), "sizeof(char *)"); + assert(8, sizeof(int *), "sizeof(int *)"); + assert(8, sizeof(long *), "sizeof(long *)"); + assert(8, sizeof(int **), "sizeof(int **)"); + assert(8, sizeof(int(*)[4]), "sizeof(int(*)[4])"); + assert(32, sizeof(int*[4]), "sizeof(int(*)[4])"); + assert(16, sizeof(int[4]), "sizeof(int[4])"); + assert(48, sizeof(int[3][4]), "sizeof(int[3][4])"); + assert(8, sizeof(struct {int a; int b;}), "sizeof(struct {int a; int b;})"); + printf("OK\n"); return 0; } -- GitLab