mirror of
https://github.com/odin-lang/Odin.git
synced 2026-01-03 03:32:37 +00:00
Fix conversion of untyped integers to pointers
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
#import "mem.odin";
|
||||
#import "opengl.odin";
|
||||
#import "os.odin";
|
||||
#import win32 "sys/windows.odin";
|
||||
#import "sync.odin";
|
||||
#import "utf8.odin";
|
||||
|
||||
@@ -16,6 +17,9 @@ main :: proc() {
|
||||
fmt.println("rawptr");
|
||||
}
|
||||
|
||||
THINGI :: 14451;
|
||||
THINGF :: 14451.1;
|
||||
|
||||
a: i32;
|
||||
b: f32;
|
||||
c: rawptr;
|
||||
@@ -35,8 +39,6 @@ main :: proc() {
|
||||
i := f as int;
|
||||
fmt.printf("f64 arg, f=%d\n", i);
|
||||
}
|
||||
THINGI :: 14451;
|
||||
THINGF :: 14451.1;
|
||||
|
||||
foo();
|
||||
foo(THINGI as int);
|
||||
|
||||
@@ -29,7 +29,6 @@ fetch_add :: proc(a: ^i32, operand: i32) -> i32 {
|
||||
}
|
||||
fetch_and :: proc(a: ^i32, operand: i32) -> i32 {
|
||||
return win32.InterlockedAnd(a, operand);
|
||||
|
||||
}
|
||||
fetch_or :: proc(a: ^i32, operand: i32) -> i32 {
|
||||
return win32.InterlockedOr(a, operand);
|
||||
|
||||
@@ -19,7 +19,7 @@ BOOL :: i32;
|
||||
WNDPROC :: type proc(HWND, u32, WPARAM, LPARAM) -> LRESULT #cc_c;
|
||||
|
||||
|
||||
INVALID_HANDLE_VALUE :: (-1 as int) as HANDLE;
|
||||
INVALID_HANDLE_VALUE :: ~int(0) as HANDLE;
|
||||
|
||||
FALSE: BOOL : 0;
|
||||
TRUE: BOOL : 1;
|
||||
@@ -46,7 +46,7 @@ WM_KEYUP :: 0x0101;
|
||||
|
||||
PM_REMOVE :: 1;
|
||||
|
||||
COLOR_BACKGROUND :: 1 as HBRUSH;
|
||||
COLOR_BACKGROUND :: HBRUSH(int(1));
|
||||
BLACK_BRUSH :: 4;
|
||||
|
||||
SM_CXSCREEN :: 0;
|
||||
|
||||
@@ -1398,7 +1398,8 @@ bool check_representable_as_constant(Checker *c, ExactValue in_value, Type *type
|
||||
return true;
|
||||
}
|
||||
if (in_value.kind == ExactValue_Integer) {
|
||||
return true;
|
||||
return false;
|
||||
// return true;
|
||||
}
|
||||
if (out_value) *out_value = in_value;
|
||||
}
|
||||
@@ -1727,6 +1728,7 @@ bool check_is_castable_to(Checker *c, Operand *operand, Type *y) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
if (dst->kind == Type_Array && src->kind == Type_Array) {
|
||||
if (are_types_identical(dst->Array.elem, src->Array.elem)) {
|
||||
return dst->Array.count == src->Array.count;
|
||||
@@ -1868,6 +1870,8 @@ void check_conversion(Checker *c, Operand *x, Type *type) {
|
||||
if (bt->kind == Type_Basic) {
|
||||
if (check_representable_as_constant(c, x->value, bt, &x->value)) {
|
||||
can_convert = true;
|
||||
} else if (is_type_pointer(type) && check_is_castable_to(c, x, type)) {
|
||||
can_convert = true;
|
||||
}
|
||||
}
|
||||
} else if (check_is_castable_to(c, x, type)) {
|
||||
@@ -2478,8 +2482,10 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (ast_node_expect(selector, AstNode_Ident)) {
|
||||
|
||||
// if (selector->kind != AstNode_Ident && selector->kind != AstNode_BasicLit) {
|
||||
if (selector->kind != AstNode_Ident) {
|
||||
error_node(selector, "Illegal selector kind: `%.*s`", LIT(ast_node_strings[selector->kind]));
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (op_expr->kind == AstNode_Ident) {
|
||||
@@ -2577,6 +2583,7 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (check_op_expr) {
|
||||
check_expr_base(c, operand, op_expr, NULL);
|
||||
if (operand->mode == Addressing_Invalid) {
|
||||
@@ -2589,6 +2596,43 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h
|
||||
sel = lookup_field(c->allocator, operand->type, selector->Ident.string, operand->mode == Addressing_Type);
|
||||
entity = sel.entity;
|
||||
}
|
||||
if (entity == NULL && selector->kind == AstNode_BasicLit) {
|
||||
if (is_type_struct(operand->type) || is_type_tuple(operand->type)) {
|
||||
Type *type = base_type(operand->type);
|
||||
Operand o = {0};
|
||||
check_expr(c, &o, selector);
|
||||
if (o.mode != Addressing_Constant ||
|
||||
!is_type_integer(o.type)) {
|
||||
error_node(op_expr, "Indexed based selectors must be a constant integer %s");
|
||||
goto error;
|
||||
}
|
||||
i64 index = o.value.value_integer;
|
||||
if (index < 0) {
|
||||
error_node(o.expr, "Index %lld cannot be a negative value", index);
|
||||
goto error;
|
||||
}
|
||||
|
||||
i64 max_count = 0;
|
||||
switch (type->kind) {
|
||||
case Type_Record: max_count = type->Record.field_count; break;
|
||||
case Type_Tuple: max_count = type->Tuple.variable_count; break;
|
||||
}
|
||||
|
||||
if (index >= max_count) {
|
||||
error_node(o.expr, "Index %lld is out of bounds range 0..<%lld", index, max_count);
|
||||
goto error;
|
||||
}
|
||||
|
||||
sel = lookup_field_from_index(heap_allocator(), type, index);
|
||||
entity = sel.entity;
|
||||
|
||||
GB_ASSERT(entity != NULL);
|
||||
|
||||
} else {
|
||||
error_node(op_expr, "Indexed based selectors may only be used on structs or tuples");
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
if (entity == NULL) {
|
||||
gbString op_str = expr_to_string(op_expr);
|
||||
gbString type_str = type_to_string(operand->type);
|
||||
|
||||
37
src/ir.c
37
src/ir.c
@@ -1718,7 +1718,10 @@ irValue *ir_emit_deep_field_gep(irProcedure *proc, Type *type, irValue *e, Selec
|
||||
} else if (type->kind == Type_Record) {
|
||||
type = type->Record.fields[index]->type;
|
||||
e = ir_emit_struct_ep(proc, e, index);
|
||||
} else if (type->kind == Type_Basic) {
|
||||
} else if (type->kind == Type_Tuple) {
|
||||
type = type->Tuple.variables[index]->type;
|
||||
e = ir_emit_struct_ep(proc, e, index);
|
||||
}else if (type->kind == Type_Basic) {
|
||||
switch (type->Basic.kind) {
|
||||
case Basic_any: {
|
||||
if (index == 0) {
|
||||
@@ -3351,19 +3354,31 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
|
||||
case_ast_node(se, SelectorExpr, expr);
|
||||
ir_emit_comment(proc, str_lit("SelectorExpr"));
|
||||
AstNode *sel = unparen_expr(se->selector);
|
||||
GB_ASSERT(sel->kind == AstNode_Ident);
|
||||
String selector = sel->Ident.string;
|
||||
Type *type = base_type(type_of_expr(proc->module->info, se->expr));
|
||||
if (sel->kind == AstNode_Ident) {
|
||||
String selector = sel->Ident.string;
|
||||
Type *type = base_type(type_of_expr(proc->module->info, se->expr));
|
||||
|
||||
if (type == t_invalid) {
|
||||
// NOTE(bill): Imports
|
||||
Entity *imp = entity_of_ident(proc->module->info, se->expr);
|
||||
if (imp != NULL) {
|
||||
GB_ASSERT(imp->kind == Entity_ImportName);
|
||||
if (type == t_invalid) {
|
||||
// NOTE(bill): Imports
|
||||
Entity *imp = entity_of_ident(proc->module->info, se->expr);
|
||||
if (imp != NULL) {
|
||||
GB_ASSERT(imp->kind == Entity_ImportName);
|
||||
}
|
||||
return ir_build_addr(proc, unparen_expr(se->selector));
|
||||
} else {
|
||||
Selection sel = lookup_field(proc->module->allocator, type, selector, false);
|
||||
GB_ASSERT(sel.entity != NULL);
|
||||
|
||||
irValue *a = ir_build_addr(proc, se->expr).addr;
|
||||
a = ir_emit_deep_field_gep(proc, type, a, sel);
|
||||
return ir_make_addr(a, expr);
|
||||
}
|
||||
return ir_build_addr(proc, unparen_expr(se->selector));
|
||||
} else {
|
||||
Selection sel = lookup_field(proc->module->allocator, type, selector, false);
|
||||
Type *type = base_type(type_of_expr(proc->module->info, se->expr));
|
||||
ExactValue val = type_and_value_of_expression(proc->module->info, sel)->value;
|
||||
i64 index = val.value_integer;
|
||||
|
||||
Selection sel = lookup_field_from_index(proc->module->allocator, type, index);
|
||||
GB_ASSERT(sel.entity != NULL);
|
||||
|
||||
irValue *a = ir_build_addr(proc, se->expr).addr;
|
||||
|
||||
10
src/parser.c
10
src/parser.c
@@ -1854,15 +1854,15 @@ AstNode *parse_atom_expr(AstFile *f, bool lhs) {
|
||||
case Token_Ident:
|
||||
operand = make_selector_expr(f, token, operand, parse_identifier(f));
|
||||
break;
|
||||
case Token_Integer:
|
||||
operand = make_selector_expr(f, token, operand, parse_expr(f, lhs));
|
||||
break;
|
||||
default: {
|
||||
// case Token_Integer:
|
||||
// operand = make_selector_expr(f, token, operand, parse_expr(f, lhs));
|
||||
// break;
|
||||
default:
|
||||
syntax_error(f->curr_token, "Expected a selector");
|
||||
next_token(f);
|
||||
operand = make_bad_expr(f, ast_node_token(operand), f->curr_token);
|
||||
// operand = make_selector_expr(f, f->curr_token, operand, NULL);
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
} break;
|
||||
|
||||
|
||||
45
src/types.c
45
src/types.c
@@ -980,6 +980,51 @@ Selection lookup_field(gbAllocator a, Type *type_, String field_name, bool is_ty
|
||||
return lookup_field_with_selection(a, type_, field_name, is_type, empty_selection);
|
||||
}
|
||||
|
||||
Selection lookup_field_from_index(gbAllocator a, Type *type, i64 index) {
|
||||
GB_ASSERT(is_type_struct(type) || is_type_tuple(type));
|
||||
type = base_type(type);
|
||||
|
||||
i64 max_count = 0;
|
||||
switch (type->kind) {
|
||||
case Type_Record: max_count = type->Record.field_count; break;
|
||||
case Type_Tuple: max_count = type->Tuple.variable_count; break;
|
||||
}
|
||||
|
||||
if (index >= max_count) {
|
||||
return empty_selection;
|
||||
}
|
||||
|
||||
switch (type->kind) {
|
||||
case Type_Record:
|
||||
for (isize i = 0; i < max_count; i++) {
|
||||
Entity *f = type->Record.fields[i];
|
||||
if (f->kind == Entity_Variable) {
|
||||
if (f->Variable.field_src_index == index) {
|
||||
Array_isize sel_array = {0};
|
||||
array_init_count(&sel_array, a, 1);
|
||||
sel_array.e[0] = i;
|
||||
return make_selection(f, sel_array, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Type_Tuple:
|
||||
for (isize i = 0; i < max_count; i++) {
|
||||
Entity *f = type->Tuple.variables[i];
|
||||
if (i == index) {
|
||||
Array_isize sel_array = {0};
|
||||
array_init_count(&sel_array, a, 1);
|
||||
sel_array.e[0] = i;
|
||||
return make_selection(f, sel_array, false);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
GB_PANIC("Illegal index");
|
||||
return empty_selection;
|
||||
}
|
||||
|
||||
Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_name, bool is_type, Selection sel) {
|
||||
GB_ASSERT(type_ != NULL);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user