diff options
| author | Andreas T Jonsson <mail@andreasjonsson.se> | 2024-04-25 22:04:40 +0200 |
|---|---|---|
| committer | Andreas T Jonsson <mail@andreasjonsson.se> | 2024-04-25 22:04:40 +0200 |
| commit | 9a008d10f3d8f97ff11ba948d6939bec7e6beb6d (patch) | |
| tree | 8b2fd91da22620b6e0a7158a66429f1af4aca210 /src/check_type.cpp | |
| parent | 3000508c027c9d30c168266d0ae276cc14de3982 (diff) | |
| parent | f745fff640ab1582bdfdd18a7239c58fa37db753 (diff) | |
Merge branch 'master' into netbsd
Diffstat (limited to 'src/check_type.cpp')
| -rw-r--r-- | src/check_type.cpp | 92 |
1 files changed, 76 insertions, 16 deletions
diff --git a/src/check_type.cpp b/src/check_type.cpp index f1d991acb..ab8c0b057 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -29,10 +29,11 @@ gb_internal void populate_using_array_index(CheckerContext *ctx, Ast *node, AstF } } -gb_internal void populate_using_entity_scope(CheckerContext *ctx, Ast *node, AstField *field, Type *t) { +gb_internal void populate_using_entity_scope(CheckerContext *ctx, Ast *node, AstField *field, Type *t, isize level) { if (t == nullptr) { return; } + Type *original_type = t; t = base_type(type_deref(t)); gbString str = nullptr; defer (gb_string_free(str)); @@ -46,16 +47,18 @@ gb_internal void populate_using_entity_scope(CheckerContext *ctx, Ast *node, Ast String name = f->token.string; Entity *e = scope_lookup_current(ctx->scope, name); if (e != nullptr && name != "_") { + gbString ot = type_to_string(original_type); // TODO(bill): Better type error if (str != nullptr) { - error(e->token, "'%.*s' is already declared in '%s'", LIT(name), str); + error(e->token, "'%.*s' is already declared in '%s', through 'using' from '%s'", LIT(name), str, ot); } else { - error(e->token, "'%.*s' is already declared", LIT(name)); + error(e->token, "'%.*s' is already declared, through 'using' from '%s'", LIT(name), ot); } + gb_string_free(ot); } else { add_entity(ctx, ctx->scope, nullptr, f); if (f->flags & EntityFlag_Using) { - populate_using_entity_scope(ctx, node, field, f->type); + populate_using_entity_scope(ctx, node, field, f->type, level+1); } } } @@ -200,7 +203,7 @@ gb_internal void check_struct_fields(CheckerContext *ctx, Ast *node, Slice<Entit continue; } - populate_using_entity_scope(ctx, node, p, type); + populate_using_entity_scope(ctx, node, p, type, 1); } if (is_subtype && p->names.count > 0) { @@ -952,14 +955,19 @@ gb_internal void check_bit_field_type(CheckerContext *ctx, Type *bit_field_type, GB_ASSERT(is_type_bit_field(bit_field_type)); Type *backing_type = check_type(ctx, bf->backing_type); - if (backing_type == nullptr || !is_valid_bit_field_backing_type(backing_type)) { - error(node, "Backing type for a bit_field must be an integer or an array of an integer"); - return; - } - bit_field_type->BitField.backing_type = backing_type; + bit_field_type->BitField.backing_type = backing_type ? backing_type : t_u8; bit_field_type->BitField.scope = ctx->scope; + if (backing_type == nullptr) { + error(bf->backing_type, "Backing type for a bit_field must be an integer or an array of an integer"); + return; + } + if (!is_valid_bit_field_backing_type(backing_type)) { + error(bf->backing_type, "Backing type for a bit_field must be an integer or an array of an integer"); + return; + } + auto fields = array_make<Entity *>(permanent_allocator(), 0, bf->fields.count); auto bit_sizes = array_make<u8> (permanent_allocator(), 0, bf->fields.count); auto tags = array_make<String> (permanent_allocator(), 0, bf->fields.count); @@ -1093,6 +1101,45 @@ gb_internal void check_bit_field_type(CheckerContext *ctx, Type *bit_field_type, gb_string_free(s); } + enum EndianKind { + Endian_Unknown, + Endian_Native, + Endian_Little, + Endian_Big, + }; + auto const &determine_endian_kind = [](Type *type) -> EndianKind { + if (is_type_boolean(type)) { + // NOTE(bill): it doesn't matter, and when it does, + // that api is absolutely stupid + return Endian_Unknown; + } else if (is_type_endian_specific(type)) { + if (is_type_endian_little(type)) { + return Endian_Little; + } else { + return Endian_Big; + } + } + return Endian_Native; + }; + + EndianKind backing_type_endian_kind = determine_endian_kind(core_array_type(backing_type)); + EndianKind endian_kind = Endian_Unknown; + for (Entity *f : fields) { + EndianKind field_kind = determine_endian_kind(f->type); + + if (field_kind && backing_type_endian_kind != field_kind) { + error(f->token, "All 'bit_field' field types must match the same endian kind as the backing type, i.e. all native, all little, or all big"); + } + + if (endian_kind == Endian_Unknown) { + endian_kind = field_kind; + } else if (field_kind && endian_kind != field_kind) { + error(f->token, "All 'bit_field' field types must be of the same endian variety, i.e. all native, all little, or all big"); + } + } + + + if (bit_sizes.count > 0 && is_type_integer(backing_type)) { bool all_booleans = is_type_boolean(fields[0]->type); bool all_ones = bit_sizes[0] == 1; @@ -2495,18 +2542,16 @@ gb_internal Type *get_map_cell_type(Type *type) { return s; } -gb_internal void init_map_internal_types(Type *type) { +gb_internal void init_map_internal_debug_types(Type *type) { GB_ASSERT(type->kind == Type_Map); GB_ASSERT(t_allocator != nullptr); - if (type->Map.lookup_result_type != nullptr) return; + if (type->Map.debug_metadata_type != nullptr) return; Type *key = type->Map.key; Type *value = type->Map.value; GB_ASSERT(key != nullptr); GB_ASSERT(value != nullptr); - - Type *key_cell = get_map_cell_type(key); Type *value_cell = get_map_cell_type(value); @@ -2541,6 +2586,18 @@ gb_internal void init_map_internal_types(Type *type) { gb_unused(type_size_of(debug_type)); type->Map.debug_metadata_type = debug_type; +} + + +gb_internal void init_map_internal_types(Type *type) { + GB_ASSERT(type->kind == Type_Map); + GB_ASSERT(t_allocator != nullptr); + if (type->Map.lookup_result_type != nullptr) return; + + Type *key = type->Map.key; + Type *value = type->Map.value; + GB_ASSERT(key != nullptr); + GB_ASSERT(value != nullptr); type->Map.lookup_result_type = make_optional_ok_type(value); } @@ -2613,8 +2670,6 @@ gb_internal void check_map_type(CheckerContext *ctx, Type *type, Ast *node) { init_core_map_type(ctx->checker); init_map_internal_types(type); - - // error(node, "'map' types are not yet implemented"); } gb_internal void check_matrix_type(CheckerContext *ctx, Type **type, Ast *node) { @@ -3233,6 +3288,11 @@ gb_internal bool check_type_internal(CheckerContext *ctx, Ast *e, Type **type, T Type *elem = t_invalid; Operand o = {}; + if (unparen_expr(pt->type) == nullptr) { + error(e, "Invalid pointer type"); + return false; + } + check_expr_or_type(&c, &o, pt->type); if (o.mode != Addressing_Invalid && o.mode != Addressing_Type) { if (o.mode == Addressing_Variable) { |