mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 15:48:51 +00:00
Correct union type checking for constants
This commit is contained in:
+107
-101
@@ -821,9 +821,11 @@ gb_internal i64 check_distance_between_types(CheckerContext *c, Operand *operand
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_type_enum(dst) && are_types_identical(dst->Enum.base_type, operand->type)) {
|
if (c != nullptr) {
|
||||||
if (c->in_enum_type) {
|
if (is_type_enum(dst) && are_types_identical(dst->Enum.base_type, operand->type)) {
|
||||||
return 3;
|
if (c->in_enum_type) {
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3590,11 +3592,7 @@ 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)) {
|
convert_to_typed(c, x, type);
|
||||||
|
|
||||||
} else {
|
|
||||||
convert_to_typed(c, x, type);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
final_type = default_type(x->type);
|
final_type = default_type(x->type);
|
||||||
}
|
}
|
||||||
@@ -8033,6 +8031,106 @@ 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_ASSERT(operand->mode == Addressing_Type);
|
||||||
|
Type *t = operand->type;
|
||||||
|
if (is_type_polymorphic_record(t)) {
|
||||||
|
CHECK_CALL_PARAMETER_MIXTURE_OR_RETURN("polymorphic type construction");
|
||||||
|
|
||||||
|
if (!is_type_named(t)) {
|
||||||
|
gbString s = expr_to_string(operand->expr);
|
||||||
|
error(call, "Illegal use of an unnamed polymorphic record, %s", s);
|
||||||
|
gb_string_free(s);
|
||||||
|
operand->mode = Addressing_Invalid;
|
||||||
|
operand->type = t_invalid;;
|
||||||
|
return Expr_Expr;
|
||||||
|
}
|
||||||
|
auto err = check_polymorphic_record_type(c, operand, call);
|
||||||
|
if (err == 0) {
|
||||||
|
Ast *ident = operand->expr;
|
||||||
|
while (ident->kind == Ast_SelectorExpr) {
|
||||||
|
Ast *s = ident->SelectorExpr.selector;
|
||||||
|
ident = s;
|
||||||
|
}
|
||||||
|
Type *ot = operand->type;
|
||||||
|
GB_ASSERT(ot->kind == Type_Named);
|
||||||
|
Entity *e = ot->Named.type_name;
|
||||||
|
add_entity_use(c, ident, e);
|
||||||
|
add_type_and_value(c, call, Addressing_Type, ot, empty_exact_value);
|
||||||
|
} else {
|
||||||
|
operand->mode = Addressing_Invalid;
|
||||||
|
operand->type = t_invalid;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
CHECK_CALL_PARAMETER_MIXTURE_OR_RETURN("type conversion");
|
||||||
|
|
||||||
|
operand->mode = Addressing_Invalid;
|
||||||
|
isize arg_count = args.count;
|
||||||
|
switch (arg_count) {
|
||||||
|
case 0:
|
||||||
|
{
|
||||||
|
gbString str = type_to_string(t);
|
||||||
|
error(call, "Missing argument in conversion to '%s'", str);
|
||||||
|
gb_string_free(str);
|
||||||
|
} break;
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
gbString str = type_to_string(t);
|
||||||
|
if (t->kind == Type_Basic) {
|
||||||
|
ERROR_BLOCK();
|
||||||
|
switch (t->Basic.kind) {
|
||||||
|
case Basic_complex32:
|
||||||
|
case Basic_complex64:
|
||||||
|
case Basic_complex128:
|
||||||
|
error(call, "Too many arguments in conversion to '%s'", str);
|
||||||
|
error_line("\tSuggestion: %s(1+2i) or construct with 'complex'\n", str);
|
||||||
|
break;
|
||||||
|
case Basic_quaternion64:
|
||||||
|
case Basic_quaternion128:
|
||||||
|
case Basic_quaternion256:
|
||||||
|
error(call, "Too many arguments in conversion to '%s'", str);
|
||||||
|
error_line("\tSuggestion: %s(1+2i+3j+4k) or construct with 'quaternion'\n", str);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
error(call, "Too many arguments in conversion to '%s'", str);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
error(call, "Too many arguments in conversion to '%s'", str);
|
||||||
|
}
|
||||||
|
gb_string_free(str);
|
||||||
|
} break;
|
||||||
|
case 1: {
|
||||||
|
Ast *arg = args[0];
|
||||||
|
if (arg->kind == Ast_FieldValue) {
|
||||||
|
error(call, "'field = value' cannot be used in a type conversion");
|
||||||
|
arg = arg->FieldValue.value;
|
||||||
|
// NOTE(bill): Carry on the cast regardless
|
||||||
|
}
|
||||||
|
check_expr_with_type_hint(c, operand, arg, t);
|
||||||
|
if (operand->mode != Addressing_Invalid) {
|
||||||
|
if (is_type_polymorphic(t)) {
|
||||||
|
error(call, "A polymorphic type cannot be used in a type conversion");
|
||||||
|
} else {
|
||||||
|
// NOTE(bill): Otherwise the compiler can override the polymorphic type
|
||||||
|
// as it assumes it is determining the type
|
||||||
|
check_cast(c, operand, t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
operand->type = t;
|
||||||
|
operand->expr = call;
|
||||||
|
|
||||||
|
|
||||||
|
if (operand->mode != Addressing_Invalid) {
|
||||||
|
update_untyped_expr_type(c, arg, t, false);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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) {
|
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 &&
|
if (proc != nullptr &&
|
||||||
@@ -8089,99 +8187,7 @@ gb_internal ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *c
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (operand->mode == Addressing_Type) {
|
if (operand->mode == Addressing_Type) {
|
||||||
Type *t = operand->type;
|
return check_call_expr_as_type_cast(c, operand, call, args, type_hint);
|
||||||
if (is_type_polymorphic_record(t)) {
|
|
||||||
CHECK_CALL_PARAMETER_MIXTURE_OR_RETURN("polymorphic type construction");
|
|
||||||
|
|
||||||
if (!is_type_named(t)) {
|
|
||||||
gbString s = expr_to_string(operand->expr);
|
|
||||||
error(call, "Illegal use of an unnamed polymorphic record, %s", s);
|
|
||||||
gb_string_free(s);
|
|
||||||
operand->mode = Addressing_Invalid;
|
|
||||||
operand->type = t_invalid;;
|
|
||||||
return Expr_Expr;
|
|
||||||
}
|
|
||||||
auto err = check_polymorphic_record_type(c, operand, call);
|
|
||||||
if (err == 0) {
|
|
||||||
Ast *ident = operand->expr;
|
|
||||||
while (ident->kind == Ast_SelectorExpr) {
|
|
||||||
Ast *s = ident->SelectorExpr.selector;
|
|
||||||
ident = s;
|
|
||||||
}
|
|
||||||
Type *ot = operand->type;
|
|
||||||
GB_ASSERT(ot->kind == Type_Named);
|
|
||||||
Entity *e = ot->Named.type_name;
|
|
||||||
add_entity_use(c, ident, e);
|
|
||||||
add_type_and_value(c, call, Addressing_Type, ot, empty_exact_value);
|
|
||||||
} else {
|
|
||||||
operand->mode = Addressing_Invalid;
|
|
||||||
operand->type = t_invalid;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
CHECK_CALL_PARAMETER_MIXTURE_OR_RETURN("type conversion");
|
|
||||||
|
|
||||||
operand->mode = Addressing_Invalid;
|
|
||||||
isize arg_count = args.count;
|
|
||||||
switch (arg_count) {
|
|
||||||
case 0:
|
|
||||||
{
|
|
||||||
gbString str = type_to_string(t);
|
|
||||||
error(call, "Missing argument in conversion to '%s'", str);
|
|
||||||
gb_string_free(str);
|
|
||||||
} break;
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
gbString str = type_to_string(t);
|
|
||||||
if (t->kind == Type_Basic) {
|
|
||||||
ERROR_BLOCK();
|
|
||||||
switch (t->Basic.kind) {
|
|
||||||
case Basic_complex32:
|
|
||||||
case Basic_complex64:
|
|
||||||
case Basic_complex128:
|
|
||||||
error(call, "Too many arguments in conversion to '%s'", str);
|
|
||||||
error_line("\tSuggestion: %s(1+2i) or construct with 'complex'\n", str);
|
|
||||||
break;
|
|
||||||
case Basic_quaternion64:
|
|
||||||
case Basic_quaternion128:
|
|
||||||
case Basic_quaternion256:
|
|
||||||
error(call, "Too many arguments in conversion to '%s'", str);
|
|
||||||
error_line("\tSuggestion: %s(1+2i+3j+4k) or construct with 'quaternion'\n", str);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
error(call, "Too many arguments in conversion to '%s'", str);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
error(call, "Too many arguments in conversion to '%s'", str);
|
|
||||||
}
|
|
||||||
gb_string_free(str);
|
|
||||||
} break;
|
|
||||||
case 1: {
|
|
||||||
Ast *arg = args[0];
|
|
||||||
if (arg->kind == Ast_FieldValue) {
|
|
||||||
error(call, "'field = value' cannot be used in a type conversion");
|
|
||||||
arg = arg->FieldValue.value;
|
|
||||||
// NOTE(bill): Carry on the cast regardless
|
|
||||||
}
|
|
||||||
check_expr_with_type_hint(c, operand, arg, t);
|
|
||||||
if (operand->mode != Addressing_Invalid) {
|
|
||||||
if (is_type_polymorphic(t)) {
|
|
||||||
error(call, "A polymorphic type cannot be used in a type conversion");
|
|
||||||
} else {
|
|
||||||
// NOTE(bill): Otherwise the compiler can override the polymorphic type
|
|
||||||
// as it assumes it is determining the type
|
|
||||||
check_cast(c, operand, t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
operand->type = t;
|
|
||||||
operand->expr = call;
|
|
||||||
if (operand->mode != Addressing_Invalid) {
|
|
||||||
update_untyped_expr_type(c, arg, t, false);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Expr_Expr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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