authorgravatar for matthew.h.borkowski@gmail.comMatthew Borkowski <matthew.h.borkowski@gmail.com> 2021-10-23 21:52:21-04:00
committergravatar for matthew.h.borkowski@gmail.comMatthew Borkowski <matthew.h.borkowski@gmail.com> 2021-10-23 22:52:43-04:00
log9c5b852f9bb47e25c878cbccdaa175517ae48fc6
treecdad612fccceb4ba7664059c790d3785b0d3fbd5
parent8a95bac593ce9aa36b76229a9f2f4aba8c8d30dd

astgen.zig: emit ZIR for callconv before return type in fnDecl and fnProtoExpr


2 files changed, 31 insertions(+), 15 deletions(-)

src/AstGen.zig+15-15
......@@ -1156,16 +1156,6 @@ fn fnProtoExpr(
11561156 return astgen.failNode(fn_proto.ast.section_expr, "linksection not allowed on function prototypes", .{});
11571157 }
11581158
1159 const maybe_bang = tree.firstToken(fn_proto.ast.return_type) - 1;
1160 const is_inferred_error = token_tags[maybe_bang] == .bang;
1161 if (is_inferred_error) {
1162 return astgen.failTok(maybe_bang, "function prototype may not have inferred error set", .{});
1163 }
1164 var ret_gz = gz.makeSubBlock(scope);
1165 defer ret_gz.instructions.deinit(gpa);
1166 const ret_ty = try expr(&ret_gz, scope, coerced_type_rl, fn_proto.ast.return_type);
1167 const ret_br = try ret_gz.addBreak(.break_inline, 0, ret_ty);
1168
11691159 const cc: Zir.Inst.Ref = if (fn_proto.ast.callconv_expr != 0)
11701160 try expr(
11711161 gz,
......@@ -1176,6 +1166,16 @@ fn fnProtoExpr(
11761166 else
11771167 Zir.Inst.Ref.none;
11781168
1169 const maybe_bang = tree.firstToken(fn_proto.ast.return_type) - 1;
1170 const is_inferred_error = token_tags[maybe_bang] == .bang;
1171 if (is_inferred_error) {
1172 return astgen.failTok(maybe_bang, "function prototype may not have inferred error set", .{});
1173 }
1174 var ret_gz = gz.makeSubBlock(scope);
1175 defer ret_gz.instructions.deinit(gpa);
1176 const ret_ty = try expr(&ret_gz, scope, coerced_type_rl, fn_proto.ast.return_type);
1177 const ret_br = try ret_gz.addBreak(.break_inline, 0, ret_ty);
1178
11791179 const result = try gz.addFunc(.{
11801180 .src_node = fn_proto.ast.proto_node,
11811181 .param_block = 0,
......@@ -3182,11 +3182,6 @@ fn fnDecl(
31823182 break :inst try comptimeExpr(&decl_gz, params_scope, .{ .ty = .const_slice_u8_type }, fn_proto.ast.section_expr);
31833183 };
31843184
3185 var ret_gz = decl_gz.makeSubBlock(params_scope);
3186 defer ret_gz.instructions.deinit(gpa);
3187 const ret_ty = try expr(&ret_gz, params_scope, coerced_type_rl, fn_proto.ast.return_type);
3188 const ret_br = try ret_gz.addBreak(.break_inline, 0, ret_ty);
3189
31903185 const cc: Zir.Inst.Ref = blk: {
31913186 if (fn_proto.ast.callconv_expr != 0) {
31923187 if (has_inline_keyword) {
......@@ -3212,6 +3207,11 @@ fn fnDecl(
32123207 }
32133208 };
32143209
3210 var ret_gz = decl_gz.makeSubBlock(params_scope);
3211 defer ret_gz.instructions.deinit(gpa);
3212 const ret_ty = try expr(&ret_gz, params_scope, coerced_type_rl, fn_proto.ast.return_type);
3213 const ret_br = try ret_gz.addBreak(.break_inline, 0, ret_ty);
3214
32153215 const func_inst: Zir.Inst.Ref = if (body_node == 0) func: {
32163216 if (!is_extern) {
32173217 return astgen.failTok(fn_proto.ast.fn_token, "non-extern function has no body", .{});
test/behavior/fn_stage1.zig+16
......@@ -204,3 +204,19 @@ test "function with inferred error set but returning no error" {
204204 const return_ty = @typeInfo(@TypeOf(S.foo)).Fn.return_type.?;
205205 try expectEqual(0, @typeInfo(@typeInfo(return_ty).ErrorUnion.error_set).ErrorSet.?.len);
206206}
207
208const nComplexCallconv = 100;
209fn fComplexCallconvRet(x: u32) callconv(blk: {
210 const s: struct { n: u32 } = .{ .n = nComplexCallconv };
211 break :blk switch (s.n) {
212 0 => .C,
213 1 => .Inline,
214 else => .Unspecified,
215 };
216}) struct { x: u32 } {
217 return .{ .x = x * x };
218}
219
220test "function with complex callconv and return type expressions" {
221 try expect(fComplexCallconvRet(3).x == 9);
222}