| author | |
| committer | |
| log | 0fd90749d10052c40d5a91881621af55e80135b3 |
| tree | 0b2834ce86d41323c35888254c7ce24b7182d349 |
| parent | 85a3f9b0544c1b90a77ce26f99f9fc26116d756b |
7 files changed, 209 insertions(+), 96 deletions(-)
src/AstGen.zig+36-16| ... | ... | @@ -2500,7 +2500,6 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As |
| 2500 | 2500 | .closure_get, |
| 2501 | 2501 | .array_base_ptr, |
| 2502 | 2502 | .field_base_ptr, |
| 2503 | .param_type, | |
| 2504 | 2503 | .ret_ptr, |
| 2505 | 2504 | .ret_type, |
| 2506 | 2505 | .@"try", |
| ... | ... | @@ -8228,6 +8227,33 @@ fn callExpr( |
| 8228 | 8227 | assert(callee != .none); |
| 8229 | 8228 | assert(node != 0); |
| 8230 | 8229 | |
| 8230 | const call_index = @intCast(Zir.Inst.Index, astgen.instructions.len); | |
| 8231 | const call_inst = Zir.indexToRef(call_index); | |
| 8232 | try gz.astgen.instructions.append(astgen.gpa, undefined); | |
| 8233 | try gz.instructions.append(astgen.gpa, call_index); | |
| 8234 | ||
| 8235 | const scratch_top = astgen.scratch.items.len; | |
| 8236 | defer astgen.scratch.items.len = scratch_top; | |
| 8237 | ||
| 8238 | var scratch_index = scratch_top; | |
| 8239 | try astgen.scratch.resize(astgen.gpa, scratch_top + call.ast.params.len); | |
| 8240 | ||
| 8241 | for (call.ast.params) |param_node| { | |
| 8242 | var arg_block = gz.makeSubBlock(scope); | |
| 8243 | defer arg_block.unstack(); | |
| 8244 | ||
| 8245 | // `call_inst` is reused to provide the param type. | |
| 8246 | const arg_ref = try expr(&arg_block, &arg_block.base, .{ .coerced_ty = call_inst }, param_node); | |
| 8247 | _ = try arg_block.addBreak(.break_inline, call_index, arg_ref); | |
| 8248 | ||
| 8249 | const body = arg_block.instructionsSlice(); | |
| 8250 | try astgen.scratch.ensureUnusedCapacity(astgen.gpa, countBodyLenAfterFixups(astgen, body)); | |
| 8251 | appendBodyWithFixupsArrayList(astgen, &astgen.scratch, body); | |
| 8252 | ||
| 8253 | astgen.scratch.items[scratch_index] = @intCast(u32, astgen.scratch.items.len - scratch_top); | |
| 8254 | scratch_index += 1; | |
| 8255 | } | |
| 8256 | ||
| 8231 | 8257 | const payload_index = try addExtra(astgen, Zir.Inst.Call{ |
| 8232 | 8258 | .callee = callee, |
| 8233 | 8259 | .flags = .{ |
| ... | ... | @@ -8235,22 +8261,16 @@ fn callExpr( |
| 8235 | 8261 | .args_len = @intCast(Zir.Inst.Call.Flags.PackedArgsLen, call.ast.params.len), |
| 8236 | 8262 | }, |
| 8237 | 8263 | }); |
| 8238 | var extra_index = try reserveExtra(astgen, call.ast.params.len); | |
| 8239 | ||
| 8240 | for (call.ast.params) |param_node, i| { | |
| 8241 | const param_type = try gz.add(.{ | |
| 8242 | .tag = .param_type, | |
| 8243 | .data = .{ .param_type = .{ | |
| 8244 | .callee = callee, | |
| 8245 | .param_index = @intCast(u32, i), | |
| 8246 | } }, | |
| 8247 | }); | |
| 8248 | const arg_ref = try expr(gz, scope, .{ .coerced_ty = param_type }, param_node); | |
| 8249 | astgen.extra.items[extra_index] = @enumToInt(arg_ref); | |
| 8250 | extra_index += 1; | |
| 8264 | if (call.ast.params.len != 0) { | |
| 8265 | try astgen.extra.appendSlice(astgen.gpa, astgen.scratch.items[scratch_top..]); | |
| 8251 | 8266 | } |
| 8252 | ||
| 8253 | const call_inst = try gz.addPlNodePayloadIndex(.call, node, payload_index); | |
| 8267 | gz.astgen.instructions.set(call_index, .{ | |
| 8268 | .tag = .call, | |
| 8269 | .data = .{ .pl_node = .{ | |
| 8270 | .src_node = gz.nodeIndexToRelative(node), | |
| 8271 | .payload_index = payload_index, | |
| 8272 | } }, | |
| 8273 | }); | |
| 8254 | 8274 | return rvalue(gz, rl, call_inst, node); // TODO function call with result location |
| 8255 | 8275 | } |
| 8256 | 8276 |
src/Sema.zig+108-48| ... | ... | @@ -772,7 +772,6 @@ fn analyzeBodyInner( |
| 772 | 772 | .optional_payload_unsafe => try sema.zirOptionalPayload(block, inst, false), |
| 773 | 773 | .optional_payload_unsafe_ptr => try sema.zirOptionalPayloadPtr(block, inst, false), |
| 774 | 774 | .optional_type => try sema.zirOptionalType(block, inst), |
| 775 | .param_type => try sema.zirParamType(block, inst), | |
| 776 | 775 | .ptr_type => try sema.zirPtrType(block, inst), |
| 777 | 776 | .overflow_arithmetic_ptr => try sema.zirOverflowArithmeticPtr(block, inst), |
| 778 | 777 | .ref => try sema.zirRef(block, inst), |
| ... | ... | @@ -4441,43 +4440,6 @@ fn zirStoreNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!v |
| 4441 | 4440 | return sema.storePtr2(block, src, ptr, src, operand, src, if (is_ret) .ret_ptr else .store); |
| 4442 | 4441 | } |
| 4443 | 4442 | |
| 4444 | fn zirParamType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | |
| 4445 | const callee_src = sema.src; | |
| 4446 | ||
| 4447 | const inst_data = sema.code.instructions.items(.data)[inst].param_type; | |
| 4448 | const callee = try sema.resolveInst(inst_data.callee); | |
| 4449 | const callee_ty = sema.typeOf(callee); | |
| 4450 | var param_index = inst_data.param_index; | |
| 4451 | ||
| 4452 | const fn_ty = if (callee_ty.tag() == .bound_fn) fn_ty: { | |
| 4453 | const bound_fn_val = try sema.resolveConstValue(block, .unneeded, callee, undefined); | |
| 4454 | const bound_fn = bound_fn_val.castTag(.bound_fn).?.data; | |
| 4455 | const fn_ty = sema.typeOf(bound_fn.func_inst); | |
| 4456 | param_index += 1; | |
| 4457 | break :fn_ty fn_ty; | |
| 4458 | } else callee_ty; | |
| 4459 | ||
| 4460 | const fn_info = if (fn_ty.zigTypeTag() == .Pointer) | |
| 4461 | fn_ty.childType().fnInfo() | |
| 4462 | else | |
| 4463 | fn_ty.fnInfo(); | |
| 4464 | ||
| 4465 | if (param_index >= fn_info.param_types.len) { | |
| 4466 | if (fn_info.is_var_args) { | |
| 4467 | return sema.addType(Type.initTag(.var_args_param)); | |
| 4468 | } | |
| 4469 | // TODO implement begin_call/end_call Zir instructions and check | |
| 4470 | // argument count before casting arguments to parameter types. | |
| 4471 | return sema.fail(block, callee_src, "wrong number of arguments", .{}); | |
| 4472 | } | |
| 4473 | ||
| 4474 | if (fn_info.param_types[param_index].tag() == .generic_poison) { | |
| 4475 | return sema.addType(Type.initTag(.var_args_param)); | |
| 4476 | } | |
| 4477 | ||
| 4478 | return sema.addType(fn_info.param_types[param_index]); | |
| 4479 | } | |
| 4480 | ||
| 4481 | 4443 | fn zirStr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 4482 | 4444 | const tracy = trace(@src()); |
| 4483 | 4445 | defer tracy.end(); |
| ... | ... | @@ -5459,13 +5421,14 @@ fn zirCall( |
| 5459 | 5421 | const func_src: LazySrcLoc = .{ .node_offset_call_func = inst_data.src_node }; |
| 5460 | 5422 | const call_src = inst_data.src(); |
| 5461 | 5423 | const extra = sema.code.extraData(Zir.Inst.Call, inst_data.payload_index); |
| 5462 | const args = sema.code.refSlice(extra.end, extra.data.flags.args_len); | |
| 5424 | const args_len = extra.data.flags.args_len; | |
| 5463 | 5425 | |
| 5464 | 5426 | const modifier = @intToEnum(std.builtin.CallOptions.Modifier, extra.data.flags.packed_modifier); |
| 5465 | 5427 | const ensure_result_used = extra.data.flags.ensure_result_used; |
| 5466 | 5428 | |
| 5467 | 5429 | var func = try sema.resolveInst(extra.data.callee); |
| 5468 | 5430 | var resolved_args: []Air.Inst.Ref = undefined; |
| 5431 | var arg_index: u32 = 0; | |
| 5469 | 5432 | |
| 5470 | 5433 | const func_type = sema.typeOf(func); |
| 5471 | 5434 | |
| ... | ... | @@ -5476,16 +5439,99 @@ fn zirCall( |
| 5476 | 5439 | const bound_func = try sema.resolveValue(block, .unneeded, func, undefined); |
| 5477 | 5440 | const bound_data = &bound_func.cast(Value.Payload.BoundFn).?.data; |
| 5478 | 5441 | func = bound_data.func_inst; |
| 5479 | resolved_args = try sema.arena.alloc(Air.Inst.Ref, args.len + 1); | |
| 5480 | resolved_args[0] = bound_data.arg0_inst; | |
| 5481 | for (args) |zir_arg, i| { | |
| 5482 | resolved_args[i + 1] = try sema.resolveInst(zir_arg); | |
| 5483 | } | |
| 5442 | resolved_args = try sema.arena.alloc(Air.Inst.Ref, args_len + 1); | |
| 5443 | resolved_args[arg_index] = bound_data.arg0_inst; | |
| 5444 | arg_index += 1; | |
| 5484 | 5445 | } else { |
| 5485 | resolved_args = try sema.arena.alloc(Air.Inst.Ref, args.len); | |
| 5486 | for (args) |zir_arg, i| { | |
| 5487 | resolved_args[i] = try sema.resolveInst(zir_arg); | |
| 5446 | resolved_args = try sema.arena.alloc(Air.Inst.Ref, args_len); | |
| 5447 | } | |
| 5448 | const total_args = args_len + @boolToInt(bound_arg_src != null); | |
| 5449 | ||
| 5450 | const callee_ty = sema.typeOf(func); | |
| 5451 | const func_ty = func_ty: { | |
| 5452 | switch (callee_ty.zigTypeTag()) { | |
| 5453 | .Fn => break :func_ty callee_ty, | |
| 5454 | .Pointer => { | |
| 5455 | const ptr_info = callee_ty.ptrInfo().data; | |
| 5456 | if (ptr_info.size == .One and ptr_info.pointee_type.zigTypeTag() == .Fn) { | |
| 5457 | break :func_ty ptr_info.pointee_type; | |
| 5458 | } | |
| 5459 | }, | |
| 5460 | else => {}, | |
| 5461 | } | |
| 5462 | return sema.fail(block, func_src, "type '{}' not a function", .{callee_ty.fmt(sema.mod)}); | |
| 5463 | }; | |
| 5464 | const func_ty_info = func_ty.fnInfo(); | |
| 5465 | ||
| 5466 | const fn_params_len = func_ty_info.param_types.len; | |
| 5467 | if (func_ty_info.is_var_args) { | |
| 5468 | assert(func_ty_info.cc == .C); | |
| 5469 | if (total_args < fn_params_len) { | |
| 5470 | // TODO add error note: declared here | |
| 5471 | if (bound_arg_src != null) { | |
| 5472 | return sema.fail( | |
| 5473 | block, | |
| 5474 | call_src, | |
| 5475 | "member function expected at least {d} argument(s), found {d}", | |
| 5476 | .{ fn_params_len - 1, args_len }, | |
| 5477 | ); | |
| 5478 | } | |
| 5479 | return sema.fail( | |
| 5480 | block, | |
| 5481 | func_src, | |
| 5482 | "expected at least {d} argument(s), found {d}", | |
| 5483 | .{ fn_params_len, args_len }, | |
| 5484 | ); | |
| 5485 | } | |
| 5486 | } else if (fn_params_len != total_args) { | |
| 5487 | // TODO add error note: declared here | |
| 5488 | if (bound_arg_src != null) { | |
| 5489 | return sema.fail( | |
| 5490 | block, | |
| 5491 | call_src, | |
| 5492 | "member function expected {d} argument(s), found {d}", | |
| 5493 | .{ fn_params_len - 1, args_len }, | |
| 5494 | ); | |
| 5495 | } | |
| 5496 | return sema.fail( | |
| 5497 | block, | |
| 5498 | call_src, | |
| 5499 | "expected {d} argument(s), found {d}", | |
| 5500 | .{ fn_params_len, args_len }, | |
| 5501 | ); | |
| 5502 | } | |
| 5503 | ||
| 5504 | const args_body = sema.code.extra[extra.end..]; | |
| 5505 | ||
| 5506 | const parent_comptime = block.is_comptime; | |
| 5507 | // `extra_index` and `arg_index` are separate since the bound function is passed as the first argument. | |
| 5508 | var extra_index: usize = 0; | |
| 5509 | var arg_start: u32 = args_len; | |
| 5510 | while (extra_index < args_len) : ({ | |
| 5511 | extra_index += 1; | |
| 5512 | arg_index += 1; | |
| 5513 | }) { | |
| 5514 | const arg_end = sema.code.extra[extra.end + extra_index]; | |
| 5515 | defer arg_start = arg_end; | |
| 5516 | ||
| 5517 | const param_ty = if (arg_index >= fn_params_len or | |
| 5518 | func_ty_info.param_types[arg_index].tag() == .generic_poison) | |
| 5519 | Type.initTag(.var_args_param) | |
| 5520 | else | |
| 5521 | func_ty_info.param_types[arg_index]; | |
| 5522 | ||
| 5523 | const old_comptime = block.is_comptime; | |
| 5524 | defer block.is_comptime = old_comptime; | |
| 5525 | // Generate args to comptime params in comptime block. | |
| 5526 | block.is_comptime = parent_comptime; | |
| 5527 | if (arg_index < fn_params_len and func_ty_info.comptime_params[arg_index]) { | |
| 5528 | block.is_comptime = true; | |
| 5488 | 5529 | } |
| 5530 | ||
| 5531 | const param_ty_inst = try sema.addType(param_ty); | |
| 5532 | try sema.inst_map.put(sema.gpa, inst, param_ty_inst); | |
| 5533 | ||
| 5534 | resolved_args[arg_index] = try sema.resolveBody(block, args_body[arg_start..arg_end], inst); | |
| 5489 | 5535 | } |
| 5490 | 5536 | |
| 5491 | 5537 | return sema.analyzeCall(block, func, func_src, call_src, modifier, ensure_result_used, resolved_args, bound_arg_src); |
| ... | ... | @@ -5964,7 +6010,18 @@ fn analyzeCall( |
| 5964 | 6010 | else => |e| return e, |
| 5965 | 6011 | }; |
| 5966 | 6012 | } else { |
| 5967 | args[i] = uncasted_arg; | |
| 6013 | args[i] = sema.coerceVarArgParam(block, uncasted_arg, .unneeded) catch |err| switch (err) { | |
| 6014 | error.NeededSourceLocation => { | |
| 6015 | const decl = sema.mod.declPtr(block.src_decl); | |
| 6016 | _ = try sema.coerceVarArgParam( | |
| 6017 | block, | |
| 6018 | uncasted_arg, | |
| 6019 | Module.argSrc(call_src.node_offset.x, sema.gpa, decl, i, bound_arg_src), | |
| 6020 | ); | |
| 6021 | return error.AnalysisFail; | |
| 6022 | }, | |
| 6023 | else => |e| return e, | |
| 6024 | }; | |
| 5968 | 6025 | } |
| 5969 | 6026 | } |
| 5970 | 6027 | |
| ... | ... | @@ -23534,7 +23591,10 @@ fn coerceVarArgParam( |
| 23534 | 23591 | inst_src: LazySrcLoc, |
| 23535 | 23592 | ) !Air.Inst.Ref { |
| 23536 | 23593 | const inst_ty = sema.typeOf(inst); |
| 23594 | if (block.is_typeof) return inst; | |
| 23595 | ||
| 23537 | 23596 | switch (inst_ty.zigTypeTag()) { |
| 23597 | // TODO consider casting to c_int/f64 if they fit | |
| 23538 | 23598 | .ComptimeInt, .ComptimeFloat => return sema.fail(block, inst_src, "integer and float literals in var args function must be casted", .{}), |
| 23539 | 23599 | else => {}, |
| 23540 | 23600 | } |
src/Zir.zig+3-17| ... | ... | @@ -490,14 +490,6 @@ pub const Inst = struct { |
| 490 | 490 | /// Merge two error sets into one, `E1 || E2`. |
| 491 | 491 | /// Uses the `pl_node` field with payload `Bin`. |
| 492 | 492 | merge_error_sets, |
| 493 | /// Given a reference to a function and a parameter index, returns the | |
| 494 | /// type of the parameter. The only usage of this instruction is for the | |
| 495 | /// result location of parameters of function calls. In the case of a function's | |
| 496 | /// parameter type being `anytype`, it is the type coercion's job to detect this | |
| 497 | /// scenario and skip the coercion, so that semantic analysis of this instruction | |
| 498 | /// is not in a position where it must create an invalid type. | |
| 499 | /// Uses the `param_type` union field. | |
| 500 | param_type, | |
| 501 | 493 | /// Turns an R-Value into a const L-Value. In other words, it takes a value, |
| 502 | 494 | /// stores it in a memory location, and returns a const pointer to it. If the value |
| 503 | 495 | /// is `comptime`, the memory location is global static constant data. Otherwise, |
| ... | ... | @@ -1095,7 +1087,6 @@ pub const Inst = struct { |
| 1095 | 1087 | .mul, |
| 1096 | 1088 | .mulwrap, |
| 1097 | 1089 | .mul_sat, |
| 1098 | .param_type, | |
| 1099 | 1090 | .ref, |
| 1100 | 1091 | .shl, |
| 1101 | 1092 | .shl_sat, |
| ... | ... | @@ -1397,7 +1388,6 @@ pub const Inst = struct { |
| 1397 | 1388 | .mul, |
| 1398 | 1389 | .mulwrap, |
| 1399 | 1390 | .mul_sat, |
| 1400 | .param_type, | |
| 1401 | 1391 | .ref, |
| 1402 | 1392 | .shl, |
| 1403 | 1393 | .shl_sat, |
| ... | ... | @@ -1569,7 +1559,6 @@ pub const Inst = struct { |
| 1569 | 1559 | .mulwrap = .pl_node, |
| 1570 | 1560 | .mul_sat = .pl_node, |
| 1571 | 1561 | |
| 1572 | .param_type = .param_type, | |
| 1573 | 1562 | .param = .pl_tok, |
| 1574 | 1563 | .param_comptime = .pl_tok, |
| 1575 | 1564 | .param_anytype = .str_tok, |
| ... | ... | @@ -2540,10 +2529,6 @@ pub const Inst = struct { |
| 2540 | 2529 | /// Points to a `Block`. |
| 2541 | 2530 | payload_index: u32, |
| 2542 | 2531 | }, |
| 2543 | param_type: struct { | |
| 2544 | callee: Ref, | |
| 2545 | param_index: u32, | |
| 2546 | }, | |
| 2547 | 2532 | @"unreachable": struct { |
| 2548 | 2533 | /// Offset from Decl AST node index. |
| 2549 | 2534 | /// `Tag` determines which kind of AST node this points to. |
| ... | ... | @@ -2614,7 +2599,6 @@ pub const Inst = struct { |
| 2614 | 2599 | ptr_type, |
| 2615 | 2600 | int_type, |
| 2616 | 2601 | bool_br, |
| 2617 | param_type, | |
| 2618 | 2602 | @"unreachable", |
| 2619 | 2603 | @"break", |
| 2620 | 2604 | switch_capture, |
| ... | ... | @@ -2794,7 +2778,9 @@ pub const Inst = struct { |
| 2794 | 2778 | }; |
| 2795 | 2779 | |
| 2796 | 2780 | /// Stored inside extra, with trailing arguments according to `args_len`. |
| 2797 | /// Each argument is a `Ref`. | |
| 2781 | /// Implicit 0. arg_0_start: u32, // always same as `args_len` | |
| 2782 | /// 1. arg_end: u32, // for each `args_len` | |
| 2783 | /// arg_N_start is the same as arg_N-1_end | |
| 2798 | 2784 | pub const Call = struct { |
| 2799 | 2785 | // Note: Flags *must* come first so that unusedResultExpr |
| 2800 | 2786 | // can find it when it goes to modify them. |
src/print_zir.zig+22-15| ... | ... | @@ -246,7 +246,6 @@ const Writer = struct { |
| 246 | 246 | |
| 247 | 247 | .validate_array_init_ty => try self.writeValidateArrayInitTy(stream, inst), |
| 248 | 248 | .array_type_sentinel => try self.writeArrayTypeSentinel(stream, inst), |
| 249 | .param_type => try self.writeParamType(stream, inst), | |
| 250 | 249 | .ptr_type => try self.writePtrType(stream, inst), |
| 251 | 250 | .int => try self.writeInt(stream, inst), |
| 252 | 251 | .int_big => try self.writeIntBig(stream, inst), |
| ... | ... | @@ -605,16 +604,6 @@ const Writer = struct { |
| 605 | 604 | try self.writeSrc(stream, inst_data.src()); |
| 606 | 605 | } |
| 607 | 606 | |
| 608 | fn writeParamType( | |
| 609 | self: *Writer, | |
| 610 | stream: anytype, | |
| 611 | inst: Zir.Inst.Index, | |
| 612 | ) (@TypeOf(stream).Error || error{OutOfMemory})!void { | |
| 613 | const inst_data = self.code.instructions.items(.data)[inst].param_type; | |
| 614 | try self.writeInstRef(stream, inst_data.callee); | |
| 615 | try stream.print(", {d})", .{inst_data.param_index}); | |
| 616 | } | |
| 617 | ||
| 618 | 607 | fn writePtrType( |
| 619 | 608 | self: *Writer, |
| 620 | 609 | stream: anytype, |
| ... | ... | @@ -1158,7 +1147,8 @@ const Writer = struct { |
| 1158 | 1147 | fn writeCall(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void { |
| 1159 | 1148 | const inst_data = self.code.instructions.items(.data)[inst].pl_node; |
| 1160 | 1149 | const extra = self.code.extraData(Zir.Inst.Call, inst_data.payload_index); |
| 1161 | const args = self.code.refSlice(extra.end, extra.data.flags.args_len); | |
| 1150 | const args_len = extra.data.flags.args_len; | |
| 1151 | const body = self.code.extra[extra.end..]; | |
| 1162 | 1152 | |
| 1163 | 1153 | if (extra.data.flags.ensure_result_used) { |
| 1164 | 1154 | try stream.writeAll("nodiscard "); |
| ... | ... | @@ -1166,10 +1156,27 @@ const Writer = struct { |
| 1166 | 1156 | try stream.print(".{s}, ", .{@tagName(@intToEnum(std.builtin.CallOptions.Modifier, extra.data.flags.packed_modifier))}); |
| 1167 | 1157 | try self.writeInstRef(stream, extra.data.callee); |
| 1168 | 1158 | try stream.writeAll(", ["); |
| 1169 | for (args) |arg, i| { | |
| 1170 | if (i != 0) try stream.writeAll(", "); | |
| 1171 | try self.writeInstRef(stream, arg); | |
| 1159 | ||
| 1160 | self.indent += 2; | |
| 1161 | if (args_len != 0) { | |
| 1162 | try stream.writeAll("\n"); | |
| 1163 | } | |
| 1164 | var i: usize = 0; | |
| 1165 | var arg_start: u32 = args_len; | |
| 1166 | while (i < args_len) : (i += 1) { | |
| 1167 | try stream.writeByteNTimes(' ', self.indent); | |
| 1168 | const arg_end = self.code.extra[extra.end + i]; | |
| 1169 | defer arg_start = arg_end; | |
| 1170 | const arg_body = body[arg_start..arg_end]; | |
| 1171 | try self.writeBracedBody(stream, arg_body); | |
| 1172 | ||
| 1173 | try stream.writeAll(",\n"); | |
| 1172 | 1174 | } |
| 1175 | self.indent -= 2; | |
| 1176 | if (args_len != 0) { | |
| 1177 | try stream.writeByteNTimes(' ', self.indent); | |
| 1178 | } | |
| 1179 | ||
| 1173 | 1180 | try stream.writeAll("]) "); |
| 1174 | 1181 | try self.writeSrc(stream, inst_data.src()); |
| 1175 | 1182 | } |
test/behavior/call.zig+15| ... | ... | @@ -246,3 +246,18 @@ test "function call with 40 arguments" { |
| 246 | 246 | }; |
| 247 | 247 | try S.doTheTest(39); |
| 248 | 248 | } |
| 249 | ||
| 250 | test "arguments to comptime parameters generated in comptime blocks" { | |
| 251 | if (builtin.zig_backend == .stage1) return error.SkipZigTest; | |
| 252 | ||
| 253 | const S = struct { | |
| 254 | fn fortyTwo() i32 { | |
| 255 | return 42; | |
| 256 | } | |
| 257 | ||
| 258 | fn foo(comptime x: i32) void { | |
| 259 | if (x != 42) @compileError("bad"); | |
| 260 | } | |
| 261 | }; | |
| 262 | S.foo(S.fortyTwo()); | |
| 263 | } |
test/cases/compile_errors/int_literal_passed_as_variadic_arg.zig created+11| ... | ... | @@ -0,0 +1,11 @@ |
| 1 | extern fn printf([*:0]const u8, ...) c_int; | |
| 2 | ||
| 3 | pub export fn entry() void { | |
| 4 | _ = printf("%d %d %d %d\n", 1, 2, 3, 4); | |
| 5 | } | |
| 6 | ||
| 7 | // error | |
| 8 | // backend=stage2 | |
| 9 | // target=native | |
| 10 | // | |
| 11 | // :4:33: error: integer and float literals in var args function must be casted |
test/cases/compile_errors/member_function_arg_mismatch.zig created+14| ... | ... | @@ -0,0 +1,14 @@ |
| 1 | const S = struct { | |
| 2 | a: u32, | |
| 3 | fn foo(_: *S, _: u32, _: bool) void {} | |
| 4 | }; | |
| 5 | pub export fn entry() void { | |
| 6 | var s: S = undefined; | |
| 7 | s.foo(true); | |
| 8 | } | |
| 9 | ||
| 10 | // error | |
| 11 | // backend=stage2 | |
| 12 | // target=native | |
| 13 | // | |
| 14 | // :7:10: error: member function expected 2 argument(s), found 1 |