fix(ast): 修复AST转储中逗号分隔符逻辑错误

在dump_decl_impl函数中,修正了列表元素间逗号分隔符的判断逻辑,
将条件从"不是最后一个元素"改为"是最后一个元素",确保正确的
分隔符输出。

BREAKING CHANGE: 逗号分隔符的逻辑被反转,影响AST转储输出格式。

---

fix(parser): 修复声明列表处理中的内存泄漏问题

调整了typedef声明的处理顺序,在解析完成前添加声明到列表,
避免了重复添加导致的内存泄漏。同时移除了不必要的错误检查。

---

refactor(parser): 重构记录类型和枚举类型的声明初始化逻辑

移除了重复的声明创建代码,统一了结构体、联合体和枚举类型的
声明初始化流程,消除了之前存在的Panic错误路径。

---

test(parser): 增加复杂声明的单元测试覆盖

添加了对结构体指针声明和typedef复合声明的测试用例,
提高了测试覆盖率并验证了解析器的正确性。

---

feat(preprocessor): 添加预定义宏支持

增加了__SCC__、_WIN64和__x86_64__等预定义宏的定义,
为不同平台提供更好的编译支持。
This commit is contained in:
zzy
2026-03-14 15:39:26 +08:00
parent eb969cdbf7
commit 82dd5f2db0
5 changed files with 122 additions and 95 deletions

View File

