authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-07-19 20:20:57+03:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-07-21 12:21:30-07:00
log79ef0cdf306c48d3cc447ce14530db4021f8c5de
treed97ae5e97c97e0f3545b0d1e80af1ecf4cbf0492
parent83b2d2cd3eb701b43d17404e73933bc00f7be828

Sema: better function parameter source location


14 files changed, 256 insertions(+), 109 deletions(-)

src/Module.zig+85
...@@ -2482,6 +2482,41 @@ pub const SrcLoc = struct {...@@ -2482,6 +2482,41 @@ pub const SrcLoc = struct {
2482 };2482 };
2483 return nodeToSpan(tree, full.ast.return_type);2483 return nodeToSpan(tree, full.ast.return_type);
2484 },2484 },
2485 .node_offset_param => |node_off| {
2486 const tree = try src_loc.file_scope.getTree(gpa);
2487 const token_tags = tree.tokens.items(.tag);
2488 const node = src_loc.declRelativeToNodeIndex(node_off);
2489
2490 var first_tok = tree.firstToken(node);
2491 while (true) switch (token_tags[first_tok - 1]) {
2492 .colon, .identifier, .keyword_comptime, .keyword_noalias => first_tok -= 1,
2493 else => break,
2494 };
2495 return tokensToSpan(
2496 tree,
2497 first_tok,
2498 tree.lastToken(node),
2499 first_tok,
2500 );
2501 },
2502 .token_offset_param => |token_off| {
2503 const tree = try src_loc.file_scope.getTree(gpa);
2504 const token_tags = tree.tokens.items(.tag);
2505 const main_token = tree.nodes.items(.main_token)[src_loc.parent_decl_node];
2506 const tok_index = @bitCast(Ast.TokenIndex, token_off + @bitCast(i32, main_token));
2507
2508 var first_tok = tok_index;
2509 while (true) switch (token_tags[first_tok - 1]) {
2510 .colon, .identifier, .keyword_comptime, .keyword_noalias => first_tok -= 1,
2511 else => break,
2512 };
2513 return tokensToSpan(
2514 tree,
2515 first_tok,
2516 tok_index,
2517 first_tok,
2518 );
2519 },
24852520
2486 .node_offset_anyframe_type => |node_off| {2521 .node_offset_anyframe_type => |node_off| {
2487 const tree = try src_loc.file_scope.getTree(gpa);2522 const tree = try src_loc.file_scope.getTree(gpa);
...@@ -2930,6 +2965,8 @@ pub const LazySrcLoc = union(enum) {...@@ -2930,6 +2965,8 @@ pub const LazySrcLoc = union(enum) {
2930 /// the return type node.2965 /// the return type node.
2931 /// The Decl is determined contextually.2966 /// The Decl is determined contextually.
2932 node_offset_fn_type_ret_ty: i32,2967 node_offset_fn_type_ret_ty: i32,
2968 node_offset_param: i32,
2969 token_offset_param: i32,
2933 /// The source location points to the type expression of an `anyframe->T`2970 /// The source location points to the type expression of an `anyframe->T`
2934 /// expression, found by taking this AST node index offset from the containing2971 /// expression, found by taking this AST node index offset from the containing
2935 /// Decl AST node, which points to a `anyframe->T` expression AST node. Next, navigate2972 /// Decl AST node, which points to a `anyframe->T` expression AST node. Next, navigate
...@@ -3046,6 +3083,8 @@ pub const LazySrcLoc = union(enum) {...@@ -3046,6 +3083,8 @@ pub const LazySrcLoc = union(enum) {
3046 .node_offset_fn_type_section,3083 .node_offset_fn_type_section,
3047 .node_offset_fn_type_cc,3084 .node_offset_fn_type_cc,
3048 .node_offset_fn_type_ret_ty,3085 .node_offset_fn_type_ret_ty,
3086 .node_offset_param,
3087 .token_offset_param,
3049 .node_offset_anyframe_type,3088 .node_offset_anyframe_type,
3050 .node_offset_lib_name,3089 .node_offset_lib_name,
3051 .node_offset_array_type_len,3090 .node_offset_array_type_len,
...@@ -5826,6 +5865,52 @@ fn queryFieldSrc(...@@ -5826,6 +5865,52 @@ fn queryFieldSrc(
5826 unreachable;5865 unreachable;
5827}5866}
58285867
5868pub fn paramSrc(
5869 func_node_offset: i32,
5870 gpa: Allocator,
5871 decl: *Decl,
5872 param_i: usize,
5873) LazySrcLoc {
5874 @setCold(true);
5875 const tree = decl.getFileScope().getTree(gpa) catch |err| {
5876 // In this case we emit a warning + a less precise source location.
5877 log.warn("unable to load {s}: {s}", .{
5878 decl.getFileScope().sub_file_path, @errorName(err),
5879 });
5880 return LazySrcLoc.nodeOffset(0);
5881 };
5882 const node_datas = tree.nodes.items(.data);
5883 const node_tags = tree.nodes.items(.tag);
5884 const node = decl.relativeToNodeIndex(func_node_offset);
5885 var params: [1]Ast.Node.Index = undefined;
5886 const full = switch (node_tags[node]) {
5887 .fn_proto_simple => tree.fnProtoSimple(&params, node),
5888 .fn_proto_multi => tree.fnProtoMulti(node),
5889 .fn_proto_one => tree.fnProtoOne(&params, node),
5890 .fn_proto => tree.fnProto(node),
5891 .fn_decl => switch (node_tags[node_datas[node].lhs]) {
5892 .fn_proto_simple => tree.fnProtoSimple(&params, node_datas[node].lhs),
5893 .fn_proto_multi => tree.fnProtoMulti(node_datas[node].lhs),
5894 .fn_proto_one => tree.fnProtoOne(&params, node_datas[node].lhs),
5895 .fn_proto => tree.fnProto(node_datas[node].lhs),
5896 else => unreachable,
5897 },
5898 else => unreachable,
5899 };
5900 var it = full.iterate(tree);
5901 while (true) {
5902 if (it.param_i == param_i) {
5903 const param = it.next().?;
5904 if (param.anytype_ellipsis3) |some| {
5905 const main_token = tree.nodes.items(.main_token)[decl.src_node];
5906 return .{ .token_offset_param = @bitCast(i32, some) - @bitCast(i32, main_token) };
5907 }
5908 return .{ .node_offset_param = decl.nodeIndexToRelative(param.type_expr) };
5909 }
5910 _ = it.next();
5911 }
5912}
5913
5829/// Called from `performAllTheWork`, after all AstGen workers have finished,5914/// Called from `performAllTheWork`, after all AstGen workers have finished,
5830/// and before the main semantic analysis loop begins.5915/// and before the main semantic analysis loop begins.
5831pub fn processOutdatedAndDeletedDecls(mod: *Module) !void {5916pub fn processOutdatedAndDeletedDecls(mod: *Module) !void {
src/Sema.zig+104-54
...@@ -7233,6 +7233,7 @@ fn funcCommon(...@@ -7233,6 +7233,7 @@ fn funcCommon(
7233 opt_lib_name: ?[]const u8,7233 opt_lib_name: ?[]const u8,
7234 noalias_bits: u32,7234 noalias_bits: u32,
7235) CompileError!Air.Inst.Ref {7235) CompileError!Air.Inst.Ref {
7236 const fn_src = LazySrcLoc.nodeOffset(src_node_offset);
7236 const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = src_node_offset };7237 const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = src_node_offset };
7237 const cc_src: LazySrcLoc = .{ .node_offset_fn_type_cc = src_node_offset };7238 const cc_src: LazySrcLoc = .{ .node_offset_fn_type_cc = src_node_offset };
72387239
...@@ -7241,10 +7242,6 @@ fn funcCommon(...@@ -7241,10 +7242,6 @@ fn funcCommon(
7241 address_space == null or7242 address_space == null or
7242 section == .generic or7243 section == .generic or
7243 cc == null;7244 cc == null;
7244 // Check for generic params.
7245 for (block.params.items) |param| {
7246 if (param.ty.tag() == .generic_poison) is_generic = true;
7247 }
72487245
7249 var destroy_fn_on_error = false;7246 var destroy_fn_on_error = false;
7250 const new_func: *Module.Fn = new_func: {7247 const new_func: *Module.Fn = new_func: {
...@@ -7304,55 +7301,35 @@ fn funcCommon(...@@ -7304,55 +7301,35 @@ fn funcCommon(
7304 const param_types = try sema.arena.alloc(Type, block.params.items.len);7301 const param_types = try sema.arena.alloc(Type, block.params.items.len);
7305 const comptime_params = try sema.arena.alloc(bool, block.params.items.len);7302 const comptime_params = try sema.arena.alloc(bool, block.params.items.len);
7306 for (block.params.items) |param, i| {7303 for (block.params.items) |param, i| {
7307 const param_src = LazySrcLoc.nodeOffset(src_node_offset); // TODO better soruce location
7308 param_types[i] = param.ty;7304 param_types[i] = param.ty;
7309 const requires_comptime = try sema.typeRequiresComptime(block, param_src, param.ty);7305 sema.analyzeParameter(
7310 comptime_params[i] = param.is_comptime or requires_comptime;7306 block,
7311 is_generic = is_generic or comptime_params[i] or param.ty.tag() == .generic_poison;7307 fn_src,
7312 if (is_extern and is_generic) {7308 .unneeded,
7313 // TODO add note: function is generic because of this parameter7309 param,
7314 return sema.fail(block, param_src, "extern function cannot be generic", .{});7310 comptime_params,
7315 }7311 i,
7316 if (!param.ty.isValidParamType()) {7312 &is_generic,
7317 const opaque_str = if (param.ty.zigTypeTag() == .Opaque) "opaque " else "";7313 is_extern,
7318 const msg = msg: {7314 cc_workaround,
7319 const msg = try sema.errMsg(block, param_src, "parameter of {s}type '{}' not allowed", .{7315 ) catch |err| switch (err) {
7320 opaque_str, param.ty.fmt(sema.mod),7316 error.NeededSourceLocation => {
7321 });7317 const decl = sema.mod.declPtr(block.src_decl);
7322 errdefer msg.destroy(sema.gpa);7318 try sema.analyzeParameter(
73237319 block,
7324 try sema.addDeclaredHereNote(msg, param.ty);7320 fn_src,
7325 break :msg msg;7321 Module.paramSrc(src_node_offset, sema.gpa, decl, i),
7326 };7322 param,
7327 return sema.failWithOwnedErrorMsg(block, msg);7323 comptime_params,
7328 }7324 i,
7329 if (!Type.fnCallingConventionAllowsZigTypes(cc_workaround) and !(try sema.validateExternType(param.ty, .param_ty))) {7325 &is_generic,
7330 const msg = msg: {7326 is_extern,
7331 const msg = try sema.errMsg(block, param_src, "parameter of type '{}' not allowed in function with calling convention '{s}'", .{7327 cc_workaround,
7332 param.ty.fmt(sema.mod), @tagName(cc_workaround),7328 );
7333 });7329 return error.AnalysisFail;
7334 errdefer msg.destroy(sema.gpa);7330 },
73357331 else => |e| return e,
7336 const src_decl = sema.mod.declPtr(block.src_decl);7332 };
7337 try sema.explainWhyTypeIsNotExtern(block, param_src, msg, param_src.toSrcLoc(src_decl), param.ty, .param_ty);
7338
7339 try sema.addDeclaredHereNote(msg, param.ty);
7340 break :msg msg;
7341 };
7342 return sema.failWithOwnedErrorMsg(block, msg);
7343 }
7344 if (requires_comptime and !param.is_comptime) {
7345 const msg = msg: {
7346 const msg = try sema.errMsg(block, param_src, "parametter of type '{}' must be declared comptime", .{
7347 param.ty.fmt(sema.mod),
7348 });
7349 errdefer msg.destroy(sema.gpa);
7350
7351 try sema.addDeclaredHereNote(msg, param.ty);
7352 break :msg msg;
7353 };
7354 return sema.failWithOwnedErrorMsg(block, msg);
7355 }
7356 }7333 }
73577334
7358 const ret_poison = if (!is_generic) rp: {7335 const ret_poison = if (!is_generic) rp: {
...@@ -7542,6 +7519,79 @@ fn funcCommon(...@@ -7542,6 +7519,79 @@ fn funcCommon(
7542 return sema.addConstant(fn_ty, Value.initPayload(&fn_payload.base));7519 return sema.addConstant(fn_ty, Value.initPayload(&fn_payload.base));
7543}7520}
75447521
7522fn analyzeParameter(
7523 sema: *Sema,
7524 block: *Block,
7525 func_src: LazySrcLoc,
7526 param_src: LazySrcLoc,
7527 param: Block.Param,
7528 comptime_params: []bool,
7529 i: usize,
7530 is_generic: *bool,
7531 is_extern: bool,
7532 cc: std.builtin.CallingConvention,
7533) !void {
7534 const requires_comptime = try sema.typeRequiresComptime(block, param_src, param.ty);
7535 comptime_params[i] = param.is_comptime or requires_comptime;
7536 const this_generic = comptime_params[i] or param.ty.tag() == .generic_poison;
7537 is_generic.* = is_generic.* or this_generic;
7538 if (is_extern and this_generic) {
7539 // TODO this check should exist somewhere for notes.
7540 if (param_src == .unneeded) return error.NeededSourceLocation;
7541 const msg = msg: {
7542 const msg = try sema.errMsg(block, func_src, "extern function cannot be generic", .{});
7543 errdefer msg.destroy(sema.gpa);
7544
7545 try sema.errNote(block, param_src, msg, "function is generic because of this parameter", .{});
7546 break :msg msg;
7547 };
7548 return sema.failWithOwnedErrorMsg(block, msg);
7549 }
7550 if (this_generic and !Type.fnCallingConventionAllowsZigTypes(cc)) {
7551 return sema.fail(block, param_src, "generic parameters not allowed in function with calling convention '{s}'", .{@tagName(cc)});
7552 }
7553 if (!param.ty.isValidParamType()) {
7554 const opaque_str = if (param.ty.zigTypeTag() == .Opaque) "opaque " else "";
7555 const msg = msg: {
7556 const msg = try sema.errMsg(block, param_src, "parameter of {s}type '{}' not allowed", .{
7557 opaque_str, param.ty.fmt(sema.mod),
7558 });
7559 errdefer msg.destroy(sema.gpa);
7560
7561 try sema.addDeclaredHereNote(msg, param.ty);
7562 break :msg msg;
7563 };
7564 return sema.failWithOwnedErrorMsg(block, msg);
7565 }
7566 if (!Type.fnCallingConventionAllowsZigTypes(cc) and !(try sema.validateExternType(param.ty, .param_ty))) {
7567 const msg = msg: {
7568 const msg = try sema.errMsg(block, param_src, "parameter of type '{}' not allowed in function with calling convention '{s}'", .{
7569 param.ty.fmt(sema.mod), @tagName(cc),
7570 });
7571 errdefer msg.destroy(sema.gpa);
7572
7573 const src_decl = sema.mod.declPtr(block.src_decl);
7574 try sema.explainWhyTypeIsNotExtern(block, param_src, msg, param_src.toSrcLoc(src_decl), param.ty, .param_ty);
7575
7576 try sema.addDeclaredHereNote(msg, param.ty);
7577 break :msg msg;
7578 };
7579 return sema.failWithOwnedErrorMsg(block, msg);
7580 }
7581 if (requires_comptime and !param.is_comptime) {
7582 const msg = msg: {
7583 const msg = try sema.errMsg(block, param_src, "parametter of type '{}' must be declared comptime", .{
7584 param.ty.fmt(sema.mod),
7585 });
7586 errdefer msg.destroy(sema.gpa);
7587
7588 try sema.addDeclaredHereNote(msg, param.ty);
7589 break :msg msg;
7590 };
7591 return sema.failWithOwnedErrorMsg(block, msg);
7592 }
7593}
7594
7545fn zirParam(7595fn zirParam(
7546 sema: *Sema,7596 sema: *Sema,
7547 block: *Block,7597 block: *Block,
...@@ -18570,9 +18620,9 @@ fn explainWhyTypeIsNotExtern(...@@ -18570,9 +18620,9 @@ fn explainWhyTypeIsNotExtern(
18570 .Union => try mod.errNoteNonLazy(src_loc, msg, "only unions with packed or extern layout are extern compatible", .{}),18620 .Union => try mod.errNoteNonLazy(src_loc, msg, "only unions with packed or extern layout are extern compatible", .{}),
18571 .Array => {18621 .Array => {
18572 if (position == .ret_ty) {18622 if (position == .ret_ty) {
18573 try mod.errNoteNonLazy(src_loc, msg, "arrays are not allowed as a return type", .{});18623 return mod.errNoteNonLazy(src_loc, msg, "arrays are not allowed as a return type", .{});
18574 } else if (position == .param_ty) {18624 } else if (position == .param_ty) {
18575 try mod.errNoteNonLazy(src_loc, msg, "arrays are not allowed as a parameter type", .{});18625 return mod.errNoteNonLazy(src_loc, msg, "arrays are not allowed as a parameter type", .{});
18576 }18626 }
18577 try sema.explainWhyTypeIsNotExtern(block, src, msg, src_loc, ty.elemType2(), position);18627 try sema.explainWhyTypeIsNotExtern(block, src, msg, src_loc, ty.elemType2(), position);
18578 },18628 },
test/cases/compile_errors/array_in_c_exported_function.zig created+16
...@@ -0,0 +1,16 @@
1export fn zig_array(x: [10]u8) void {
2 try std.testing.expect(std.mem.eql(u8, &x, "1234567890"));
3}
4const std = @import("std");
5export fn zig_return_array() [10]u8 {
6 return "1234567890".*;
7}
8
9// error
10// backend=stage2
11// target=native
12//
13// :1:21: error: parameter of type '[10]u8' not allowed in function with calling convention 'C'
14// :1:21: note: arrays are not allowed as a parameter type
15// :5:30: error: return type '[10]u8' not allowed in function with calling convention 'C'
16// :5:30: note: arrays are not allowed as a return type
test/cases/compile_errors/export_function_with_comptime_parameter.zig created+9
...@@ -0,0 +1,9 @@
1export fn foo(comptime x: anytype, y: i32) i32{
2 return x + y;
3}
4
5// error
6// backend=stage2
7// target=native
8//
9// :1:15: error: generic parameters not allowed in function with calling convention 'C'
test/cases/compile_errors/export_generic_function.zig created+10
...@@ -0,0 +1,10 @@
1export fn foo(num: anytype) i32 {
2 _ = num;
3 return 0;
4}
5
6// error
7// backend=stage2
8// target=native
9//
10// :1:15: error: generic parameters not allowed in function with calling convention 'C'
test/cases/compile_errors/extern_function_with_comptime_parameter.zig created+20
...@@ -0,0 +1,20 @@
1extern fn foo(comptime x: i32, y: i32) i32;
2fn f() i32 {
3 return foo(1, 2);
4}
5pub extern fn entry1(b: u32, comptime a: [2]u8, c: i32) void;
6pub extern fn entry2(b: u32, noalias a: anytype, i43) void;
7comptime { _ = f; }
8comptime { _ = entry1; }
9comptime { _ = entry2; }
10
11// error
12// backend=stage2
13// target=native
14//
15// :5:12: error: extern function cannot be generic
16// :5:30: note: function is generic because of this parameter
17// :6:12: error: extern function cannot be generic
18// :6:30: note: function is generic because of this parameter
19// :1:8: error: extern function cannot be generic
20// :1:15: note: function is generic because of this parameter
test/cases/compile_errors/function_parameter_is_opaque.zig+5-4
...@@ -23,8 +23,9 @@ export fn entry4() void {...@@ -23,8 +23,9 @@ export fn entry4() void {
23// backend=stage223// backend=stage2
24// target=native24// target=native
25//25//
26// :3:24: error: parameter of opaque type 'tmp.FooType' not allowed26// :3:28: error: parameter of opaque type 'tmp.FooType' not allowed
27// :1:17: note: opaque declared here27// :1:17: note: opaque declared here
28// :8:24: error: parameter of type '@TypeOf(null)' not allowed28// :8:28: error: parameter of type '@TypeOf(null)' not allowed
29// :12:1: error: parameter of opaque type 'tmp.FooType' not allowed29// :12:8: error: parameter of opaque type 'tmp.FooType' not allowed
30// :17:1: error: parameter of type '@TypeOf(null)' not allowed30// :1:17: note: opaque declared here
31// :17:8: error: parameter of type '@TypeOf(null)' not allowed
test/cases/compile_errors/function_with_non-extern_non-packed_enum_parameter.zig+3-3
...@@ -5,7 +5,7 @@ export fn entry(foo: Foo) void { _ = foo; }...@@ -5,7 +5,7 @@ export fn entry(foo: Foo) void { _ = foo; }
5// backend=stage25// backend=stage2
6// target=native6// target=native
7//7//
8// :2:8: error: parameter of type 'tmp.Foo' not allowed in function with calling convention 'C'8// :2:17: error: parameter of type 'tmp.Foo' not allowed in function with calling convention 'C'
9// :2:8: note: enum tag type 'u2' is not extern compatible9// :2:17: note: enum tag type 'u2' is not extern compatible
10// :2:8: note: only integers with power of two bits are extern compatible10// :2:17: note: only integers with power of two bits are extern compatible
11// :1:13: note: enum declared here11// :1:13: note: enum declared here
test/cases/compile_errors/function_with_non-extern_non-packed_struct_parameter.zig+2-2
...@@ -9,6 +9,6 @@ export fn entry(foo: Foo) void { _ = foo; }...@@ -9,6 +9,6 @@ export fn entry(foo: Foo) void { _ = foo; }
9// backend=stage29// backend=stage2
10// target=native10// target=native
11//11//
12// :6:8: error: parameter of type 'tmp.Foo' not allowed in function with calling convention 'C'12// :6:17: error: parameter of type 'tmp.Foo' not allowed in function with calling convention 'C'
13// :6:8: note: only structs with packed or extern layout are extern compatible13// :6:17: note: only structs with packed or extern layout are extern compatible
14// :1:13: note: struct declared here14// :1:13: note: struct declared here
test/cases/compile_errors/function_with_non-extern_non-packed_union_parameter.zig+2-2
...@@ -9,6 +9,6 @@ export fn entry(foo: Foo) void { _ = foo; }...@@ -9,6 +9,6 @@ export fn entry(foo: Foo) void { _ = foo; }
9// backend=stage29// backend=stage2
10// target=native10// target=native
11//11//
12// :6:8: error: parameter of type 'tmp.Foo' not allowed in function with calling convention 'C'12// :6:17: error: parameter of type 'tmp.Foo' not allowed in function with calling convention 'C'
13// :6:8: note: only unions with packed or extern layout are extern compatible13// :6:17: note: only unions with packed or extern layout are extern compatible
14// :1:13: note: union declared here14// :1:13: note: union declared here
test/cases/compile_errors/stage1/obj/array_in_c_exported_function.zig deleted-14
...@@ -1,14 +0,0 @@
1export fn zig_array(x: [10]u8) void {
2 try std.testing.expect(std.mem.eql(u8, &x, "1234567890"));
3}
4const std = @import("std");
5export fn zig_return_array() [10]u8 {
6 return "1234567890".*;
7}
8
9// error
10// backend=stage1
11// target=native
12//
13// tmp.zig:1:24: error: parameter of type '[10]u8' not allowed in function with calling convention 'C'
14// tmp.zig:5:30: error: return type '[10]u8' not allowed in function with calling convention 'C'
test/cases/compile_errors/stage1/obj/export_function_with_comptime_parameter.zig deleted-9
...@@ -1,9 +0,0 @@
1export fn foo(comptime x: i32, y: i32) i32{
2 return x + y;
3}
4
5// error
6// backend=stage1
7// target=native
8//
9// tmp.zig:1:15: error: comptime parameter not allowed in function with calling convention 'C'
test/cases/compile_errors/stage1/obj/export_generic_function.zig deleted-10
...@@ -1,10 +0,0 @@
1export fn foo(num: anytype) i32 {
2 _ = num;
3 return 0;
4}
5
6// error
7// backend=stage1
8// target=native
9//
10// tmp.zig:1:15: error: parameter of type 'anytype' not allowed in function with calling convention 'C'
test/cases/compile_errors/stage1/obj/extern_function_with_comptime_parameter.zig deleted-11
...@@ -1,11 +0,0 @@
1extern fn foo(comptime x: i32, y: i32) i32;
2fn f() i32 {
3 return foo(1, 2);
4}
5export fn entry() usize { return @sizeOf(@TypeOf(f)); }
6
7// error
8// backend=stage1
9// target=native
10//
11// tmp.zig:1:15: error: comptime parameter not allowed in function with calling convention 'C'