packed structs can have enums with explicit tag types

See #305
master
Andrew Kelley 2017-12-01 00:34:29 -05:00
parent b62e2fd870
commit 264c86853b
3 changed files with 81 additions and 2 deletions

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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;
}