aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2025-05-04 21:25:46 +0900
committernsfisis <nsfisis@gmail.com>2025-05-04 21:43:26 +0900
commit3bfcc240c7c68fd3aff8535df4e9e8e384eb9205 (patch)
tree92d098b47536604f44ad5b7f6702da19c815b654
parent28c604c82bd76ec6bcbb0960ecadd706a6c20614 (diff)
downloadP4Dcc-3bfcc240c7c68fd3aff8535df4e9e8e384eb9205.tar.gz
P4Dcc-3bfcc240c7c68fd3aff8535df4e9e8e384eb9205.tar.zst
P4Dcc-3bfcc240c7c68fd3aff8535df4e9e8e384eb9205.zip
fix forward struct decl
-rw-r--r--main.c18
-rw-r--r--tests/036.sh27
2 files changed, 35 insertions, 10 deletions
diff --git a/main.c b/main.c
index 7b3ae57..25d0274 100644
--- a/main.c
+++ b/main.c
@@ -350,7 +350,7 @@ struct AstNode;
struct Type {
int kind;
struct Type* to;
- struct AstNode* members;
+ struct AstNode* struct_def;
};
struct Type* type_new(int kind) {
@@ -521,7 +521,7 @@ int type_sizeof_struct(struct Type* ty) {
int next_offset = 0;
int struct_align = 0;
- struct AstNode* member = ty->members->next;
+ struct AstNode* member = ty->struct_def->node1->next;
for (0; member; 0) {
int size = type_sizeof(member->ty);
int align = type_alignof(member->ty);
@@ -547,7 +547,7 @@ int type_sizeof_struct(struct Type* ty) {
int type_alignof_struct(struct Type* ty) {
int struct_align = 0;
- struct AstNode* member = ty->members->next;
+ struct AstNode* member = ty->struct_def->node1->next;
for (0; member; 0) {
int align = type_alignof(member->ty);
@@ -567,7 +567,7 @@ int type_offsetof(struct Type* ty, char* name) {
int next_offset = 0;
- struct AstNode* member = ty->members->next;
+ struct AstNode* member = ty->struct_def->node1->next;
for (0; member; 0) {
int size = type_sizeof(member->ty);
int align = type_alignof(member->ty);
@@ -592,7 +592,7 @@ struct Type* type_member_typeof(struct Type* ty, char* name) {
fatal_error("type_offsetof: type is not a struct");
}
- struct AstNode* member = ty->members->next;
+ struct AstNode* member = ty->struct_def->node1->next;
for (0; member; 0) {
if (strcmp(member->name, name) == 0) {
return member->ty;
@@ -856,7 +856,7 @@ struct Type* parse_type(struct Parser* p) {
sprintf(buf, "parse_type: unknown struct, %s", name);
fatal_error(buf);
}
- ty->members = p->structs[struct_index].node1;
+ ty->struct_def = p->structs + struct_index;
} else {
fatal_error("unreachable");
}
@@ -1308,6 +1308,7 @@ struct AstNode* parse_struct_decl_or_def(struct Parser* p) {
}
}
if (struct_index == p->n_structs) {
+ p->structs[struct_index].kind = AST_STRUCT_DEF;
p->structs[struct_index].name = name;
p->n_structs = p->n_structs + 1;
}
@@ -1324,11 +1325,8 @@ struct AstNode* parse_struct_decl_or_def(struct Parser* p) {
struct AstNode* members = parse_struct_members(p);
expect(p, TK_BRACE_R);
expect(p, TK_SEMICOLON);
- struct AstNode* s = ast_new(AST_STRUCT_DEF);
- s->name = name;
- s->node1 = members;
p->structs[struct_index].node1 = members;
- return s;
+ return p->structs + struct_index;
}
struct AstNode* parse_toplevel(struct Parser* p) {
diff --git a/tests/036.sh b/tests/036.sh
new file mode 100644
index 0000000..2a60cf9
--- /dev/null
+++ b/tests/036.sh
@@ -0,0 +1,27 @@
+set -e
+
+cat <<'EOF' > expected
+42
+EOF
+bash ../../test_diff.sh <<'EOF'
+void* calloc();
+int printf();
+
+struct T;
+
+struct S {
+ struct T* a;
+};
+
+struct T {
+ int b;
+};
+
+int main() {
+ struct S* s = calloc(1, sizeof(struct S));
+ s->a = calloc(1, sizeof(struct T));
+ s->a->b = 42;
+ printf("%d\n", s->a->b);
+ return 0;
+}
+EOF