authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-12-01 00:34:29-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-12-01 00:34:29-05:00
log264c86853b714482d006baa38482a6f7d55e8d94
tree2e402053b226aeae2dbbf732edaa761cdeb8828b
parentb62e2fd8703129fcf0dc80675800f005e84ee724

packed structs can have enums with explicit tag types

See #305

3 files changed, 81 insertions(+), 2 deletions(-)

src/analyze.cpp+3-1
...@@ -1536,7 +1536,6 @@ static bool type_allowed_in_packed_struct(TypeTableEntry *type_entry) {...@@ -1536,7 +1536,6 @@ static bool type_allowed_in_packed_struct(TypeTableEntry *type_entry) {
1536 case TypeTableEntryIdNullLit:1536 case TypeTableEntryIdNullLit:
1537 case TypeTableEntryIdErrorUnion:1537 case TypeTableEntryIdErrorUnion:
1538 case TypeTableEntryIdPureError:1538 case TypeTableEntryIdPureError:
1539 case TypeTableEntryIdEnum:
1540 case TypeTableEntryIdEnumTag:1539 case TypeTableEntryIdEnumTag:
1541 case TypeTableEntryIdNamespace:1540 case TypeTableEntryIdNamespace:
1542 case TypeTableEntryIdBlock:1541 case TypeTableEntryIdBlock:
...@@ -1560,6 +1559,9 @@ static bool type_allowed_in_packed_struct(TypeTableEntry *type_entry) {...@@ -1560,6 +1559,9 @@ static bool type_allowed_in_packed_struct(TypeTableEntry *type_entry) {
1560 TypeTableEntry *child_type = type_entry->data.maybe.child_type;1559 TypeTableEntry *child_type = type_entry->data.maybe.child_type;
1561 return child_type->id == TypeTableEntryIdPointer || child_type->id == TypeTableEntryIdFn;1560 return child_type->id == TypeTableEntryIdPointer || child_type->id == TypeTableEntryIdFn;
1562 }1561 }
1562 case TypeTableEntryIdEnum:
1563 return type_entry->data.enumeration.gen_field_count == 0 &&
1564 type_entry->data.enumeration.decl_node->data.container_decl.init_arg_expr != nullptr;
1563 }1565 }
1564 zig_unreachable();1566 zig_unreachable();
1565}1567}
src/codegen.cpp+8-1
...@@ -3762,7 +3762,6 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con...@@ -3762,7 +3762,6 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con
3762 case TypeTableEntryIdNullLit:3762 case TypeTableEntryIdNullLit:
3763 case TypeTableEntryIdErrorUnion:3763 case TypeTableEntryIdErrorUnion:
3764 case TypeTableEntryIdPureError:3764 case TypeTableEntryIdPureError:
3765 case TypeTableEntryIdEnum:
3766 case TypeTableEntryIdEnumTag:3765 case TypeTableEntryIdEnumTag:
3767 case TypeTableEntryIdNamespace:3766 case TypeTableEntryIdNamespace:
3768 case TypeTableEntryIdBlock:3767 case TypeTableEntryIdBlock:
...@@ -3773,6 +3772,13 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con...@@ -3773,6 +3772,13 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con
3773 zig_unreachable();3772 zig_unreachable();
3774 case TypeTableEntryIdBool:3773 case TypeTableEntryIdBool:
3775 return LLVMConstInt(big_int_type_ref, const_val->data.x_bool ? 1 : 0, false);3774 return LLVMConstInt(big_int_type_ref, const_val->data.x_bool ? 1 : 0, false);
3775 case TypeTableEntryIdEnum:
3776 {
3777 assert(type_entry->data.enumeration.gen_field_count == 0);
3778 assert(type_entry->data.enumeration.decl_node->data.container_decl.init_arg_expr != nullptr);
3779 LLVMValueRef int_val = gen_const_val(g, const_val);
3780 return LLVMConstZExt(int_val, big_int_type_ref);
3781 }
3776 case TypeTableEntryIdInt:3782 case TypeTableEntryIdInt:
3777 {3783 {
3778 LLVMValueRef int_val = gen_const_val(g, const_val);3784 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...@@ -3814,6 +3820,7 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con
3814 }3820 }
3815 return val;3821 return val;
3816 }3822 }
3823
3817 }3824 }
3818 zig_unreachable();3825 zig_unreachable();
3819}3826}
test/cases/enum.zig+70
...@@ -214,3 +214,73 @@ test "set enum tag type" {...@@ -214,3 +214,73 @@ test "set enum tag type" {
214 comptime assert(@EnumTagType(Small2) == u2);214 comptime assert(@EnumTagType(Small2) == u2);
215 }215 }
216}216}
217
218
219const A = enum (u3) {
220 One,
221 Two,
222 Three,
223 Four,
224 One2,
225 Two2,
226 Three2,
227 Four2,
228};
229
230const B = enum (u3) {
231 One3,
232 Two3,
233 Three3,
234 Four3,
235 One23,
236 Two23,
237 Three23,
238 Four23,
239};
240
241const C = enum (u2) {
242 One4,
243 Two4,
244 Three4,
245 Four4,
246};
247
248const BitFieldOfEnums = packed struct {
249 a: A,
250 b: B,
251 c: C,
252};
253
254const bit_field_1 = BitFieldOfEnums {
255 .a = A.Two,
256 .b = B.Three3,
257 .c = C.Four4,
258};
259
260test "bit field access with enum fields" {
261 var data = bit_field_1;
262 assert(getA(&data) == A.Two);
263 assert(getB(&data) == B.Three3);
264 assert(getC(&data) == C.Four4);
265 comptime assert(@sizeOf(BitFieldOfEnums) == 1);
266
267 data.b = B.Four3;
268 assert(data.b == B.Four3);
269
270 data.a = A.Three;
271 assert(data.a == A.Three);
272 assert(data.b == B.Four3);
273}
274
275fn getA(data: &const BitFieldOfEnums) -> A {
276 return data.a;
277}
278
279fn getB(data: &const BitFieldOfEnums) -> B {
280 return data.b;
281}
282
283fn getC(data: &const BitFieldOfEnums) -> C {
284 return data.c;
285}
286