aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2025-05-04 20:58:02 +0900
committernsfisis <nsfisis@gmail.com>2025-05-04 21:43:26 +0900
commit576b2064e05633b34de216e04b71407a5f15164b (patch)
treed67667fe75c753323b61778a0be03bbd4a4853ac
parent6c12928c82d694b7b7b96a7b08d61d211f966867 (diff)
downloadP4Dcc-576b2064e05633b34de216e04b71407a5f15164b.tar.gz
P4Dcc-576b2064e05633b34de216e04b71407a5f15164b.tar.zst
P4Dcc-576b2064e05633b34de216e04b71407a5f15164b.zip
fix parse error if function returns a pointer of struct
-rw-r--r--main.c112
-rw-r--r--tests/034.sh17
2 files changed, 76 insertions, 53 deletions
diff --git a/main.c b/main.c
index 9a8de99..5c240ac 100644
--- a/main.c
+++ b/main.c
@@ -1195,59 +1195,6 @@ struct AstNode* parse_stmt(struct Parser* p) {
}
}
-struct AstNode* parse_struct_member(struct Parser* p) {
- struct Type* ty = parse_type(p);
- char* name = parse_ident(p);
- expect(p, TK_SEMICOLON);
- struct AstNode* member = ast_new(AST_STRUCT_MEMBER);
- member->name = name;
- member->ty = ty;
- return member;
-}
-
-struct AstNode* parse_struct_members(struct Parser* p) {
- struct AstNode* list = ast_new_list(AST_STRUCT_MEMBER_LIST);
- for (0; peek_token(p)->kind != TK_BRACE_R; 0) {
- struct AstNode* member = parse_struct_member(p);
- list->last->next = member;
- list->last = member;
- }
- return list;
-}
-
-struct AstNode* parse_struct_decl_or_def(struct Parser* p) {
- expect(p, TK_K_STRUCT);
- char* name = parse_ident(p);
- int struct_index;
- for (struct_index = 0; struct_index < p->n_structs; struct_index = struct_index + 1) {
- if (strcmp(name, p->structs[struct_index].name) == 0) {
- break;
- }
- }
- if (struct_index == p->n_structs) {
- p->structs[struct_index].name = name;
- p->n_structs = p->n_structs + 1;
- }
- if (peek_token(p)->kind == TK_SEMICOLON) {
- next_token(p);
- return ast_new(AST_STRUCT_DECL);
- }
- if (p->structs[struct_index].node1) {
- char* buf = calloc(1024, sizeof(char));
- sprintf(buf, "parse_struct_decl_or_def: struct %s redefined", name);
- fatal_error(buf);
- }
- expect(p, TK_BRACE_L);
- 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;
-}
-
void enter_func(struct Parser* p) {
p->locals = calloc(LVAR_MAX, sizeof(struct LVar));
p->n_locals = 0;
@@ -1319,6 +1266,65 @@ struct AstNode* parse_func_decl_or_def(struct Parser* p) {
return func;
}
+struct AstNode* parse_struct_member(struct Parser* p) {
+ struct Type* ty = parse_type(p);
+ char* name = parse_ident(p);
+ expect(p, TK_SEMICOLON);
+ struct AstNode* member = ast_new(AST_STRUCT_MEMBER);
+ member->name = name;
+ member->ty = ty;
+ return member;
+}
+
+struct AstNode* parse_struct_members(struct Parser* p) {
+ struct AstNode* list = ast_new_list(AST_STRUCT_MEMBER_LIST);
+ for (0; peek_token(p)->kind != TK_BRACE_R; 0) {
+ struct AstNode* member = parse_struct_member(p);
+ list->last->next = member;
+ list->last = member;
+ }
+ return list;
+}
+
+struct AstNode* parse_struct_decl_or_def(struct Parser* p) {
+ expect(p, TK_K_STRUCT);
+ char* name = parse_ident(p);
+
+ if (peek_token(p)->kind != TK_SEMICOLON && peek_token(p)->kind != TK_BRACE_L) {
+ p->pos = p->pos - 2;
+ return parse_func_decl_or_def(p);
+ }
+
+ int struct_index;
+ for (struct_index = 0; struct_index < p->n_structs; struct_index = struct_index + 1) {
+ if (strcmp(name, p->structs[struct_index].name) == 0) {
+ break;
+ }
+ }
+ if (struct_index == p->n_structs) {
+ p->structs[struct_index].name = name;
+ p->n_structs = p->n_structs + 1;
+ }
+ if (peek_token(p)->kind == TK_SEMICOLON) {
+ next_token(p);
+ return ast_new(AST_STRUCT_DECL);
+ }
+ if (p->structs[struct_index].node1) {
+ char* buf = calloc(1024, sizeof(char));
+ sprintf(buf, "parse_struct_decl_or_def: struct %s redefined", name);
+ fatal_error(buf);
+ }
+ expect(p, TK_BRACE_L);
+ 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;
+}
+
struct AstNode* parse_toplevel(struct Parser* p) {
if (peek_token(p)->kind == TK_K_STRUCT) {
return parse_struct_decl_or_def(p);
diff --git a/tests/034.sh b/tests/034.sh
new file mode 100644
index 0000000..12391f4
--- /dev/null
+++ b/tests/034.sh
@@ -0,0 +1,17 @@
+set -e
+
+cat <<'EOF' > expected
+EOF
+bash ../../test_diff.sh <<'EOF'
+struct S {
+ int a;
+};
+
+struct S* f();
+
+struct S* g() {}
+
+int main() {
+ return 0;
+}
+EOF