From cbabcb0907e6430571c14d21fcb09c150275d99b Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 5 Jun 2024 15:43:15 +0100 Subject: Fix #3682 --- src/check_expr.cpp | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src/check_expr.cpp') diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 0830f65bd..d2d01deda 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -8866,6 +8866,10 @@ gb_internal void check_compound_literal_field_values(CheckerContext *c, SliceArray.elem; break; + case Type_BitField: + is_constant = false; + ft = bt->BitField.fields[index]->type; + break; default: GB_PANIC("invalid type: %s", type_to_string(ft)); break; @@ -8892,6 +8896,9 @@ gb_internal void check_compound_literal_field_values(CheckerContext *c, SliceArray.elem; break; + case Type_BitField: + nested_ft = bt->BitField.fields[index]->type; + break; default: GB_PANIC("invalid type %s", type_to_string(nested_ft)); break; -- cgit v1.2.3 From 7044a7d77650e922a66f3bfe99711f3ed370e1ba Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 6 Jun 2024 23:55:48 +0100 Subject: Try to fix a possible race condition with polymorphic record parameters --- src/check_builtin.cpp | 31 ++++++++----------------------- src/check_expr.cpp | 11 +++-------- src/check_type.cpp | 30 +++++++++++++----------------- src/checker.cpp | 4 ++++ src/types.cpp | 18 ++++++++++++++++++ 5 files changed, 46 insertions(+), 48 deletions(-) (limited to 'src/check_expr.cpp') diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index 7e3bcb7ee..eef925d94 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -5912,15 +5912,9 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As if (operand->mode != Addressing_Type) { error(operand->expr, "Expected a record type for '%.*s'", LIT(builtin_name)); } else { - Type *bt = base_type(operand->type); - if (bt->kind == Type_Struct) { - if (bt->Struct.polymorphic_params != nullptr) { - operand->value = exact_value_i64(bt->Struct.polymorphic_params->Tuple.variables.count); - } - } else if (bt->kind == Type_Union) { - if (bt->Union.polymorphic_params != nullptr) { - operand->value = exact_value_i64(bt->Union.polymorphic_params->Tuple.variables.count); - } + TypeTuple *tuple = get_record_polymorphic_params(operand->type); + if (tuple) { + operand->value = exact_value_i64(tuple->variables.count); } else { error(operand->expr, "Expected a record type for '%.*s'", LIT(builtin_name)); } @@ -5952,20 +5946,11 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As Entity *param = nullptr; i64 count = 0; - Type *bt = base_type(operand->type); - if (bt->kind == Type_Struct) { - if (bt->Struct.polymorphic_params != nullptr) { - count = bt->Struct.polymorphic_params->Tuple.variables.count; - if (index < count) { - param = bt->Struct.polymorphic_params->Tuple.variables[cast(isize)index]; - } - } - } else if (bt->kind == Type_Union) { - if (bt->Union.polymorphic_params != nullptr) { - count = bt->Union.polymorphic_params->Tuple.variables.count; - if (index < count) { - param = bt->Union.polymorphic_params->Tuple.variables[cast(isize)index]; - } + TypeTuple *tuple = get_record_polymorphic_params(operand->type); + if (tuple) { + count = tuple->variables.count; + if (index < count) { + param = tuple->variables[cast(isize)index]; } } else { error(operand->expr, "Expected a specialized polymorphic record type for '%.*s'", LIT(builtin_name)); diff --git a/src/check_expr.cpp b/src/check_expr.cpp index d2d01deda..ad546858c 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -7331,14 +7331,9 @@ gb_internal CallArgumentError check_polymorphic_record_type(CheckerContext *c, O gbString s = gb_string_make_reserve(heap_allocator(), e->token.string.len+3); s = gb_string_append_fmt(s, "%.*s(", LIT(e->token.string)); - Type *params = nullptr; - switch (bt->kind) { - case Type_Struct: params = bt->Struct.polymorphic_params; break; - case Type_Union: params = bt->Union.polymorphic_params; break; - } - - if (params != nullptr) for_array(i, params->Tuple.variables) { - Entity *v = params->Tuple.variables[i]; + TypeTuple *tuple = get_record_polymorphic_params(e->type); + if (tuple != nullptr) for_array(i, tuple->variables) { + Entity *v = tuple->variables[i]; String name = v->token.string; if (i > 0) { s = gb_string_append_fmt(s, ", "); diff --git a/src/check_type.cpp b/src/check_type.cpp index 7ed657bee..e0dea19cb 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -564,19 +564,7 @@ gb_internal bool check_record_poly_operand_specialization(CheckerContext *ctx, T gb_internal Entity *find_polymorphic_record_entity(GenTypesData *found_gen_types, isize param_count, Array const &ordered_operands) { for (Entity *e : found_gen_types->types) { Type *t = base_type(e->type); - TypeTuple *tuple = nullptr; - switch (t->kind) { - case Type_Struct: - if (t->Struct.polymorphic_params) { - tuple = &t->Struct.polymorphic_params->Tuple; - } - break; - case Type_Union: - if (t->Union.polymorphic_params) { - tuple = &t->Union.polymorphic_params->Tuple; - } - break; - } + TypeTuple *tuple = get_record_polymorphic_params(t); GB_ASSERT_MSG(tuple != nullptr, "%s :: %s", type_to_string(e->type), type_to_string(t)); GB_ASSERT(param_count == tuple->variables.count); @@ -663,6 +651,8 @@ gb_internal void check_struct_type(CheckerContext *ctx, Type *struct_type, Ast * &struct_type->Struct.is_polymorphic, node, poly_operands ); + wait_signal_set(&struct_type->Struct.polymorphic_wait_signal); + struct_type->Struct.is_poly_specialized = check_record_poly_operand_specialization(ctx, struct_type, poly_operands, &struct_type->Struct.is_polymorphic); if (original_type_for_poly) { GB_ASSERT(named_type != nullptr); @@ -712,6 +702,8 @@ gb_internal void check_union_type(CheckerContext *ctx, Type *union_type, Ast *no &union_type->Union.is_polymorphic, node, poly_operands ); + wait_signal_set(&union_type->Union.polymorphic_wait_signal); + union_type->Union.is_poly_specialized = check_record_poly_operand_specialization(ctx, union_type, poly_operands, &union_type->Union.is_polymorphic); if (original_type_for_poly) { GB_ASSERT(named_type != nullptr); @@ -1453,12 +1445,14 @@ gb_internal bool check_type_specialization_to(CheckerContext *ctx, Type *special return true; } + wait_for_record_polymorphic_params(s); + wait_for_record_polymorphic_params(t); if (t->Struct.polymorphic_parent == s->Struct.polymorphic_parent && s->Struct.polymorphic_params != nullptr && t->Struct.polymorphic_params != nullptr) { - TypeTuple *s_tuple = &s->Struct.polymorphic_params->Tuple; - TypeTuple *t_tuple = &t->Struct.polymorphic_params->Tuple; + TypeTuple *s_tuple = get_record_polymorphic_params(s); + TypeTuple *t_tuple = get_record_polymorphic_params(t); GB_ASSERT(t_tuple->variables.count == s_tuple->variables.count); for_array(i, s_tuple->variables) { Entity *s_e = s_tuple->variables[i]; @@ -1506,12 +1500,14 @@ gb_internal bool check_type_specialization_to(CheckerContext *ctx, Type *special return true; } + wait_for_record_polymorphic_params(s); + wait_for_record_polymorphic_params(t); if (t->Union.polymorphic_parent == s->Union.polymorphic_parent && s->Union.polymorphic_params != nullptr && t->Union.polymorphic_params != nullptr) { - TypeTuple *s_tuple = &s->Union.polymorphic_params->Tuple; - TypeTuple *t_tuple = &t->Union.polymorphic_params->Tuple; + TypeTuple *s_tuple = get_record_polymorphic_params(s); + TypeTuple *t_tuple = get_record_polymorphic_params(t); GB_ASSERT(t_tuple->variables.count == s_tuple->variables.count); for_array(i, s_tuple->variables) { Entity *s_e = s_tuple->variables[i]; diff --git a/src/checker.cpp b/src/checker.cpp index 8a58bb425..e90509c1f 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -2031,6 +2031,7 @@ gb_internal void add_type_info_type_internal(CheckerContext *c, Type *t) { } else { add_type_info_type_internal(c, t_type_info_ptr); } + wait_for_record_polymorphic_params(bt); add_type_info_type_internal(c, bt->Union.polymorphic_params); for_array(i, bt->Union.variants) { add_type_info_type_internal(c, bt->Union.variants[i]); @@ -2063,6 +2064,7 @@ gb_internal void add_type_info_type_internal(CheckerContext *c, Type *t) { } } } + wait_for_record_polymorphic_params(bt); add_type_info_type_internal(c, bt->Struct.polymorphic_params); for_array(i, bt->Struct.fields) { Entity *f = bt->Struct.fields[i]; @@ -2292,6 +2294,7 @@ gb_internal void add_min_dep_type_info(Checker *c, Type *t) { } else { add_min_dep_type_info(c, t_type_info_ptr); } + wait_for_record_polymorphic_params(bt); add_min_dep_type_info(c, bt->Union.polymorphic_params); for_array(i, bt->Union.variants) { add_min_dep_type_info(c, bt->Union.variants[i]); @@ -2321,6 +2324,7 @@ gb_internal void add_min_dep_type_info(Checker *c, Type *t) { } } } + wait_for_record_polymorphic_params(bt); add_min_dep_type_info(c, bt->Struct.polymorphic_params); for_array(i, bt->Struct.fields) { Entity *f = bt->Struct.fields[i]; diff --git a/src/types.cpp b/src/types.cpp index 45aa26894..4ceba5244 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -140,6 +140,7 @@ struct TypeStruct { i64 custom_field_align; Type * polymorphic_params; // Type_Tuple Type * polymorphic_parent; + Wait_Signal polymorphic_wait_signal; Type * soa_elem; i32 soa_count; @@ -167,6 +168,7 @@ struct TypeUnion { i64 custom_align; Type * polymorphic_params; // Type_Tuple Type * polymorphic_parent; + Wait_Signal polymorphic_wait_signal; i16 tag_size; bool is_polymorphic; @@ -1093,6 +1095,7 @@ gb_internal Type *alloc_type_struct() { gb_internal Type *alloc_type_struct_complete() { Type *t = alloc_type(Type_Struct); wait_signal_set(&t->Struct.fields_wait_signal); + wait_signal_set(&t->Struct.polymorphic_wait_signal); return t; } @@ -2136,15 +2139,30 @@ gb_internal bool is_type_polymorphic_record_unspecialized(Type *t) { return false; } +gb_internal void wait_for_record_polymorphic_params(Type *t) { + t = base_type(t); + switch (t->kind) { + case Type_Struct: + wait_signal_until_available(&t->Struct.polymorphic_wait_signal); + break; + case Type_Union: + wait_signal_until_available(&t->Union.polymorphic_wait_signal); + break; + } +} + + gb_internal TypeTuple *get_record_polymorphic_params(Type *t) { t = base_type(t); switch (t->kind) { case Type_Struct: + wait_signal_until_available(&t->Struct.polymorphic_wait_signal); if (t->Struct.polymorphic_params) { return &t->Struct.polymorphic_params->Tuple; } break; case Type_Union: + wait_signal_until_available(&t->Union.polymorphic_wait_signal); if (t->Union.polymorphic_params) { return &t->Union.polymorphic_params->Tuple; } -- cgit v1.2.3 From 4b52f7fe2bd68d74efffa55ef8b4582164c1e268 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 9 Jun 2024 13:35:22 +0100 Subject: Fix #3713 --- src/check_expr.cpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'src/check_expr.cpp') diff --git a/src/check_expr.cpp b/src/check_expr.cpp index ad546858c..4115cd1e9 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -3336,11 +3336,12 @@ gb_internal void check_cast(CheckerContext *c, Operand *x, Type *type) { } if (is_type_untyped(x->type)) { - Type *final_type = type; - if (is_const_expr && !is_type_constant_type(type)) { - final_type = default_type(x->type); - } - update_untyped_expr_type(c, x->expr, final_type, true); + convert_to_typed(c, x, type); + // Type *final_type = type; + // if (is_const_expr && !is_type_constant_type(type)) { + // final_type = default_type(x->type); + // } + // update_untyped_expr_type(c, x->expr, final_type, true); } else { Type *src = core_type(x->type); Type *dst = core_type(type); @@ -4286,7 +4287,8 @@ gb_internal void convert_to_typed(CheckerContext *c, Operand *operand, Type *tar } else { switch (operand->type->Basic.kind) { case Basic_UntypedBool: - if (!is_type_boolean(target_type)) { + if (!is_type_boolean(target_type) && + !is_type_integer(target_type)) { operand->mode = Addressing_Invalid; convert_untyped_error(c, operand, target_type); return; @@ -7527,9 +7529,6 @@ gb_internal ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *c } operand->type = t; operand->expr = call; - if (operand->mode != Addressing_Invalid) { - update_untyped_expr_type(c, arg, t, false); - } break; } } -- cgit v1.2.3 From c17981ac38ace6cac12463029273d16068bf23c3 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 9 Jun 2024 14:02:01 +0100 Subject: Add edge case to `error_operand_no_value` --- src/check_expr.cpp | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) (limited to 'src/check_expr.cpp') diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 4115cd1e9..1e6d6e2ab 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -281,8 +281,20 @@ gb_internal void error_operand_not_expression(Operand *o) { gb_internal void error_operand_no_value(Operand *o) { if (o->mode == Addressing_NoValue) { - gbString err = expr_to_string(o->expr); Ast *x = unparen_expr(o->expr); + + if (x->kind == Ast_CallExpr) { + Ast *p = unparen_expr(x->CallExpr.proc); + if (p->kind == Ast_BasicDirective) { + String tag = p->BasicDirective.name.string; + if (tag == "panic" || + tag == "assert") { + return; + } + } + } + + gbString err = expr_to_string(o->expr); if (x->kind == Ast_CallExpr) { error(o->expr, "'%s' call does not return a value and cannot be used as a value", err); } else { @@ -3336,12 +3348,11 @@ gb_internal void check_cast(CheckerContext *c, Operand *x, Type *type) { } if (is_type_untyped(x->type)) { - convert_to_typed(c, x, type); - // Type *final_type = type; - // if (is_const_expr && !is_type_constant_type(type)) { - // final_type = default_type(x->type); - // } - // update_untyped_expr_type(c, x->expr, final_type, true); + Type *final_type = type; + if (is_const_expr && !is_type_constant_type(type)) { + final_type = default_type(x->type); + } + update_untyped_expr_type(c, x->expr, final_type, true); } else { Type *src = core_type(x->type); Type *dst = core_type(type); @@ -4287,8 +4298,7 @@ gb_internal void convert_to_typed(CheckerContext *c, Operand *operand, Type *tar } else { switch (operand->type->Basic.kind) { case Basic_UntypedBool: - if (!is_type_boolean(target_type) && - !is_type_integer(target_type)) { + if (!is_type_boolean(target_type)) { operand->mode = Addressing_Invalid; convert_untyped_error(c, operand, target_type); return; @@ -7529,6 +7539,9 @@ gb_internal ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *c } operand->type = t; operand->expr = call; + if (operand->mode != Addressing_Invalid) { + update_untyped_expr_type(c, arg, t, false); + } break; } } @@ -8336,7 +8349,7 @@ gb_internal ExprKind check_basic_directive_expr(CheckerContext *c, Operand *o, A name == "assert" || name == "defined" || name == "config" || - name == "exists" || + name == "exists" || name == "load" || name == "load_hash" || name == "load_directory" || -- cgit v1.2.3 From ef7c6b98951aacc72bd25750e1c4a3a8c30c7d06 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 9 Jun 2024 14:07:07 +0100 Subject: Re Fix #3713 --- src/check_expr.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src/check_expr.cpp') diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 1e6d6e2ab..13d0e277d 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -3350,6 +3350,9 @@ gb_internal void check_cast(CheckerContext *c, Operand *x, Type *type) { if (is_type_untyped(x->type)) { Type *final_type = type; if (is_const_expr && !is_type_constant_type(type)) { + if (is_type_union(type)) { + convert_to_typed(c, x, type); + } final_type = default_type(x->type); } update_untyped_expr_type(c, x->expr, final_type, true); @@ -4298,7 +4301,8 @@ gb_internal void convert_to_typed(CheckerContext *c, Operand *operand, Type *tar } else { switch (operand->type->Basic.kind) { case Basic_UntypedBool: - if (!is_type_boolean(target_type)) { + if (!is_type_boolean(target_type) && + !is_type_integer(target_type)) { operand->mode = Addressing_Invalid; convert_untyped_error(c, operand, target_type); return; -- cgit v1.2.3