mirror of https://github.com/rui314/chibicc
Add a notion of an incomplete struct type
This commit is contained in:
parent
0993b404fc
commit
f9a327ae97
|
@ -225,6 +225,7 @@ Type *pointer_to(Type *base);
|
|||
Type *func_type(Type *return_ty);
|
||||
Type *array_of(Type *base, int size);
|
||||
Type *enum_type(void);
|
||||
Type *struct_type(void);
|
||||
void add_type(Node *node);
|
||||
|
||||
//
|
||||
|
|
42
parse.c
42
parse.c
|
@ -1060,22 +1060,36 @@ static Type *struct_union_decl(Token **rest, Token *tok) {
|
|||
}
|
||||
|
||||
if (tag && !equal(tok, "{")) {
|
||||
TagScope *sc = find_tag(tag);
|
||||
if (!sc)
|
||||
error_tok(tag, "unknown struct type");
|
||||
*rest = tok;
|
||||
return sc->ty;
|
||||
|
||||
TagScope *sc = find_tag(tag);
|
||||
if (sc)
|
||||
return sc->ty;
|
||||
|
||||
Type *ty = struct_type();
|
||||
ty->size = -1;
|
||||
push_tag_scope(tag, ty);
|
||||
return ty;
|
||||
}
|
||||
|
||||
// Construct a struct object.
|
||||
Type *ty = calloc(1, sizeof(Type));
|
||||
ty->kind = TY_STRUCT;
|
||||
struct_members(rest, tok->next, ty);
|
||||
ty->align = 1;
|
||||
tok = skip(tok, "{");
|
||||
|
||||
// Construct a struct object.
|
||||
Type *ty = struct_type();
|
||||
struct_members(rest, tok, ty);
|
||||
|
||||
if (tag) {
|
||||
// If this is a redefinition, overwrite a previous type.
|
||||
// Otherwise, register the struct type.
|
||||
TagScope *sc = find_tag(tag);
|
||||
if (sc && sc->depth == scope_depth) {
|
||||
*sc->ty = *ty;
|
||||
return sc->ty;
|
||||
}
|
||||
|
||||
// Register the struct type if a name was given.
|
||||
if (tag)
|
||||
push_tag_scope(tag, ty);
|
||||
}
|
||||
|
||||
return ty;
|
||||
}
|
||||
|
||||
|
@ -1084,6 +1098,9 @@ static Type *struct_decl(Token **rest, Token *tok) {
|
|||
Type *ty = struct_union_decl(rest, tok);
|
||||
ty->kind = TY_STRUCT;
|
||||
|
||||
if (ty->size < 0)
|
||||
return ty;
|
||||
|
||||
// Assign offsets within the struct to members.
|
||||
int offset = 0;
|
||||
for (Member *mem = ty->members; mem; mem = mem->next) {
|
||||
|
@ -1103,6 +1120,9 @@ static Type *union_decl(Token **rest, Token *tok) {
|
|||
Type *ty = struct_union_decl(rest, tok);
|
||||
ty->kind = TY_UNION;
|
||||
|
||||
if (ty->size < 0)
|
||||
return ty;
|
||||
|
||||
// If union, we don't have to assign offsets because they
|
||||
// are already initialized to zero. We need to compute the
|
||||
// alignment and the size though.
|
||||
|
|
|
@ -52,6 +52,11 @@ int main() {
|
|||
ASSERT(16, ({ struct {char a; long b;} x; sizeof(x); }));
|
||||
ASSERT(4, ({ struct {char a; short b;} x; sizeof(x); }));
|
||||
|
||||
ASSERT(8, ({ struct foo *bar; sizeof(bar); }));
|
||||
ASSERT(4, ({ struct T *foo; struct T {int x;}; sizeof(struct T); }));
|
||||
ASSERT(1, ({ struct T { struct T *next; int x; } a; struct T b; b.x=1; a.next=&b; a.next->x; }));
|
||||
ASSERT(4, ({ typedef struct T T; struct T { int x; }; sizeof(T); }));
|
||||
|
||||
printf("OK\n");
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue