authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-07-11 13:23:37-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-07-11 14:08:56-04:00
log3f30897fdcdb6c5579bc5609dda9746f67551870
tree6f3eb8ce8761b6a5cf8ab7d5e8a4694664c6dca0
parent3aaf814b9df6eecb6be025c4c73b8e9c46a112ba

add compile error for disallowed types in extern structs

closes #1218

3 files changed, 48 insertions(+), 4 deletions(-)

src/analyze.cpp+20-3
......@@ -1430,10 +1430,10 @@ static bool type_allowed_in_extern(CodeGen *g, TypeTableEntry *type_entry) {
14301430 case TypeTableEntryIdBoundFn:
14311431 case TypeTableEntryIdArgTuple:
14321432 case TypeTableEntryIdPromise:
1433 case TypeTableEntryIdVoid:
14331434 return false;
14341435 case TypeTableEntryIdOpaque:
14351436 case TypeTableEntryIdUnreachable:
1436 case TypeTableEntryIdVoid:
14371437 case TypeTableEntryIdBool:
14381438 return true;
14391439 case TypeTableEntryIdInt:
......@@ -1460,7 +1460,10 @@ static bool type_allowed_in_extern(CodeGen *g, TypeTableEntry *type_entry) {
14601460 case TypeTableEntryIdOptional:
14611461 {
14621462 TypeTableEntry *child_type = type_entry->data.maybe.child_type;
1463 return child_type->id == TypeTableEntryIdPointer || child_type->id == TypeTableEntryIdFn;
1463 if (child_type->id != TypeTableEntryIdPointer && child_type->id != TypeTableEntryIdFn) {
1464 return false;
1465 }
1466 return type_allowed_in_extern(g, child_type);
14641467 }
14651468 case TypeTableEntryIdEnum:
14661469 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
16371640 fn_type_id.return_type = specified_return_type;
16381641 }
16391642
1640 if (!calling_convention_allows_zig_types(fn_type_id.cc) && !type_allowed_in_extern(g, fn_type_id.return_type)) {
1643 if (!calling_convention_allows_zig_types(fn_type_id.cc) &&
1644 fn_type_id.return_type->id != TypeTableEntryIdVoid &&
1645 !type_allowed_in_extern(g, fn_type_id.return_type))
1646 {
16411647 add_node_error(g, fn_proto->return_type,
16421648 buf_sprintf("return type '%s' not allowed in function with calling convention '%s'",
16431649 buf_ptr(&fn_type_id.return_type->name),
......@@ -1939,6 +1945,17 @@ static void resolve_struct_type(CodeGen *g, TypeTableEntry *struct_type) {
19391945 break;
19401946 }
19411947
1948 if (struct_type->data.structure.layout == ContainerLayoutExtern) {
1949 if (!type_allowed_in_extern(g, field_type)) {
1950 AstNode *field_source_node = decl_node->data.container_decl.fields.at(i);
1951 add_node_error(g, field_source_node,
1952 buf_sprintf("extern structs cannot contain fields of type '%s'",
1953 buf_ptr(&field_type->name)));
1954 struct_type->data.structure.is_invalid = true;
1955 break;
1956 }
1957 }
1958
19421959 if (!type_has_bits(field_type))
19431960 continue;
19441961
std/c/darwin.zig+1-1
......@@ -44,7 +44,7 @@ pub const timezone = extern struct {
4444 tz_dsttime: i32,
4545};
4646
47pub const mach_timebase_info_data = struct {
47pub const mach_timebase_info_data = extern struct {
4848 numer: u32,
4949 denom: u32,
5050};
test/compile_errors.zig+27
......@@ -1,6 +1,33 @@
11const tests = @import("tests.zig");
22
33pub fn addCases(cases: *tests.CompileErrorContext) void {
4 cases.add(
5 "optional pointer to void in extern struct",
6 \\const Foo = extern struct {
7 \\ x: ?*const void,
8 \\};
9 \\const Bar = extern struct {
10 \\ foo: Foo,
11 \\ y: i32,
12 \\};
13 \\export fn entry(bar: *Bar) void {}
14 ,
15 ".tmp_source.zig:2:5: error: extern structs cannot contain fields of type '?*const void'",
16 );
17
18 cases.add(
19 "use of comptime-known undefined function value",
20 \\const Cmd = struct {
21 \\ exec: fn () void,
22 \\};
23 \\export fn entry() void {
24 \\ const command = Cmd{ .exec = undefined };
25 \\ command.exec();
26 \\}
27 ,
28 ".tmp_source.zig:6:12: error: use of undefined value",
29 );
30
431 cases.add(
532 "use of comptime-known undefined function value",
633 \\const Cmd = struct {