mirror of
https://github.com/ziglang/zig.git
synced 2026-02-15 13:58:27 +00:00
stage1: Disallow arrays in function parameters or return types
Closes #6535.
This commit is contained in:
parent
eb33394d14
commit
0e57f220fb
@ -1754,7 +1754,7 @@ static Error emit_error_unless_type_allowed_in_packed_union(CodeGen *g, ZigType
|
||||
return emit_error_unless_type_allowed_in_packed_container(g, type_entry, source_node, "union");
|
||||
}
|
||||
|
||||
Error type_allowed_in_extern(CodeGen *g, ZigType *type_entry, bool *result) {
|
||||
Error type_allowed_in_extern(CodeGen *g, ZigType *type_entry, ExternPosition position, bool *result) {
|
||||
Error err;
|
||||
switch (type_entry->id) {
|
||||
case ZigTypeIdInvalid:
|
||||
@ -1773,8 +1773,10 @@ Error type_allowed_in_extern(CodeGen *g, ZigType *type_entry, bool *result) {
|
||||
case ZigTypeIdAnyFrame:
|
||||
*result = false;
|
||||
return ErrorNone;
|
||||
case ZigTypeIdOpaque:
|
||||
case ZigTypeIdUnreachable:
|
||||
*result = position == ExternPositionFunctionReturn;
|
||||
return ErrorNone;
|
||||
case ZigTypeIdOpaque:
|
||||
case ZigTypeIdBool:
|
||||
*result = true;
|
||||
return ErrorNone;
|
||||
@ -1792,23 +1794,27 @@ Error type_allowed_in_extern(CodeGen *g, ZigType *type_entry, bool *result) {
|
||||
return ErrorNone;
|
||||
}
|
||||
case ZigTypeIdVector:
|
||||
return type_allowed_in_extern(g, type_entry->data.vector.elem_type, result);
|
||||
return type_allowed_in_extern(g, type_entry->data.vector.elem_type, ExternPositionOther, result);
|
||||
case ZigTypeIdFloat:
|
||||
*result = true;
|
||||
return ErrorNone;
|
||||
case ZigTypeIdArray:
|
||||
return type_allowed_in_extern(g, type_entry->data.array.child_type, result);
|
||||
if ((err = type_allowed_in_extern(g, type_entry->data.array.child_type, ExternPositionOther, result)))
|
||||
return err;
|
||||
*result = *result &&
|
||||
position != ExternPositionFunctionParameter &&
|
||||
position != ExternPositionFunctionReturn;
|
||||
return ErrorNone;
|
||||
case ZigTypeIdFn:
|
||||
*result = !calling_convention_allows_zig_types(type_entry->data.fn.fn_type_id.cc);
|
||||
return ErrorNone;
|
||||
case ZigTypeIdPointer:
|
||||
if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown)))
|
||||
return err;
|
||||
if (!type_has_bits(g, type_entry)) {
|
||||
*result = false;
|
||||
return ErrorNone;
|
||||
}
|
||||
*result = true;
|
||||
bool has_bits;
|
||||
if ((err = type_has_bits2(g, type_entry, &has_bits)))
|
||||
return err;
|
||||
*result = has_bits;
|
||||
return ErrorNone;
|
||||
case ZigTypeIdStruct:
|
||||
*result = type_entry->data.structure.layout == ContainerLayoutExtern ||
|
||||
@ -1820,23 +1826,24 @@ Error type_allowed_in_extern(CodeGen *g, ZigType *type_entry, bool *result) {
|
||||
*result = false;
|
||||
return ErrorNone;
|
||||
}
|
||||
if (!type_is_nonnull_ptr(g, child_type)) {
|
||||
bool is_nonnull_ptr;
|
||||
if ((err = type_is_nonnull_ptr2(g, child_type, &is_nonnull_ptr)))
|
||||
return err;
|
||||
if (!is_nonnull_ptr) {
|
||||
*result = false;
|
||||
return ErrorNone;
|
||||
}
|
||||
return type_allowed_in_extern(g, child_type, result);
|
||||
return type_allowed_in_extern(g, child_type, ExternPositionOther, result);
|
||||
}
|
||||
case ZigTypeIdEnum: {
|
||||
if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown)))
|
||||
return err;
|
||||
ZigType *tag_int_type = type_entry->data.enumeration.tag_int_type;
|
||||
if (type_entry->data.enumeration.has_explicit_tag_type) {
|
||||
return type_allowed_in_extern(g, tag_int_type, result);
|
||||
} else {
|
||||
*result = type_entry->data.enumeration.layout == ContainerLayoutExtern ||
|
||||
type_entry->data.enumeration.layout == ContainerLayoutPacked;
|
||||
return ErrorNone;
|
||||
}
|
||||
if (type_entry->data.enumeration.has_explicit_tag_type)
|
||||
return type_allowed_in_extern(g, tag_int_type, position, result);
|
||||
*result = type_entry->data.enumeration.layout == ContainerLayoutExtern ||
|
||||
type_entry->data.enumeration.layout == ContainerLayoutPacked;
|
||||
return ErrorNone;
|
||||
}
|
||||
case ZigTypeIdUnion:
|
||||
*result = type_entry->data.unionation.layout == ContainerLayoutExtern ||
|
||||
@ -1933,7 +1940,7 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc
|
||||
|
||||
if (!calling_convention_allows_zig_types(fn_type_id.cc)) {
|
||||
bool ok_type;
|
||||
if ((err = type_allowed_in_extern(g, type_entry, &ok_type)))
|
||||
if ((err = type_allowed_in_extern(g, type_entry, ExternPositionFunctionParameter, &ok_type)))
|
||||
return g->builtin_types.entry_invalid;
|
||||
if (!ok_type) {
|
||||
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
|
||||
if ((err = type_resolve(g, fn_type_id.return_type, ResolveStatusSizeKnown)))
|
||||
return g->builtin_types.entry_invalid;
|
||||
bool ok_type;
|
||||
if ((err = type_allowed_in_extern(g, fn_type_id.return_type, &ok_type)))
|
||||
if ((err = type_allowed_in_extern(g, fn_type_id.return_type, ExternPositionFunctionReturn, &ok_type)))
|
||||
return g->builtin_types.entry_invalid;
|
||||
if (!ok_type) {
|
||||
add_node_error(g, fn_proto->return_type,
|
||||
@ -2357,7 +2364,7 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {
|
||||
|
||||
if (struct_type->data.structure.layout == ContainerLayoutExtern) {
|
||||
bool ok_type;
|
||||
if ((err = type_allowed_in_extern(g, field_type, &ok_type))) {
|
||||
if ((err = type_allowed_in_extern(g, field_type, ExternPositionOther, &ok_type))) {
|
||||
struct_type->data.structure.resolve_status = ResolveStatusInvalid;
|
||||
return ErrorSemanticAnalyzeFail;
|
||||
}
|
||||
@ -2612,7 +2619,7 @@ static Error type_is_valid_extern_enum_tag(CodeGen *g, ZigType *ty, bool *result
|
||||
// signed char, a signed integer or an unsigned one. But GCC/Clang allow
|
||||
// other integral types as a compiler extension so let's accomodate them
|
||||
// aswell.
|
||||
return type_allowed_in_extern(g, ty, result);
|
||||
return type_allowed_in_extern(g, ty, ExternPositionOther, result);
|
||||
}
|
||||
|
||||
static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
|
||||
|
||||
@ -50,7 +50,13 @@ bool handle_is_ptr(CodeGen *g, ZigType *type_entry);
|
||||
bool type_has_bits(CodeGen *g, ZigType *type_entry);
|
||||
Error type_has_bits2(CodeGen *g, ZigType *type_entry, bool *result);
|
||||
|
||||
Error type_allowed_in_extern(CodeGen *g, ZigType *type_entry, bool *result);
|
||||
enum ExternPosition {
|
||||
ExternPositionFunctionParameter,
|
||||
ExternPositionFunctionReturn,
|
||||
ExternPositionOther, // array element, struct field, optional element, etc
|
||||
};
|
||||
|
||||
Error type_allowed_in_extern(CodeGen *g, ZigType *type_entry, ExternPosition position, bool *result);
|
||||
bool ptr_allows_addr_zero(ZigType *ptr_type);
|
||||
|
||||
// Deprecated, use `type_is_nonnull_ptr2`
|
||||
|
||||
@ -18963,7 +18963,7 @@ static IrInstGen *ir_analyze_instruction_export(IrAnalyze *ira, IrInstSrcExport
|
||||
break;
|
||||
case ZigTypeIdArray: {
|
||||
bool ok_type;
|
||||
if ((err = type_allowed_in_extern(ira->codegen, target->value->type->data.array.child_type, &ok_type)))
|
||||
if ((err = type_allowed_in_extern(ira->codegen, target->value->type->data.array.child_type, ExternPositionOther, &ok_type)))
|
||||
return ira->codegen->invalid_inst_gen;
|
||||
|
||||
if (!ok_type) {
|
||||
@ -32745,7 +32745,7 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ZigValue *val) {
|
||||
return ErrorSemanticAnalyzeFail;
|
||||
} else if (lazy_ptr_type->ptr_len == PtrLenC) {
|
||||
bool ok_type;
|
||||
if ((err = type_allowed_in_extern(ira->codegen, elem_type, &ok_type)))
|
||||
if ((err = type_allowed_in_extern(ira->codegen, elem_type, ExternPositionOther, &ok_type)))
|
||||
return err;
|
||||
if (!ok_type) {
|
||||
ir_add_error(ira, &lazy_ptr_type->elem_type->base,
|
||||
|
||||
@ -2,6 +2,19 @@ const tests = @import("tests.zig");
|
||||
const std = @import("std");
|
||||
|
||||
pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
cases.add("array in c exported function",
|
||||
\\export fn zig_array(x: [10]u8) void {
|
||||
\\ expect(std.mem.eql(u8, &x, "1234567890"));
|
||||
\\}
|
||||
\\
|
||||
\\export fn zig_return_array() [10]u8 {
|
||||
\\ return "1234567890".*;
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
"tmp.zig:1:24: error: parameter of type '[10]u8' not allowed in function with calling convention 'C'",
|
||||
"tmp.zig:5:30: error: return type '[10]u8' not allowed in function with calling convention 'C'",
|
||||
});
|
||||
|
||||
cases.add("@Type for exhaustive enum with undefined tag type",
|
||||
\\const TypeInfo = @import("builtin").TypeInfo;
|
||||
\\const Tag = @Type(.{
|
||||
|
||||
@ -28,8 +28,6 @@ void zig_ptr(void *);
|
||||
|
||||
void zig_bool(bool);
|
||||
|
||||
void zig_array(uint8_t[10]);
|
||||
|
||||
struct BigStruct {
|
||||
uint64_t a;
|
||||
uint64_t b;
|
||||
@ -97,9 +95,6 @@ void run_c_tests(void) {
|
||||
|
||||
zig_bool(true);
|
||||
|
||||
uint8_t array[10] = {'1', '2', '3', '4', '5', '6', '7', '8', '9', '0'};
|
||||
zig_array(array);
|
||||
|
||||
{
|
||||
struct BigStruct s = {1, 2, 3, 4, 5};
|
||||
zig_big_struct(s);
|
||||
@ -190,19 +185,6 @@ void c_five_floats(float a, float b, float c, float d, float e) {
|
||||
assert_or_panic(e == 5.0);
|
||||
}
|
||||
|
||||
void c_array(uint8_t x[10]) {
|
||||
assert_or_panic(x[0] == '1');
|
||||
assert_or_panic(x[1] == '2');
|
||||
assert_or_panic(x[2] == '3');
|
||||
assert_or_panic(x[3] == '4');
|
||||
assert_or_panic(x[4] == '5');
|
||||
assert_or_panic(x[5] == '6');
|
||||
assert_or_panic(x[6] == '7');
|
||||
assert_or_panic(x[7] == '8');
|
||||
assert_or_panic(x[8] == '9');
|
||||
assert_or_panic(x[9] == '0');
|
||||
}
|
||||
|
||||
void c_big_struct(struct BigStruct x) {
|
||||
assert_or_panic(x.a == 1);
|
||||
assert_or_panic(x.b == 2);
|
||||
|
||||
@ -116,17 +116,6 @@ export fn zig_bool(x: bool) void {
|
||||
expect(x);
|
||||
}
|
||||
|
||||
extern fn c_array([10]u8) void;
|
||||
|
||||
test "C ABI array" {
|
||||
var array: [10]u8 = "1234567890".*;
|
||||
c_array(array);
|
||||
}
|
||||
|
||||
export fn zig_array(x: [10]u8) void {
|
||||
expect(std.mem.eql(u8, &x, "1234567890"));
|
||||
}
|
||||
|
||||
const BigStruct = extern struct {
|
||||
a: u64,
|
||||
b: u64,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user