Correct union type checking for constants

This commit is contained in:
gingerBill
2025-09-28 21:00:36 +01:00
parent 421bec2d17
commit f743110f63
2 changed files with 108 additions and 102 deletions
+66 -60
View File
@@ -821,11 +821,13 @@ gb_internal i64 check_distance_between_types(CheckerContext *c, Operand *operand
} }
} }
if (c != nullptr) {
if (is_type_enum(dst) && are_types_identical(dst->Enum.base_type, operand->type)) { if (is_type_enum(dst) && are_types_identical(dst->Enum.base_type, operand->type)) {
if (c->in_enum_type) { if (c->in_enum_type) {
return 3; return 3;
} }
} }
}
{ {
@@ -3590,12 +3592,8 @@ gb_internal void check_cast(CheckerContext *c, Operand *x, Type *type, bool forb
Type *final_type = type; Type *final_type = type;
if (is_const_expr && !is_type_constant_type(type)) { if (is_const_expr && !is_type_constant_type(type)) {
if (is_type_union(type)) { if (is_type_union(type)) {
if (is_type_union_constantable(type)) {
} else {
convert_to_typed(c, x, type); convert_to_typed(c, x, type);
} }
}
final_type = default_type(x->type); final_type = default_type(x->type);
} }
update_untyped_expr_type(c, x->expr, final_type, true); update_untyped_expr_type(c, x->expr, final_type, true);
@@ -8033,62 +8031,8 @@ gb_internal bool check_call_parameter_mixture(Slice<Ast *> const &args, char con
return Expr_Stmt; \ return Expr_Stmt; \
} }
gb_internal ExprKind check_call_expr_as_type_cast(CheckerContext *c, Operand *operand, Ast *call, Slice<Ast *> const &args, Type *type_hint) {
gb_internal ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *call, Ast *proc, Slice<Ast *> const &args, ProcInlining inlining, Type *type_hint) { GB_ASSERT(operand->mode == Addressing_Type);
if (proc != nullptr &&
proc->kind == Ast_BasicDirective) {
ast_node(bd, BasicDirective, proc);
String name = bd->name.string;
if (
name == "location" ||
name == "exists" ||
name == "assert" ||
name == "panic" ||
name == "defined" ||
name == "config" ||
name == "load" ||
name == "load_directory" ||
name == "load_hash" ||
name == "hash" ||
name == "caller_expression"
) {
operand->mode = Addressing_Builtin;
operand->builtin_id = BuiltinProc_DIRECTIVE;
operand->expr = proc;
operand->type = t_invalid;
add_type_and_value(c, proc, operand->mode, operand->type, operand->value);
} else {
error(proc, "Unknown directive: #%.*s", LIT(name));
operand->expr = proc;
operand->type = t_invalid;
operand->mode = Addressing_Invalid;
return Expr_Expr;
}
if (inlining != ProcInlining_none) {
error(call, "Inlining operators are not allowed on built-in procedures");
}
} else {
if (proc != nullptr) {
check_expr_or_type(c, operand, proc);
} else {
GB_ASSERT(operand->expr != nullptr);
}
}
if (operand->mode == Addressing_Invalid) {
CHECK_CALL_PARAMETER_MIXTURE_OR_RETURN("procedure call");
for (Ast *arg : args) {
if (arg->kind == Ast_FieldValue) {
arg = arg->FieldValue.value;
}
check_expr_base(c, operand, arg, nullptr);
}
operand->mode = Addressing_Invalid;
operand->expr = call;
return Expr_Stmt;
}
if (operand->mode == Addressing_Type) {
Type *t = operand->type; Type *t = operand->type;
if (is_type_polymorphic_record(t)) { if (is_type_polymorphic_record(t)) {
CHECK_CALL_PARAMETER_MIXTURE_OR_RETURN("polymorphic type construction"); CHECK_CALL_PARAMETER_MIXTURE_OR_RETURN("polymorphic type construction");
@@ -8174,6 +8118,8 @@ gb_internal ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *c
} }
operand->type = t; operand->type = t;
operand->expr = call; operand->expr = call;
if (operand->mode != Addressing_Invalid) { if (operand->mode != Addressing_Invalid) {
update_untyped_expr_type(c, arg, t, false); update_untyped_expr_type(c, arg, t, false);
} }
@@ -8184,6 +8130,66 @@ gb_internal ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *c
return Expr_Expr; return Expr_Expr;
} }
gb_internal ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *call, Ast *proc, Slice<Ast *> const &args, ProcInlining inlining, Type *type_hint) {
if (proc != nullptr &&
proc->kind == Ast_BasicDirective) {
ast_node(bd, BasicDirective, proc);
String name = bd->name.string;
if (
name == "location" ||
name == "exists" ||
name == "assert" ||
name == "panic" ||
name == "defined" ||
name == "config" ||
name == "load" ||
name == "load_directory" ||
name == "load_hash" ||
name == "hash" ||
name == "caller_expression"
) {
operand->mode = Addressing_Builtin;
operand->builtin_id = BuiltinProc_DIRECTIVE;
operand->expr = proc;
operand->type = t_invalid;
add_type_and_value(c, proc, operand->mode, operand->type, operand->value);
} else {
error(proc, "Unknown directive: #%.*s", LIT(name));
operand->expr = proc;
operand->type = t_invalid;
operand->mode = Addressing_Invalid;
return Expr_Expr;
}
if (inlining != ProcInlining_none) {
error(call, "Inlining operators are not allowed on built-in procedures");
}
} else {
if (proc != nullptr) {
check_expr_or_type(c, operand, proc);
} else {
GB_ASSERT(operand->expr != nullptr);
}
}
if (operand->mode == Addressing_Invalid) {
CHECK_CALL_PARAMETER_MIXTURE_OR_RETURN("procedure call");
for (Ast *arg : args) {
if (arg->kind == Ast_FieldValue) {
arg = arg->FieldValue.value;
}
check_expr_base(c, operand, arg, nullptr);
}
operand->mode = Addressing_Invalid;
operand->expr = call;
return Expr_Stmt;
}
if (operand->mode == Addressing_Type) {
return check_call_expr_as_type_cast(c, operand, call, args, type_hint);
}
if (operand->mode == Addressing_Builtin) { if (operand->mode == Addressing_Builtin) {
CHECK_CALL_PARAMETER_MIXTURE_OR_RETURN("builtin call"); CHECK_CALL_PARAMETER_MIXTURE_OR_RETURN("builtin call");
+1 -1
View File
@@ -3256,7 +3256,7 @@ gb_internal lbAddr lb_add_global_generated_with_name(lbModule *m, Type *type, lb
LLVMTypeRef actual_type = lb_type(m, type); LLVMTypeRef actual_type = lb_type(m, type);
if (value.value != nullptr) { if (value.value != nullptr) {
LLVMTypeRef value_type = LLVMTypeOf(value.value); LLVMTypeRef value_type = LLVMTypeOf(value.value);
GB_ASSERT(lb_sizeof(actual_type) == lb_sizeof(value_type)); GB_ASSERT_MSG(lb_sizeof(actual_type) == lb_sizeof(value_type), "%s vs %s", LLVMPrintTypeToString(actual_type), LLVMPrintTypeToString(value_type));
actual_type = value_type; actual_type = value_type;
} }