mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 23:58:50 +00:00
Correct union type checking for constants
This commit is contained in:
+66
-60
@@ -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);
|
||||||
}
|
}
|
||||||
@@ -8182,6 +8128,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) {
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user