diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 04da20ea5..54d610c0f 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -2929,6 +2929,7 @@ void check_binary_expr(CheckerContext *c, Operand *x, Ast *node, Type *type_hint void update_expr_type(CheckerContext *c, Ast *e, Type *type, bool final) { GB_ASSERT(e != nullptr); gb_mutex_lock(&c->info->untyped_mutex); + defer (gb_mutex_unlock(&c->info->untyped_mutex)); ExprInfo *old = check_get_expr_info(c->info, e); if (old == nullptr) { if (type != nullptr && type != t_invalid) { @@ -2939,26 +2940,6 @@ void update_expr_type(CheckerContext *c, Ast *e, Type *type, bool final) { return; } - if (!final && is_type_untyped(type)) { - old->type = base_type(type); - } else { - - // We need to remove it and then give it a new one - map_remove(&c->info->untyped, hash_node(e)); - - if (old->is_lhs && !is_type_integer(type)) { - gbString expr_str = expr_to_string(e); - gbString type_str = type_to_string(type); - error(e, "Shifted operand %s must be an integer, got %s", expr_str, type_str); - gb_string_free(type_str); - gb_string_free(expr_str); - return; - } - - add_type_and_value(c->info, e, old->mode, type, old->value); - } - gb_mutex_unlock(&c->info->untyped_mutex); - switch (e->kind) { case_ast_node(ue, UnaryExpr, e); if (old->value.kind != ExactValue_Invalid) { @@ -3009,6 +2990,25 @@ void update_expr_type(CheckerContext *c, Ast *e, Type *type, bool final) { update_expr_type(c, pe->expr, type, final); case_end; } + + if (!final && is_type_untyped(type)) { + old->type = base_type(type); + return; + } + + // We need to remove it and then give it a new one + map_remove(&c->info->untyped, hash_node(e)); + + if (old->is_lhs && !is_type_integer(type)) { + gbString expr_str = expr_to_string(e); + gbString type_str = type_to_string(type); + error(e, "Shifted operand %s must be an integer, got %s", expr_str, type_str); + gb_string_free(type_str); + gb_string_free(expr_str); + return; + } + + add_type_and_value(c->info, e, old->mode, type, old->value); } void update_expr_value(CheckerContext *c, Ast *e, ExactValue value) { @@ -3247,7 +3247,9 @@ void convert_to_typed(CheckerContext *c, Operand *operand, Type *target_type) { if (i > 0 && count > 2) error_line(", "); if (i == count-1) { if (count == 2) error_line(" "); - error_line("or "); + if (count > 1) { + error_line("or "); + } } gbString str = type_to_string(v); error_line("'%s'", str); diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index a457f5c57..c351876d4 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -8106,6 +8106,14 @@ lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) { return lb_addr_load(p, gen); } + if (is_type_integer(src) && is_type_complex(dst)) { + Type *ft = base_complex_elem_type(dst); + lbAddr gen = lb_add_local_generated(p, dst, true); + lbValue gp = lb_addr_get_ptr(p, gen); + lbValue real = lb_emit_conv(p, value, ft); + lb_emit_store(p, lb_emit_struct_ep(p, gp, 0), real); + return lb_addr_load(p, gen); + } if (is_type_float(src) && is_type_complex(dst)) { Type *ft = base_complex_elem_type(dst); lbAddr gen = lb_add_local_generated(p, dst, true); @@ -8114,6 +8122,17 @@ lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) { lb_emit_store(p, lb_emit_struct_ep(p, gp, 0), real); return lb_addr_load(p, gen); } + + + if (is_type_integer(src) && is_type_quaternion(dst)) { + Type *ft = base_complex_elem_type(dst); + lbAddr gen = lb_add_local_generated(p, dst, true); + lbValue gp = lb_addr_get_ptr(p, gen); + lbValue real = lb_emit_conv(p, value, ft); + // @QuaternionLayout + lb_emit_store(p, lb_emit_struct_ep(p, gp, 3), real); + return lb_addr_load(p, gen); + } if (is_type_float(src) && is_type_quaternion(dst)) { Type *ft = base_complex_elem_type(dst); lbAddr gen = lb_add_local_generated(p, dst, true);