| author | |
| committer | |
| log | a4e19f94f10445273b977e21e721d236a37c5cf4 |
| tree | 842e06c40599c418b67553dfa6859c3dfcf220bc |
| parent | e74a7264ad3b221dfef0c959c1fdd6275f7c70ef |
4 files changed, 47 insertions(+), 14 deletions(-)
src/all_types.hpp+1-1| ... | ... | @@ -340,7 +340,7 @@ enum CastOp { |
| 340 | 340 | CastOpNoop, // fn call expr is a cast, but does nothing |
| 341 | 341 | CastOpPtrToInt, |
| 342 | 342 | CastOpIntToPtr, |
| 343 | CastOpIntWidenOrShorten, | |
| 343 | CastOpWidenOrShorten, | |
| 344 | 344 | CastOpToUnknownSizeArray, |
| 345 | 345 | CastOpMaybeWrap, |
| 346 | 346 | CastOpErrorWrap, |
src/analyze.cpp+15-5| ... | ... | @@ -1681,6 +1681,14 @@ static bool types_match_with_implicit_cast(CodeGen *g, TypeTableEntry *expected_ |
| 1681 | 1681 | return true; |
| 1682 | 1682 | } |
| 1683 | 1683 | |
| 1684 | // implicit float widening conversion | |
| 1685 | if (expected_type->id == TypeTableEntryIdFloat && | |
| 1686 | actual_type->id == TypeTableEntryIdFloat && | |
| 1687 | expected_type->size_in_bits >= actual_type->size_in_bits) | |
| 1688 | { | |
| 1689 | return true; | |
| 1690 | } | |
| 1691 | ||
| 1684 | 1692 | // implicit constant sized array to unknown size array conversion |
| 1685 | 1693 | if (expected_type->id == TypeTableEntryIdStruct && |
| 1686 | 1694 | expected_type->data.structure.is_unknown_size_array && |
| ... | ... | @@ -3366,7 +3374,7 @@ static void eval_const_expr_implicit_cast(CodeGen *g, AstNode *node, AstNode *ex |
| 3366 | 3374 | case CastOpNoCast: |
| 3367 | 3375 | zig_unreachable(); |
| 3368 | 3376 | case CastOpNoop: |
| 3369 | case CastOpIntWidenOrShorten: | |
| 3377 | case CastOpWidenOrShorten: | |
| 3370 | 3378 | case CastOpPointerReinterpret: |
| 3371 | 3379 | *const_val = *other_val; |
| 3372 | 3380 | break; |
| ... | ... | @@ -3477,11 +3485,13 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B |
| 3477 | 3485 | return wanted_type; |
| 3478 | 3486 | } |
| 3479 | 3487 | |
| 3480 | // explicit cast from any int to any other int | |
| 3481 | if (wanted_type->id == TypeTableEntryIdInt && | |
| 3482 | actual_type->id == TypeTableEntryIdInt) | |
| 3488 | // explicit widening or shortening cast | |
| 3489 | if ((wanted_type->id == TypeTableEntryIdInt && | |
| 3490 | actual_type->id == TypeTableEntryIdInt) || | |
| 3491 | (wanted_type->id == TypeTableEntryIdFloat && | |
| 3492 | actual_type->id == TypeTableEntryIdFloat)) | |
| 3483 | 3493 | { |
| 3484 | node->data.fn_call_expr.cast_op = CastOpIntWidenOrShorten; | |
| 3494 | node->data.fn_call_expr.cast_op = CastOpWidenOrShorten; | |
| 3485 | 3495 | eval_const_expr_implicit_cast(g, node, expr_node); |
| 3486 | 3496 | return wanted_type; |
| 3487 | 3497 | } |
src/codegen.cpp+23-7| ... | ... | @@ -349,20 +349,36 @@ static LLVMValueRef gen_enum_value_expr(CodeGen *g, AstNode *node, TypeTableEntr |
| 349 | 349 | static LLVMValueRef gen_widen_or_shorten(CodeGen *g, AstNode *source_node, TypeTableEntry *actual_type, |
| 350 | 350 | TypeTableEntry *wanted_type, LLVMValueRef expr_val) |
| 351 | 351 | { |
| 352 | assert(actual_type->id == wanted_type->id); | |
| 352 | 353 | if (actual_type->size_in_bits == wanted_type->size_in_bits) { |
| 353 | 354 | return expr_val; |
| 354 | 355 | } else if (actual_type->size_in_bits < wanted_type->size_in_bits) { |
| 355 | if (actual_type->data.integral.is_signed) { | |
| 356 | if (actual_type->id == TypeTableEntryIdFloat) { | |
| 356 | 357 | add_debug_source_node(g, source_node); |
| 357 | return LLVMBuildSExt(g->builder, expr_val, wanted_type->type_ref, ""); | |
| 358 | return LLVMBuildFPExt(g->builder, expr_val, wanted_type->type_ref, ""); | |
| 359 | } else if (actual_type->id == TypeTableEntryIdInt) { | |
| 360 | if (actual_type->data.integral.is_signed) { | |
| 361 | add_debug_source_node(g, source_node); | |
| 362 | return LLVMBuildSExt(g->builder, expr_val, wanted_type->type_ref, ""); | |
| 363 | } else { | |
| 364 | add_debug_source_node(g, source_node); | |
| 365 | return LLVMBuildZExt(g->builder, expr_val, wanted_type->type_ref, ""); | |
| 366 | } | |
| 358 | 367 | } else { |
| 368 | zig_unreachable(); | |
| 369 | } | |
| 370 | } else if (actual_type->size_in_bits > wanted_type->size_in_bits) { | |
| 371 | if (actual_type->id == TypeTableEntryIdFloat) { | |
| 359 | 372 | add_debug_source_node(g, source_node); |
| 360 | return LLVMBuildZExt(g->builder, expr_val, wanted_type->type_ref, ""); | |
| 373 | return LLVMBuildFPTrunc(g->builder, expr_val, wanted_type->type_ref, ""); | |
| 374 | } else if (actual_type->id == TypeTableEntryIdInt) { | |
| 375 | add_debug_source_node(g, source_node); | |
| 376 | return LLVMBuildTrunc(g->builder, expr_val, wanted_type->type_ref, ""); | |
| 377 | } else { | |
| 378 | zig_unreachable(); | |
| 361 | 379 | } |
| 362 | 380 | } else { |
| 363 | assert(actual_type->size_in_bits > wanted_type->size_in_bits); | |
| 364 | add_debug_source_node(g, source_node); | |
| 365 | return LLVMBuildTrunc(g->builder, expr_val, wanted_type->type_ref, ""); | |
| 381 | zig_unreachable(); | |
| 366 | 382 | } |
| 367 | 383 | } |
| 368 | 384 | |
| ... | ... | @@ -455,7 +471,7 @@ static LLVMValueRef gen_cast_expr(CodeGen *g, AstNode *node) { |
| 455 | 471 | case CastOpPointerReinterpret: |
| 456 | 472 | add_debug_source_node(g, node); |
| 457 | 473 | return LLVMBuildBitCast(g->builder, expr_val, wanted_type->type_ref, ""); |
| 458 | case CastOpIntWidenOrShorten: | |
| 474 | case CastOpWidenOrShorten: | |
| 459 | 475 | return gen_widen_or_shorten(g, node, actual_type, wanted_type, expr_val); |
| 460 | 476 | case CastOpToUnknownSizeArray: |
| 461 | 477 | { |
test/run_tests.cpp+8-1| ... | ... | @@ -1493,7 +1493,8 @@ c_import { |
| 1493 | 1493 | @c_include("stdio.h"); |
| 1494 | 1494 | } |
| 1495 | 1495 | export fn main(argc: c_int, argv: &&u8) -> c_int { |
| 1496 | const x : f64 = 3.25; | |
| 1496 | const small: f32 = 3.25; | |
| 1497 | const x: f64 = small; | |
| 1497 | 1498 | const y = i32(x); |
| 1498 | 1499 | const z = f64(y); |
| 1499 | 1500 | printf(c"%.2f\n%d\n%.2f\n", x, y, z); |
| ... | ... | @@ -1945,6 +1946,12 @@ pub fn a(x: i32) -> i32 {x + 0} |
| 1945 | 1946 | pub fn b(x: i32) -> i32 {x + 1} |
| 1946 | 1947 | export fn c(x: i32) -> i32 {x + 2} |
| 1947 | 1948 | )SOURCE", 1, ".tmp_source.zig:2:37: error: expected type 'fn(i32) -> i32', got 'extern fn(i32) -> i32'"); |
| 1949 | ||
| 1950 | ||
| 1951 | add_compile_fail_case("implicit cast from f64 to f32", R"SOURCE( | |
| 1952 | const x : f64 = 1.0; | |
| 1953 | const y : f32 = x; | |
| 1954 | )SOURCE", 1, ".tmp_source.zig:3:17: error: expected type 'f32', got 'f64'"); | |
| 1948 | 1955 | } |
| 1949 | 1956 | |
| 1950 | 1957 | ////////////////////////////////////////////////////////////////////////////// |