From cdae3ec936f019fc040ad461e56de26358a50ff6 Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Sat, 21 Sep 2024 13:43:52 +0200 Subject: [PATCH] Some refactoring of the bitstruct representation. Correctly represent inner types. #1471 --- releasenotes.md | 5 +-- src/compiler/ast.c | 2 -- src/compiler/codegen_internal.h | 2 +- src/compiler/compiler_internal.h | 38 +++++++++++--------- src/compiler/copying.c | 6 ++-- src/compiler/headers.c | 8 ++--- src/compiler/llvm_codegen_expr.c | 20 +++++------ src/compiler/llvm_codegen_type.c | 4 +-- src/compiler/parse_global.c | 15 ++++---- src/compiler/sema_casts.c | 32 ++++++++++++++--- src/compiler/sema_decls.c | 32 ++++++++--------- src/compiler/sema_expr.c | 4 +-- src/compiler/sema_initializers.c | 2 +- src/compiler/types.c | 46 +++++++++++++++++++++---- test/test_suite/cast/inner_type_cast.c3 | 21 +++++++++++ test/test_suite/struct/member_access.c3 | 2 +- 16 files changed, 162 insertions(+), 77 deletions(-) create mode 100644 test/test_suite/cast/inner_type_cast.c3 diff --git a/releasenotes.md b/releasenotes.md index 420c218a9..55d4f7e80 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -45,8 +45,9 @@ - User defined attributes could not have more than 1 parameter due to bug. - Folding a constant array of structs at compile time would cause an assert. - Enum attributes would be overwritten by enum value attributes. -- LLVM issue with try when bool is combined #1467 -- Segfault using ternary with no assignment #1468 +- LLVM issue with try when bool is combined #1467. +- Segfault using ternary with no assignment #1468. +- Inner types make some errors misleading #1471. ### Stdlib changes - Additional init functions for hashmap. diff --git a/src/compiler/ast.c b/src/compiler/ast.c index e1b8769a8..fac8cbe80 100644 --- a/src/compiler/ast.c +++ b/src/compiler/ast.c @@ -421,8 +421,6 @@ AlignSize decl_find_member_offset(Decl *decl, Decl *member) switch (decl->decl_kind) { case DECL_BITSTRUCT: - members = decl->bitstruct.members; - break; case DECL_STRUCT: case DECL_UNION: members = decl->strukt.members; diff --git a/src/compiler/codegen_internal.h b/src/compiler/codegen_internal.h index e72dcbc5f..57bbebe2b 100644 --- a/src/compiler/codegen_internal.h +++ b/src/compiler/codegen_internal.h @@ -50,7 +50,7 @@ static inline Type *type_lowering(Type *type) case TYPE_FAULTTYPE: return type_iptr->canonical; case TYPE_BITSTRUCT: - type = type->decl->bitstruct.base_type->type; + type = type->decl->strukt.container_type->type; continue; case TYPE_WILDCARD: type = type_void; diff --git a/src/compiler/compiler_internal.h b/src/compiler/compiler_internal.h index 7277e4a21..50d490949 100644 --- a/src/compiler/compiler_internal.h +++ b/src/compiler/compiler_internal.h @@ -369,24 +369,30 @@ typedef struct typedef struct { - TypeSize size; Decl **members; - DeclId padded_decl_id; - StructIndex union_rep; - AlignSize padding : 16; + DeclId parent; + union + { + struct + { + TypeSize size; + DeclId padded_decl_id; + StructIndex union_rep; + AlignSize padding : 16; + }; + struct + { + TypeInfo *container_type; + bool msb0 : 1; + bool big_endian : 1; + bool little_endian : 1; + bool overlap : 1; + bool consecutive : 1; + }; + }; } StructDecl; -typedef struct -{ - TypeInfo *base_type; - Decl **members; - bool msb0 : 1; - bool big_endian : 1; - bool little_endian : 1; - bool overlap : 1; - bool consecutive : 1; -} BitStructDecl; typedef struct VarDecl_ { @@ -624,11 +630,10 @@ typedef struct Decl_ Decl **methods; union { - BitStructDecl bitstruct; // Enums and Fault EnumDecl enums; TypeInfo *distinct; - // Unions, Struct use strukt + // Unions, Struct, Bitstruct use strukt StructDecl strukt; Decl **interface_methods; }; @@ -2413,6 +2418,7 @@ void type_append_name_to_scratch(Type *type); TypeCmpResult type_is_pointer_equivalent(SemaContext *context, Type *to_pointer, Type *from_pointer, bool flatten_distinct); TypeCmpResult type_array_element_is_equivalent(SemaContext *context, Type *element1, Type *element2, bool is_explicit); FunctionPrototype *type_get_resolved_prototype(Type *type); +bool type_is_inner_type(Type *type); const char *type_to_error_string(Type *type); const char *type_quoted_error_string(Type *type); INLINE bool type_may_negate(Type *type); diff --git a/src/compiler/copying.c b/src/compiler/copying.c index 8a8efe979..013dd0a28 100644 --- a/src/compiler/copying.c +++ b/src/compiler/copying.c @@ -966,6 +966,7 @@ Decl *copy_decl(CopyStruct *c, Decl *decl) case DECL_UNION: case DECL_STRUCT: copy_decl_type(copy); + fixup_declid(c, ©->strukt.parent); MACRO_COPY_TYPE_LIST(copy->interfaces); MACRO_COPY_DECL_LIST(copy->strukt.members); MACRO_COPY_DECLID(copy->strukt.padded_decl_id); @@ -976,9 +977,10 @@ Decl *copy_decl(CopyStruct *c, Decl *decl) UNREACHABLE case DECL_BITSTRUCT: copy_decl_type(copy); + fixup_declid(c, ©->strukt.parent); MACRO_COPY_TYPE_LIST(copy->interfaces); - MACRO_COPY_DECL_LIST(copy->bitstruct.members); - MACRO_COPY_TYPE(copy->bitstruct.base_type); + MACRO_COPY_DECL_LIST(copy->strukt.members); + MACRO_COPY_TYPE(copy->strukt.container_type); MACRO_COPY_DECL_LIST(copy->methods); break; case DECL_ENUM: diff --git a/src/compiler/headers.c b/src/compiler/headers.c index ca4781460..0ae8ba2c4 100644 --- a/src/compiler/headers.c +++ b/src/compiler/headers.c @@ -172,7 +172,7 @@ static void header_print_type(HeaderContext *c, Type *type) PRINTF("%s", decl_get_extname(type->decl)); return; } - header_print_type(c, type->decl->bitstruct.base_type->type); + header_print_type(c, type->decl->strukt.container_type->type); return; case TYPE_ANYFAULT: case TYPE_FAULTTYPE: @@ -362,7 +362,7 @@ static void header_gen_members(HeaderContext *c, int indent, Decl **members) break; case DECL_BITSTRUCT: INDENT(); - header_print_type(c, member->bitstruct.base_type->type->canonical); + header_print_type(c, member->strukt.container_type->type->canonical); if (member->name) { PRINTF(" %s;\n", member->name); @@ -534,7 +534,7 @@ RETRY: case TYPE_BITSTRUCT: { if (!header_try_gen_both(c, type)) return; - Type *underlying_type = type->decl->bitstruct.base_type->type; + Type *underlying_type = type->decl->strukt.container_type->type; header_gen_maybe_generate_type(c, underlying_type, is_pointer); PRINTF("typedef "); header_print_type(c, underlying_type); @@ -601,7 +601,7 @@ static void header_gen_global_var(HeaderContext *c, Decl *decl, bool fn_globals, } } // Flatten bitstructs. - if (type->type_kind == TYPE_BITSTRUCT) type = type->decl->bitstruct.base_type->type->canonical; + if (type->type_kind == TYPE_BITSTRUCT) type = type->decl->strukt.container_type->type->canonical; // We will lower some consts to defines, if they are: // 1. Not an address // 2. Not user defined (i.e. struct or union) diff --git a/src/compiler/llvm_codegen_expr.c b/src/compiler/llvm_codegen_expr.c index 22dbe9b98..dc761bc30 100644 --- a/src/compiler/llvm_codegen_expr.c +++ b/src/compiler/llvm_codegen_expr.c @@ -1418,7 +1418,7 @@ static LLVMValueRef llvm_emit_char_array_zero(GenContext *c, BEValue *value, boo } static void llvm_emit_bitstruct_to_bool(GenContext *c, BEValue *value, Type *to_type, Type *from_type) { - Type *base_type = type_flatten(from_type->decl->bitstruct.base_type->type); + Type *base_type = type_flatten(from_type->decl->strukt.container_type->type); if (base_type->type_kind != TYPE_ARRAY) { llvm_emit_int_comp_zero(c, value, value, BINARYOP_NE); @@ -1903,7 +1903,7 @@ INLINE void llvm_emit_initialize_reference_bitstruct_array(GenContext *c, BEValu // Now walk through the elements. FOREACH_IDX(i, Expr *, init, elements) { - Decl *member = bitstruct->bitstruct.members[i]; + Decl *member = bitstruct->strukt.members[i]; BEValue val; llvm_emit_expr(c, &val, init); llvm_emit_update_bitstruct_array(c, array_ptr, alignment, type, is_bitswap, member, @@ -1926,7 +1926,7 @@ static inline void llvm_emit_initialize_reference_bitstruct(GenContext *c, BEVal // Now walk through the elements. FOREACH_IDX(i, Expr *, init, elements) { - Decl *member = bitstruct->bitstruct.members[i]; + Decl *member = bitstruct->strukt.members[i]; BEValue val; llvm_emit_expr(c, &val, init); data = llvm_emit_bitstruct_value_update(c, data, bits, type, member, llvm_load_value_store(c, &val)); @@ -2075,7 +2075,7 @@ static void llvm_emit_initialize_designated_element(GenContext *c, BEValue *ref, if (type->type_kind == TYPE_BITSTRUCT && last == current + 1) { assert(llvm_value_is_addr(&value)); - Decl *member = type->decl->bitstruct.members[last[0]->index]; + Decl *member = type->decl->strukt.members[last[0]->index]; // Special handling of bitstructs. Type *underlying_type = value.type; assert(!emitted_value); @@ -2129,7 +2129,7 @@ static inline void llvm_emit_initialize_reference_designated_bitstruct_array(Gen assert(vec_size(designator->designator_expr.path) == 1); DesignatorElement *element = designator->designator_expr.path[0]; assert(element->kind == DESIGNATOR_FIELD); - Decl *member = bitstruct->bitstruct.members[element->index]; + Decl *member = bitstruct->strukt.members[element->index]; BEValue val; llvm_emit_expr(c, &val, designator->designator_expr.value); llvm_emit_update_bitstruct_array(c, array_ptr, alignment, type, is_bitswap, member, llvm_load_value_store(c, &val)); @@ -2154,7 +2154,7 @@ static inline void llvm_emit_initialize_reference_designated_bitstruct(GenContex assert(vec_size(designator->designator_expr.path) == 1); DesignatorElement *element = designator->designator_expr.path[0]; assert(element->kind == DESIGNATOR_FIELD); - Decl *member = bitstruct->bitstruct.members[element->index]; + Decl *member = bitstruct->strukt.members[element->index]; BEValue val; llvm_emit_expr(c, &val, designator->designator_expr.value); data = llvm_emit_bitstruct_value_update(c, data, bits, type, member, llvm_load_value_store(c, &val)); @@ -2198,15 +2198,15 @@ static bool bitstruct_requires_bitswap(Decl *decl) { assert(decl->decl_kind == DECL_BITSTRUCT); bool big_endian = compiler.platform.big_endian; - if (decl->bitstruct.big_endian) return !big_endian; - if (decl->bitstruct.little_endian) return big_endian; + if (decl->strukt.big_endian) return !big_endian; + if (decl->strukt.little_endian) return big_endian; return false; } LLVMValueRef llvm_emit_const_bitstruct_array(GenContext *c, ConstInitializer *initializer) { Decl *decl = initializer->type->decl; - Type *base_type = decl->bitstruct.base_type->type; + Type *base_type = decl->strukt.container_type->type; unsigned elements = base_type->array.len; LLVMValueRef stack_data[MAX_AGG]; LLVMValueRef* slots = elements > MAX_AGG ? MALLOC(elements * sizeof(LLVMValueRef)) : stack_data; @@ -2283,7 +2283,7 @@ LLVMValueRef llvm_emit_const_bitstruct_array(GenContext *c, ConstInitializer *in LLVMValueRef llvm_emit_const_bitstruct(GenContext *c, ConstInitializer *initializer) { Decl *decl = initializer->type->decl; - Type *base_type = decl->bitstruct.base_type->type; + Type *base_type = decl->strukt.container_type->type; if (initializer->kind == CONST_INIT_ZERO) return llvm_get_zero(c, base_type); bool char_array = base_type->type_kind == TYPE_ARRAY; if (char_array) diff --git a/src/compiler/llvm_codegen_type.c b/src/compiler/llvm_codegen_type.c index b972782ed..fa5b17d5d 100644 --- a/src/compiler/llvm_codegen_type.c +++ b/src/compiler/llvm_codegen_type.c @@ -20,7 +20,7 @@ static inline LLVMTypeRef llvm_type_from_decl(GenContext *c, Decl *decl) case DECL_INTERFACE: UNREACHABLE case DECL_BITSTRUCT: - return llvm_get_type(c, decl->bitstruct.base_type->type); + return llvm_get_type(c, decl->strukt.container_type->type); case DECL_FUNC: UNREACHABLE case DECL_TYPEDEF: @@ -661,7 +661,7 @@ LLVMValueRef llvm_get_typeid(GenContext *c, Type *type) case TYPE_BITSTRUCT: { LLVMValueRef ref = llvm_generate_temp_introspection_global(c, type); - return llvm_generate_introspection_global(c, ref, type, INTROSPECT_TYPE_BITSTRUCT, type->decl->bitstruct.base_type->type, 0, NULL, false); + return llvm_generate_introspection_global(c, ref, type, INTROSPECT_TYPE_BITSTRUCT, type->decl->strukt.container_type->type, 0, NULL, false); } case TYPE_TYPEDEF: return llvm_get_typeid(c, type->canonical); diff --git a/src/compiler/parse_global.c b/src/compiler/parse_global.c index 1bb99efb7..6d4b3b311 100644 --- a/src/compiler/parse_global.c +++ b/src/compiler/parse_global.c @@ -1456,10 +1456,11 @@ bool parse_struct_body(ParseContext *c, Decl *parent) member = decl_new_with_type(symstr(c), c->span, decl_kind); advance_and_verify(c, TOKEN_IDENT); } + member->strukt.parent = declid(parent); if (decl_kind == DECL_BITSTRUCT) { TRY_CONSUME_OR_RET(TOKEN_COLON, "':' followed by bitstruct type (e.g. 'int') was expected here.", poisoned_decl); - ASSIGN_TYPE_OR_RET(member->bitstruct.base_type, parse_type(c), poisoned_decl); + ASSIGN_TYPE_OR_RET(member->strukt.container_type, parse_type(c), poisoned_decl); if (!parse_attributes_for_global(c, member)) return decl_poison(parent); if (!parse_bitstruct_body(c, member)) return decl_poison(parent); } @@ -1631,7 +1632,7 @@ static inline bool parse_bitstruct_body(ParseContext *c, Decl *decl) { if (!is_consecutive) { - if (decl->bitstruct.members) + if (decl->strukt.members) { RETURN_PRINT_ERROR_AT(false, member_decl, "Bitstructs either have bit ranges for all members, or no members have ranges – mixing is not permitted. Either add a range to this member or remove ranges from the other member(s)."); } @@ -1641,10 +1642,10 @@ static inline bool parse_bitstruct_body(ParseContext *c, Decl *decl) if (!parse_attributes(c, &member_decl->attributes, NULL, NULL, &is_cond)) return false; member_decl->is_cond = is_cond; CONSUME_OR_RET(TOKEN_EOS, false); - unsigned index = vec_size(decl->bitstruct.members); + unsigned index = vec_size(decl->strukt.members); member_decl->var.start_bit = index; member_decl->var.end_bit = index; - vec_add(decl->bitstruct.members, member_decl); + vec_add(decl->strukt.members, member_decl); continue; } CONSUME_OR_RET(TOKEN_COLON, false); @@ -1666,9 +1667,9 @@ static inline bool parse_bitstruct_body(ParseContext *c, Decl *decl) { RETURN_PRINT_ERROR_AT(false, member_decl->var.start, "Bitstructs either have bit ranges for all members, or no members have ranges – mixing is not permitted. Either remove this range, or add ranges to all other members."); } - vec_add(decl->bitstruct.members, member_decl); + vec_add(decl->strukt.members, member_decl); } - decl->bitstruct.consecutive = is_consecutive; + decl->strukt.consecutive = is_consecutive; return true; } @@ -1720,7 +1721,7 @@ static inline Decl *parse_bitstruct_declaration(ParseContext *c) TRY_CONSUME_OR_RET(TOKEN_COLON, "':' followed by bitstruct type (e.g. 'int') was expected here.", poisoned_decl); - ASSIGN_TYPE_OR_RET(decl->bitstruct.base_type, parse_type(c), poisoned_decl); + ASSIGN_TYPE_OR_RET(decl->strukt.container_type, parse_type(c), poisoned_decl); if (!parse_attributes_for_global(c, decl)) return poisoned_decl; diff --git a/src/compiler/sema_casts.c b/src/compiler/sema_casts.c index a2f66d911..b5ee5dd35 100644 --- a/src/compiler/sema_casts.c +++ b/src/compiler/sema_casts.c @@ -111,6 +111,10 @@ static bool cast_is_allowed(CastContext *cc, bool is_explicit, bool is_silent) if (!rule) { if (is_silent) return false; + if (type_is_inner_type(cc->to_type)) + { + RETURN_CAST_ERROR(cc->expr, "You cannot cast %s to the inner type %s.", type_quoted_error_string(cc->expr->type), type_quoted_error_string(cc->to_type)); + } RETURN_CAST_ERROR(cc->expr, "You cannot cast %s to %s.", type_quoted_error_string(cc->expr->type), type_quoted_error_string(cc->to_type)); } @@ -663,6 +667,24 @@ static bool report_cast_error(CastContext *cc, bool may_cast_explicit) { Expr *expr = cc->expr; Type *to = cc->to_type; + if (type_is_inner_type(to)) + { + if (may_cast_explicit) + { + RETURN_CAST_ERROR(expr, + "Implicitly casting %s to the inner type %s is not permitted, but you may do an explicit cast by placing '($typefrom(%s.typeid))' before the expression.", + type_quoted_error_string(type_no_optional(expr->type)), + type_quoted_error_string(to), + type_to_error_string(type_no_optional(to))); + } + else + { + RETURN_CAST_ERROR(expr, + "It is not possible to cast %s to the inner type %s.", + type_quoted_error_string(type_no_optional(expr->type)), type_quoted_error_string(to)); + } + + } if (may_cast_explicit) { RETURN_CAST_ERROR(expr, @@ -1335,7 +1357,7 @@ static bool rule_expand_to_vec(CastContext *cc, bool is_explicit, bool is_silent static bool rule_int_to_bits(CastContext *cc, bool is_explicit, bool is_silent) { - Type *base_type = cc->to->decl->bitstruct.base_type->type; + Type *base_type = cc->to->decl->strukt.container_type->type; Type *from_type = cc->from; bool success = type_is_integer(base_type) && type_size(from_type) == type_size(base_type); if (!is_explicit || !success) return sema_cast_error(cc, success, is_silent); @@ -1344,7 +1366,7 @@ static bool rule_int_to_bits(CastContext *cc, bool is_explicit, bool is_silent) static bool rule_arr_to_bits(CastContext *cc, bool is_explicit, bool is_silent) { - Type *base_type = cc->to->decl->bitstruct.base_type->type; + Type *base_type = cc->to->decl->strukt.container_type->type; Type *from_type = cc->from; bool success = from_type == base_type; if (!is_explicit || !success) return sema_cast_error(cc, success, is_silent); @@ -1383,7 +1405,7 @@ static bool rule_int_to_enum(CastContext *cc, bool is_explicit, bool is_silent) static bool rule_bits_to_arr(CastContext *cc, bool is_explicit, bool is_silent) { if (is_silent && !is_explicit) return false; - Type *base_type = cc->from->decl->bitstruct.base_type->type->canonical; + Type *base_type = cc->from->decl->strukt.container_type->type->canonical; Type *to = cc->to; if (base_type != to) return sema_cast_error(cc, false, is_silent); if (!is_explicit) return sema_cast_error(cc, true, is_silent); @@ -1393,7 +1415,7 @@ static bool rule_bits_to_arr(CastContext *cc, bool is_explicit, bool is_silent) static bool rule_bits_to_int(CastContext *cc, bool is_explicit, bool is_silent) { if (is_silent && !is_explicit) return false; - Type *base_type = cc->from->decl->bitstruct.base_type->type->canonical; + Type *base_type = cc->from->decl->strukt.container_type->type->canonical; Type *to = cc->to; if (base_type != to) { @@ -1589,7 +1611,7 @@ static inline Type *type_flatten_to_int(Type *type) type = type->optional; break; case TYPE_BITSTRUCT: - type = type->decl->bitstruct.base_type->type; + type = type->decl->strukt.container_type->type; break; case TYPE_ENUM: type = type->decl->enums.type_info->type; diff --git a/src/compiler/sema_decls.c b/src/compiler/sema_decls.c index 2e717177f..1b5efd091 100644 --- a/src/compiler/sema_decls.c +++ b/src/compiler/sema_decls.c @@ -459,7 +459,7 @@ RETRY:; return max; } case TYPE_BITSTRUCT: - type = type->decl->bitstruct.base_type->type; + type = type->decl->strukt.container_type->type; goto RETRY; case TYPE_ARRAY: case TYPE_FLEXIBLE_ARRAY: @@ -744,7 +744,7 @@ static inline bool sema_analyse_bitstruct_member(SemaContext *context, Decl *par if (member->name) sema_decl_stack_push(member); } - bool is_consecutive = parent->bitstruct.consecutive; + bool is_consecutive = parent->strukt.consecutive; // Resolve the type. if (!sema_resolve_type_info(context, type_info, RESOLVE_TYPE_DEFAULT)) return false; @@ -762,11 +762,11 @@ static inline bool sema_analyse_bitstruct_member(SemaContext *context, Decl *par } // Grab the underlying bit type size. - BitSize bits = type_size(parent->bitstruct.base_type->type) * (BitSize)8; + BitSize bits = type_size(parent->strukt.container_type->type) * (BitSize)8; if (bits > MAX_BITSTRUCT) { - SEMA_ERROR(parent->bitstruct.base_type, "Bitstruct size may not exceed %d bits.", MAX_BITSTRUCT); + SEMA_ERROR(parent->strukt.container_type, "Bitstruct size may not exceed %d bits.", MAX_BITSTRUCT); return false; } Int max_bits = (Int) { .type = TYPE_I64, .i = { .low = bits } }; @@ -877,7 +877,7 @@ AFTER_BIT_CHECK: // Check for overlap if (!allow_overlap) { - Decl **members = parent->bitstruct.members; + Decl **members = parent->strukt.members; for (unsigned i = 0; i < index; i++) { Decl *other_member = members[i]; @@ -1049,16 +1049,16 @@ static bool sema_analyse_bitstruct(SemaContext *context, Decl *decl, bool *erase if (!sema_resolve_implemented_interfaces(context, decl, false)) return decl_poison(decl); if (*erase_decl) return true; DEBUG_LOG("Beginning analysis of %s.", decl->name ? decl->name : ".anon"); - if (!sema_resolve_type_info(context, decl->bitstruct.base_type, RESOLVE_TYPE_DEFAULT)) return false; - Type *type = decl->bitstruct.base_type->type->canonical; + if (!sema_resolve_type_info(context, decl->strukt.container_type, RESOLVE_TYPE_DEFAULT)) return false; + Type *type = decl->strukt.container_type->type->canonical; Type *base_type = type->type_kind == TYPE_ARRAY ? type->array.base : type; if (!type_is_integer(base_type)) { - SEMA_ERROR(decl->bitstruct.base_type, "The type of the bitstruct cannot be %s but must be an integer or an array of integers.", - type_quoted_error_string(decl->bitstruct.base_type->type)); + SEMA_ERROR(decl->strukt.container_type, "The type of the bitstruct cannot be %s but must be an integer or an array of integers.", + type_quoted_error_string(decl->strukt.container_type->type)); return false; } - Decl **members = decl->bitstruct.members; + Decl **members = decl->strukt.members; unsigned member_count = vec_size(members); Decl **state = decl->name ? sema_decl_stack_store() : NULL; @@ -1068,7 +1068,7 @@ static bool sema_analyse_bitstruct(SemaContext *context, Decl *decl, bool *erase Decl *member = members[i]; if (!decl_ok(member)) goto ERROR; bool erase_decl_member = false; - if (!sema_analyse_bitstruct_member(context, decl, member, i, decl->bitstruct.overlap, &erase_decl_member)) goto ERROR; + if (!sema_analyse_bitstruct_member(context, decl, member, i, decl->strukt.overlap, &erase_decl_member)) goto ERROR; if (erase_decl_member) { vec_erase_at(members, i); @@ -2735,26 +2735,26 @@ static bool sema_analyse_attribute(SemaContext *context, ResolvedAttrData *attr_ decl->func_decl.attr_naked = true; break; case ATTRIBUTE_OVERLAP: - decl->bitstruct.overlap = true; + decl->strukt.overlap = true; break; case ATTRIBUTE_DYNAMIC: decl->func_decl.attr_dynamic = true; break; case ATTRIBUTE_BIGENDIAN: - if (decl->bitstruct.little_endian) + if (decl->strukt.little_endian) { SEMA_ERROR(attr, "Attribute cannot be combined with @littleendian"); return decl_poison(decl); } - decl->bitstruct.big_endian = true; + decl->strukt.big_endian = true; break; case ATTRIBUTE_LITTLEENDIAN: - if (decl->bitstruct.big_endian) + if (decl->strukt.big_endian) { SEMA_ERROR(attr, "Attribute cannot be combined with @bigendian"); return decl_poison(decl); } - decl->bitstruct.little_endian = true; + decl->strukt.little_endian = true; break; case ATTRIBUTE_PACKED: decl->is_packed = true; diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index f8de4ad49..aa5e33f82 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -3744,7 +3744,7 @@ static inline bool sema_create_const_inner(SemaContext *context, Expr *expr, Typ inner = type->decl->enums.type_info->type->canonical; break; case TYPE_BITSTRUCT: - inner = type->decl->bitstruct.base_type->type->canonical; + inner = type->decl->strukt.container_type->type->canonical; break; case TYPE_ARRAY: case TYPE_FLEXIBLE_ARRAY: @@ -3902,7 +3902,7 @@ static inline void sema_create_const_membersof(SemaContext *context, Expr *expr, } else if (type->type_kind == TYPE_BITSTRUCT) { - members = type->decl->bitstruct.members; + members = type->decl->strukt.members; } else { diff --git a/src/compiler/sema_initializers.c b/src/compiler/sema_initializers.c index 319677d77..e05e2b7a8 100644 --- a/src/compiler/sema_initializers.c +++ b/src/compiler/sema_initializers.c @@ -121,7 +121,7 @@ static inline bool sema_expr_analyse_struct_plain_initializer(SemaContext *conte bool optional = false; bool is_bitstruct = assigned->decl_kind == DECL_BITSTRUCT; - if (is_bitstruct && assigned->bitstruct.overlap) + if (is_bitstruct && assigned->strukt.overlap) { if (vec_size(assigned->strukt.members) > 1 && vec_size(elements) > 1) { diff --git a/src/compiler/types.c b/src/compiler/types.c index 51912dd6d..918055d59 100644 --- a/src/compiler/types.c +++ b/src/compiler/types.c @@ -200,6 +200,39 @@ static void type_append_func_to_scratch(FunctionPrototype *prototype) scratch_buffer_append_char(')'); } +bool type_is_inner_type(Type *type) +{ + switch (type->type_kind) + { + case TYPE_STRUCT: + case TYPE_UNION: + case TYPE_BITSTRUCT: + return type->decl->strukt.parent != 0; + default: + return false; + } +} + +static void type_add_parent_to_scratch(Decl *decl) +{ + switch (decl->decl_kind) + { + case DECL_STRUCT: + case DECL_UNION: + case DECL_BITSTRUCT: + if (decl->strukt.parent) + { + Decl *parent = declptr(decl->strukt.parent); + type_add_parent_to_scratch(parent); + if (!parent->name) return; + scratch_buffer_append(parent->name); + scratch_buffer_append_char('.'); + } + return; + default: + return; + } +} const char *type_to_error_string(Type *type) { switch (type->type_kind) @@ -227,10 +260,11 @@ const char *type_to_error_string(Type *type) { Decl *decl = type->decl; const char *suffix = decl->unit->module->generic_suffix; - if (!suffix) return type->name; + if (!suffix && !type_is_inner_type(type)) return type->name; scratch_buffer_clear(); + type_add_parent_to_scratch(decl); scratch_buffer_append(decl->name); - scratch_buffer_append(suffix); + if (suffix) scratch_buffer_append(suffix); return scratch_buffer_copy(); } case TYPE_FUNC_PTR: @@ -285,7 +319,7 @@ RETRY: { case TYPE_BITSTRUCT: assert(type->decl->resolve_status == RESOLVE_DONE); - type = type->decl->bitstruct.base_type->type; + type = type->decl->strukt.container_type->type; goto RETRY; case TYPE_DISTINCT: assert(type->decl->resolve_status == RESOLVE_DONE); @@ -487,7 +521,7 @@ bool type_is_comparable(Type *type) case TYPE_STRUCT: return type->decl->attr_compact; case TYPE_BITSTRUCT: - type = type->decl->bitstruct.base_type->type; + type = type->decl->strukt.container_type->type; goto RETRY; case TYPE_TYPEDEF: type = type->canonical; @@ -649,7 +683,7 @@ AlignSize type_abi_alignment(Type *type) case TYPE_WILDCARD: UNREACHABLE; case TYPE_BITSTRUCT: - type = type->decl->bitstruct.base_type->type; + type = type->decl->strukt.container_type->type; goto RETRY; case TYPE_INFERRED_VECTOR: case TYPE_VECTOR: @@ -1435,7 +1469,7 @@ bool type_is_scalar(Type *type) case TYPE_ANYFAULT: return true; case TYPE_BITSTRUCT: - type = type->decl->bitstruct.base_type->type; + type = type->decl->strukt.container_type->type; goto RETRY; case TYPE_DISTINCT: type = type->decl->distinct->type; diff --git a/test/test_suite/cast/inner_type_cast.c3 b/test/test_suite/cast/inner_type_cast.c3 new file mode 100644 index 000000000..ec015cad4 --- /dev/null +++ b/test/test_suite/cast/inner_type_cast.c3 @@ -0,0 +1,21 @@ +module test; + +struct Foo +{ + bitstruct abc : int + { + bool a; + } +} + +fn void test1() +{ + Foo x; + x.abc = "abc"; // #error: to the inner type 'Foo.abc' +} + +fn void test2() +{ + Foo x; + x.abc = 2; // #error: type 'Foo.abc' is not permitted, but you may do an explicit +} \ No newline at end of file diff --git a/test/test_suite/struct/member_access.c3 b/test/test_suite/struct/member_access.c3 index 5753cc1d3..c8a95f80e 100644 --- a/test/test_suite/struct/member_access.c3 +++ b/test/test_suite/struct/member_access.c3 @@ -71,7 +71,7 @@ struct Aa1 fn void test_conversion_struct() { Aa1 a1; - int aa = a1.bb; // #error: 'bb' to 'int' + int aa = a1.bb; // #error: 'Aa1.bb' to 'int' } struct Struct