Commit 8c640b3e60

LemonBoy <thatlemon@gmail.com>
2020-01-06 19:54:14
Prevent bitCast to enum types
Stop the user from creating invalid enum values.
1 parent 7e7d0e1
Changed files (2)
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) {
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);