From 99a1a102864689bd8904f10e1a7fe0f79363399f Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 17 Sep 2022 11:01:56 +0100 Subject: Fixed #2044 Uninitialised constant struct member values can cause crash Foo :: struct { x: i32, data: sa.Small_Array(10, i32), } defaultFoo :: Foo{ x = 1, // The 'data' value is not set! } fmt.println(defaultFoo.data) // caused the bug --- src/check_expr.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'src/check_expr.cpp') diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 38d17c131..891a9ebcb 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -4022,6 +4022,7 @@ ExactValue get_constant_field_single(CheckerContext *c, ExactValue value, i32 in if (cl->elems[0]->kind == Ast_FieldValue) { if (is_type_struct(node->tav.type)) { + bool found = false; for_array(i, cl->elems) { Ast *elem = cl->elems[i]; if (elem->kind != Ast_FieldValue) { @@ -4033,9 +4034,14 @@ ExactValue get_constant_field_single(CheckerContext *c, ExactValue value, i32 in defer (array_free(&sub_sel.index)); if (sub_sel.index[0] == index) { value = fv->value->tav.value; + found = true; break; } } + if (!found) { + // Use the zero value if it is not found + value = {}; + } } else if (is_type_array(node->tav.type) || is_type_enumerated_array(node->tav.type)) { for_array(i, cl->elems) { Ast *elem = cl->elems[i]; @@ -4677,7 +4683,7 @@ Entity *check_selector(CheckerContext *c, Operand *operand, Ast *node, Type *typ switch (entity->kind) { case Entity_Constant: - operand->value = entity->Constant.value; + operand->value = entity->Constant.value; operand->mode = Addressing_Constant; if (operand->value.kind == ExactValue_Procedure) { Entity *proc = strip_entity_wrapping(operand->value.value_procedure); -- cgit v1.2.3 From eb7a9c55b03efe0245eb4ccd1abd552edc99224d Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 20 Sep 2022 22:47:53 +0100 Subject: Improve parapoly support for `^T` to `[^]$V` and vice versa --- src/check_expr.cpp | 12 ++++++++++++ src/types.cpp | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) (limited to 'src/check_expr.cpp') diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 891a9ebcb..196982084 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -1143,6 +1143,12 @@ bool is_polymorphic_type_assignable(CheckerContext *c, Type *poly, Type *source, return true; } return is_polymorphic_type_assignable(c, poly->Pointer.elem, source->Pointer.elem, true, modify_type); + } else if (source->kind == Type_MultiPointer) { + isize level = check_is_assignable_to_using_subtype(source->MultiPointer.elem, poly->Pointer.elem); + if (level > 0) { + return true; + } + return is_polymorphic_type_assignable(c, poly->Pointer.elem, source->MultiPointer.elem, true, modify_type); } return false; @@ -1153,6 +1159,12 @@ bool is_polymorphic_type_assignable(CheckerContext *c, Type *poly, Type *source, return true; } return is_polymorphic_type_assignable(c, poly->MultiPointer.elem, source->MultiPointer.elem, true, modify_type); + } else if (source->kind == Type_Pointer) { + isize level = check_is_assignable_to_using_subtype(source->Pointer.elem, poly->MultiPointer.elem); + if (level > 0) { + return true; + } + return is_polymorphic_type_assignable(c, poly->MultiPointer.elem, source->Pointer.elem, true, modify_type); } return false; case Type_Array: diff --git a/src/types.cpp b/src/types.cpp index e917d30fa..5ebc8689f 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -2107,6 +2107,9 @@ bool is_type_polymorphic(Type *t, bool or_specialized=false) { case Type_Pointer: return is_type_polymorphic(t->Pointer.elem, or_specialized); + case Type_MultiPointer: + return is_type_polymorphic(t->MultiPointer.elem, or_specialized); + case Type_SoaPointer: return is_type_polymorphic(t->SoaPointer.elem, or_specialized); @@ -2130,6 +2133,15 @@ bool is_type_polymorphic(Type *t, bool or_specialized=false) { case Type_Slice: return is_type_polymorphic(t->Slice.elem, or_specialized); + case Type_Matrix: + if (t->Matrix.generic_row_count != nullptr) { + return true; + } + if (t->Matrix.generic_column_count != nullptr) { + return true; + } + return is_type_polymorphic(t->Matrix.elem, or_specialized); + case Type_Tuple: for_array(i, t->Tuple.variables) { if (is_type_polymorphic(t->Tuple.variables[i]->type, or_specialized)) { @@ -2196,6 +2208,34 @@ bool is_type_polymorphic(Type *t, bool or_specialized=false) { } break; + case Type_BitSet: + if (is_type_polymorphic(t->BitSet.elem, or_specialized)) { + return true; + } + if (t->BitSet.underlying != nullptr && + is_type_polymorphic(t->BitSet.underlying, or_specialized)) { + return true; + } + break; + + case Type_RelativeSlice: + if (is_type_polymorphic(t->RelativeSlice.slice_type, or_specialized)) { + return true; + } + if (t->RelativeSlice.base_integer != nullptr && + is_type_polymorphic(t->RelativeSlice.base_integer, or_specialized)) { + return true; + } + break; + case Type_RelativePointer: + if (is_type_polymorphic(t->RelativePointer.pointer_type, or_specialized)) { + return true; + } + if (t->RelativePointer.base_integer != nullptr && + is_type_polymorphic(t->RelativePointer.base_integer, or_specialized)) { + return true; + } + break; } return false; -- cgit v1.2.3 From 8c3f01fbfa73f707e9150b0dbe2629d7d5ac2f8d Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 22 Sep 2022 00:05:11 +0100 Subject: Correct parapoly determination of generated internal type of a `map` --- src/check_expr.cpp | 8 +++++++- src/check_type.cpp | 2 -- src/checker.cpp | 4 ++-- src/llvm_backend.cpp | 1 - src/llvm_backend_type.cpp | 2 +- src/llvm_backend_utility.cpp | 2 +- src/types.cpp | 1 - 7 files changed, 11 insertions(+), 9 deletions(-) (limited to 'src/check_expr.cpp') diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 196982084..3f4f11813 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -1360,7 +1360,13 @@ bool is_polymorphic_type_assignable(CheckerContext *c, Type *poly, Type *source, if (source->kind == Type_Map) { bool key = is_polymorphic_type_assignable(c, poly->Map.key, source->Map.key, true, modify_type); bool value = is_polymorphic_type_assignable(c, poly->Map.value, source->Map.value, true, modify_type); - return key || value; + if (key || value) { + poly->Map.entry_type = nullptr; + poly->Map.internal_type = nullptr; + poly->Map.lookup_result_type = nullptr; + init_map_internal_types(poly); + return true; + } } return false; diff --git a/src/check_type.cpp b/src/check_type.cpp index c024e0842..2ffe04342 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -2211,7 +2211,6 @@ void init_map_internal_types(Type *type) { GB_ASSERT(type->kind == Type_Map); init_map_entry_type(type); if (type->Map.internal_type != nullptr) return; - if (type->Map.generated_struct_type != nullptr) return; Type *key = type->Map.key; Type *value = type->Map.value; @@ -2239,7 +2238,6 @@ void init_map_internal_types(Type *type) { generated_struct_type->Struct.fields = fields; type_set_offsets(generated_struct_type); - type->Map.generated_struct_type = generated_struct_type; type->Map.internal_type = generated_struct_type; type->Map.lookup_result_type = make_optional_ok_type(value); } diff --git a/src/checker.cpp b/src/checker.cpp index e30dea6e1..5bdc5b010 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -1922,7 +1922,7 @@ void add_type_info_type_internal(CheckerContext *c, Type *t) { init_map_internal_types(bt); add_type_info_type_internal(c, bt->Map.key); add_type_info_type_internal(c, bt->Map.value); - add_type_info_type_internal(c, bt->Map.generated_struct_type); + add_type_info_type_internal(c, bt->Map.internal_type); break; case Type_Tuple: @@ -2144,7 +2144,7 @@ void add_min_dep_type_info(Checker *c, Type *t) { init_map_internal_types(bt); add_min_dep_type_info(c, bt->Map.key); add_min_dep_type_info(c, bt->Map.value); - add_min_dep_type_info(c, bt->Map.generated_struct_type); + add_min_dep_type_info(c, bt->Map.internal_type); break; case Type_Tuple: diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 8bee5c9e5..e563fabb7 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -521,7 +521,6 @@ lbValue lb_gen_map_header_table_internal(lbProcedure *p, Type *map_type) { i64 value_offset = type_offset_of(map_type->Map.entry_type, 3); i64 value_size = type_size_of (map_type->Map.value); - Type *key_type = map_type->Map.key; Type *val_type = map_type->Map.value; gb_unused(val_type); diff --git a/src/llvm_backend_type.cpp b/src/llvm_backend_type.cpp index d424fa5b2..61955d934 100644 --- a/src/llvm_backend_type.cpp +++ b/src/llvm_backend_type.cpp @@ -787,7 +787,7 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da tag = lb_const_ptr_cast(m, variant_ptr, t_type_info_map_ptr); init_map_internal_types(t); - lbValue gst = lb_type_info(m, t->Map.generated_struct_type); + lbValue gst = lb_type_info(m, t->Map.internal_type); LLVMValueRef vals[5] = { lb_type_info(m, t->Map.key).value, diff --git a/src/llvm_backend_utility.cpp b/src/llvm_backend_utility.cpp index 14592f29a..a54171b51 100644 --- a/src/llvm_backend_utility.cpp +++ b/src/llvm_backend_utility.cpp @@ -1130,7 +1130,7 @@ lbValue lb_emit_struct_ev(lbProcedure *p, lbValue s, i32 index) { case Type_Map: { init_map_internal_types(t); - Type *gst = t->Map.generated_struct_type; + Type *gst = t->Map.internal_type; switch (index) { case 0: result_type = get_struct_field_type(gst, 0); break; case 1: result_type = get_struct_field_type(gst, 1); break; diff --git a/src/types.cpp b/src/types.cpp index 321f42aa0..fec324bf4 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -227,7 +227,6 @@ struct TypeProc { Type *key; \ Type *value; \ Type *entry_type; \ - Type *generated_struct_type; \ Type *internal_type; \ Type *lookup_result_type; \ }) \ -- cgit v1.2.3 From 3aea9a7c206f225af3bc327738f2df30d7fe0a58 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 22 Sep 2022 00:30:10 +0100 Subject: Improve error messages for compile time known bounds checking --- src/check_expr.cpp | 12 ++++++++---- src/exact_value.cpp | 3 --- 2 files changed, 8 insertions(+), 7 deletions(-) (limited to 'src/check_expr.cpp') diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 3f4f11813..1168a9ba3 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -3922,7 +3922,9 @@ bool check_index_value(CheckerContext *c, Type *main_type, bool open_range, Ast } } else if (!is_type_integer(operand.type) && !is_type_enum(operand.type)) { gbString expr_str = expr_to_string(operand.expr); - error(operand.expr, "Index '%s' must be an integer", expr_str); + gbString type_str = type_to_string(operand.type); + error(operand.expr, "Index '%s' must be an integer, got %s", expr_str, type_str); + gb_string_free(type_str); gb_string_free(expr_str); if (value) *value = 0; return false; @@ -3932,8 +3934,9 @@ bool check_index_value(CheckerContext *c, Type *main_type, bool open_range, Ast (c->state_flags & StateFlag_no_bounds_check) == 0) { BigInt i = exact_value_to_integer(operand.value).value_integer; if (i.sign && !is_type_enum(index_type) && !is_type_multi_pointer(main_type)) { + String idx_str = big_int_to_string(temporary_allocator(), &i); gbString expr_str = expr_to_string(operand.expr); - error(operand.expr, "Index '%s' cannot be a negative value", expr_str); + error(operand.expr, "Index '%s' cannot be a negative value, got %.*s", expr_str, LIT(idx_str)); gb_string_free(expr_str); if (value) *value = 0; return false; @@ -3964,7 +3967,7 @@ bool check_index_value(CheckerContext *c, Type *main_type, bool open_range, Ast if (out_of_bounds) { gbString expr_str = expr_to_string(operand.expr); if (lo_str.len > 0) { - error(operand.expr, "Index '%s' is out of bounds range %.*s .. %.*s", expr_str, LIT(lo_str), LIT(hi_str)); + error(operand.expr, "Index '%s' is out of bounds range %.*s ..= %.*s", expr_str, LIT(lo_str), LIT(hi_str)); } else { gbString index_type_str = type_to_string(index_type); error(operand.expr, "Index '%s' is out of bounds range of enum type %s", expr_str, index_type_str); @@ -3994,8 +3997,9 @@ bool check_index_value(CheckerContext *c, Type *main_type, bool open_range, Ast } if (out_of_bounds) { + String idx_str = big_int_to_string(temporary_allocator(), &i); gbString expr_str = expr_to_string(operand.expr); - error(operand.expr, "Index '%s' is out of bounds range 0..<%lld", expr_str, max_count); + error(operand.expr, "Index '%s' is out of bounds range 0..<%lld, got %.*s", expr_str, max_count, LIT(idx_str)); gb_string_free(expr_str); return false; } diff --git a/src/exact_value.cpp b/src/exact_value.cpp index 175cb61f6..1572b564f 100644 --- a/src/exact_value.cpp +++ b/src/exact_value.cpp @@ -1,8 +1,5 @@ #include -// TODO(bill): Big numbers -// IMPORTANT TODO(bill): This needs to be completely fixed!!!!!!!! - gb_global BlockingMutex hash_exact_value_mutex; struct Ast; -- cgit v1.2.3 From dade5b5ef2ee5a35cbe2c5a3d524cbc3e84402f0 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 22 Sep 2022 00:34:36 +0100 Subject: Improve error message for `check_is_expressible` (Cannot convert X to Y from Z) --- src/check_expr.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'src/check_expr.cpp') diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 1168a9ba3..0a42c6618 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -2053,15 +2053,18 @@ bool check_is_expressible(CheckerContext *ctx, Operand *o, Type *type) { o->mode = Addressing_Invalid; ); + gbString s = exact_value_to_string(o->value); + defer (gb_string_free(s)); + if (is_type_numeric(o->type) && is_type_numeric(type)) { if (!is_type_integer(o->type) && is_type_integer(type)) { - error(o->expr, "'%s' truncated to '%s'", a, b); + error(o->expr, "'%s' truncated to '%s', got %s", a, b, s); } else { - error(o->expr, "Cannot convert numeric value '%s' to '%s' from '%s", a, b, c); + error(o->expr, "Cannot convert numeric value '%s' to '%s' from '%s', got %s", a, b, c, s); check_assignment_error_suggestion(ctx, o, type); } } else { - error(o->expr, "Cannot convert '%s' to '%s' from '%s", a, b, c); + error(o->expr, "Cannot convert '%s' to '%s' from '%s', got %s", a, b, c, s); check_assignment_error_suggestion(ctx, o, type); } return false; -- cgit v1.2.3 From 0ddf1bf6603b2ea647f8c71b1bb5e26faf3e0807 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 22 Sep 2022 00:36:31 +0100 Subject: Minor style change --- src/check_expr.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src/check_expr.cpp') diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 0a42c6618..83df0fa4e 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -2046,16 +2046,15 @@ bool check_is_expressible(CheckerContext *ctx, Operand *o, Type *type) { gbString a = expr_to_string(o->expr); gbString b = type_to_string(type); gbString c = type_to_string(o->type); + gbString s = exact_value_to_string(o->value); defer( + gb_string_free(s); gb_string_free(c); gb_string_free(b); gb_string_free(a); o->mode = Addressing_Invalid; ); - gbString s = exact_value_to_string(o->value); - defer (gb_string_free(s)); - if (is_type_numeric(o->type) && is_type_numeric(type)) { if (!is_type_integer(o->type) && is_type_integer(type)) { error(o->expr, "'%s' truncated to '%s', got %s", a, b, s); -- cgit v1.2.3 From b15968f14061ba41fe5e800e191901c28c270bbe Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 22 Sep 2022 00:42:03 +0100 Subject: Improve suggestions for certain assignments --- src/check_expr.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'src/check_expr.cpp') diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 83df0fa4e..dea8574da 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -1060,6 +1060,8 @@ void check_assignment(CheckerContext *c, Operand *operand, Type *type, String co type_extra = gb_string_append_fmt(type_extra, " (package %.*s)", LIT(type_pkg->name)); } } + + ERROR_BLOCK(); error(operand->expr, "Cannot assign value '%s' of type '%s%s' to '%s%s' in %.*s", expr_str, @@ -1983,10 +1985,18 @@ void check_assignment_error_suggestion(CheckerContext *c, Operand *o, Type *type if (are_types_identical(s, d)) { error_line("\tSuggestion: the array expression may be sliced with %s[:]\n", a); } - } else if (are_types_identical(src, dst)) { + } else if (is_type_dynamic_array(src) && is_type_slice(dst)) { + Type *s = src->DynamicArray.elem; + Type *d = dst->Slice.elem; + if (are_types_identical(s, d)) { + error_line("\tSuggestion: the dynamic array expression may be sliced with %s[:]\n", a); + } + }else if (are_types_identical(src, dst) && !are_types_identical(o->type, type)) { error_line("\tSuggestion: the expression may be directly casted to type %s\n", b); } else if (are_types_identical(src, t_string) && is_type_u8_slice(dst)) { error_line("\tSuggestion: a string may be transmuted to %s\n", b); + error_line("\t This is an UNSAFE operation as string data is assumed to be immutable, \n"); + error_line("\t whereas slices in general are assumed to be mutable.\n"); } else if (is_type_u8_slice(src) && are_types_identical(dst, t_string)) { error_line("\tSuggestion: the expression may be casted to %s\n", b); } @@ -2059,10 +2069,12 @@ bool check_is_expressible(CheckerContext *ctx, Operand *o, Type *type) { if (!is_type_integer(o->type) && is_type_integer(type)) { error(o->expr, "'%s' truncated to '%s', got %s", a, b, s); } else { + ERROR_BLOCK(); error(o->expr, "Cannot convert numeric value '%s' to '%s' from '%s', got %s", a, b, c, s); check_assignment_error_suggestion(ctx, o, type); } } else { + ERROR_BLOCK(); error(o->expr, "Cannot convert '%s' to '%s' from '%s', got %s", a, b, c, s); check_assignment_error_suggestion(ctx, o, type); } -- cgit v1.2.3 From 6fe1825db9350813a41627273268dc41983eb1f7 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 22 Sep 2022 00:47:23 +0100 Subject: Improve error message for slicing an enumerated array --- src/check_expr.cpp | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'src/check_expr.cpp') diff --git a/src/check_expr.cpp b/src/check_expr.cpp index dea8574da..0686d9cb2 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -9106,7 +9106,20 @@ ExprKind check_slice_expr(CheckerContext *c, Operand *o, Ast *node, Type *type_h o->type = t->RelativeSlice.slice_type; if (o->mode != Addressing_Variable) { gbString str = expr_to_string(node); - error(node, "Cannot relative slice '%s', value is not addressable", str); + error(node, "Cannot relative slice '%s', as value is not addressable", str); + gb_string_free(str); + o->mode = Addressing_Invalid; + o->expr = node; + return kind; + } + break; + + case Type_EnumeratedArray: + { + gbString str = expr_to_string(o->expr); + gbString type_str = type_to_string(o->type); + error(o->expr, "Cannot slice '%s' of type '%s', as enumerated arrays cannot be sliced", str, type_str); + gb_string_free(type_str); gb_string_free(str); o->mode = Addressing_Invalid; o->expr = node; -- cgit v1.2.3