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) {
15361536 case TypeTableEntryIdNullLit:
15371537 case TypeTableEntryIdErrorUnion:
15381538 case TypeTableEntryIdPureError:
1539 case TypeTableEntryIdEnum:
15401539 case TypeTableEntryIdEnumTag:
15411540 case TypeTableEntryIdNamespace:
15421541 case TypeTableEntryIdBlock:
......@@ -1560,6 +1559,9 @@ static bool type_allowed_in_packed_struct(TypeTableEntry *type_entry) {
15601559 TypeTableEntry *child_type = type_entry->data.maybe.child_type;
15611560 return child_type->id == TypeTableEntryIdPointer || child_type->id == TypeTableEntryIdFn;
15621561 }
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;
15631565 }
15641566 zig_unreachable();
15651567}
src/codegen.cpp+8-1
......@@ -3762,7 +3762,6 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con
37623762 case TypeTableEntryIdNullLit:
37633763 case TypeTableEntryIdErrorUnion:
37643764 case TypeTableEntryIdPureError:
3765 case TypeTableEntryIdEnum:
37663765 case TypeTableEntryIdEnumTag:
37673766 case TypeTableEntryIdNamespace:
37683767 case TypeTableEntryIdBlock:
......@@ -3773,6 +3772,13 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con
37733772 zig_unreachable();
37743773 case TypeTableEntryIdBool:
37753774 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 }
37763782 case TypeTableEntryIdInt:
37773783 {
37783784 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
38143820 }
38153821 return val;
38163822 }
3823
38173824 }
38183825 zig_unreachable();
38193826}
test/cases/enum.zig+70
......@@ -214,3 +214,73 @@ test "set enum tag type" {
214214 comptime assert(@EnumTagType(Small2) == u2);
215215 }
216216}
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