From 2722de65b7e2397c0b968abc4c652711095ec7ca Mon Sep 17 00:00:00 2001 From: Ginger Bill Date: Tue, 14 Feb 2017 17:24:56 +0000 Subject: [PATCH] Prevent `cast` on pointer to union types --- code/demo.odin | 7 +++++++ core/_preload.odin | 2 +- core/fmt.odin | 2 +- core/types.odin | 2 +- src/check_expr.c | 17 ++++++++++++++--- src/parser.c | 6 +++--- src/tokenizer.c | 2 ++ 7 files changed, 29 insertions(+), 9 deletions(-) diff --git a/code/demo.odin b/code/demo.odin index a2049654c..438488045 100644 --- a/code/demo.odin +++ b/code/demo.odin @@ -1,4 +1,11 @@ #import "fmt.odin"; +#import "atomic.odin"; +#import "hash.odin"; +#import "math.odin"; +#import "mem.odin"; +#import "opengl.odin"; +#import "os.odin"; +#import "utf8.odin"; main :: proc() { diff --git a/core/_preload.odin b/core/_preload.odin index 5114e8ef2..28cd761f4 100644 --- a/core/_preload.odin +++ b/core/_preload.odin @@ -381,7 +381,7 @@ Raw_Dynamic_Array :: struct #ordered { }; Raw_Dynamic_Map :: struct #ordered { - hashes: [...]int, + hashes: [dynamic]int, entries: Raw_Dynamic_Array, }; diff --git a/core/fmt.odin b/core/fmt.odin index 937d15c8a..86af31a59 100644 --- a/core/fmt.odin +++ b/core/fmt.odin @@ -140,7 +140,7 @@ buffer_write_type :: proc(buf: ^Buffer, ti: ^Type_Info) { if info.params == nil { buffer_write_string(buf, "()"); } else { - t := cast(^Tuple)info.params; + t := union_cast(^Tuple)info.params; buffer_write_string(buf, "("); for type, i in t.types { if i > 0 { buffer_write_string(buf, ", "); } diff --git a/core/types.odin b/core/types.odin index 5a46770d5..c541aaac5 100644 --- a/core/types.odin +++ b/core/types.odin @@ -1,6 +1,6 @@ is_signed :: proc(info: ^Type_Info) -> bool { if is_integer(info) { - i := cast(^Type_Info.Integer)info; + i := union_cast(^Type_Info.Integer)info; return i.signed; } if is_float(info) { diff --git a/src/check_expr.c b/src/check_expr.c index a93165574..9ea57bd21 100644 --- a/src/check_expr.c +++ b/src/check_expr.c @@ -1071,7 +1071,7 @@ i64 check_array_or_map_count(Checker *c, AstNode *e, bool is_map) { } Operand o = {0}; if (e->kind == AstNode_UnaryExpr && - e->UnaryExpr.op.kind == Token_Question) { + e->UnaryExpr.op.kind == Token_Ellipsis) { return -1; } @@ -1966,10 +1966,21 @@ bool check_is_castable_to(Checker *c, Operand *operand, Type *y) { // Cast between pointers if (is_type_pointer(src) && is_type_pointer(dst)) { + Type *s = base_type(type_deref(src)); + if (is_type_union(s)) { + // NOTE(bill): Should the error be here?! + // NOTE(bill): This error should suppress the next casting error as it's at the same position + gbString xs = type_to_string(x); + gbString ys = type_to_string(y); + error_node(operand->expr, "Cannot cast from a union pointer `%s` to `%s`, try using `union_cast` or cast to a `rawptr`", xs, ys); + gb_string_free(ys); + gb_string_free(xs); + return false; + } return true; } - // (u)int <-> pointer + // (u)int <-> rawptr if (is_type_int_or_uint(src) && is_type_rawptr(dst)) { return true; } @@ -4494,7 +4505,7 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint if (cl->type->kind == AstNode_ArrayType && cl->type->ArrayType.count != NULL) { AstNode *count = cl->type->ArrayType.count; if (count->kind == AstNode_UnaryExpr && - count->UnaryExpr.op.kind == Token_Question) { + count->UnaryExpr.op.kind == Token_Ellipsis) { type = make_type_array(c->allocator, check_type(c, cl->type->ArrayType.elem), -1); is_to_be_determined_array_count = true; } diff --git a/src/parser.c b/src/parser.c index fedde531e..987022068 100644 --- a/src/parser.c +++ b/src/parser.c @@ -2574,8 +2574,8 @@ AstNode *parse_type_or_ident(AstFile *f) { AstNode *count_expr = NULL; bool is_vector = false; - if (f->curr_token.kind == Token_Question) { - count_expr = ast_unary_expr(f, expect_token(f, Token_Question), NULL); + if (f->curr_token.kind == Token_Ellipsis) { + count_expr = ast_unary_expr(f, expect_token(f, Token_Ellipsis), NULL); } else if (f->curr_token.kind == Token_vector) { next_token(f); if (f->curr_token.kind != Token_CloseBracket) { @@ -2586,7 +2586,7 @@ AstNode *parse_type_or_ident(AstFile *f) { syntax_error(f->curr_token, "Vector type missing count"); } is_vector = true; - } else if (f->curr_token.kind == Token_Ellipsis) { + } else if (f->curr_token.kind == Token_dynamic) { next_token(f); expect_token(f, Token_CloseBracket); return ast_dynamic_array_type(f, token, parse_type(f)); diff --git a/src/tokenizer.c b/src/tokenizer.c index fc85fd927..68ab270be 100644 --- a/src/tokenizer.c +++ b/src/tokenizer.c @@ -99,6 +99,8 @@ TOKEN_KIND(Token__KeywordBegin, "_KeywordBegin"), \ TOKEN_KIND(Token_raw_union, "raw_union"), \ TOKEN_KIND(Token_enum, "enum"), \ TOKEN_KIND(Token_vector, "vector"), \ + TOKEN_KIND(Token_static, "static"), \ + TOKEN_KIND(Token_dynamic, "dynamic"), \ TOKEN_KIND(Token_map, "map"), \ TOKEN_KIND(Token_using, "using"), \ TOKEN_KIND(Token_no_alias, "no_alias"), \