From 72f5bac3469f2ec3cc2caff8c8030efdb7c7ff0b Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Mon, 31 Jul 2023 12:35:41 +0200 Subject: [PATCH] When a member is checked, still add it to the environment. Addresses #903. --- src/compiler/sema_decls.c | 39 ++++++++++------------ src/compiler/sema_expr.c | 11 ++++-- test/test_suite/struct/duplicate_member.c3 | 7 ++-- 3 files changed, 31 insertions(+), 26 deletions(-) diff --git a/src/compiler/sema_decls.c b/src/compiler/sema_decls.c index 8dde8043c..66e7cfb35 100644 --- a/src/compiler/sema_decls.c +++ b/src/compiler/sema_decls.c @@ -134,7 +134,12 @@ static inline bool sema_check_param_uniqueness_and_type(Decl **decls, Decl *curr static inline bool sema_analyse_struct_member(SemaContext *context, Decl *parent, Decl *decl, bool *erase_decl) { - if (decl->resolve_status == RESOLVE_DONE) return decl_ok(decl); + if (decl->resolve_status == RESOLVE_DONE) + { + if (!decl_ok(decl)) return false; + if (decl->name) sema_decl_stack_push(decl); + return true; + } if (decl->resolve_status == RESOLVE_RUNNING) { RETURN_SEMA_ERROR(decl, "Circular dependency resolving member."); @@ -216,18 +221,12 @@ static bool sema_analyse_union_members(SemaContext *context, Decl *decl, Decl ** Decl *member = members[i]; if (!decl_ok(member)) { - decl_poison(decl); - continue; + return decl_poison(decl); } bool erase_decl = false; if (!sema_analyse_struct_member(context, decl, member, &erase_decl)) { - if (decl_ok(decl)) - { - decl_poison(decl); - continue; - } - continue; + return decl_poison(member) || decl_poison(decl); } if (erase_decl) { @@ -239,7 +238,7 @@ static bool sema_analyse_union_members(SemaContext *context, Decl *decl, Decl ** if (member->type->type_kind == TYPE_INFERRED_ARRAY) { SEMA_ERROR(member, "Flexible array members not allowed in unions."); - return false; + return decl_poison(member) || decl_poison(decl); } AlignSize member_alignment; if (!sema_set_abi_alignment(context, member->type, &member_alignment)) return false; @@ -324,16 +323,11 @@ static bool sema_analyse_struct_members(SemaContext *context, Decl *decl, Decl * { AGAIN:; Decl *member = struct_members[i]; - if (!decl_ok(member)) - { - decl_poison(decl); - continue; - } + if (!decl_ok(member)) return decl_poison(decl); bool erase_decl = false; if (!sema_analyse_struct_member(context, decl, member, &erase_decl)) { - decl_poison(member); - return decl_poison(decl); + return decl_poison(member) || decl_poison(decl); } if (erase_decl) { @@ -348,7 +342,7 @@ static bool sema_analyse_struct_members(SemaContext *context, Decl *decl, Decl * if (i != member_count - 1) { SEMA_ERROR(member, "A struct member with a flexible array must be the last element."); - return false; + return decl_poison(member) || decl_poison(decl); } decl->has_variable_array = true; } @@ -357,12 +351,12 @@ static bool sema_analyse_struct_members(SemaContext *context, Decl *decl, Decl * if (i != member_count - 1) { SEMA_ERROR(member, "The flexible array member must be the last element."); - return false; + return decl_poison(member) || decl_poison(decl); } if (i == 0) { SEMA_ERROR(member, "The flexible array member cannot be the only element."); - return false; + return decl_poison(member) || decl_poison(decl); } member->type = type_get_flexible_array(member->type->array.base); decl->has_variable_array = true; @@ -3379,8 +3373,10 @@ RETRY: case TYPE_TYPEINFO: case TYPE_MEMBER: return true; - case TYPE_ENUM: case TYPE_FUNC: + if (!type->decl) return true; + FALLTHROUGH; + case TYPE_ENUM: case TYPE_STRUCT: case TYPE_UNION: case TYPE_BITSTRUCT: @@ -3416,6 +3412,7 @@ bool sema_analyse_decl(SemaContext *context, Decl *decl) SemaContext temp_context; context = context_transform_for_eval(context, &temp_context, decl->unit); + DEBUG_LOG(">>> Analysing %s.", decl->name ? decl->name : ".anon"); if (decl->resolve_status == RESOLVE_RUNNING) { diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index 06b787f33..284eecf24 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -826,10 +826,11 @@ static inline bool sema_expr_analyse_ternary(SemaContext *context, Expr *expr) static inline bool sema_expr_analyse_enum_constant(SemaContext *context, Expr *expr, const char *name, Decl *decl) { Decl *enum_constant = decl_find_enum_constant(decl, name); - - if (!sema_resolve_type_decl(context, decl->type)) return false; if (!enum_constant) return false; + // Resolve the structure at this point, since we might want to use the enum_constant + if (!sema_resolve_type_structure(context, decl->type, decl->span)) return false; + assert(enum_constant->resolve_status == RESOLVE_DONE); expr->type = decl->type; @@ -2914,6 +2915,9 @@ static inline bool sema_expr_analyse_type_access(SemaContext *context, Expr *exp const char *name = identifier->identifier_expr.ident; bool is_const = identifier->identifier_expr.is_const; + // Make sure that we have the full type structure. + if (!sema_resolve_type_structure(context, parent_type, expr->span)) return false; + if (!is_const) { if (sema_expr_rewrite_to_type_property(context, expr, canonical, type_property_by_name(name), parent_type)) return true; @@ -3508,6 +3512,7 @@ static bool sema_expr_rewrite_to_type_property(SemaContext *context, Expr *expr, assert(type == type->canonical); if (property == TYPE_PROPERTY_NONE) return false; Type *flat = type_flatten(type); + if (!sema_resolve_type_structure(context, flat, expr->span)) return false; switch (property) { case TYPE_PROPERTY_INF: @@ -3931,6 +3936,7 @@ CHECK_DEEPER: // 10. Dump all members and methods into the scope. Decl *decl = type->decl; + Decl *member = sema_decl_stack_find_decl_member(decl, kw); if (member && decl_is_enum_kind(decl) && member->decl_kind == DECL_VAR && expr_is_const(parent)) @@ -7576,7 +7582,6 @@ static inline bool sema_expr_analyse_compound_literal(SemaContext *context, Expr { if (!sema_resolve_type_info(context, expr->expr_compound_literal.type_info)) return false; Type *type = expr->expr_compound_literal.type_info->type; - if (!sema_resolve_type_decl(context, type)) return false; if (type_is_optional(type)) { SEMA_ERROR(expr->expr_compound_literal.type_info, diff --git a/test/test_suite/struct/duplicate_member.c3 b/test/test_suite/struct/duplicate_member.c3 index 345871af5..c2a6f8c54 100644 --- a/test/test_suite/struct/duplicate_member.c3 +++ b/test/test_suite/struct/duplicate_member.c3 @@ -20,6 +20,11 @@ union Cc { int a; int a; // #error: Duplicate member name 'a' +} + +union Cc2 +{ + int a; struct b { @@ -27,7 +32,6 @@ union Cc int c; // #error: Duplicate member name 'c' } } - struct Dd { int b; @@ -37,7 +41,6 @@ struct Dd union { short a; // #error: Duplicate member name 'a' - int b; // #error: Duplicate member name 'b' } } }