Commit 74d0b5bf7c
Changed files (2)
src
src/analyze.cpp
@@ -1432,8 +1432,8 @@ static bool analyze_const_string(CodeGen *g, Scope *scope, AstNode *node, Buf **
return true;
}
-static Error emit_error_unless_type_allowed_in_packed_struct(CodeGen *g, ZigType *type_entry,
- AstNode *source_node)
+static Error emit_error_unless_type_allowed_in_packed_container(CodeGen *g, ZigType *type_entry,
+ AstNode *source_node, const char* container_name)
{
Error err;
switch (type_entry->id) {
@@ -1454,8 +1454,8 @@ static Error emit_error_unless_type_allowed_in_packed_struct(CodeGen *g, ZigType
case ZigTypeIdFnFrame:
case ZigTypeIdAnyFrame:
add_node_error(g, source_node,
- buf_sprintf("type '%s' not allowed in packed struct; no guaranteed in-memory representation",
- buf_ptr(&type_entry->name)));
+ buf_sprintf("type '%s' not allowed in packed %s; no guaranteed in-memory representation",
+ buf_ptr(&type_entry->name), container_name));
return ErrorSemanticAnalyzeFail;
case ZigTypeIdVoid:
case ZigTypeIdBool:
@@ -1467,14 +1467,14 @@ static Error emit_error_unless_type_allowed_in_packed_struct(CodeGen *g, ZigType
return ErrorNone;
case ZigTypeIdArray: {
ZigType *elem_type = type_entry->data.array.child_type;
- if ((err = emit_error_unless_type_allowed_in_packed_struct(g, elem_type, source_node)))
+ if ((err = emit_error_unless_type_allowed_in_packed_container(g, elem_type, source_node, container_name)))
return err;
// TODO revisit this when doing https://github.com/ziglang/zig/issues/1512
if (type_size(g, type_entry) * 8 == type_size_bits(g, type_entry))
return ErrorNone;
add_node_error(g, source_node,
- buf_sprintf("array of '%s' not allowed in packed struct due to padding bits",
- buf_ptr(&elem_type->name)));
+ buf_sprintf("array of '%s' not allowed in packed %s due to padding bits",
+ buf_ptr(&elem_type->name), container_name));
return ErrorSemanticAnalyzeFail;
}
case ZigTypeIdStruct:
@@ -1484,8 +1484,8 @@ static Error emit_error_unless_type_allowed_in_packed_struct(CodeGen *g, ZigType
return ErrorNone;
case ContainerLayoutAuto:
add_node_error(g, source_node,
- buf_sprintf("non-packed, non-extern struct '%s' not allowed in packed struct; no guaranteed in-memory representation",
- buf_ptr(&type_entry->name)));
+ buf_sprintf("non-packed, non-extern struct '%s' not allowed in packed %s; no guaranteed in-memory representation",
+ buf_ptr(&type_entry->name), container_name));
return ErrorSemanticAnalyzeFail;
}
zig_unreachable();
@@ -1496,8 +1496,8 @@ static Error emit_error_unless_type_allowed_in_packed_struct(CodeGen *g, ZigType
return ErrorNone;
case ContainerLayoutAuto:
add_node_error(g, source_node,
- buf_sprintf("non-packed, non-extern union '%s' not allowed in packed struct; no guaranteed in-memory representation",
- buf_ptr(&type_entry->name)));
+ buf_sprintf("non-packed, non-extern union '%s' not allowed in packed %s; no guaranteed in-memory representation",
+ buf_ptr(&type_entry->name), container_name));
return ErrorSemanticAnalyzeFail;
}
zig_unreachable();
@@ -1506,8 +1506,8 @@ static Error emit_error_unless_type_allowed_in_packed_struct(CodeGen *g, ZigType
return ErrorNone;
} else {
add_node_error(g, source_node,
- buf_sprintf("type '%s' not allowed in packed struct; no guaranteed in-memory representation",
- buf_ptr(&type_entry->name)));
+ buf_sprintf("type '%s' not allowed in packed %s; no guaranteed in-memory representation",
+ buf_ptr(&type_entry->name), container_name));
return ErrorSemanticAnalyzeFail;
}
case ZigTypeIdEnum: {
@@ -1516,8 +1516,8 @@ static Error emit_error_unless_type_allowed_in_packed_struct(CodeGen *g, ZigType
return ErrorNone;
}
ErrorMsg *msg = add_node_error(g, source_node,
- buf_sprintf("type '%s' not allowed in packed struct; no guaranteed in-memory representation",
- buf_ptr(&type_entry->name)));
+ buf_sprintf("type '%s' not allowed in packed %s; no guaranteed in-memory representation",
+ buf_ptr(&type_entry->name), container_name));
add_error_note(g, msg, decl_node,
buf_sprintf("enum declaration does not specify an integer tag type"));
return ErrorSemanticAnalyzeFail;
@@ -1526,6 +1526,18 @@ static Error emit_error_unless_type_allowed_in_packed_struct(CodeGen *g, ZigType
zig_unreachable();
}
+static Error emit_error_unless_type_allowed_in_packed_struct(CodeGen *g, ZigType *type_entry,
+ AstNode *source_node)
+{
+ return emit_error_unless_type_allowed_in_packed_container(g, type_entry, source_node, "struct");
+}
+
+static Error emit_error_unless_type_allowed_in_packed_union(CodeGen *g, ZigType *type_entry,
+ AstNode *source_node)
+{
+ return emit_error_unless_type_allowed_in_packed_container(g, type_entry, source_node, "union");
+}
+
bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry) {
switch (type_entry->id) {
case ZigTypeIdInvalid:
@@ -2286,6 +2298,8 @@ static Error resolve_union_type(CodeGen *g, ZigType *union_type) {
// set temporary flag
union_type->data.unionation.resolve_loop_flag_other = true;
+ const bool is_packed = union_type->data.unionation.layout == ContainerLayoutPacked;
+
for (uint32_t i = 0; i < field_count; i += 1) {
TypeUnionField *union_field = &union_type->data.unionation.fields[i];
ZigType *field_type = resolve_union_field_type(g, union_field);
@@ -2298,6 +2312,12 @@ static Error resolve_union_type(CodeGen *g, ZigType *union_type) {
union_type->data.unionation.resolve_status = ResolveStatusInvalid;
return ErrorSemanticAnalyzeFail;
}
+ if (is_packed) {
+ if ((err = emit_error_unless_type_allowed_in_packed_union(g, field_type, union_field->decl_node))) {
+ union_type->data.unionation.resolve_status = ResolveStatusInvalid;
+ return err;
+ }
+ }
if (type_is_invalid(union_type))
return ErrorSemanticAnalyzeFail;
test/compile_errors.zig
@@ -6308,6 +6308,23 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
"tmp.zig:6:30: error: packed union does not support enum tag type",
);
+ cases.add(
+ "packed union with automatic layout field",
+ \\const Foo = struct {
+ \\ a: u32,
+ \\ b: f32,
+ \\};
+ \\const Payload = packed union {
+ \\ A: Foo,
+ \\ B: bool,
+ \\};
+ \\export fn entry() void {
+ \\ var a = Payload { .B = true };
+ \\}
+ ,
+ "tmp.zig:6:5: error: non-packed, non-extern struct 'Foo' not allowed in packed union; no guaranteed in-memory representation",
+ );
+
cases.add(
"switch on union with no attached enum",
\\const Payload = union {