Parcourir la source

Prevent `cast` on pointer to union types

Ginger Bill il y a 8 ans
Parent
commit
2722de65b7
7 fichiers modifiés avec 29 ajouts et 9 suppressions
  1. 7 0
      code/demo.odin
  2. 1 1
      core/_preload.odin
  3. 1 1
      core/fmt.odin
  4. 1 1
      core/types.odin
  5. 14 3
      src/check_expr.c
  6. 3 3
      src/parser.c
  7. 2 0
      src/tokenizer.c

+ 7 - 0
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() {

+ 1 - 1
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,
 };
 

+ 1 - 1
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, ", "); }

+ 1 - 1
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) {

+ 14 - 3
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;
 				}

+ 3 - 3
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));

+ 2 - 0
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"),            \