Commit 264c86853b

Andrew Kelley <superjoe30@gmail.com>
2017-12-01 06:34:29
packed structs can have enums with explicit tag types
See #305
1 parent b62e2fd
Changed files (3)
src/analyze.cpp
@@ -1536,7 +1536,6 @@ static bool type_allowed_in_packed_struct(TypeTableEntry *type_entry) {
         case TypeTableEntryIdNullLit:
         case TypeTableEntryIdErrorUnion:
         case TypeTableEntryIdPureError:
-        case TypeTableEntryIdEnum:
         case TypeTableEntryIdEnumTag:
         case TypeTableEntryIdNamespace:
         case TypeTableEntryIdBlock:
@@ -1560,6 +1559,9 @@ static bool type_allowed_in_packed_struct(TypeTableEntry *type_entry) {
                 TypeTableEntry *child_type = type_entry->data.maybe.child_type;
                 return child_type->id == TypeTableEntryIdPointer || child_type->id == TypeTableEntryIdFn;
             }
+        case TypeTableEntryIdEnum:
+            return type_entry->data.enumeration.gen_field_count == 0 &&
+                type_entry->data.enumeration.decl_node->data.container_decl.init_arg_expr != nullptr;
     }
     zig_unreachable();
 }
src/codegen.cpp
@@ -3762,7 +3762,6 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con
         case TypeTableEntryIdNullLit:
         case TypeTableEntryIdErrorUnion:
         case TypeTableEntryIdPureError:
-        case TypeTableEntryIdEnum:
         case TypeTableEntryIdEnumTag:
         case TypeTableEntryIdNamespace:
         case TypeTableEntryIdBlock:
@@ -3773,6 +3772,13 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con
             zig_unreachable();
         case TypeTableEntryIdBool:
             return LLVMConstInt(big_int_type_ref, const_val->data.x_bool ? 1 : 0, false);
+        case TypeTableEntryIdEnum:
+            {
+                assert(type_entry->data.enumeration.gen_field_count == 0);
+                assert(type_entry->data.enumeration.decl_node->data.container_decl.init_arg_expr != nullptr);
+                LLVMValueRef int_val = gen_const_val(g, const_val);
+                return LLVMConstZExt(int_val, big_int_type_ref);
+            }
         case TypeTableEntryIdInt:
             {
                 LLVMValueRef int_val = gen_const_val(g, const_val);
@@ -3814,6 +3820,7 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con
                 }
                 return val;
             }
+
     }
     zig_unreachable();
 }
test/cases/enum.zig
@@ -214,3 +214,73 @@ test "set enum tag type" {
         comptime assert(@EnumTagType(Small2) == u2);
     }
 }
+
+
+const A = enum (u3) {
+    One,
+    Two,
+    Three,
+    Four,
+    One2,
+    Two2,
+    Three2,
+    Four2,
+};
+
+const B = enum (u3) {
+    One3,
+    Two3,
+    Three3,
+    Four3,
+    One23,
+    Two23,
+    Three23,
+    Four23,
+};
+
+const C = enum (u2) {
+    One4,
+    Two4,
+    Three4,
+    Four4,
+};
+
+const BitFieldOfEnums = packed struct {
+    a: A,
+    b: B,
+    c: C,
+};
+
+const bit_field_1 = BitFieldOfEnums {
+    .a = A.Two,
+    .b = B.Three3,
+    .c = C.Four4,
+};
+
+test "bit field access with enum fields" {
+    var data = bit_field_1;
+    assert(getA(&data) == A.Two);
+    assert(getB(&data) == B.Three3);
+    assert(getC(&data) == C.Four4);
+    comptime assert(@sizeOf(BitFieldOfEnums) == 1);
+
+    data.b = B.Four3;
+    assert(data.b == B.Four3);
+
+    data.a = A.Three;
+    assert(data.a == A.Three);
+    assert(data.b == B.Four3);
+}
+
+fn getA(data: &const BitFieldOfEnums) -> A {
+    return data.a;
+}
+
+fn getB(data: &const BitFieldOfEnums) -> B {
+    return data.b;
+}
+
+fn getC(data: &const BitFieldOfEnums) -> C {
+    return data.c;
+}
+