| author | |
| committer | |
| log | 8c640b3e604e597ba49abbda39bd97c379072a3a |
| tree | ab0aedc4572504248d61a074faa31637444b0ae9 |
| parent | 7e7d0e1ffaaee4f3deb49d3b98ffd5fcefaf85b1 |
Stop the user from creating invalid enum values.2 files changed, 18 insertions(+), 5 deletions(-)
src/ir.cpp+8-1| ... | ... | @@ -27078,13 +27078,20 @@ static IrInstruction *ir_analyze_bit_cast(IrAnalyze *ira, IrInstruction *source_ |
| 27078 | 27078 | ir_assert(get_codegen_ptr_type(dest_type) == nullptr, source_instr); |
| 27079 | 27079 | ir_assert(type_can_bit_cast(dest_type), source_instr); |
| 27080 | 27080 | |
| 27081 | if (dest_type->id == ZigTypeIdEnum) { | |
| 27082 | ErrorMsg *msg = ir_add_error_node(ira, source_instr->source_node, | |
| 27083 | buf_sprintf("cannot cast a value of type '%s'", buf_ptr(&dest_type->name))); | |
| 27084 | add_error_note(ira->codegen, msg, source_instr->source_node, | |
| 27085 | buf_sprintf("use @intToEnum for type coercion")); | |
| 27086 | return ira->codegen->invalid_instruction; | |
| 27087 | } | |
| 27088 | ||
| 27081 | 27089 | if ((err = type_resolve(ira->codegen, dest_type, ResolveStatusSizeKnown))) |
| 27082 | 27090 | return ira->codegen->invalid_instruction; |
| 27083 | 27091 | |
| 27084 | 27092 | if ((err = type_resolve(ira->codegen, src_type, ResolveStatusSizeKnown))) |
| 27085 | 27093 | return ira->codegen->invalid_instruction; |
| 27086 | 27094 | |
| 27087 | ||
| 27088 | 27095 | uint64_t dest_size_bytes = type_size(ira->codegen, dest_type); |
| 27089 | 27096 | uint64_t src_size_bytes = type_size(ira->codegen, src_type); |
| 27090 | 27097 | if (dest_size_bytes != src_size_bytes) { |
test/compile_errors.zig+10-4| ... | ... | @@ -2,6 +2,14 @@ const tests = @import("tests.zig"); |
| 2 | 2 | const builtin = @import("builtin"); |
| 3 | 3 | |
| 4 | 4 | pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 5 | cases.add("bitCast to enum type", | |
| 6 | \\export fn entry() void { | |
| 7 | \\ const y = @bitCast(enum(u32) { a, b }, @as(u32, 3)); | |
| 8 | \\} | |
| 9 | , &[_][]const u8{ | |
| 10 | "tmp.zig:2:24: error: cannot cast a value of type 'y'", | |
| 11 | }); | |
| 12 | ||
| 5 | 13 | cases.add("comparing against undefined produces undefined value", |
| 6 | 14 | \\export fn entry() void { |
| 7 | 15 | \\ if (2 == undefined) {} |
| ... | ... | @@ -31,8 +39,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 31 | 39 | "tmp.zig:3:12: note: destination pointer requires a terminating '0' sentinel", |
| 32 | 40 | }); |
| 33 | 41 | |
| 34 | cases.add( | |
| 35 | "cmpxchg with float", | |
| 42 | cases.add("cmpxchg with float", | |
| 36 | 43 | \\export fn entry() void { |
| 37 | 44 | \\ var x: f32 = 0; |
| 38 | 45 | \\ _ = @cmpxchgWeak(f32, &x, 1, 2, .SeqCst, .SeqCst); |
| ... | ... | @@ -41,8 +48,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 41 | 48 | "tmp.zig:3:22: error: expected integer, enum or pointer type, found 'f32'", |
| 42 | 49 | }); |
| 43 | 50 | |
| 44 | cases.add( | |
| 45 | "atomicrmw with float op not .Xchg, .Add or .Sub", | |
| 51 | cases.add("atomicrmw with float op not .Xchg, .Add or .Sub", | |
| 46 | 52 | \\export fn entry() void { |
| 47 | 53 | \\ var x: f32 = 0; |
| 48 | 54 | \\ _ = @atomicRmw(f32, &x, .And, 2, .SeqCst); |