aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-02-07 15:18:18 +0900
committernsfisis <nsfisis@gmail.com>2026-02-07 15:18:18 +0900
commitb8780671f6768e3b5a09084d9f80c01bd544d2e8 (patch)
tree57a7e27baa0df450b98376db53ce46b3e1d594da
parenta76908958f4fb404ec24bf86d3aa59f0ec5f6be0 (diff)
downloadducc-b8780671f6768e3b5a09084d9f80c01bd544d2e8.tar.gz
ducc-b8780671f6768e3b5a09084d9f80c01bd544d2e8.tar.zst
ducc-b8780671f6768e3b5a09084d9f80c01bd544d2e8.zip
feat: support anonymous struct members
-rw-r--r--src/parse.c17
-rw-r--r--tests/structs.sh25
2 files changed, 37 insertions, 5 deletions
diff --git a/src/parse.c b/src/parse.c
index 1b5db5b..88c2920 100644
--- a/src/parse.c
+++ b/src/parse.c
@@ -1410,7 +1410,7 @@ void parse_typedef_decl(Parser* p, AstNode* decls) {
}
}
-static char* generate_new_anonymous_user_type_name(Parser* p) {
+static char* generate_anonymous_name(Parser* p) {
char* buf = calloc(32, sizeof(char));
sprintf(buf, "__anonymous_%d__", p->anonymous_user_type_counter++);
return buf;
@@ -1707,7 +1707,7 @@ static Type* parse_struct_specifier(Parser* p) {
const Token* name;
char* anonymous_name = NULL;
if (peek_token(p)->kind == TokenKind_brace_l) {
- anonymous_name = generate_new_anonymous_user_type_name(p);
+ anonymous_name = generate_anonymous_name(p);
Token* anonymous_token = calloc(1, sizeof(Token));
anonymous_token->kind = TokenKind_ident;
anonymous_token->value.string = anonymous_name;
@@ -1768,7 +1768,7 @@ static Type* parse_union_specifier(Parser* p) {
const Token* name;
char* anonymous_name = NULL;
if (peek_token(p)->kind == TokenKind_brace_l) {
- anonymous_name = generate_new_anonymous_user_type_name(p);
+ anonymous_name = generate_anonymous_name(p);
Token* anonymous_token = calloc(1, sizeof(Token));
anonymous_token->kind = TokenKind_ident;
anonymous_token->value.string = anonymous_name;
@@ -1840,7 +1840,14 @@ static AstNode* parse_member_declaration(Parser* p) {
AstNode* decls = NULL;
if (consume_token_if(p, TokenKind_semicolon)) {
- unimplemented();
+ char* name = generate_anonymous_name(p);
+ AstNode* decls = ast_new_list(1);
+ AstNode* member = ast_new(AstNodeKind_struct_member);
+ member->ty = base_ty;
+ member->as.struct_member = calloc(1, sizeof(StructMemberNode));
+ member->as.struct_member->name = name;
+ ast_append(decls, member);
+ return decls;
}
decls = parse_member_declarator_list(p, base_ty);
@@ -2051,7 +2058,7 @@ static Type* parse_enum_specifier(Parser* p) {
const Token* name;
char* anonymous_name = NULL;
if (peek_token(p)->kind == TokenKind_brace_l) {
- anonymous_name = generate_new_anonymous_user_type_name(p);
+ anonymous_name = generate_anonymous_name(p);
Token* anonymous_token = calloc(1, sizeof(Token));
anonymous_token->kind = TokenKind_ident;
anonymous_token->value.string = anonymous_name;
diff --git a/tests/structs.sh b/tests/structs.sh
index 4c8ff6d..3df4f9c 100644
--- a/tests/structs.sh
+++ b/tests/structs.sh
@@ -362,3 +362,28 @@ int main() {
printf("%zu\n", sizeof(E));
}
EOF
+
+cat <<'EOF' > expected
+EOF
+
+test_diff <<'EOF'
+int printf();
+
+struct S1 {
+ struct {
+ int x;
+ int y;
+ };
+ struct {
+ int z;
+ };
+};
+
+int main() {
+ // TODO
+ // struct S1 a = {1, 2, 3};
+ // printf("%d\n", a.x);
+ // printf("%d\n", a.y);
+ // printf("%d\n", a.z);
+}
+EOF