parent
3aaf814b9d
commit
3f30897fdc
@ -1430,10 +1430,10 @@ static bool type_allowed_in_extern(CodeGen *g, TypeTableEntry *type_entry) {
|
||||
case TypeTableEntryIdBoundFn:
|
||||
case TypeTableEntryIdArgTuple:
|
||||
case TypeTableEntryIdPromise:
|
||||
case TypeTableEntryIdVoid:
|
||||
return false;
|
||||
case TypeTableEntryIdOpaque:
|
||||
case TypeTableEntryIdUnreachable:
|
||||
case TypeTableEntryIdVoid:
|
||||
case TypeTableEntryIdBool:
|
||||
return true;
|
||||
case TypeTableEntryIdInt:
|
||||
@ -1460,7 +1460,10 @@ static bool type_allowed_in_extern(CodeGen *g, TypeTableEntry *type_entry) {
|
||||
case TypeTableEntryIdOptional:
|
||||
{
|
||||
TypeTableEntry *child_type = type_entry->data.maybe.child_type;
|
||||
return child_type->id == TypeTableEntryIdPointer || child_type->id == TypeTableEntryIdFn;
|
||||
if (child_type->id != TypeTableEntryIdPointer && child_type->id != TypeTableEntryIdFn) {
|
||||
return false;
|
||||
}
|
||||
return type_allowed_in_extern(g, child_type);
|
||||
}
|
||||
case TypeTableEntryIdEnum:
|
||||
return type_entry->data.enumeration.layout == ContainerLayoutExtern || type_entry->data.enumeration.layout == ContainerLayoutPacked;
|
||||
@ -1637,7 +1640,10 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c
|
||||
fn_type_id.return_type = specified_return_type;
|
||||
}
|
||||
|
||||
if (!calling_convention_allows_zig_types(fn_type_id.cc) && !type_allowed_in_extern(g, fn_type_id.return_type)) {
|
||||
if (!calling_convention_allows_zig_types(fn_type_id.cc) &&
|
||||
fn_type_id.return_type->id != TypeTableEntryIdVoid &&
|
||||
!type_allowed_in_extern(g, fn_type_id.return_type))
|
||||
{
|
||||
add_node_error(g, fn_proto->return_type,
|
||||
buf_sprintf("return type '%s' not allowed in function with calling convention '%s'",
|
||||
buf_ptr(&fn_type_id.return_type->name),
|
||||
@ -1939,6 +1945,17 @@ static void resolve_struct_type(CodeGen *g, TypeTableEntry *struct_type) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (struct_type->data.structure.layout == ContainerLayoutExtern) {
|
||||
if (!type_allowed_in_extern(g, field_type)) {
|
||||
AstNode *field_source_node = decl_node->data.container_decl.fields.at(i);
|
||||
add_node_error(g, field_source_node,
|
||||
buf_sprintf("extern structs cannot contain fields of type '%s'",
|
||||
buf_ptr(&field_type->name)));
|
||||
struct_type->data.structure.is_invalid = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!type_has_bits(field_type))
|
||||
continue;
|
||||
|
||||
|
@ -44,7 +44,7 @@ pub const timezone = extern struct {
|
||||
tz_dsttime: i32,
|
||||
};
|
||||
|
||||
pub const mach_timebase_info_data = struct {
|
||||
pub const mach_timebase_info_data = extern struct {
|
||||
numer: u32,
|
||||
denom: u32,
|
||||
};
|
||||
|
@ -1,6 +1,33 @@
|
||||
const tests = @import("tests.zig");
|
||||
|
||||
pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
cases.add(
|
||||
"optional pointer to void in extern struct",
|
||||
\\const Foo = extern struct {
|
||||
\\ x: ?*const void,
|
||||
\\};
|
||||
\\const Bar = extern struct {
|
||||
\\ foo: Foo,
|
||||
\\ y: i32,
|
||||
\\};
|
||||
\\export fn entry(bar: *Bar) void {}
|
||||
,
|
||||
".tmp_source.zig:2:5: error: extern structs cannot contain fields of type '?*const void'",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
"use of comptime-known undefined function value",
|
||||
\\const Cmd = struct {
|
||||
\\ exec: fn () void,
|
||||
\\};
|
||||
\\export fn entry() void {
|
||||
\\ const command = Cmd{ .exec = undefined };
|
||||
\\ command.exec();
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:6:12: error: use of undefined value",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
"use of comptime-known undefined function value",
|
||||
\\const Cmd = struct {
|
||||
|
Loading…
x
Reference in New Issue
Block a user