| author | |
| committer | |
| log | 2e037fd827487ce94ae0beb313a1f0536085d61e |
| tree | 273cedc57f162c4ece5c09788dfd3d6bb3d39171 |
| parent | eddc68ad9470730a2742084a29ab08fa5363c754 |
3 files changed, 44 insertions(+), 21 deletions(-)
src/ir.cpp+13-7| ... | @@ -13020,7 +13020,11 @@ static IrInstGen *ir_resolve_cast(IrAnalyze *ira, IrInst *source_instr, IrInstGe | ... | @@ -13020,7 +13020,11 @@ static IrInstGen *ir_resolve_cast(IrAnalyze *ira, IrInst *source_instr, IrInstGe |
| 13020 | { | 13020 | { |
| 13021 | if (instr_is_comptime(value) || !type_has_bits(ira->codegen, wanted_type)) { | 13021 | if (instr_is_comptime(value) || !type_has_bits(ira->codegen, wanted_type)) { |
| 13022 | IrInstGen *result = ir_const(ira, source_instr, wanted_type); | 13022 | IrInstGen *result = ir_const(ira, source_instr, wanted_type); |
| 13023 | if (!eval_const_expr_implicit_cast(ira, source_instr, cast_op, value->value, value->value->type, | 13023 | ZigValue *val = ir_resolve_const(ira, value, UndefBad); |
| 13024 | if (val == nullptr) | ||
| 13025 | return ira->codegen->invalid_inst_gen; | ||
| 13026 | |||
| 13027 | if (!eval_const_expr_implicit_cast(ira, source_instr, cast_op, val, val->type, | ||
| 13024 | result->value, wanted_type)) | 13028 | result->value, wanted_type)) |
| 13025 | { | 13029 | { |
| 13026 | return ira->codegen->invalid_inst_gen; | 13030 | return ira->codegen->invalid_inst_gen; |
| ... | @@ -26680,6 +26684,10 @@ static IrInstGen *ir_analyze_instruction_int_cast(IrAnalyze *ira, IrInstSrcIntCa | ... | @@ -26680,6 +26684,10 @@ static IrInstGen *ir_analyze_instruction_int_cast(IrAnalyze *ira, IrInstSrcIntCa |
| 26680 | } | 26684 | } |
| 26681 | 26685 | ||
| 26682 | if (instr_is_comptime(target) || dest_type->id == ZigTypeIdComptimeInt) { | 26686 | if (instr_is_comptime(target) || dest_type->id == ZigTypeIdComptimeInt) { |
| 26687 | ZigValue *val = ir_resolve_const(ira, target, UndefBad); | ||
| 26688 | if (val == nullptr) | ||
| 26689 | return ira->codegen->invalid_inst_gen; | ||
| 26690 | |||
| 26683 | return ir_implicit_cast2(ira, &instruction->target->base, target, dest_type); | 26691 | return ir_implicit_cast2(ira, &instruction->target->base, target, dest_type); |
| 26684 | } | 26692 | } |
| 26685 | 26693 | ||
| ... | @@ -26718,13 +26726,11 @@ static IrInstGen *ir_analyze_instruction_float_cast(IrAnalyze *ira, IrInstSrcFlo | ... | @@ -26718,13 +26726,11 @@ static IrInstGen *ir_analyze_instruction_float_cast(IrAnalyze *ira, IrInstSrcFlo |
| 26718 | } | 26726 | } |
| 26719 | 26727 | ||
| 26720 | if (instr_is_comptime(target) || dest_type->id == ZigTypeIdComptimeFloat) { | 26728 | if (instr_is_comptime(target) || dest_type->id == ZigTypeIdComptimeFloat) { |
| 26721 | return ir_implicit_cast2(ira, &instruction->target->base, target, dest_type); | 26729 | ZigValue *val = ir_resolve_const(ira, target, UndefBad); |
| 26722 | } | 26730 | if (val == nullptr) |
| 26731 | return ira->codegen->invalid_inst_gen; | ||
| 26723 | 26732 | ||
| 26724 | if (target->value->type->id != ZigTypeIdFloat) { | 26733 | return ir_analyze_widen_or_shorten(ira, &instruction->target->base, target, dest_type); |
| 26725 | ir_add_error(ira, &instruction->target->base, buf_sprintf("expected float type, found '%s'", | ||
| 26726 | buf_ptr(&target->value->type->name))); | ||
| 26727 | return ira->codegen->invalid_inst_gen; | ||
| 26728 | } | 26734 | } |
| 26729 | 26735 | ||
| 26730 | return ir_analyze_widen_or_shorten(ira, &instruction->base.base, target, dest_type); | 26736 | return ir_analyze_widen_or_shorten(ira, &instruction->base.base, target, dest_type); |
test/compile_errors.zig+18-14| ... | @@ -2,6 +2,22 @@ const tests = @import("tests.zig"); | ... | @@ -2,6 +2,22 @@ const tests = @import("tests.zig"); |
| 2 | const std = @import("std"); | 2 | const std = @import("std"); |
| 3 | 3 | ||
| 4 | pub fn addCases(cases: *tests.CompileErrorContext) void { | 4 | pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 5 | cases.addTest("int/float conversion to comptime_int/float", | ||
| 6 | \\export fn foo() void { | ||
| 7 | \\ var a: f32 = 2; | ||
| 8 | \\ _ = @floatToInt(comptime_int, a); | ||
| 9 | \\} | ||
| 10 | \\export fn bar() void { | ||
| 11 | \\ var a: u32 = 2; | ||
| 12 | \\ _ = @intToFloat(comptime_float, a); | ||
| 13 | \\} | ||
| 14 | , &[_][]const u8{ | ||
| 15 | "tmp.zig:3:35: error: unable to evaluate constant expression", | ||
| 16 | "tmp.zig:3:9: note: referenced here", | ||
| 17 | "tmp.zig:7:37: error: unable to evaluate constant expression", | ||
| 18 | "tmp.zig:7:9: note: referenced here", | ||
| 19 | }); | ||
| 20 | |||
| 5 | cases.add("extern variable has no type", | 21 | cases.add("extern variable has no type", |
| 6 | \\extern var foo; | 22 | \\extern var foo; |
| 7 | \\pub export fn entry() void { | 23 | \\pub export fn entry() void { |
| ... | @@ -90,19 +106,13 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -90,19 +106,13 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 90 | \\ var a: u32 = 2; | 106 | \\ var a: u32 = 2; |
| 91 | \\ _ = @floatToInt(u32, a); | 107 | \\ _ = @floatToInt(u32, a); |
| 92 | \\} | 108 | \\} |
| 93 | \\export fn qux() void { | ||
| 94 | \\ var a: u32 = 2; | ||
| 95 | \\ _ = @intCast(comptime_int, a); | ||
| 96 | \\} | ||
| 97 | , &[_][]const u8{ | 109 | , &[_][]const u8{ |
| 98 | "tmp.zig:3:32: error: expected type 'comptime_int', found 'u32'", | 110 | "tmp.zig:3:32: error: unable to evaluate constant expression", |
| 99 | "tmp.zig:3:9: note: referenced here", | 111 | "tmp.zig:3:9: note: referenced here", |
| 100 | "tmp.zig:7:21: error: expected float type, found 'u32'", | 112 | "tmp.zig:7:21: error: expected float type, found 'u32'", |
| 101 | "tmp.zig:7:9: note: referenced here", | 113 | "tmp.zig:7:9: note: referenced here", |
| 102 | "tmp.zig:11:26: error: expected float type, found 'u32'", | 114 | "tmp.zig:11:26: error: expected float type, found 'u32'", |
| 103 | "tmp.zig:11:9: note: referenced here", | 115 | "tmp.zig:11:9: note: referenced here", |
| 104 | "tmp.zig:15:32: error: expected type 'comptime_int', found 'u32'", | ||
| 105 | "tmp.zig:15:9: note: referenced here", | ||
| 106 | }); | 116 | }); |
| 107 | 117 | ||
| 108 | cases.addTest("invalid float casts", | 118 | cases.addTest("invalid float casts", |
| ... | @@ -118,19 +128,13 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -118,19 +128,13 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 118 | \\ var a: f32 = 2; | 128 | \\ var a: f32 = 2; |
| 119 | \\ _ = @intToFloat(f32, a); | 129 | \\ _ = @intToFloat(f32, a); |
| 120 | \\} | 130 | \\} |
| 121 | \\export fn qux() void { | ||
| 122 | \\ var a: f32 = 2; | ||
| 123 | \\ _ = @floatCast(comptime_float, a); | ||
| 124 | \\} | ||
| 125 | , &[_][]const u8{ | 131 | , &[_][]const u8{ |
| 126 | "tmp.zig:3:36: error: expected type 'comptime_float', found 'f32'", | 132 | "tmp.zig:3:36: error: unable to evaluate constant expression", |
| 127 | "tmp.zig:3:9: note: referenced here", | 133 | "tmp.zig:3:9: note: referenced here", |
| 128 | "tmp.zig:7:21: error: expected integer type, found 'f32'", | 134 | "tmp.zig:7:21: error: expected integer type, found 'f32'", |
| 129 | "tmp.zig:7:9: note: referenced here", | 135 | "tmp.zig:7:9: note: referenced here", |
| 130 | "tmp.zig:11:26: error: expected int type, found 'f32'", | 136 | "tmp.zig:11:26: error: expected int type, found 'f32'", |
| 131 | "tmp.zig:11:9: note: referenced here", | 137 | "tmp.zig:11:9: note: referenced here", |
| 132 | "tmp.zig:15:36: error: expected type 'comptime_float', found 'f32'", | ||
| 133 | "tmp.zig:15:9: note: referenced here", | ||
| 134 | }); | 138 | }); |
| 135 | 139 | ||
| 136 | cases.addTest("invalid assignments", | 140 | cases.addTest("invalid assignments", |
test/stage1/behavior/cast.zig+13| ... | @@ -384,6 +384,19 @@ test "@intCast i32 to u7" { | ... | @@ -384,6 +384,19 @@ test "@intCast i32 to u7" { |
| 384 | expect(z == 0xff); | 384 | expect(z == 0xff); |
| 385 | } | 385 | } |
| 386 | 386 | ||
| 387 | test "@floatCast cast down" { | ||
| 388 | { | ||
| 389 | var double: f64 = 0.001534; | ||
| 390 | var single = @floatCast(f32, double); | ||
| 391 | expect(single == 0.001534); | ||
| 392 | } | ||
| 393 | { | ||
| 394 | const double: f64 = 0.001534; | ||
| 395 | const single = @floatCast(f32, double); | ||
| 396 | expect(single == 0.001534); | ||
| 397 | } | ||
| 398 | } | ||
| 399 | |||
| 387 | test "implicit cast undefined to optional" { | 400 | test "implicit cast undefined to optional" { |
| 388 | expect(MakeType(void).getNull() == null); | 401 | expect(MakeType(void).getNull() == null); |
| 389 | expect(MakeType(void).getNonNull() != null); | 402 | expect(MakeType(void).getNonNull() != null); |