authorgravatar for me@tadeo.caTadeo Kondrak <me@tadeo.ca> 2020-10-05 16:39:51-06:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-10-08 04:17:32-04:00
log0e57f220fb71efefa9c6246818758d9c30994f73
tree8b2ceb2b337f99291ebdadad5257e55fc112cd5b
parenteb33394d14e29600d36280b6797de0d8f40076c1

stage1: Disallow arrays in function parameters or return types

Closes #6535.

6 files changed, 51 insertions(+), 54 deletions(-)

src/stage1/analyze.cpp+29-22
...@@ -1754,7 +1754,7 @@ static Error emit_error_unless_type_allowed_in_packed_union(CodeGen *g, ZigType...@@ -1754,7 +1754,7 @@ static Error emit_error_unless_type_allowed_in_packed_union(CodeGen *g, ZigType
1754 return emit_error_unless_type_allowed_in_packed_container(g, type_entry, source_node, "union");1754 return emit_error_unless_type_allowed_in_packed_container(g, type_entry, source_node, "union");
1755}1755}
17561756
1757Error type_allowed_in_extern(CodeGen *g, ZigType *type_entry, bool *result) {1757Error type_allowed_in_extern(CodeGen *g, ZigType *type_entry, ExternPosition position, bool *result) {
1758 Error err;1758 Error err;
1759 switch (type_entry->id) {1759 switch (type_entry->id) {
1760 case ZigTypeIdInvalid:1760 case ZigTypeIdInvalid:
...@@ -1773,8 +1773,10 @@ Error type_allowed_in_extern(CodeGen *g, ZigType *type_entry, bool *result) {...@@ -1773,8 +1773,10 @@ Error type_allowed_in_extern(CodeGen *g, ZigType *type_entry, bool *result) {
1773 case ZigTypeIdAnyFrame:1773 case ZigTypeIdAnyFrame:
1774 *result = false;1774 *result = false;
1775 return ErrorNone;1775 return ErrorNone;
1776 case ZigTypeIdOpaque:
1777 case ZigTypeIdUnreachable:1776 case ZigTypeIdUnreachable:
1777 *result = position == ExternPositionFunctionReturn;
1778 return ErrorNone;
1779 case ZigTypeIdOpaque:
1778 case ZigTypeIdBool:1780 case ZigTypeIdBool:
1779 *result = true;1781 *result = true;
1780 return ErrorNone;1782 return ErrorNone;
...@@ -1792,23 +1794,27 @@ Error type_allowed_in_extern(CodeGen *g, ZigType *type_entry, bool *result) {...@@ -1792,23 +1794,27 @@ Error type_allowed_in_extern(CodeGen *g, ZigType *type_entry, bool *result) {
1792 return ErrorNone;1794 return ErrorNone;
1793 }1795 }
1794 case ZigTypeIdVector:1796 case ZigTypeIdVector:
1795 return type_allowed_in_extern(g, type_entry->data.vector.elem_type, result);1797 return type_allowed_in_extern(g, type_entry->data.vector.elem_type, ExternPositionOther, result);
1796 case ZigTypeIdFloat:1798 case ZigTypeIdFloat:
1797 *result = true;1799 *result = true;
1798 return ErrorNone;1800 return ErrorNone;
1799 case ZigTypeIdArray:1801 case ZigTypeIdArray:
1800 return type_allowed_in_extern(g, type_entry->data.array.child_type, result);1802 if ((err = type_allowed_in_extern(g, type_entry->data.array.child_type, ExternPositionOther, result)))
1803 return err;
1804 *result = *result &&
1805 position != ExternPositionFunctionParameter &&
1806 position != ExternPositionFunctionReturn;
1807 return ErrorNone;
1801 case ZigTypeIdFn:1808 case ZigTypeIdFn:
1802 *result = !calling_convention_allows_zig_types(type_entry->data.fn.fn_type_id.cc);1809 *result = !calling_convention_allows_zig_types(type_entry->data.fn.fn_type_id.cc);
1803 return ErrorNone;1810 return ErrorNone;
1804 case ZigTypeIdPointer:1811 case ZigTypeIdPointer:
1805 if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown)))1812 if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown)))
1806 return err;1813 return err;
1807 if (!type_has_bits(g, type_entry)) {1814 bool has_bits;
1808 *result = false;1815 if ((err = type_has_bits2(g, type_entry, &has_bits)))
1809 return ErrorNone;1816 return err;
1810 }1817 *result = has_bits;
1811 *result = true;
1812 return ErrorNone;1818 return ErrorNone;
1813 case ZigTypeIdStruct:1819 case ZigTypeIdStruct:
1814 *result = type_entry->data.structure.layout == ContainerLayoutExtern ||1820 *result = type_entry->data.structure.layout == ContainerLayoutExtern ||
...@@ -1820,23 +1826,24 @@ Error type_allowed_in_extern(CodeGen *g, ZigType *type_entry, bool *result) {...@@ -1820,23 +1826,24 @@ Error type_allowed_in_extern(CodeGen *g, ZigType *type_entry, bool *result) {
1820 *result = false;1826 *result = false;
1821 return ErrorNone;1827 return ErrorNone;
1822 }1828 }
1823 if (!type_is_nonnull_ptr(g, child_type)) {1829 bool is_nonnull_ptr;
1830 if ((err = type_is_nonnull_ptr2(g, child_type, &is_nonnull_ptr)))
1831 return err;
1832 if (!is_nonnull_ptr) {
1824 *result = false;1833 *result = false;
1825 return ErrorNone;1834 return ErrorNone;
1826 }1835 }
1827 return type_allowed_in_extern(g, child_type, result);1836 return type_allowed_in_extern(g, child_type, ExternPositionOther, result);
1828 }1837 }
1829 case ZigTypeIdEnum: {1838 case ZigTypeIdEnum: {
1830 if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown)))1839 if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown)))
1831 return err;1840 return err;
1832 ZigType *tag_int_type = type_entry->data.enumeration.tag_int_type;1841 ZigType *tag_int_type = type_entry->data.enumeration.tag_int_type;
1833 if (type_entry->data.enumeration.has_explicit_tag_type) {1842 if (type_entry->data.enumeration.has_explicit_tag_type)
1834 return type_allowed_in_extern(g, tag_int_type, result);1843 return type_allowed_in_extern(g, tag_int_type, position, result);
1835 } else {1844 *result = type_entry->data.enumeration.layout == ContainerLayoutExtern ||
1836 *result = type_entry->data.enumeration.layout == ContainerLayoutExtern ||1845 type_entry->data.enumeration.layout == ContainerLayoutPacked;
1837 type_entry->data.enumeration.layout == ContainerLayoutPacked;1846 return ErrorNone;
1838 return ErrorNone;
1839 }
1840 }1847 }
1841 case ZigTypeIdUnion:1848 case ZigTypeIdUnion:
1842 *result = type_entry->data.unionation.layout == ContainerLayoutExtern ||1849 *result = type_entry->data.unionation.layout == ContainerLayoutExtern ||
...@@ -1933,7 +1940,7 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc...@@ -1933,7 +1940,7 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc
19331940
1934 if (!calling_convention_allows_zig_types(fn_type_id.cc)) {1941 if (!calling_convention_allows_zig_types(fn_type_id.cc)) {
1935 bool ok_type;1942 bool ok_type;
1936 if ((err = type_allowed_in_extern(g, type_entry, &ok_type)))1943 if ((err = type_allowed_in_extern(g, type_entry, ExternPositionFunctionParameter, &ok_type)))
1937 return g->builtin_types.entry_invalid;1944 return g->builtin_types.entry_invalid;
1938 if (!ok_type) {1945 if (!ok_type) {
1939 add_node_error(g, param_node->data.param_decl.type,1946 add_node_error(g, param_node->data.param_decl.type,
...@@ -2038,7 +2045,7 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc...@@ -2038,7 +2045,7 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc
2038 if ((err = type_resolve(g, fn_type_id.return_type, ResolveStatusSizeKnown)))2045 if ((err = type_resolve(g, fn_type_id.return_type, ResolveStatusSizeKnown)))
2039 return g->builtin_types.entry_invalid;2046 return g->builtin_types.entry_invalid;
2040 bool ok_type;2047 bool ok_type;
2041 if ((err = type_allowed_in_extern(g, fn_type_id.return_type, &ok_type)))2048 if ((err = type_allowed_in_extern(g, fn_type_id.return_type, ExternPositionFunctionReturn, &ok_type)))
2042 return g->builtin_types.entry_invalid;2049 return g->builtin_types.entry_invalid;
2043 if (!ok_type) {2050 if (!ok_type) {
2044 add_node_error(g, fn_proto->return_type,2051 add_node_error(g, fn_proto->return_type,
...@@ -2357,7 +2364,7 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {...@@ -2357,7 +2364,7 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {
23572364
2358 if (struct_type->data.structure.layout == ContainerLayoutExtern) {2365 if (struct_type->data.structure.layout == ContainerLayoutExtern) {
2359 bool ok_type;2366 bool ok_type;
2360 if ((err = type_allowed_in_extern(g, field_type, &ok_type))) {2367 if ((err = type_allowed_in_extern(g, field_type, ExternPositionOther, &ok_type))) {
2361 struct_type->data.structure.resolve_status = ResolveStatusInvalid;2368 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
2362 return ErrorSemanticAnalyzeFail;2369 return ErrorSemanticAnalyzeFail;
2363 }2370 }
...@@ -2612,7 +2619,7 @@ static Error type_is_valid_extern_enum_tag(CodeGen *g, ZigType *ty, bool *result...@@ -2612,7 +2619,7 @@ static Error type_is_valid_extern_enum_tag(CodeGen *g, ZigType *ty, bool *result
2612 // signed char, a signed integer or an unsigned one. But GCC/Clang allow2619 // signed char, a signed integer or an unsigned one. But GCC/Clang allow
2613 // other integral types as a compiler extension so let's accomodate them2620 // other integral types as a compiler extension so let's accomodate them
2614 // aswell.2621 // aswell.
2615 return type_allowed_in_extern(g, ty, result);2622 return type_allowed_in_extern(g, ty, ExternPositionOther, result);
2616}2623}
26172624
2618static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {2625static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
src/stage1/analyze.hpp+7-1
...@@ -50,7 +50,13 @@ bool handle_is_ptr(CodeGen *g, ZigType *type_entry);...@@ -50,7 +50,13 @@ bool handle_is_ptr(CodeGen *g, ZigType *type_entry);
50bool type_has_bits(CodeGen *g, ZigType *type_entry);50bool type_has_bits(CodeGen *g, ZigType *type_entry);
51Error type_has_bits2(CodeGen *g, ZigType *type_entry, bool *result);51Error type_has_bits2(CodeGen *g, ZigType *type_entry, bool *result);
5252
53Error type_allowed_in_extern(CodeGen *g, ZigType *type_entry, bool *result);53enum ExternPosition {
54 ExternPositionFunctionParameter,
55 ExternPositionFunctionReturn,
56 ExternPositionOther, // array element, struct field, optional element, etc
57};
58
59Error type_allowed_in_extern(CodeGen *g, ZigType *type_entry, ExternPosition position, bool *result);
54bool ptr_allows_addr_zero(ZigType *ptr_type);60bool ptr_allows_addr_zero(ZigType *ptr_type);
5561
56// Deprecated, use `type_is_nonnull_ptr2`62// Deprecated, use `type_is_nonnull_ptr2`
src/stage1/ir.cpp+2-2
...@@ -18963,7 +18963,7 @@ static IrInstGen *ir_analyze_instruction_export(IrAnalyze *ira, IrInstSrcExport...@@ -18963,7 +18963,7 @@ static IrInstGen *ir_analyze_instruction_export(IrAnalyze *ira, IrInstSrcExport
18963 break;18963 break;
18964 case ZigTypeIdArray: {18964 case ZigTypeIdArray: {
18965 bool ok_type;18965 bool ok_type;
18966 if ((err = type_allowed_in_extern(ira->codegen, target->value->type->data.array.child_type, &ok_type)))18966 if ((err = type_allowed_in_extern(ira->codegen, target->value->type->data.array.child_type, ExternPositionOther, &ok_type)))
18967 return ira->codegen->invalid_inst_gen;18967 return ira->codegen->invalid_inst_gen;
1896818968
18969 if (!ok_type) {18969 if (!ok_type) {
...@@ -32745,7 +32745,7 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ZigValue *val) {...@@ -32745,7 +32745,7 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ZigValue *val) {
32745 return ErrorSemanticAnalyzeFail;32745 return ErrorSemanticAnalyzeFail;
32746 } else if (lazy_ptr_type->ptr_len == PtrLenC) {32746 } else if (lazy_ptr_type->ptr_len == PtrLenC) {
32747 bool ok_type;32747 bool ok_type;
32748 if ((err = type_allowed_in_extern(ira->codegen, elem_type, &ok_type)))32748 if ((err = type_allowed_in_extern(ira->codegen, elem_type, ExternPositionOther, &ok_type)))
32749 return err;32749 return err;
32750 if (!ok_type) {32750 if (!ok_type) {
32751 ir_add_error(ira, &lazy_ptr_type->elem_type->base,32751 ir_add_error(ira, &lazy_ptr_type->elem_type->base,
test/compile_errors.zig+13
...@@ -2,6 +2,19 @@ const tests = @import("tests.zig");...@@ -2,6 +2,19 @@ const tests = @import("tests.zig");
2const std = @import("std");2const std = @import("std");
33
4pub fn addCases(cases: *tests.CompileErrorContext) void {4pub fn addCases(cases: *tests.CompileErrorContext) void {
5 cases.add("array in c exported function",
6 \\export fn zig_array(x: [10]u8) void {
7 \\ expect(std.mem.eql(u8, &x, "1234567890"));
8 \\}
9 \\
10 \\export fn zig_return_array() [10]u8 {
11 \\ return "1234567890".*;
12 \\}
13 , &[_][]const u8{
14 "tmp.zig:1:24: error: parameter of type '[10]u8' not allowed in function with calling convention 'C'",
15 "tmp.zig:5:30: error: return type '[10]u8' not allowed in function with calling convention 'C'",
16 });
17
5 cases.add("@Type for exhaustive enum with undefined tag type",18 cases.add("@Type for exhaustive enum with undefined tag type",
6 \\const TypeInfo = @import("builtin").TypeInfo;19 \\const TypeInfo = @import("builtin").TypeInfo;
7 \\const Tag = @Type(.{20 \\const Tag = @Type(.{
test/stage1/c_abi/cfuncs.c-18
...@@ -28,8 +28,6 @@ void zig_ptr(void *);...@@ -28,8 +28,6 @@ void zig_ptr(void *);
2828
29void zig_bool(bool);29void zig_bool(bool);
3030
31void zig_array(uint8_t[10]);
32
33struct BigStruct {31struct BigStruct {
34 uint64_t a;32 uint64_t a;
35 uint64_t b;33 uint64_t b;
...@@ -97,9 +95,6 @@ void run_c_tests(void) {...@@ -97,9 +95,6 @@ void run_c_tests(void) {
9795
98 zig_bool(true);96 zig_bool(true);
9997
100 uint8_t array[10] = {'1', '2', '3', '4', '5', '6', '7', '8', '9', '0'};
101 zig_array(array);
102
103 {98 {
104 struct BigStruct s = {1, 2, 3, 4, 5};99 struct BigStruct s = {1, 2, 3, 4, 5};
105 zig_big_struct(s);100 zig_big_struct(s);
...@@ -190,19 +185,6 @@ void c_five_floats(float a, float b, float c, float d, float e) {...@@ -190,19 +185,6 @@ void c_five_floats(float a, float b, float c, float d, float e) {
190 assert_or_panic(e == 5.0);185 assert_or_panic(e == 5.0);
191}186}
192187
193void c_array(uint8_t x[10]) {
194 assert_or_panic(x[0] == '1');
195 assert_or_panic(x[1] == '2');
196 assert_or_panic(x[2] == '3');
197 assert_or_panic(x[3] == '4');
198 assert_or_panic(x[4] == '5');
199 assert_or_panic(x[5] == '6');
200 assert_or_panic(x[6] == '7');
201 assert_or_panic(x[7] == '8');
202 assert_or_panic(x[8] == '9');
203 assert_or_panic(x[9] == '0');
204}
205
206void c_big_struct(struct BigStruct x) {188void c_big_struct(struct BigStruct x) {
207 assert_or_panic(x.a == 1);189 assert_or_panic(x.a == 1);
208 assert_or_panic(x.b == 2);190 assert_or_panic(x.b == 2);
test/stage1/c_abi/main.zig-11
...@@ -116,17 +116,6 @@ export fn zig_bool(x: bool) void {...@@ -116,17 +116,6 @@ export fn zig_bool(x: bool) void {
116 expect(x);116 expect(x);
117}117}
118118
119extern fn c_array([10]u8) void;
120
121test "C ABI array" {
122 var array: [10]u8 = "1234567890".*;
123 c_array(array);
124}
125
126export fn zig_array(x: [10]u8) void {
127 expect(std.mem.eql(u8, &x, "1234567890"));
128}
129
130const BigStruct = extern struct {119const BigStruct = extern struct {
131 a: u64,120 a: u64,
132 b: u64,121 b: u64,