aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Kelley <superjoe30@gmail.com>2017-12-01 00:34:29 -0500
committerAndrew Kelley <superjoe30@gmail.com>2017-12-01 00:34:29 -0500
commit264c86853b714482d006baa38482a6f7d55e8d94 (patch)
tree2e402053b226aeae2dbbf732edaa761cdeb8828b
parentb62e2fd8703129fcf0dc80675800f005e84ee724 (diff)
downloadzig-264c86853b714482d006baa38482a6f7d55e8d94.tar.gz
zig-264c86853b714482d006baa38482a6f7d55e8d94.zip
packed structs can have enums with explicit tag types
See #305
-rw-r--r--src/analyze.cpp4
-rw-r--r--src/codegen.cpp9
-rw-r--r--test/cases/enum.zig70
3 files changed, 81 insertions, 2 deletions
diff --git a/src/analyze.cpp b/src/analyze.cpp
index 33d6ccdc39..235aeea682 100644
--- a/src/analyze.cpp
+++ b/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();
}
diff --git a/src/codegen.cpp b/src/codegen.cpp
index da94dd4bcd..a5f8b85e22 100644
--- a/src/codegen.cpp
+++ b/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();
}
diff --git a/test/cases/enum.zig b/test/cases/enum.zig
index a56ed398b8..1b2ff10a9b 100644
--- a/test/cases/enum.zig
+++ b/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;
+}
+