@@ -299,19 +299,19 @@ CONTINUE:
tok_ptr = scc_parser_peek(parser);
if (tok_ptr->type == SCC_TOK_SEMICOLON) {
scc_parser_next_consume(parser, null);
if (decl_list)
scc_vec_push(decl_list_vec, decl);
if (spec.is_typedef) {
if (decl_list) {
scc_vec_foreach(decl_list_vec, i) {
decl = scc_vec_at(decl_list_vec, i);
scc_ast_decl_typedef_init(decl, decl->name, type);
scc_ast_decl_typedef_init(decl, decl->name, decl->var.type);
}
} else {
scc_ast_decl_typedef_init(decl, decl->name, decl->var.type);
}
}
if (decl_list != null) {
scc_vec_push(decl_list_vec, decl);
scc_vec_foreach(decl_list_vec, i) {
decl = scc_vec_at(decl_list_vec, i);
scc_parse_decl_sema(parser, decl);

View File

@@ -626,20 +626,13 @@ static scc_ast_type_t *parse_record_type(scc_parser_t *parser,
// FIXME memory leak
return null;
}
decl = scc_malloc(sizeof(scc_ast_decl_t));
Assert(decl != null);
if (type_kind == SCC_AST_TYPE_STRUCT) {
scc_ast_decl_struct_init(decl, name, null);
} else {
scc_ast_decl_union_init(decl, name, null);
}
}
scc_ast_type_t *type = ast_type_alloc();
_scc_ast_type_record_init(type, type_kind, name, decl);
return type;
}
static scc_ast_type_t *parse_enum_type(scc_parser_t *parser) {
/*
(6.7.2.2)
@@ -713,9 +706,6 @@ static scc_ast_type_t *parse_enum_type(scc_parser_t *parser) {
// FIXME memory leak
return null;
}
decl = scc_malloc(sizeof(scc_ast_decl_t));
Assert(decl != null);
scc_ast_decl_enum_init(decl, name, null);
}
scc_ast_type_t *type = ast_type_alloc();
@@ -1182,20 +1172,27 @@ scc_ast_decl_t *scc_parse_declarator(scc_parser_t *parser,
if (decl_type->base.type == SCC_AST_TYPE_STRUCT ||
decl_type->base.type == SCC_AST_TYPE_UNION) {
if (decl_type->record.decl == null) {
SCC_ERROR(scc_parser_got_current_pos(parser),
"record don't have a decl");
Panic();
decl = scc_malloc(sizeof(scc_ast_decl_t));
Assert(decl != null);
if (decl_type->base.type == SCC_AST_TYPE_STRUCT) {
scc_ast_decl_struct_init(decl, decl_type->record.name,
null);
} else {
scc_ast_decl_union_init(decl, decl_type->record.name, null);
}
} else {
decl = decl_type->record.decl;
scc_free(decl_type); // FIXME
}
decl = decl_type->record.decl;
scc_free(decl_type); // FIXME
} else if (decl_type->base.type == SCC_AST_TYPE_ENUM) {
if (decl_type->enumeration.decl == null) {
SCC_ERROR(scc_parser_got_current_pos(parser),
"enum don't have a decl");
Panic();
decl = scc_malloc(sizeof(scc_ast_decl_t));
Assert(decl != null);
scc_ast_decl_enum_init(decl, type->enumeration.name, null);
} else {
decl = type->enumeration.decl;
scc_free(decl_type); // FIXME
}
decl = type->enumeration.decl;
scc_free(decl_type); // FIXME
} else {
decl = scc_malloc(sizeof(scc_ast_decl_t));
scc_ast_decl_unsafe_val_init(decl, type, null, null);
@@ -1224,66 +1221,6 @@ scc_ast_type_t *scc_parse_declaration_specifiers(scc_parser_t *parser) {
specifier->quals = spec;
return specifier;
// scc_lexer_tok_t tok_ident = {0};
// scc_ast_type_t *type = parse_declarator(parser, ret, null, &tok_ident);
// scc_ast_decl_t *decl = null;
// if (tok_ident.type == SCC_TOK_IDENT) {
// decl = scc_malloc(sizeof(scc_ast_decl_t));
// Assert(decl != null);
// }
// const char *name = decl ? scc_cstring_as_cstr(&tok_ident.lexeme) : null;
// if (is_typedef_decl) {
// if (decl == null) {
// SCC_ERROR(scc_parser_got_current_pos(parser),
// "typedef don't have a ident");
// parser->errcode = 1;
// } else {
// scc_ast_decl_typedef_init(decl, name, type);
// }
// } else if (decl) {
// if (type->base.type == SCC_AST_TYPE_FUNCTION) {
// scc_ast_decl_func_init(decl, type, name, null);
// // TODO using sema to change it
// if (spec.is_inline) {
// type->quals.is_inline = true;
// }
// } else {
// scc_ast_decl_val_init(decl, type, name, null);
// }
// }
// scc_ast_node_t *type_or_decl = decl != null ? &decl->base : &type->base;
// if (SCC_AST_IS_A(scc_ast_type_t, type_or_decl)) {
// scc_ast_type_t *type = SCC_AST_CAST_TO(scc_ast_type_t, type_or_decl);
// if (type->base.type == SCC_AST_TYPE_STRUCT ||
// type->base.type == SCC_AST_TYPE_UNION) {
// if (type->record.decl == null) {
// SCC_ERROR(scc_parser_got_current_pos(parser),
// "record don't have a decl");
// Panic();
// }
// decl = type->record.decl;
// scc_free(type_or_decl); // FIXME
// } else if (type->base.type == SCC_AST_TYPE_ENUM) {
// if (type->enumeration.decl == null) {
// SCC_ERROR(scc_parser_got_current_pos(parser),
// "enum don't have a decl");
// Panic();
// }
// decl = type->enumeration.decl;
// scc_free(type_or_decl); // FIXME
// } else {
// decl = scc_malloc(sizeof(scc_ast_decl_t));
// scc_ast_decl_unsafe_val_init(decl, type, null, null);
// }
// } else if (SCC_AST_IS_A(scc_ast_decl_t, type_or_decl)) {
// decl = SCC_AST_CAST_TO(scc_ast_decl_t, type_or_decl);
// } else {
// SCC_ERROR(scc_parser_got_current_pos(parser), "invalid declaration");
// return null;
// }
// return decl;
}
scc_ast_type_t *scc_parse_type_name(scc_parser_t *parser) {