From 8c640b3e604e597ba49abbda39bd97c379072a3a Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Mon, 6 Jan 2020 19:54:14 +0100 Subject: [PATCH] Prevent bitCast to enum types Stop the user from creating invalid enum values. --- src/ir.cpp | 9 ++++++++- test/compile_errors.zig | 14 ++++++++++---- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/ir.cpp b/src/ir.cpp index 8332cbd2d6..9b6265e1e4 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -27078,13 +27078,20 @@ static IrInstruction *ir_analyze_bit_cast(IrAnalyze *ira, IrInstruction *source_ ir_assert(get_codegen_ptr_type(dest_type) == nullptr, source_instr); ir_assert(type_can_bit_cast(dest_type), source_instr); + if (dest_type->id == ZigTypeIdEnum) { + ErrorMsg *msg = ir_add_error_node(ira, source_instr->source_node, + buf_sprintf("cannot cast a value of type '%s'", buf_ptr(&dest_type->name))); + add_error_note(ira->codegen, msg, source_instr->source_node, + buf_sprintf("use @intToEnum for type coercion")); + return ira->codegen->invalid_instruction; + } + if ((err = type_resolve(ira->codegen, dest_type, ResolveStatusSizeKnown))) return ira->codegen->invalid_instruction; if ((err = type_resolve(ira->codegen, src_type, ResolveStatusSizeKnown))) return ira->codegen->invalid_instruction; - uint64_t dest_size_bytes = type_size(ira->codegen, dest_type); uint64_t src_size_bytes = type_size(ira->codegen, src_type); if (dest_size_bytes != src_size_bytes) { diff --git a/test/compile_errors.zig b/test/compile_errors.zig index fb1cf88e74..e88811af7c 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -2,6 +2,14 @@ const tests = @import("tests.zig"); const builtin = @import("builtin"); pub fn addCases(cases: *tests.CompileErrorContext) void { + cases.add("bitCast to enum type", + \\export fn entry() void { + \\ const y = @bitCast(enum(u32) { a, b }, @as(u32, 3)); + \\} + , &[_][]const u8{ + "tmp.zig:2:24: error: cannot cast a value of type 'y'", + }); + cases.add("comparing against undefined produces undefined value", \\export fn entry() void { \\ if (2 == undefined) {} @@ -31,8 +39,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { "tmp.zig:3:12: note: destination pointer requires a terminating '0' sentinel", }); - cases.add( - "cmpxchg with float", + cases.add("cmpxchg with float", \\export fn entry() void { \\ var x: f32 = 0; \\ _ = @cmpxchgWeak(f32, &x, 1, 2, .SeqCst, .SeqCst); @@ -41,8 +48,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { "tmp.zig:3:22: error: expected integer, enum or pointer type, found 'f32'", }); - cases.add( - "atomicrmw with float op not .Xchg, .Add or .Sub", + cases.add("atomicrmw with float op not .Xchg, .Add or .Sub", \\export fn entry() void { \\ var x: f32 = 0; \\ _ = @atomicRmw(f32, &x, .And, 2, .SeqCst);