authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-11-13 17:35:57+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-01-09 14:01:01-07:00
logb494f6a9dc078c55aea4b27306178084cccb36a8
tree8e723d7091f143158e0c63a7c9382328e3d6d589
parent7748d2bb44dabbf60bfd7f65b1c5e2ebf0b49207

Merge pull request #13497 from Vexu/stage2-fixes

Stage2 bug fixes

17 files changed, 329 insertions(+), 65 deletions(-)

src/AstGen.zig+156-34
...@@ -339,6 +339,8 @@ pub const ResultInfo = struct {...@@ -339,6 +339,8 @@ pub const ResultInfo = struct {
339 fn_arg,339 fn_arg,
340 /// The expression is the right-hand side of an initializer for a `const` variable340 /// The expression is the right-hand side of an initializer for a `const` variable
341 const_init,341 const_init,
342 /// The expression is the right-hand side of an assignment expression.
343 assignment,
342 /// No specific operator in particular.344 /// No specific operator in particular.
343 none,345 none,
344 };346 };
...@@ -826,7 +828,13 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE...@@ -826,7 +828,13 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
826828
827 .slice_open => {829 .slice_open => {
828 const lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs);830 const lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs);
831
832 maybeAdvanceSourceCursorToMainToken(gz, node);
833 const line = gz.astgen.source_line - gz.decl_line;
834 const column = gz.astgen.source_column;
835
829 const start = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, node_datas[node].rhs);836 const start = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, node_datas[node].rhs);
837 try emitDbgStmt(gz, line, column);
830 const result = try gz.addPlNode(.slice_start, node, Zir.Inst.SliceStart{838 const result = try gz.addPlNode(.slice_start, node, Zir.Inst.SliceStart{
831 .lhs = lhs,839 .lhs = lhs,
832 .start = start,840 .start = start,
...@@ -835,9 +843,15 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE...@@ -835,9 +843,15 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
835 },843 },
836 .slice => {844 .slice => {
837 const lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs);845 const lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs);
846
847 maybeAdvanceSourceCursorToMainToken(gz, node);
848 const line = gz.astgen.source_line - gz.decl_line;
849 const column = gz.astgen.source_column;
850
838 const extra = tree.extraData(node_datas[node].rhs, Ast.Node.Slice);851 const extra = tree.extraData(node_datas[node].rhs, Ast.Node.Slice);
839 const start = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, extra.start);852 const start = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, extra.start);
840 const end = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, extra.end);853 const end = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, extra.end);
854 try emitDbgStmt(gz, line, column);
841 const result = try gz.addPlNode(.slice_end, node, Zir.Inst.SliceEnd{855 const result = try gz.addPlNode(.slice_end, node, Zir.Inst.SliceEnd{
842 .lhs = lhs,856 .lhs = lhs,
843 .start = start,857 .start = start,
...@@ -847,10 +861,16 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE...@@ -847,10 +861,16 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
847 },861 },
848 .slice_sentinel => {862 .slice_sentinel => {
849 const lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs);863 const lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs);
864
865 maybeAdvanceSourceCursorToMainToken(gz, node);
866 const line = gz.astgen.source_line - gz.decl_line;
867 const column = gz.astgen.source_column;
868
850 const extra = tree.extraData(node_datas[node].rhs, Ast.Node.SliceSentinel);869 const extra = tree.extraData(node_datas[node].rhs, Ast.Node.SliceSentinel);
851 const start = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, extra.start);870 const start = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, extra.start);
852 const end = if (extra.end != 0) try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, extra.end) else .none;871 const end = if (extra.end != 0) try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, extra.end) else .none;
853 const sentinel = try expr(gz, scope, .{ .rl = .none }, extra.sentinel);872 const sentinel = try expr(gz, scope, .{ .rl = .none }, extra.sentinel);
873 try emitDbgStmt(gz, line, column);
854 const result = try gz.addPlNode(.slice_sentinel, node, Zir.Inst.SliceSentinel{874 const result = try gz.addPlNode(.slice_sentinel, node, Zir.Inst.SliceSentinel{
855 .lhs = lhs,875 .lhs = lhs,
856 .start = start,876 .start = start,
...@@ -881,16 +901,26 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE...@@ -881,16 +901,26 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
881 return rvalue(gz, ri, result, node);901 return rvalue(gz, ri, result, node);
882 },902 },
883 .unwrap_optional => switch (ri.rl) {903 .unwrap_optional => switch (ri.rl) {
884 .ref => return gz.addUnNode(904 .ref => {
885 .optional_payload_safe_ptr,905 const lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs);
886 try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs),906
887 node,907 maybeAdvanceSourceCursorToMainToken(gz, node);
888 ),908 const line = gz.astgen.source_line - gz.decl_line;
889 else => return rvalue(gz, ri, try gz.addUnNode(909 const column = gz.astgen.source_column;
890 .optional_payload_safe,910 try emitDbgStmt(gz, line, column);
891 try expr(gz, scope, .{ .rl = .none }, node_datas[node].lhs),911
892 node,912 return gz.addUnNode(.optional_payload_safe_ptr, lhs, node);
893 ), node),913 },
914 else => {
915 const lhs = try expr(gz, scope, .{ .rl = .none }, node_datas[node].lhs);
916
917 maybeAdvanceSourceCursorToMainToken(gz, node);
918 const line = gz.astgen.source_line - gz.decl_line;
919 const column = gz.astgen.source_column;
920 try emitDbgStmt(gz, line, column);
921
922 return rvalue(gz, ri, try gz.addUnNode(.optional_payload_safe, lhs, node), node);
923 },
894 },924 },
895 .block_two, .block_two_semicolon => {925 .block_two, .block_two_semicolon => {
896 const statements = [2]Ast.Node.Index{ node_datas[node].lhs, node_datas[node].rhs };926 const statements = [2]Ast.Node.Index{ node_datas[node].lhs, node_datas[node].rhs };
...@@ -3216,7 +3246,7 @@ fn assign(gz: *GenZir, scope: *Scope, infix_node: Ast.Node.Index) InnerError!voi...@@ -3216,7 +3246,7 @@ fn assign(gz: *GenZir, scope: *Scope, infix_node: Ast.Node.Index) InnerError!voi
3216 // This intentionally does not support `@"_"` syntax.3246 // This intentionally does not support `@"_"` syntax.
3217 const ident_name = tree.tokenSlice(main_tokens[lhs]);3247 const ident_name = tree.tokenSlice(main_tokens[lhs]);
3218 if (mem.eql(u8, ident_name, "_")) {3248 if (mem.eql(u8, ident_name, "_")) {
3219 _ = try expr(gz, scope, .{ .rl = .discard }, rhs);3249 _ = try expr(gz, scope, .{ .rl = .discard, .ctx = .assignment }, rhs);
3220 return;3250 return;
3221 }3251 }
3222 }3252 }
...@@ -3239,10 +3269,27 @@ fn assignOp(...@@ -3239,10 +3269,27 @@ fn assignOp(
3239 const node_datas = tree.nodes.items(.data);3269 const node_datas = tree.nodes.items(.data);
32403270
3241 const lhs_ptr = try lvalExpr(gz, scope, node_datas[infix_node].lhs);3271 const lhs_ptr = try lvalExpr(gz, scope, node_datas[infix_node].lhs);
3272
3273 var line: u32 = undefined;
3274 var column: u32 = undefined;
3275 switch (op_inst_tag) {
3276 .add, .sub, .mul, .div, .mod_rem => {
3277 maybeAdvanceSourceCursorToMainToken(gz, infix_node);
3278 line = gz.astgen.source_line - gz.decl_line;
3279 column = gz.astgen.source_column;
3280 },
3281 else => {},
3282 }
3242 const lhs = try gz.addUnNode(.load, lhs_ptr, infix_node);3283 const lhs = try gz.addUnNode(.load, lhs_ptr, infix_node);
3243 const lhs_type = try gz.addUnNode(.typeof, lhs, infix_node);3284 const lhs_type = try gz.addUnNode(.typeof, lhs, infix_node);
3244 const rhs = try expr(gz, scope, .{ .rl = .{ .coerced_ty = lhs_type } }, node_datas[infix_node].rhs);3285 const rhs = try expr(gz, scope, .{ .rl = .{ .coerced_ty = lhs_type } }, node_datas[infix_node].rhs);
32453286
3287 switch (op_inst_tag) {
3288 .add, .sub, .mul, .div, .mod_rem => {
3289 try emitDbgStmt(gz, line, column);
3290 },
3291 else => {},
3292 }
3246 const result = try gz.addPlNode(op_inst_tag, infix_node, Zir.Inst.Bin{3293 const result = try gz.addPlNode(op_inst_tag, infix_node, Zir.Inst.Bin{
3247 .lhs = lhs,3294 .lhs = lhs,
3248 .rhs = rhs,3295 .rhs = rhs,
...@@ -5294,9 +5341,11 @@ fn orelseCatchExpr(...@@ -5294,9 +5341,11 @@ fn orelseCatchExpr(
5294 // up for this fact by calling rvalue on the else branch.5341 // up for this fact by calling rvalue on the else branch.
5295 const operand = try reachableExpr(&block_scope, &block_scope.base, operand_ri, lhs, rhs);5342 const operand = try reachableExpr(&block_scope, &block_scope.base, operand_ri, lhs, rhs);
5296 const cond = try block_scope.addUnNode(cond_op, operand, node);5343 const cond = try block_scope.addUnNode(cond_op, operand, node);
5297 const condbr = try block_scope.addCondBr(.condbr, node);5344 const condbr_tag: Zir.Inst.Tag = if (parent_gz.force_comptime) .condbr_inline else .condbr;
5345 const condbr = try block_scope.addCondBr(condbr_tag, node);
52985346
5299 const block = try parent_gz.makeBlockInst(.block, node);5347 const block_tag: Zir.Inst.Tag = if (parent_gz.force_comptime) .block_inline else .block;
5348 const block = try parent_gz.makeBlockInst(block_tag, node);
5300 try block_scope.setBlockBody(block);5349 try block_scope.setBlockBody(block);
5301 // block_scope unstacked now, can add new instructions to parent_gz5350 // block_scope unstacked now, can add new instructions to parent_gz
5302 try parent_gz.instructions.append(astgen.gpa, block);5351 try parent_gz.instructions.append(astgen.gpa, block);
...@@ -5471,9 +5520,15 @@ fn addFieldAccess(...@@ -5471,9 +5520,15 @@ fn addFieldAccess(
5471 const dot_token = main_tokens[node];5520 const dot_token = main_tokens[node];
5472 const field_ident = dot_token + 1;5521 const field_ident = dot_token + 1;
5473 const str_index = try astgen.identAsString(field_ident);5522 const str_index = try astgen.identAsString(field_ident);
5523 const lhs = try expr(gz, scope, lhs_ri, object_node);
5524
5525 maybeAdvanceSourceCursorToMainToken(gz, node);
5526 const line = gz.astgen.source_line - gz.decl_line;
5527 const column = gz.astgen.source_column;
5528 try emitDbgStmt(gz, line, column);
54745529
5475 return gz.addPlNode(tag, node, Zir.Inst.Field{5530 return gz.addPlNode(tag, node, Zir.Inst.Field{
5476 .lhs = try expr(gz, scope, lhs_ri, object_node),5531 .lhs = lhs,
5477 .field_name_start = str_index,5532 .field_name_start = str_index,
5478 });5533 });
5479}5534}
...@@ -5484,18 +5539,33 @@ fn arrayAccess(...@@ -5484,18 +5539,33 @@ fn arrayAccess(
5484 ri: ResultInfo,5539 ri: ResultInfo,
5485 node: Ast.Node.Index,5540 node: Ast.Node.Index,
5486) InnerError!Zir.Inst.Ref {5541) InnerError!Zir.Inst.Ref {
5487 const astgen = gz.astgen;5542 const tree = gz.astgen.tree;
5488 const tree = astgen.tree;
5489 const node_datas = tree.nodes.items(.data);5543 const node_datas = tree.nodes.items(.data);
5490 switch (ri.rl) {5544 switch (ri.rl) {
5491 .ref => return gz.addPlNode(.elem_ptr_node, node, Zir.Inst.Bin{5545 .ref => {
5492 .lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs),5546 const lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs);
5493 .rhs = try expr(gz, scope, .{ .rl = .{ .ty = .usize_type } }, node_datas[node].rhs),5547
5494 }),5548 maybeAdvanceSourceCursorToMainToken(gz, node);
5495 else => return rvalue(gz, ri, try gz.addPlNode(.elem_val_node, node, Zir.Inst.Bin{5549 const line = gz.astgen.source_line - gz.decl_line;
5496 .lhs = try expr(gz, scope, .{ .rl = .none }, node_datas[node].lhs),5550 const column = gz.astgen.source_column;
5497 .rhs = try expr(gz, scope, .{ .rl = .{ .ty = .usize_type } }, node_datas[node].rhs),5551
5498 }), node),5552 const rhs = try expr(gz, scope, .{ .rl = .{ .ty = .usize_type } }, node_datas[node].rhs);
5553 try emitDbgStmt(gz, line, column);
5554
5555 return gz.addPlNode(.elem_ptr_node, node, Zir.Inst.Bin{ .lhs = lhs, .rhs = rhs });
5556 },
5557 else => {
5558 const lhs = try expr(gz, scope, .{ .rl = .none }, node_datas[node].lhs);
5559
5560 maybeAdvanceSourceCursorToMainToken(gz, node);
5561 const line = gz.astgen.source_line - gz.decl_line;
5562 const column = gz.astgen.source_column;
5563
5564 const rhs = try expr(gz, scope, .{ .rl = .{ .ty = .usize_type } }, node_datas[node].rhs);
5565 try emitDbgStmt(gz, line, column);
5566
5567 return rvalue(gz, ri, try gz.addPlNode(.elem_val_node, node, Zir.Inst.Bin{ .lhs = lhs, .rhs = rhs }), node);
5568 },
5499 }5569 }
5500}5570}
55015571
...@@ -5510,10 +5580,26 @@ fn simpleBinOp(...@@ -5510,10 +5580,26 @@ fn simpleBinOp(
5510 const tree = astgen.tree;5580 const tree = astgen.tree;
5511 const node_datas = tree.nodes.items(.data);5581 const node_datas = tree.nodes.items(.data);
55125582
5513 const result = try gz.addPlNode(op_inst_tag, node, Zir.Inst.Bin{5583 const lhs = try reachableExpr(gz, scope, .{ .rl = .none }, node_datas[node].lhs, node);
5514 .lhs = try reachableExpr(gz, scope, .{ .rl = .none }, node_datas[node].lhs, node),5584 var line: u32 = undefined;
5515 .rhs = try reachableExpr(gz, scope, .{ .rl = .none }, node_datas[node].rhs, node),5585 var column: u32 = undefined;
5516 });5586 switch (op_inst_tag) {
5587 .add, .sub, .mul, .div, .mod_rem => {
5588 maybeAdvanceSourceCursorToMainToken(gz, node);
5589 line = gz.astgen.source_line - gz.decl_line;
5590 column = gz.astgen.source_column;
5591 },
5592 else => {},
5593 }
5594 const rhs = try reachableExpr(gz, scope, .{ .rl = .none }, node_datas[node].rhs, node);
5595
5596 switch (op_inst_tag) {
5597 .add, .sub, .mul, .div, .mod_rem => {
5598 try emitDbgStmt(gz, line, column);
5599 },
5600 else => {},
5601 }
5602 const result = try gz.addPlNode(op_inst_tag, node, Zir.Inst.Bin{ .lhs = lhs, .rhs = rhs });
5517 return rvalue(gz, ri, result, node);5603 return rvalue(gz, ri, result, node);
5518}5604}
55195605
...@@ -5608,9 +5694,11 @@ fn ifExpr(...@@ -5608,9 +5694,11 @@ fn ifExpr(
5608 }5694 }
5609 };5695 };
56105696
5611 const condbr = try block_scope.addCondBr(.condbr, node);5697 const condbr_tag: Zir.Inst.Tag = if (parent_gz.force_comptime) .condbr_inline else .condbr;
5698 const condbr = try block_scope.addCondBr(condbr_tag, node);
56125699
5613 const block = try parent_gz.makeBlockInst(.block, node);5700 const block_tag: Zir.Inst.Tag = if (parent_gz.force_comptime) .block_inline else .block;
5701 const block = try parent_gz.makeBlockInst(block_tag, node);
5614 try block_scope.setBlockBody(block);5702 try block_scope.setBlockBody(block);
5615 // block_scope unstacked now, can add new instructions to parent_gz5703 // block_scope unstacked now, can add new instructions to parent_gz
5616 try parent_gz.instructions.append(astgen.gpa, block);5704 try parent_gz.instructions.append(astgen.gpa, block);
...@@ -7084,7 +7172,7 @@ fn localVarRef(...@@ -7084,7 +7172,7 @@ fn localVarRef(
7084 if (local_val.name == name_str_index) {7172 if (local_val.name == name_str_index) {
7085 // Locals cannot shadow anything, so we do not need to look for ambiguous7173 // Locals cannot shadow anything, so we do not need to look for ambiguous
7086 // references in this case.7174 // references in this case.
7087 if (ri.rl == .discard) {7175 if (ri.rl == .discard and ri.ctx == .assignment) {
7088 local_val.discarded = ident_token;7176 local_val.discarded = ident_token;
7089 } else {7177 } else {
7090 local_val.used = ident_token;7178 local_val.used = ident_token;
...@@ -7107,7 +7195,7 @@ fn localVarRef(...@@ -7107,7 +7195,7 @@ fn localVarRef(
7107 .local_ptr => {7195 .local_ptr => {
7108 const local_ptr = s.cast(Scope.LocalPtr).?;7196 const local_ptr = s.cast(Scope.LocalPtr).?;
7109 if (local_ptr.name == name_str_index) {7197 if (local_ptr.name == name_str_index) {
7110 if (ri.rl == .discard) {7198 if (ri.rl == .discard and ri.ctx == .assignment) {
7111 local_ptr.discarded = ident_token;7199 local_ptr.discarded = ident_token;
7112 } else {7200 } else {
7113 local_ptr.used = ident_token;7201 local_ptr.used = ident_token;
...@@ -7969,6 +8057,8 @@ fn builtinCall(...@@ -7969,6 +8057,8 @@ fn builtinCall(
7969 return rvalue(gz, ri, result, node);8057 return rvalue(gz, ri, result, node);
7970 },8058 },
7971 .err_set_cast => {8059 .err_set_cast => {
8060 try emitDbgNode(gz, node);
8061
7972 const result = try gz.addExtendedPayload(.err_set_cast, Zir.Inst.BinNode{8062 const result = try gz.addExtendedPayload(.err_set_cast, Zir.Inst.BinNode{
7973 .lhs = try typeExpr(gz, scope, params[0]),8063 .lhs = try typeExpr(gz, scope, params[0]),
7974 .rhs = try expr(gz, scope, .{ .rl = .none }, params[1]),8064 .rhs = try expr(gz, scope, .{ .rl = .none }, params[1]),
...@@ -8274,6 +8364,8 @@ fn typeCast(...@@ -8274,6 +8364,8 @@ fn typeCast(
8274 rhs_node: Ast.Node.Index,8364 rhs_node: Ast.Node.Index,
8275 tag: Zir.Inst.Tag,8365 tag: Zir.Inst.Tag,
8276) InnerError!Zir.Inst.Ref {8366) InnerError!Zir.Inst.Ref {
8367 try emitDbgNode(gz, node);
8368
8277 const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{8369 const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{
8278 .lhs = try typeExpr(gz, scope, lhs_node),8370 .lhs = try typeExpr(gz, scope, lhs_node),
8279 .rhs = try expr(gz, scope, .{ .rl = .none }, rhs_node),8371 .rhs = try expr(gz, scope, .{ .rl = .none }, rhs_node),
...@@ -8303,6 +8395,10 @@ fn simpleUnOp(...@@ -8303,6 +8395,10 @@ fn simpleUnOp(
8303 operand_node: Ast.Node.Index,8395 operand_node: Ast.Node.Index,
8304 tag: Zir.Inst.Tag,8396 tag: Zir.Inst.Tag,
8305) InnerError!Zir.Inst.Ref {8397) InnerError!Zir.Inst.Ref {
8398 switch (tag) {
8399 .tag_name, .error_name, .ptr_to_int => try emitDbgNode(gz, node),
8400 else => {},
8401 }
8306 const operand = try expr(gz, scope, operand_ri, operand_node);8402 const operand = try expr(gz, scope, operand_ri, operand_node);
8307 const result = try gz.addUnNode(tag, operand, node);8403 const result = try gz.addUnNode(tag, operand, node);
8308 return rvalue(gz, ri, result, node);8404 return rvalue(gz, ri, result, node);
...@@ -8375,6 +8471,8 @@ fn divBuiltin(...@@ -8375,6 +8471,8 @@ fn divBuiltin(
8375 rhs_node: Ast.Node.Index,8471 rhs_node: Ast.Node.Index,
8376 tag: Zir.Inst.Tag,8472 tag: Zir.Inst.Tag,
8377) InnerError!Zir.Inst.Ref {8473) InnerError!Zir.Inst.Ref {
8474 try emitDbgNode(gz, node);
8475
8378 const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{8476 const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{
8379 .lhs = try expr(gz, scope, .{ .rl = .none }, lhs_node),8477 .lhs = try expr(gz, scope, .{ .rl = .none }, lhs_node),
8380 .rhs = try expr(gz, scope, .{ .rl = .none }, rhs_node),8478 .rhs = try expr(gz, scope, .{ .rl = .none }, rhs_node),
...@@ -8428,8 +8526,15 @@ fn shiftOp(...@@ -8428,8 +8526,15 @@ fn shiftOp(
8428 tag: Zir.Inst.Tag,8526 tag: Zir.Inst.Tag,
8429) InnerError!Zir.Inst.Ref {8527) InnerError!Zir.Inst.Ref {
8430 const lhs = try expr(gz, scope, .{ .rl = .none }, lhs_node);8528 const lhs = try expr(gz, scope, .{ .rl = .none }, lhs_node);
8529
8530 maybeAdvanceSourceCursorToMainToken(gz, node);
8531 const line = gz.astgen.source_line - gz.decl_line;
8532 const column = gz.astgen.source_column;
8533
8431 const log2_int_type = try gz.addUnNode(.typeof_log2_int_type, lhs, lhs_node);8534 const log2_int_type = try gz.addUnNode(.typeof_log2_int_type, lhs, lhs_node);
8432 const rhs = try expr(gz, scope, .{ .rl = .{ .ty = log2_int_type }, .ctx = .shift_op }, rhs_node);8535 const rhs = try expr(gz, scope, .{ .rl = .{ .ty = log2_int_type }, .ctx = .shift_op }, rhs_node);
8536
8537 try emitDbgStmt(gz, line, column);
8433 const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{8538 const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{
8434 .lhs = lhs,8539 .lhs = lhs,
8435 .rhs = rhs,8540 .rhs = rhs,
...@@ -10668,14 +10773,19 @@ const GenZir = struct {...@@ -10668,14 +10773,19 @@ const GenZir = struct {
10668 gz.break_result_info = parent_ri;10773 gz.break_result_info = parent_ri;
10669 },10774 },
1067010775
10671 .discard, .none, .ref => {10776 .none, .ref => {
10672 gz.rl_ty_inst = .none;10777 gz.rl_ty_inst = .none;
10673 gz.break_result_info = parent_ri;10778 gz.break_result_info = parent_ri;
10674 },10779 },
1067510780
10781 .discard => {
10782 gz.rl_ty_inst = .none;
10783 gz.break_result_info = .{ .rl = .discard };
10784 },
10785
10676 .ptr => |ptr_res| {10786 .ptr => |ptr_res| {
10677 gz.rl_ty_inst = .none;10787 gz.rl_ty_inst = .none;
10678 gz.break_result_info = .{ .rl = .{ .ptr = .{ .inst = ptr_res.inst } } };10788 gz.break_result_info = .{ .rl = .{ .ptr = .{ .inst = ptr_res.inst } }, .ctx = parent_ri.ctx };
10679 },10789 },
1068010790
10681 .inferred_ptr => |ptr| {10791 .inferred_ptr => |ptr| {
...@@ -12054,6 +12164,18 @@ fn detectLocalShadowing(...@@ -12054,6 +12164,18 @@ fn detectLocalShadowing(
12054 };12164 };
12055}12165}
1205612166
12167/// Advances the source cursor to the main token of `node` if not in comptime scope.
12168/// Usually paired with `emitDbgStmt`.
12169fn maybeAdvanceSourceCursorToMainToken(gz: *GenZir, node: Ast.Node.Index) void {
12170 if (gz.force_comptime) return;
12171
12172 const tree = gz.astgen.tree;
12173 const token_starts = tree.tokens.items(.start);
12174 const main_tokens = tree.nodes.items(.main_token);
12175 const node_start = token_starts[main_tokens[node]];
12176 gz.astgen.advanceSourceCursor(node_start);
12177}
12178
12057/// Advances the source cursor to the beginning of `node`.12179/// Advances the source cursor to the beginning of `node`.
12058fn advanceSourceCursorToNode(astgen: *AstGen, node: Ast.Node.Index) void {12180fn advanceSourceCursorToNode(astgen: *AstGen, node: Ast.Node.Index) void {
12059 const tree = astgen.tree;12181 const tree = astgen.tree;
src/Autodoc.zig+12-3
...@@ -2129,7 +2129,15 @@ fn walkInstruction(...@@ -2129,7 +2129,15 @@ fn walkInstruction(
2129 file,2129 file,
2130 parent_scope,2130 parent_scope,
2131 parent_src,2131 parent_src,
2132 getBlockInlineBreak(file.zir, inst_index),2132 getBlockInlineBreak(file.zir, inst_index) orelse {
2133 const res = DocData.WalkResult{ .expr = .{
2134 .comptimeExpr = self.comptime_exprs.items.len,
2135 } };
2136 try self.comptime_exprs.append(self.arena, .{
2137 .code = "if (...) { ... }",
2138 });
2139 return res;
2140 },
2133 need_type,2141 need_type,
2134 );2142 );
2135 },2143 },
...@@ -3155,7 +3163,7 @@ fn walkDecls(...@@ -3155,7 +3163,7 @@ fn walkDecls(
3155 2 => {3163 2 => {
3156 // decl test3164 // decl test
3157 const decl_being_tested = scope.resolveDeclName(doc_comment_index);3165 const decl_being_tested = scope.resolveDeclName(doc_comment_index);
3158 const func_index = getBlockInlineBreak(file.zir, value_index);3166 const func_index = getBlockInlineBreak(file.zir, value_index).?;
31593167
3160 const pl_node = data[Zir.refToIndex(func_index).?].pl_node;3168 const pl_node = data[Zir.refToIndex(func_index).?].pl_node;
3161 const fn_src = try self.srcLocInfo(file, pl_node.src_node, decl_src);3169 const fn_src = try self.srcLocInfo(file, pl_node.src_node, decl_src);
...@@ -4301,12 +4309,13 @@ fn walkRef(...@@ -4301,12 +4309,13 @@ fn walkRef(
4301 }4309 }
4302}4310}
43034311
4304fn getBlockInlineBreak(zir: Zir, inst_index: usize) Zir.Inst.Ref {4312fn getBlockInlineBreak(zir: Zir, inst_index: usize) ?Zir.Inst.Ref {
4305 const tags = zir.instructions.items(.tag);4313 const tags = zir.instructions.items(.tag);
4306 const data = zir.instructions.items(.data);4314 const data = zir.instructions.items(.data);
4307 const pl_node = data[inst_index].pl_node;4315 const pl_node = data[inst_index].pl_node;
4308 const extra = zir.extraData(Zir.Inst.Block, pl_node.payload_index);4316 const extra = zir.extraData(Zir.Inst.Block, pl_node.payload_index);
4309 const break_index = zir.extra[extra.end..][extra.data.body_len - 1];4317 const break_index = zir.extra[extra.end..][extra.data.body_len - 1];
4318 if (tags[break_index] == .condbr_inline) return null;
4310 std.debug.assert(tags[break_index] == .break_inline);4319 std.debug.assert(tags[break_index] == .break_inline);
4311 return data[break_index].@"break".operand;4320 return data[break_index].@"break".operand;
4312}4321}
src/Sema.zig+9-12
...@@ -1491,6 +1491,8 @@ fn analyzeBodyInner(...@@ -1491,6 +1491,8 @@ fn analyzeBodyInner(
1491 return err;1491 return err;
1492 };1492 };
1493 const inline_body = if (cond.val.toBool()) then_body else else_body;1493 const inline_body = if (cond.val.toBool()) then_body else else_body;
1494
1495 try sema.maybeErrorUnwrapCondbr(block, inline_body, extra.data.condition, cond_src);
1494 const old_runtime_index = block.runtime_index;1496 const old_runtime_index = block.runtime_index;
1495 defer block.runtime_index = old_runtime_index;1497 defer block.runtime_index = old_runtime_index;
1496 const break_data = (try sema.analyzeBodyBreak(block, inline_body)) orelse1498 const break_data = (try sema.analyzeBodyBreak(block, inline_body)) orelse
...@@ -5658,14 +5660,14 @@ fn lookupInNamespace(...@@ -5658,14 +5660,14 @@ fn lookupInNamespace(
5658 const src_file = block.namespace.file_scope;5660 const src_file = block.namespace.file_scope;
56595661
5660 const gpa = sema.gpa;5662 const gpa = sema.gpa;
5661 var checked_namespaces: std.AutoArrayHashMapUnmanaged(*Namespace, void) = .{};5663 var checked_namespaces: std.AutoArrayHashMapUnmanaged(*Namespace, bool) = .{};
5662 defer checked_namespaces.deinit(gpa);5664 defer checked_namespaces.deinit(gpa);
56635665
5664 // Keep track of name conflicts for error notes.5666 // Keep track of name conflicts for error notes.
5665 var candidates: std.ArrayListUnmanaged(Decl.Index) = .{};5667 var candidates: std.ArrayListUnmanaged(Decl.Index) = .{};
5666 defer candidates.deinit(gpa);5668 defer candidates.deinit(gpa);
56675669
5668 try checked_namespaces.put(gpa, namespace, {});5670 try checked_namespaces.put(gpa, namespace, namespace.file_scope == src_file);
5669 var check_i: usize = 0;5671 var check_i: usize = 0;
56705672
5671 while (check_i < checked_namespaces.count()) : (check_i += 1) {5673 while (check_i < checked_namespaces.count()) : (check_i += 1) {
...@@ -5674,7 +5676,7 @@ fn lookupInNamespace(...@@ -5674,7 +5676,7 @@ fn lookupInNamespace(
5674 // Skip decls which are not marked pub, which are in a different5676 // Skip decls which are not marked pub, which are in a different
5675 // file than the `a.b`/`@hasDecl` syntax.5677 // file than the `a.b`/`@hasDecl` syntax.
5676 const decl = mod.declPtr(decl_index);5678 const decl = mod.declPtr(decl_index);
5677 if (decl.is_pub or src_file == decl.getFileScope()) {5679 if (decl.is_pub or (src_file == decl.getFileScope() and checked_namespaces.values()[check_i])) {
5678 try candidates.append(gpa, decl_index);5680 try candidates.append(gpa, decl_index);
5679 }5681 }
5680 }5682 }
...@@ -5693,7 +5695,7 @@ fn lookupInNamespace(...@@ -5693,7 +5695,7 @@ fn lookupInNamespace(
5693 try sema.ensureDeclAnalyzed(sub_usingnamespace_decl_index);5695 try sema.ensureDeclAnalyzed(sub_usingnamespace_decl_index);
5694 const ns_ty = sub_usingnamespace_decl.val.castTag(.ty).?.data;5696 const ns_ty = sub_usingnamespace_decl.val.castTag(.ty).?.data;
5695 const sub_ns = ns_ty.getNamespace().?;5697 const sub_ns = ns_ty.getNamespace().?;
5696 try checked_namespaces.put(gpa, sub_ns, {});5698 try checked_namespaces.put(gpa, sub_ns, src_file == sub_usingnamespace_decl.getFileScope());
5697 }5699 }
5698 }5700 }
56995701
...@@ -6331,6 +6333,7 @@ fn analyzeCall(...@@ -6331,6 +6333,7 @@ fn analyzeCall(
6331 .instructions = .{},6333 .instructions = .{},
6332 .label = null,6334 .label = null,
6333 .inlining = &inlining,6335 .inlining = &inlining,
6336 .is_typeof = block.is_typeof,
6334 .is_comptime = is_comptime_call,6337 .is_comptime = is_comptime_call,
6335 .comptime_reason = comptime_reason,6338 .comptime_reason = comptime_reason,
6336 .error_return_trace_index = block.error_return_trace_index,6339 .error_return_trace_index = block.error_return_trace_index,
...@@ -16530,9 +16533,6 @@ fn zirSaveErrRetIndex(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE...@@ -16530,9 +16533,6 @@ fn zirSaveErrRetIndex(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
16530 // This is only relevant at runtime.16533 // This is only relevant at runtime.
16531 if (block.is_comptime or block.is_typeof) return;16534 if (block.is_comptime or block.is_typeof) return;
1653216535
16533 // This is only relevant within functions.
16534 if (sema.func == null) return;
16535
16536 const save_index = inst_data.operand == .none or b: {16536 const save_index = inst_data.operand == .none or b: {
16537 const operand = try sema.resolveInst(inst_data.operand);16537 const operand = try sema.resolveInst(inst_data.operand);
16538 const operand_ty = sema.typeOf(operand);16538 const operand_ty = sema.typeOf(operand);
...@@ -20179,8 +20179,8 @@ fn analyzeShuffle(...@@ -20179,8 +20179,8 @@ fn analyzeShuffle(
20179 .elem_type = elem_ty,20179 .elem_type = elem_ty,
20180 });20180 });
2018120181
20182 if (maybe_a_len == null) a = try sema.addConstUndef(a_ty);20182 if (maybe_a_len == null) a = try sema.addConstUndef(a_ty) else a = try sema.coerce(block, a_ty, a, a_src);
20183 if (maybe_b_len == null) b = try sema.addConstUndef(b_ty);20183 if (maybe_b_len == null) b = try sema.addConstUndef(b_ty) else b = try sema.coerce(block, b_ty, b, b_src);
2018420184
20185 const operand_info = [2]std.meta.Tuple(&.{ u64, LazySrcLoc, Type }){20185 const operand_info = [2]std.meta.Tuple(&.{ u64, LazySrcLoc, Type }){
20186 .{ a_len, a_src, a_ty },20186 .{ a_len, a_src, a_ty },
...@@ -27503,9 +27503,6 @@ fn analyzeLoad(...@@ -27503,9 +27503,6 @@ fn analyzeLoad(
27503 if (try sema.pointerDeref(block, src, ptr_val, ptr_ty)) |elem_val| {27503 if (try sema.pointerDeref(block, src, ptr_val, ptr_ty)) |elem_val| {
27504 return sema.addConstant(elem_ty, elem_val);27504 return sema.addConstant(elem_ty, elem_val);
27505 }27505 }
27506 if (block.is_typeof) {
27507 return sema.addConstUndef(elem_ty);
27508 }
27509 }27506 }
2751027507
27511 return block.addTyOp(.load, elem_ty, ptr);27508 return block.addTyOp(.load, elem_ty, ptr);
src/codegen/llvm.zig+17-14
...@@ -1966,7 +1966,7 @@ pub const Object = struct {...@@ -1966,7 +1966,7 @@ pub const Object = struct {
19661966
1967 for (tuple.types) |field_ty, i| {1967 for (tuple.types) |field_ty, i| {
1968 const field_val = tuple.values[i];1968 const field_val = tuple.values[i];
1969 if (field_val.tag() != .unreachable_value) continue;1969 if (field_val.tag() != .unreachable_value or !field_ty.hasRuntimeBits()) continue;
19701970
1971 const field_size = field_ty.abiSize(target);1971 const field_size = field_ty.abiSize(target);
1972 const field_align = field_ty.abiAlignment(target);1972 const field_align = field_ty.abiAlignment(target);
...@@ -2901,7 +2901,7 @@ pub const DeclGen = struct {...@@ -2901,7 +2901,7 @@ pub const DeclGen = struct {
29012901
2902 for (tuple.types) |field_ty, i| {2902 for (tuple.types) |field_ty, i| {
2903 const field_val = tuple.values[i];2903 const field_val = tuple.values[i];
2904 if (field_val.tag() != .unreachable_value) continue;2904 if (field_val.tag() != .unreachable_value or !field_ty.hasRuntimeBits()) continue;
29052905
2906 const field_align = field_ty.abiAlignment(target);2906 const field_align = field_ty.abiAlignment(target);
2907 big_align = @max(big_align, field_align);2907 big_align = @max(big_align, field_align);
...@@ -3198,7 +3198,8 @@ pub const DeclGen = struct {...@@ -3198,7 +3198,8 @@ pub const DeclGen = struct {
3198 /// There are other similar cases handled here as well.3198 /// There are other similar cases handled here as well.
3199 fn lowerPtrElemTy(dg: *DeclGen, elem_ty: Type) Allocator.Error!*llvm.Type {3199 fn lowerPtrElemTy(dg: *DeclGen, elem_ty: Type) Allocator.Error!*llvm.Type {
3200 const lower_elem_ty = switch (elem_ty.zigTypeTag()) {3200 const lower_elem_ty = switch (elem_ty.zigTypeTag()) {
3201 .Opaque, .Fn => true,3201 .Opaque => true,
3202 .Fn => !elem_ty.fnInfo().is_generic,
3202 .Array => elem_ty.childType().hasRuntimeBitsIgnoreComptime(),3203 .Array => elem_ty.childType().hasRuntimeBitsIgnoreComptime(),
3203 else => elem_ty.hasRuntimeBitsIgnoreComptime(),3204 else => elem_ty.hasRuntimeBitsIgnoreComptime(),
3204 };3205 };
...@@ -4145,7 +4146,9 @@ pub const DeclGen = struct {...@@ -4145,7 +4146,9 @@ pub const DeclGen = struct {
4145 }4146 }
41464147
4147 const is_fn_body = decl.ty.zigTypeTag() == .Fn;4148 const is_fn_body = decl.ty.zigTypeTag() == .Fn;
4148 if (!is_fn_body and !decl.ty.hasRuntimeBits()) {4149 if ((!is_fn_body and !decl.ty.hasRuntimeBits()) or
4150 (is_fn_body and decl.ty.fnInfo().is_generic))
4151 {
4149 return self.lowerPtrToVoid(tv.ty);4152 return self.lowerPtrToVoid(tv.ty);
4150 }4153 }
41514154
...@@ -8671,9 +8674,9 @@ pub const FuncGen = struct {...@@ -8671,9 +8674,9 @@ pub const FuncGen = struct {
8671 const arena = arena_allocator.allocator();8674 const arena = arena_allocator.allocator();
86728675
8673 const mod = self.dg.module;8676 const mod = self.dg.module;
8674 const llvm_fn_name = try std.fmt.allocPrintZ(arena, "__zig_is_named_enum_value_{s}", .{8677 const fqn = try mod.declPtr(enum_decl).getFullyQualifiedName(mod);
8675 try mod.declPtr(enum_decl).getFullyQualifiedName(mod),8678 defer self.gpa.free(fqn);
8676 });8679 const llvm_fn_name = try std.fmt.allocPrintZ(arena, "__zig_is_named_enum_value_{s}", .{fqn});
86778680
8678 var int_tag_type_buffer: Type.Payload.Bits = undefined;8681 var int_tag_type_buffer: Type.Payload.Bits = undefined;
8679 const int_tag_ty = enum_ty.intTagType(&int_tag_type_buffer);8682 const int_tag_ty = enum_ty.intTagType(&int_tag_type_buffer);
...@@ -8752,9 +8755,9 @@ pub const FuncGen = struct {...@@ -8752,9 +8755,9 @@ pub const FuncGen = struct {
8752 const arena = arena_allocator.allocator();8755 const arena = arena_allocator.allocator();
87538756
8754 const mod = self.dg.module;8757 const mod = self.dg.module;
8755 const llvm_fn_name = try std.fmt.allocPrintZ(arena, "__zig_tag_name_{s}", .{8758 const fqn = try mod.declPtr(enum_decl).getFullyQualifiedName(mod);
8756 try mod.declPtr(enum_decl).getFullyQualifiedName(mod),8759 defer self.gpa.free(fqn);
8757 });8760 const llvm_fn_name = try std.fmt.allocPrintZ(arena, "__zig_tag_name_{s}", .{fqn});
87588761
8759 const slice_ty = Type.initTag(.const_slice_u8_sentinel_0);8762 const slice_ty = Type.initTag(.const_slice_u8_sentinel_0);
8760 const llvm_ret_ty = try self.dg.lowerType(slice_ty);8763 const llvm_ret_ty = try self.dg.lowerType(slice_ty);
...@@ -10204,7 +10207,7 @@ fn llvmFieldIndex(...@@ -10204,7 +10207,7 @@ fn llvmFieldIndex(
10204 const tuple = ty.tupleFields();10207 const tuple = ty.tupleFields();
10205 var llvm_field_index: c_uint = 0;10208 var llvm_field_index: c_uint = 0;
10206 for (tuple.types) |field_ty, i| {10209 for (tuple.types) |field_ty, i| {
10207 if (tuple.values[i].tag() != .unreachable_value) continue;10210 if (tuple.values[i].tag() != .unreachable_value or !field_ty.hasRuntimeBits()) continue;
1020810211
10209 const field_align = field_ty.abiAlignment(target);10212 const field_align = field_ty.abiAlignment(target);
10210 big_align = @max(big_align, field_align);10213 big_align = @max(big_align, field_align);
...@@ -10216,7 +10219,7 @@ fn llvmFieldIndex(...@@ -10216,7 +10219,7 @@ fn llvmFieldIndex(
10216 llvm_field_index += 1;10219 llvm_field_index += 1;
10217 }10220 }
1021810221
10219 if (field_index == i) {10222 if (field_index <= i) {
10220 ptr_pl_buf.* = .{10223 ptr_pl_buf.* = .{
10221 .data = .{10224 .data = .{
10222 .pointee_type = field_ty,10225 .pointee_type = field_ty,
...@@ -10249,7 +10252,7 @@ fn llvmFieldIndex(...@@ -10249,7 +10252,7 @@ fn llvmFieldIndex(
10249 llvm_field_index += 1;10252 llvm_field_index += 1;
10250 }10253 }
1025110254
10252 if (field_index == i) {10255 if (field_index <= i) {
10253 ptr_pl_buf.* = .{10256 ptr_pl_buf.* = .{
10254 .data = .{10257 .data = .{
10255 .pointee_type = field.ty,10258 .pointee_type = field.ty,
...@@ -10768,7 +10771,7 @@ fn isByRef(ty: Type) bool {...@@ -10768,7 +10771,7 @@ fn isByRef(ty: Type) bool {
10768 const tuple = ty.tupleFields();10771 const tuple = ty.tupleFields();
10769 var count: usize = 0;10772 var count: usize = 0;
10770 for (tuple.values) |field_val, i| {10773 for (tuple.values) |field_val, i| {
10771 if (field_val.tag() != .unreachable_value) continue;10774 if (field_val.tag() != .unreachable_value or !tuple.types[i].hasRuntimeBits()) continue;
1077210775
10773 count += 1;10776 count += 1;
10774 if (count > max_fields_byval) return true;10777 if (count > max_fields_byval) return true;
src/type.zig+4-2
...@@ -640,7 +640,9 @@ pub const Type = extern union {...@@ -640,7 +640,9 @@ pub const Type = extern union {
640 const a_info = a.fnInfo();640 const a_info = a.fnInfo();
641 const b_info = b.fnInfo();641 const b_info = b.fnInfo();
642642
643 if (!eql(a_info.return_type, b_info.return_type, mod))643 if (a_info.return_type.tag() != .generic_poison and
644 b_info.return_type.tag() != .generic_poison and
645 !eql(a_info.return_type, b_info.return_type, mod))
644 return false;646 return false;
645647
646 if (a_info.is_var_args != b_info.is_var_args)648 if (a_info.is_var_args != b_info.is_var_args)
...@@ -5757,7 +5759,7 @@ pub const Type = extern union {...@@ -5757,7 +5759,7 @@ pub const Type = extern union {
57575759
5758 for (tuple.types) |field_ty, i| {5760 for (tuple.types) |field_ty, i| {
5759 const field_val = tuple.values[i];5761 const field_val = tuple.values[i];
5760 if (field_val.tag() != .unreachable_value) {5762 if (field_val.tag() != .unreachable_value or !field_ty.hasRuntimeBits()) {
5761 // comptime field5763 // comptime field
5762 if (i == index) return offset;5764 if (i == index) return offset;
5763 continue;5765 continue;
test/behavior/eval.zig+8
...@@ -1499,3 +1499,11 @@ test "non-optional and optional array elements concatenated" {...@@ -1499,3 +1499,11 @@ test "non-optional and optional array elements concatenated" {
1499 var index: usize = 0;1499 var index: usize = 0;
1500 try expect(array[index].? == 'A');1500 try expect(array[index].? == 'A');
1501}1501}
1502
1503test "inline call in @TypeOf inherits is_inline property" {
1504 const S = struct {
1505 inline fn doNothing() void {}
1506 const T = @TypeOf(doNothing());
1507 };
1508 try expect(S.T == void);
1509}
test/behavior/generics.zig+12
...@@ -405,3 +405,15 @@ test "null sentinel pointer passed as generic argument" {...@@ -405,3 +405,15 @@ test "null sentinel pointer passed as generic argument" {
405 };405 };
406 try S.doTheTest((@intToPtr([*:null]const [*c]const u8, 8)));406 try S.doTheTest((@intToPtr([*:null]const [*c]const u8, 8)));
407}407}
408
409test "generic function passed as comptime argument" {
410 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
411
412 const S = struct {
413 fn doMath(comptime f: fn (type, i32, i32) error{Overflow}!i32, a: i32, b: i32) !void {
414 const result = try f(i32, a, b);
415 try expect(result == 11);
416 }
417 };
418 try S.doMath(std.math.add, 5, 6);
419}
test/behavior/pointers.zig+17
...@@ -489,3 +489,20 @@ test "ptrCast comptime known slice to C pointer" {...@@ -489,3 +489,20 @@ test "ptrCast comptime known slice to C pointer" {
489 var p = @ptrCast([*c]const u8, s);489 var p = @ptrCast([*c]const u8, s);
490 try std.testing.expectEqualStrings(s, std.mem.sliceTo(p, 0));490 try std.testing.expectEqualStrings(s, std.mem.sliceTo(p, 0));
491}491}
492
493test "ptrToInt on a generic function" {
494 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
495 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
496 if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag != .linux) return error.SkipZigTest; // TODO
497 if (builtin.zig_backend == .stage2_x86_64 and builtin.os.tag != .linux) return error.SkipZigTest; // TODO
498
499 const S = struct {
500 fn generic(i: anytype) @TypeOf(i) {
501 return i;
502 }
503 fn doTheTest(a: anytype) !void {
504 try expect(@ptrToInt(a) != 0);
505 }
506 };
507 try S.doTheTest(&S.generic);
508}
test/behavior/struct.zig+20
...@@ -1398,3 +1398,23 @@ test "under-aligned struct field" {...@@ -1398,3 +1398,23 @@ test "under-aligned struct field" {
1398 const result = std.mem.readIntNative(u64, array[4..12]);1398 const result = std.mem.readIntNative(u64, array[4..12]);
1399 try expect(result == 1234);1399 try expect(result == 1234);
1400}1400}
1401
1402test "address of zero-bit field is equal to address of only field" {
1403 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1404 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1405 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1406 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1407
1408 {
1409 const A = struct { b: void = {}, u: u8 };
1410 var a = A{ .u = 0 };
1411 const a_ptr = @fieldParentPtr(A, "b", &a.b);
1412 try std.testing.expectEqual(&a, a_ptr);
1413 }
1414 {
1415 const A = struct { u: u8, b: void = {} };
1416 var a = A{ .u = 0 };
1417 const a_ptr = @fieldParentPtr(A, "b", &a.b);
1418 try std.testing.expectEqual(&a, a_ptr);
1419 }
1420}
test/behavior/tuple.zig+10
...@@ -323,3 +323,13 @@ test "zero sized struct in tuple handled correctly" {...@@ -323,3 +323,13 @@ test "zero sized struct in tuple handled correctly" {
323 var s: State = undefined;323 var s: State = undefined;
324 try expect(s.do() == 0);324 try expect(s.do() == 0);
325}325}
326
327test "tuple type with void field and a runtime field" {
328 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
329 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
330 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
331
332 const T = std.meta.Tuple(&[_]type{ usize, void });
333 var t: T = .{ 5, {} };
334 try expect(t[0] == 5);
335}
test/behavior/usingnamespace.zig+4
...@@ -75,3 +75,7 @@ test {...@@ -75,3 +75,7 @@ test {
75 const a = AA.b(42);75 const a = AA.b(42);
76 try expect(a.x == AA.c().expected);76 try expect(a.x == AA.c().expected);
77}77}
78
79comptime {
80 _ = @import("usingnamespace/file_1.zig");
81}
test/behavior/usingnamespace/file_0.zig created+1
...@@ -0,0 +1 @@
1pub const A = 123;
test/behavior/usingnamespace/file_1.zig created+9
...@@ -0,0 +1,9 @@
1const std = @import("std");
2const expect = std.testing.expect;
3const imports = @import("imports.zig");
4
5const A = 456;
6
7test {
8 try expect(imports.A == 123);
9}
test/behavior/usingnamespace/imports.zig created+5
...@@ -0,0 +1,5 @@
1const file_0 = @import("file_0.zig");
2const file_1 = @import("file_1.zig");
3
4pub usingnamespace file_0;
5pub usingnamespace file_1;
test/behavior/vector.zig+15
...@@ -3,6 +3,7 @@ const builtin = @import("builtin");...@@ -3,6 +3,7 @@ const builtin = @import("builtin");
3const mem = std.mem;3const mem = std.mem;
4const math = std.math;4const math = std.math;
5const expect = std.testing.expect;5const expect = std.testing.expect;
6const expectEqual = std.testing.expectEqual;
67
7test "implicit cast vector to array - bool" {8test "implicit cast vector to array - bool" {
8 if (builtin.zig_backend == .stage1) {9 if (builtin.zig_backend == .stage1) {
...@@ -1231,3 +1232,17 @@ test "modRem with zero divisor" {...@@ -1231,3 +1232,17 @@ test "modRem with zero divisor" {
1231 _ = zeros[0];1232 _ = zeros[0];
1232 }1233 }
1233}1234}
1235
1236test "array operands to shuffle are coerced to vectors" {
1237 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1238 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1239 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1240 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1241 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1242
1243 const mask = [5]i32{ -1, 0, 1, 2, 3 };
1244
1245 var a = [5]u32{ 3, 5, 7, 9, 0 };
1246 var b = @shuffle(u32, a, @splat(5, @as(u24, 0)), mask);
1247 try expectEqual([_]u32{ 0, 3, 5, 7, 9 }, b);
1248}
test/cases/compile_errors/branch_in_comptime_only_scope_uses_condbr_inline.zig created+22
...@@ -0,0 +1,22 @@
1pub export fn entry1() void {
2 var x: u32 = 3;
3 _ = @shuffle(u32, [_]u32{0}, @splat(1, @as(u32, 0)), [_]i8{
4 if (x > 1) 1 else -1,
5 });
6}
7
8pub export fn entry2() void {
9 var y: ?i8 = -1;
10 _ = @shuffle(u32, [_]u32{0}, @splat(1, @as(u32, 0)), [_]i8{
11 y orelse 1,
12 });
13}
14
15// error
16// backend=stage2
17// target=native
18//
19// :4:15: error: unable to resolve comptime value
20// :4:15: note: condition in comptime branch must be comptime-known
21// :11:11: error: unable to resolve comptime value
22// :11:11: note: condition in comptime branch must be comptime-known
test/cases/compile_errors/pointless discard.zig +8
...@@ -3,6 +3,14 @@ export fn foo() void {...@@ -3,6 +3,14 @@ export fn foo() void {
3 x += 1;3 x += 1;
4 _ = x;4 _ = x;
5}5}
6export fn bar() void {
7 var b: u32 = 1;
8 _ = blk: {
9 const a = 1;
10 b = a;
11 break :blk a;
12 };
13}
614
7// error15// error
8// backend=stage216// backend=stage2