commit
6b2274fd99
|
@ -3619,12 +3619,18 @@ static void add_top_level_decl(CodeGen *g, ScopeDecls *decls_scope, Tld *tld) {
|
|||
assert(tld->source_node->type == NodeTypeFnProto);
|
||||
is_export = tld->source_node->data.fn_proto.is_export;
|
||||
|
||||
if (!is_export && !tld->source_node->data.fn_proto.is_extern &&
|
||||
if (!tld->source_node->data.fn_proto.is_extern &&
|
||||
tld->source_node->data.fn_proto.fn_def_node == nullptr)
|
||||
{
|
||||
add_node_error(g, tld->source_node, buf_sprintf("non-extern function has no body"));
|
||||
return;
|
||||
}
|
||||
if (!tld->source_node->data.fn_proto.is_extern &&
|
||||
tld->source_node->data.fn_proto.is_var_args)
|
||||
{
|
||||
add_node_error(g, tld->source_node, buf_sprintf("non-extern function is variadic"));
|
||||
return;
|
||||
}
|
||||
} else if (tld->id == TldIdUsingNamespace) {
|
||||
g->resolve_queue.append(tld);
|
||||
}
|
||||
|
|
15
src/ir.cpp
15
src/ir.cpp
|
@ -25375,7 +25375,7 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInst *source_instr, ZigTypeI
|
|||
case ZigTypeIdBoundFn:
|
||||
case ZigTypeIdStruct:
|
||||
ir_add_error(ira, source_instr, buf_sprintf(
|
||||
"@Type not availble for 'TypeInfo.%s'", type_id_name(tagTypeId)));
|
||||
"@Type not available for 'TypeInfo.%s'", type_id_name(tagTypeId)));
|
||||
return ira->codegen->invalid_inst_gen->value->type;
|
||||
}
|
||||
zig_unreachable();
|
||||
|
@ -27910,11 +27910,10 @@ static IrInstGen *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstSrcFnPro
|
|||
|
||||
if (cc == CallingConventionC) {
|
||||
break;
|
||||
} else if (cc == CallingConventionUnspecified) {
|
||||
lazy_fn_type->is_generic = true;
|
||||
return result;
|
||||
} else {
|
||||
zig_unreachable();
|
||||
ir_add_error(ira, &instruction->base.base,
|
||||
buf_sprintf("var args only allowed in functions with C calling convention"));
|
||||
return ira->codegen->invalid_inst_gen;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -30979,10 +30978,10 @@ static ZigType *ir_resolve_lazy_fn_type(IrAnalyze *ira, AstNode *source_node, La
|
|||
if (fn_type_id.cc == CallingConventionC) {
|
||||
fn_type_id.param_count = fn_type_id.next_param_index;
|
||||
break;
|
||||
} else if (fn_type_id.cc == CallingConventionUnspecified) {
|
||||
return get_generic_fn_type(ira->codegen, &fn_type_id);
|
||||
} else {
|
||||
zig_unreachable();
|
||||
ir_add_error_node(ira, param_node,
|
||||
buf_sprintf("var args only allowed in functions with C calling convention"));
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
FnTypeParamInfo *param_info = &fn_type_id.param_info[fn_type_id.next_param_index];
|
||||
|
|
|
@ -2,6 +2,15 @@ const tests = @import("tests.zig");
|
|||
const std = @import("std");
|
||||
|
||||
pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
cases.add("non-extern function with var args",
|
||||
\\fn foo(args: ...) void {}
|
||||
\\export fn entry() void {
|
||||
\\ foo();
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
"tmp.zig:1:1: error: non-extern function is variadic",
|
||||
});
|
||||
|
||||
cases.addTest("invalid int casts",
|
||||
\\export fn foo() void {
|
||||
\\ var a: u32 = 2;
|
||||
|
@ -703,15 +712,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
|||
"tmp.zig:2:28: error: invalid character: ';'",
|
||||
});
|
||||
|
||||
cases.add("var args without c calling conv",
|
||||
\\fn foo(args: ...) void {}
|
||||
\\comptime {
|
||||
\\ _ = foo;
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
"tmp.zig:1:8: error: var args only allowed in functions with C calling convention",
|
||||
});
|
||||
|
||||
cases.add("comptime struct field, no init value",
|
||||
\\const Foo = struct {
|
||||
\\ comptime b: i32,
|
||||
|
@ -856,7 +856,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
|||
"tmp.zig:11:25: error: expected type 'u32', found '@TypeOf(get_uval).ReturnType.ErrorSet!u32'",
|
||||
});
|
||||
|
||||
cases.add("asigning to struct or union fields that are not optionals with a function that returns an optional",
|
||||
cases.add("assigning to struct or union fields that are not optionals with a function that returns an optional",
|
||||
\\fn maybe(is: bool) ?u8 {
|
||||
\\ if (is) return @as(u8, 10) else return null;
|
||||
\\}
|
||||
|
@ -1084,7 +1084,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
|||
\\ _ = @Type(@typeInfo(struct { }));
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
"tmp.zig:2:15: error: @Type not availble for 'TypeInfo.Struct'",
|
||||
"tmp.zig:2:15: error: @Type not available for 'TypeInfo.Struct'",
|
||||
});
|
||||
|
||||
cases.add("wrong type for result ptr to @asyncCall",
|
||||
|
@ -2659,7 +2659,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
|||
"tmp.zig:7:17: error: switch on type 'type' provides no expression parameter",
|
||||
});
|
||||
|
||||
cases.add("function protoype with no body",
|
||||
cases.add("function prototype with no body",
|
||||
\\fn foo() void;
|
||||
\\export fn entry() void {
|
||||
\\ foo();
|
||||
|
|
|
@ -13,7 +13,7 @@ test "type info: tag type, void info" {
|
|||
fn testBasic() void {
|
||||
expect(@TagType(TypeInfo) == TypeId);
|
||||
const void_info = @typeInfo(void);
|
||||
expect(@as(TypeId, void_info) == TypeId.Void);
|
||||
expect(void_info == TypeId.Void);
|
||||
expect(void_info.Void == {});
|
||||
}
|
||||
|
||||
|
@ -24,12 +24,12 @@ test "type info: integer, floating point type info" {
|
|||
|
||||
fn testIntFloat() void {
|
||||
const u8_info = @typeInfo(u8);
|
||||
expect(@as(TypeId, u8_info) == TypeId.Int);
|
||||
expect(u8_info == .Int);
|
||||
expect(!u8_info.Int.is_signed);
|
||||
expect(u8_info.Int.bits == 8);
|
||||
|
||||
const f64_info = @typeInfo(f64);
|
||||
expect(@as(TypeId, f64_info) == TypeId.Float);
|
||||
expect(f64_info == .Float);
|
||||
expect(f64_info.Float.bits == 64);
|
||||
}
|
||||
|
||||
|
@ -40,7 +40,7 @@ test "type info: pointer type info" {
|
|||
|
||||
fn testPointer() void {
|
||||
const u32_ptr_info = @typeInfo(*u32);
|
||||
expect(@as(TypeId, u32_ptr_info) == TypeId.Pointer);
|
||||
expect(u32_ptr_info == .Pointer);
|
||||
expect(u32_ptr_info.Pointer.size == TypeInfo.Pointer.Size.One);
|
||||
expect(u32_ptr_info.Pointer.is_const == false);
|
||||
expect(u32_ptr_info.Pointer.is_volatile == false);
|
||||
|
@ -56,7 +56,7 @@ test "type info: unknown length pointer type info" {
|
|||
|
||||
fn testUnknownLenPtr() void {
|
||||
const u32_ptr_info = @typeInfo([*]const volatile f64);
|
||||
expect(@as(TypeId, u32_ptr_info) == TypeId.Pointer);
|
||||
expect(u32_ptr_info == .Pointer);
|
||||
expect(u32_ptr_info.Pointer.size == TypeInfo.Pointer.Size.Many);
|
||||
expect(u32_ptr_info.Pointer.is_const == true);
|
||||
expect(u32_ptr_info.Pointer.is_volatile == true);
|
||||
|
@ -72,7 +72,7 @@ test "type info: null terminated pointer type info" {
|
|||
|
||||
fn testNullTerminatedPtr() void {
|
||||
const ptr_info = @typeInfo([*:0]u8);
|
||||
expect(@as(TypeId, ptr_info) == TypeId.Pointer);
|
||||
expect(ptr_info == .Pointer);
|
||||
expect(ptr_info.Pointer.size == TypeInfo.Pointer.Size.Many);
|
||||
expect(ptr_info.Pointer.is_const == false);
|
||||
expect(ptr_info.Pointer.is_volatile == false);
|
||||
|
@ -91,8 +91,8 @@ test "type info: C pointer type info" {
|
|||
|
||||
fn testCPtr() void {
|
||||
const ptr_info = @typeInfo([*c]align(4) const i8);
|
||||
expect(@as(TypeId, ptr_info) == TypeId.Pointer);
|
||||
expect(ptr_info.Pointer.size == TypeInfo.Pointer.Size.C);
|
||||
expect(ptr_info == .Pointer);
|
||||
expect(ptr_info.Pointer.size == .C);
|
||||
expect(ptr_info.Pointer.is_const);
|
||||
expect(!ptr_info.Pointer.is_volatile);
|
||||
expect(ptr_info.Pointer.alignment == 4);
|
||||
|
@ -106,8 +106,8 @@ test "type info: slice type info" {
|
|||
|
||||
fn testSlice() void {
|
||||
const u32_slice_info = @typeInfo([]u32);
|
||||
expect(@as(TypeId, u32_slice_info) == TypeId.Pointer);
|
||||
expect(u32_slice_info.Pointer.size == TypeInfo.Pointer.Size.Slice);
|
||||
expect(u32_slice_info == .Pointer);
|
||||
expect(u32_slice_info.Pointer.size == .Slice);
|
||||
expect(u32_slice_info.Pointer.is_const == false);
|
||||
expect(u32_slice_info.Pointer.is_volatile == false);
|
||||
expect(u32_slice_info.Pointer.alignment == 4);
|
||||
|
@ -121,7 +121,7 @@ test "type info: array type info" {
|
|||
|
||||
fn testArray() void {
|
||||
const arr_info = @typeInfo([42]bool);
|
||||
expect(@as(TypeId, arr_info) == TypeId.Array);
|
||||
expect(arr_info == .Array);
|
||||
expect(arr_info.Array.len == 42);
|
||||
expect(arr_info.Array.child == bool);
|
||||
}
|
||||
|
@ -133,7 +133,7 @@ test "type info: optional type info" {
|
|||
|
||||
fn testOptional() void {
|
||||
const null_info = @typeInfo(?void);
|
||||
expect(@as(TypeId, null_info) == TypeId.Optional);
|
||||
expect(null_info == .Optional);
|
||||
expect(null_info.Optional.child == void);
|
||||
}
|
||||
|
||||
|
@ -150,18 +150,18 @@ fn testErrorSet() void {
|
|||
};
|
||||
|
||||
const error_set_info = @typeInfo(TestErrorSet);
|
||||
expect(@as(TypeId, error_set_info) == TypeId.ErrorSet);
|
||||
expect(error_set_info == .ErrorSet);
|
||||
expect(error_set_info.ErrorSet.?.len == 3);
|
||||
expect(mem.eql(u8, error_set_info.ErrorSet.?[0].name, "First"));
|
||||
expect(error_set_info.ErrorSet.?[2].value == @errorToInt(TestErrorSet.Third));
|
||||
|
||||
const error_union_info = @typeInfo(TestErrorSet!usize);
|
||||
expect(@as(TypeId, error_union_info) == TypeId.ErrorUnion);
|
||||
expect(error_union_info == .ErrorUnion);
|
||||
expect(error_union_info.ErrorUnion.error_set == TestErrorSet);
|
||||
expect(error_union_info.ErrorUnion.payload == usize);
|
||||
|
||||
const global_info = @typeInfo(anyerror);
|
||||
expect(@as(TypeId, global_info) == TypeId.ErrorSet);
|
||||
expect(global_info == .ErrorSet);
|
||||
expect(global_info.ErrorSet == null);
|
||||
}
|
||||
|
||||
|
@ -179,8 +179,8 @@ fn testEnum() void {
|
|||
};
|
||||
|
||||
const os_info = @typeInfo(Os);
|
||||
expect(@as(TypeId, os_info) == TypeId.Enum);
|
||||
expect(os_info.Enum.layout == TypeInfo.ContainerLayout.Auto);
|
||||
expect(os_info == .Enum);
|
||||
expect(os_info.Enum.layout == .Auto);
|
||||
expect(os_info.Enum.fields.len == 4);
|
||||
expect(mem.eql(u8, os_info.Enum.fields[1].name, "Macos"));
|
||||
expect(os_info.Enum.fields[3].value == 3);
|
||||
|
@ -195,8 +195,8 @@ test "type info: union info" {
|
|||
|
||||
fn testUnion() void {
|
||||
const typeinfo_info = @typeInfo(TypeInfo);
|
||||
expect(@as(TypeId, typeinfo_info) == TypeId.Union);
|
||||
expect(typeinfo_info.Union.layout == TypeInfo.ContainerLayout.Auto);
|
||||
expect(typeinfo_info == .Union);
|
||||
expect(typeinfo_info.Union.layout == .Auto);
|
||||
expect(typeinfo_info.Union.tag_type.? == TypeId);
|
||||
expect(typeinfo_info.Union.fields.len == 25);
|
||||
expect(typeinfo_info.Union.fields[4].enum_field != null);
|
||||
|
@ -210,9 +210,9 @@ fn testUnion() void {
|
|||
};
|
||||
|
||||
const notag_union_info = @typeInfo(TestNoTagUnion);
|
||||
expect(@as(TypeId, notag_union_info) == TypeId.Union);
|
||||
expect(notag_union_info == .Union);
|
||||
expect(notag_union_info.Union.tag_type == null);
|
||||
expect(notag_union_info.Union.layout == TypeInfo.ContainerLayout.Auto);
|
||||
expect(notag_union_info.Union.layout == .Auto);
|
||||
expect(notag_union_info.Union.fields.len == 2);
|
||||
expect(notag_union_info.Union.fields[0].enum_field == null);
|
||||
expect(notag_union_info.Union.fields[1].field_type == u32);
|
||||
|
@ -222,7 +222,7 @@ fn testUnion() void {
|
|||
};
|
||||
|
||||
const extern_union_info = @typeInfo(TestExternUnion);
|
||||
expect(extern_union_info.Union.layout == TypeInfo.ContainerLayout.Extern);
|
||||
expect(extern_union_info.Union.layout == .Extern);
|
||||
expect(extern_union_info.Union.tag_type == null);
|
||||
expect(extern_union_info.Union.fields[0].enum_field == null);
|
||||
expect(extern_union_info.Union.fields[0].field_type == *c_void);
|
||||
|
@ -235,8 +235,8 @@ test "type info: struct info" {
|
|||
|
||||
fn testStruct() void {
|
||||
const struct_info = @typeInfo(TestStruct);
|
||||
expect(@as(TypeId, struct_info) == TypeId.Struct);
|
||||
expect(struct_info.Struct.layout == TypeInfo.ContainerLayout.Packed);
|
||||
expect(struct_info == .Struct);
|
||||
expect(struct_info.Struct.layout == .Packed);
|
||||
expect(struct_info.Struct.fields.len == 4);
|
||||
expect(struct_info.Struct.fields[1].offset == null);
|
||||
expect(struct_info.Struct.fields[2].field_type == *TestStruct);
|
||||
|
@ -268,22 +268,20 @@ test "type info: function type info" {
|
|||
|
||||
fn testFunction() void {
|
||||
const fn_info = @typeInfo(@TypeOf(foo));
|
||||
expect(@as(TypeId, fn_info) == TypeId.Fn);
|
||||
expect(fn_info.Fn.calling_convention == .Unspecified);
|
||||
expect(fn_info.Fn.is_generic);
|
||||
expect(fn_info == .Fn);
|
||||
expect(fn_info.Fn.calling_convention == .C);
|
||||
expect(!fn_info.Fn.is_generic);
|
||||
expect(fn_info.Fn.args.len == 2);
|
||||
expect(fn_info.Fn.is_var_args);
|
||||
expect(fn_info.Fn.return_type == null);
|
||||
expect(fn_info.Fn.return_type.? == usize);
|
||||
|
||||
const test_instance: TestStruct = undefined;
|
||||
const bound_fn_info = @typeInfo(@TypeOf(test_instance.foo));
|
||||
expect(@as(TypeId, bound_fn_info) == TypeId.BoundFn);
|
||||
expect(bound_fn_info == .BoundFn);
|
||||
expect(bound_fn_info.BoundFn.args[0].arg_type.? == *const TestStruct);
|
||||
}
|
||||
|
||||
fn foo(comptime a: usize, b: bool, args: ...) usize {
|
||||
return 0;
|
||||
}
|
||||
extern fn foo(a: usize, b: bool, args: ...) usize;
|
||||
|
||||
test "typeInfo with comptime parameter in struct fn def" {
|
||||
const S = struct {
|
||||
|
@ -299,7 +297,7 @@ test "type info: vectors" {
|
|||
|
||||
fn testVector() void {
|
||||
const vec_info = @typeInfo(@Vector(4, i32));
|
||||
expect(@as(TypeId, vec_info) == TypeId.Vector);
|
||||
expect(vec_info == .Vector);
|
||||
expect(vec_info.Vector.len == 4);
|
||||
expect(vec_info.Vector.child == i32);
|
||||
}
|
||||
|
@ -312,13 +310,13 @@ test "type info: anyframe and anyframe->T" {
|
|||
fn testAnyFrame() void {
|
||||
{
|
||||
const anyframe_info = @typeInfo(anyframe->i32);
|
||||
expect(@as(TypeId, anyframe_info) == .AnyFrame);
|
||||
expect(anyframe_info == .AnyFrame);
|
||||
expect(anyframe_info.AnyFrame.child.? == i32);
|
||||
}
|
||||
|
||||
{
|
||||
const anyframe_info = @typeInfo(anyframe);
|
||||
expect(@as(TypeId, anyframe_info) == .AnyFrame);
|
||||
expect(anyframe_info == .AnyFrame);
|
||||
expect(anyframe_info.AnyFrame.child == null);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue