| author | |
| committer | |
| log | f5b99abc93b44239e95378d9958e72999abb6b44 |
| tree | d18a9199d13c761b986d885dc7e4105559c13541 |
| parent | 50139aa23245c7b6b6a5faff95f1a2c854051a38 |
| parent | 13e472aa2a8113df6417c09727297a6106127f8e |
| signature |
Add error for unused/duplicate labels.11 files changed, 264 insertions(+), 102 deletions(-)
lib/std/dwarf.zig+1-1| ... | ... | @@ -322,7 +322,7 @@ fn parseFormValue(allocator: *mem.Allocator, in_stream: anytype, form_id: u64, e |
| 322 | 322 | FORM_block1 => parseFormValueBlock(allocator, in_stream, endian, 1), |
| 323 | 323 | FORM_block2 => parseFormValueBlock(allocator, in_stream, endian, 2), |
| 324 | 324 | FORM_block4 => parseFormValueBlock(allocator, in_stream, endian, 4), |
| 325 | FORM_block => x: { | |
| 325 | FORM_block => { | |
| 326 | 326 | const block_len = try nosuspend leb.readULEB128(usize, in_stream); |
| 327 | 327 | return parseFormValueBlockLen(allocator, in_stream, block_len); |
| 328 | 328 | }, |
lib/std/hash/auto_hash.zig+1-1| ... | ... | @@ -129,7 +129,7 @@ pub fn hash(hasher: anytype, key: anytype, comptime strat: HashStrategy) void { |
| 129 | 129 | } |
| 130 | 130 | }, |
| 131 | 131 | |
| 132 | .Union => |info| blk: { | |
| 132 | .Union => |info| { | |
| 133 | 133 | if (info.tag_type) |tag_type| { |
| 134 | 134 | const tag = meta.activeTag(key); |
| 135 | 135 | const s = hash(hasher, tag, strat); |
lib/std/special/c.zig+3-3| ... | ... | @@ -536,7 +536,7 @@ fn generic_fmod(comptime T: type, x: T, y: T) T { |
| 536 | 536 | // normalize x and y |
| 537 | 537 | if (ex == 0) { |
| 538 | 538 | i = ux << exp_bits; |
| 539 | while (i >> bits_minus_1 == 0) : (b: { | |
| 539 | while (i >> bits_minus_1 == 0) : ({ | |
| 540 | 540 | ex -= 1; |
| 541 | 541 | i <<= 1; |
| 542 | 542 | }) {} |
| ... | ... | @@ -547,7 +547,7 @@ fn generic_fmod(comptime T: type, x: T, y: T) T { |
| 547 | 547 | } |
| 548 | 548 | if (ey == 0) { |
| 549 | 549 | i = uy << exp_bits; |
| 550 | while (i >> bits_minus_1 == 0) : (b: { | |
| 550 | while (i >> bits_minus_1 == 0) : ({ | |
| 551 | 551 | ey -= 1; |
| 552 | 552 | i <<= 1; |
| 553 | 553 | }) {} |
| ... | ... | @@ -573,7 +573,7 @@ fn generic_fmod(comptime T: type, x: T, y: T) T { |
| 573 | 573 | return 0 * x; |
| 574 | 574 | ux = i; |
| 575 | 575 | } |
| 576 | while (ux >> digits == 0) : (b: { | |
| 576 | while (ux >> digits == 0) : ({ | |
| 577 | 577 | ux <<= 1; |
| 578 | 578 | ex -= 1; |
| 579 | 579 | }) {} |
lib/std/zig/render.zig+1-1| ... | ... | @@ -2385,7 +2385,7 @@ fn renderTokenOffset( |
| 2385 | 2385 | } |
| 2386 | 2386 | } |
| 2387 | 2387 | |
| 2388 | if (next_token_id != .LineComment) blk: { | |
| 2388 | if (next_token_id != .LineComment) { | |
| 2389 | 2389 | switch (space) { |
| 2390 | 2390 | Space.None, Space.NoNewline => return, |
| 2391 | 2391 | Space.Newline => { |
src-self-hosted/Module.zig+2-2| ... | ... | @@ -2811,7 +2811,7 @@ pub fn floatAdd(self: *Module, scope: *Scope, float_type: Type, src: usize, lhs: |
| 2811 | 2811 | val_payload.* = .{ .val = lhs_val + rhs_val }; |
| 2812 | 2812 | break :blk &val_payload.base; |
| 2813 | 2813 | }, |
| 2814 | 128 => blk: { | |
| 2814 | 128 => { | |
| 2815 | 2815 | return self.fail(scope, src, "TODO Implement addition for big floats", .{}); |
| 2816 | 2816 | }, |
| 2817 | 2817 | else => unreachable, |
| ... | ... | @@ -2845,7 +2845,7 @@ pub fn floatSub(self: *Module, scope: *Scope, float_type: Type, src: usize, lhs: |
| 2845 | 2845 | val_payload.* = .{ .val = lhs_val - rhs_val }; |
| 2846 | 2846 | break :blk &val_payload.base; |
| 2847 | 2847 | }, |
| 2848 | 128 => blk: { | |
| 2848 | 128 => { | |
| 2849 | 2849 | return self.fail(scope, src, "TODO Implement substraction for big floats", .{}); |
| 2850 | 2850 | }, |
| 2851 | 2851 | else => unreachable, |
src-self-hosted/translate_c.zig+114-62| ... | ... | @@ -61,7 +61,8 @@ const Scope = struct { |
| 61 | 61 | pending_block: Block, |
| 62 | 62 | cases: []*ast.Node, |
| 63 | 63 | case_index: usize, |
| 64 | has_default: bool = false, | |
| 64 | switch_label: ?[]const u8, | |
| 65 | default_label: ?[]const u8, | |
| 65 | 66 | }; |
| 66 | 67 | |
| 67 | 68 | /// Used for the scope of condition expressions, for example `if (cond)`. |
| ... | ... | @@ -73,7 +74,7 @@ const Scope = struct { |
| 73 | 74 | |
| 74 | 75 | fn getBlockScope(self: *Condition, c: *Context) !*Block { |
| 75 | 76 | if (self.block) |*b| return b; |
| 76 | self.block = try Block.init(c, &self.base, "blk"); | |
| 77 | self.block = try Block.init(c, &self.base, true); | |
| 77 | 78 | return &self.block.?; |
| 78 | 79 | } |
| 79 | 80 | |
| ... | ... | @@ -93,21 +94,22 @@ const Scope = struct { |
| 93 | 94 | mangle_count: u32 = 0, |
| 94 | 95 | lbrace: ast.TokenIndex, |
| 95 | 96 | |
| 96 | fn init(c: *Context, parent: *Scope, label: ?[]const u8) !Block { | |
| 97 | return Block{ | |
| 97 | fn init(c: *Context, parent: *Scope, labeled: bool) !Block { | |
| 98 | var blk = Block{ | |
| 98 | 99 | .base = .{ |
| 99 | 100 | .id = .Block, |
| 100 | 101 | .parent = parent, |
| 101 | 102 | }, |
| 102 | 103 | .statements = std.ArrayList(*ast.Node).init(c.gpa), |
| 103 | 104 | .variables = AliasList.init(c.gpa), |
| 104 | .label = if (label) |l| blk: { | |
| 105 | const ll = try appendIdentifier(c, l); | |
| 106 | _ = try appendToken(c, .Colon, ":"); | |
| 107 | break :blk ll; | |
| 108 | } else null, | |
| 105 | .label = null, | |
| 109 | 106 | .lbrace = try appendToken(c, .LBrace, "{"), |
| 110 | 107 | }; |
| 108 | if (labeled) { | |
| 109 | blk.label = try appendIdentifier(c, try blk.makeMangledName(c, "blk")); | |
| 110 | _ = try appendToken(c, .Colon, ":"); | |
| 111 | } | |
| 112 | return blk; | |
| 111 | 113 | } |
| 112 | 114 | |
| 113 | 115 | fn deinit(self: *Block) void { |
| ... | ... | @@ -577,7 +579,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void { |
| 577 | 579 | |
| 578 | 580 | // actual function definition with body |
| 579 | 581 | const body_stmt = ZigClangFunctionDecl_getBody(fn_decl); |
| 580 | var block_scope = try Scope.Block.init(rp.c, &c.global_scope.base, null); | |
| 582 | var block_scope = try Scope.Block.init(rp.c, &c.global_scope.base, false); | |
| 581 | 583 | defer block_scope.deinit(); |
| 582 | 584 | var scope = &block_scope.base; |
| 583 | 585 | |
| ... | ... | @@ -626,6 +628,46 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void { |
| 626 | 628 | error.UnsupportedType, |
| 627 | 629 | => return failDecl(c, fn_decl_loc, fn_name, "unable to translate function", .{}), |
| 628 | 630 | }; |
| 631 | // add return statement if the function didn't have one | |
| 632 | blk: { | |
| 633 | const fn_ty = @ptrCast(*const ZigClangFunctionType, fn_type); | |
| 634 | ||
| 635 | if (ZigClangFunctionType_getNoReturnAttr(fn_ty)) break :blk; | |
| 636 | const return_qt = ZigClangFunctionType_getReturnType(fn_ty); | |
| 637 | if (isCVoid(return_qt)) break :blk; | |
| 638 | ||
| 639 | if (block_scope.statements.items.len > 0) { | |
| 640 | var last = block_scope.statements.items[block_scope.statements.items.len - 1]; | |
| 641 | while (true) { | |
| 642 | switch (last.tag) { | |
| 643 | .Block => { | |
| 644 | const stmts = last.castTag(.Block).?.statements(); | |
| 645 | if (stmts.len == 0) break; | |
| 646 | ||
| 647 | last = stmts[stmts.len - 1]; | |
| 648 | }, | |
| 649 | // no extra return needed | |
| 650 | .Return => break :blk, | |
| 651 | else => break, | |
| 652 | } | |
| 653 | } | |
| 654 | } | |
| 655 | ||
| 656 | const return_expr = try ast.Node.ControlFlowExpression.create(rp.c.arena, .{ | |
| 657 | .ltoken = try appendToken(rp.c, .Keyword_return, "return"), | |
| 658 | .tag = .Return, | |
| 659 | }, .{ | |
| 660 | .rhs = transZeroInitExpr(rp, scope, fn_decl_loc, ZigClangQualType_getTypePtr(return_qt)) catch |err| switch (err) { | |
| 661 | error.OutOfMemory => |e| return e, | |
| 662 | error.UnsupportedTranslation, | |
| 663 | error.UnsupportedType, | |
| 664 | => return failDecl(c, fn_decl_loc, fn_name, "unable to create a return value for function", .{}), | |
| 665 | }, | |
| 666 | }); | |
| 667 | _ = try appendToken(rp.c, .Semicolon, ";"); | |
| 668 | try block_scope.statements.append(&return_expr.base); | |
| 669 | } | |
| 670 | ||
| 629 | 671 | const body_node = try block_scope.complete(rp.c); |
| 630 | 672 | proto_node.setTrailer("body_node", &body_node.base); |
| 631 | 673 | return addTopLevelDecl(c, fn_name, &proto_node.base); |
| ... | ... | @@ -931,7 +973,7 @@ fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!?* |
| 931 | 973 | else => |e| return e, |
| 932 | 974 | }; |
| 933 | 975 | |
| 934 | const align_expr = blk: { | |
| 976 | const align_expr = blk_2: { | |
| 935 | 977 | const alignment = ZigClangFieldDecl_getAlignedAttribute(field_decl, rp.c.clang_context); |
| 936 | 978 | if (alignment != 0) { |
| 937 | 979 | _ = try appendToken(rp.c, .Keyword_align, "align"); |
| ... | ... | @@ -940,9 +982,9 @@ fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!?* |
| 940 | 982 | const expr = try transCreateNodeInt(rp.c, alignment / 8); |
| 941 | 983 | _ = try appendToken(rp.c, .RParen, ")"); |
| 942 | 984 | |
| 943 | break :blk expr; | |
| 985 | break :blk_2 expr; | |
| 944 | 986 | } |
| 945 | break :blk null; | |
| 987 | break :blk_2 null; | |
| 946 | 988 | }; |
| 947 | 989 | |
| 948 | 990 | const field_node = try c.arena.create(ast.Node.ContainerField); |
| ... | ... | @@ -1073,9 +1115,9 @@ fn transEnumDecl(c: *Context, enum_decl: *const ZigClangEnumDecl) Error!?*ast.No |
| 1073 | 1115 | |
| 1074 | 1116 | const field_name_tok = try appendIdentifier(c, field_name); |
| 1075 | 1117 | |
| 1076 | const int_node = if (!pure_enum) blk: { | |
| 1118 | const int_node = if (!pure_enum) blk_2: { | |
| 1077 | 1119 | _ = try appendToken(c, .Colon, "="); |
| 1078 | break :blk try transCreateNodeAPInt(c, ZigClangEnumConstantDecl_getInitVal(enum_const)); | |
| 1120 | break :blk_2 try transCreateNodeAPInt(c, ZigClangEnumConstantDecl_getInitVal(enum_const)); | |
| 1079 | 1121 | } else |
| 1080 | 1122 | null; |
| 1081 | 1123 | |
| ... | ... | @@ -1307,7 +1349,7 @@ fn transBinaryOperator( |
| 1307 | 1349 | const rhs = try transExpr(rp, &block_scope.base, ZigClangBinaryOperator_getRHS(stmt), .used, .r_value); |
| 1308 | 1350 | if (expr) { |
| 1309 | 1351 | _ = try appendToken(rp.c, .Semicolon, ";"); |
| 1310 | const break_node = try transCreateNodeBreakToken(rp.c, block_scope.label, rhs); | |
| 1352 | const break_node = try transCreateNodeBreak(rp.c, block_scope.label, rhs); | |
| 1311 | 1353 | try block_scope.statements.append(&break_node.base); |
| 1312 | 1354 | const block_node = try block_scope.complete(rp.c); |
| 1313 | 1355 | const rparen = try appendToken(rp.c, .RParen, ")"); |
| ... | ... | @@ -1476,7 +1518,7 @@ fn transCompoundStmtInline( |
| 1476 | 1518 | } |
| 1477 | 1519 | |
| 1478 | 1520 | fn transCompoundStmt(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangCompoundStmt) TransError!*ast.Node { |
| 1479 | var block_scope = try Scope.Block.init(rp.c, scope, null); | |
| 1521 | var block_scope = try Scope.Block.init(rp.c, scope, false); | |
| 1480 | 1522 | defer block_scope.deinit(); |
| 1481 | 1523 | try transCompoundStmtInline(rp, &block_scope.base, stmt, &block_scope); |
| 1482 | 1524 | const node = try block_scope.complete(rp.c); |
| ... | ... | @@ -2388,7 +2430,7 @@ fn transZeroInitExpr( |
| 2388 | 2430 | ty: *const ZigClangType, |
| 2389 | 2431 | ) TransError!*ast.Node { |
| 2390 | 2432 | switch (ZigClangType_getTypeClass(ty)) { |
| 2391 | .Builtin => blk: { | |
| 2433 | .Builtin => { | |
| 2392 | 2434 | const builtin_ty = @ptrCast(*const ZigClangBuiltinType, ty); |
| 2393 | 2435 | switch (ZigClangBuiltinType_getKind(builtin_ty)) { |
| 2394 | 2436 | .Bool => return try transCreateNodeBoolLiteral(rp.c, false), |
| ... | ... | @@ -2587,7 +2629,7 @@ fn transForLoop( |
| 2587 | 2629 | defer if (block_scope) |*bs| bs.deinit(); |
| 2588 | 2630 | |
| 2589 | 2631 | if (ZigClangForStmt_getInit(stmt)) |init| { |
| 2590 | block_scope = try Scope.Block.init(rp.c, scope, null); | |
| 2632 | block_scope = try Scope.Block.init(rp.c, scope, false); | |
| 2591 | 2633 | loop_scope.parent = &block_scope.?.base; |
| 2592 | 2634 | const init_node = try transStmt(rp, &block_scope.?.base, init, .unused, .r_value); |
| 2593 | 2635 | try block_scope.?.statements.append(init_node); |
| ... | ... | @@ -2673,17 +2715,19 @@ fn transSwitch( |
| 2673 | 2715 | .cases = switch_node.cases(), |
| 2674 | 2716 | .case_index = 0, |
| 2675 | 2717 | .pending_block = undefined, |
| 2718 | .default_label = null, | |
| 2719 | .switch_label = null, | |
| 2676 | 2720 | }; |
| 2677 | 2721 | |
| 2678 | 2722 | // tmp block that all statements will go before being picked up by a case or default |
| 2679 | var block_scope = try Scope.Block.init(rp.c, &switch_scope.base, null); | |
| 2723 | var block_scope = try Scope.Block.init(rp.c, &switch_scope.base, false); | |
| 2680 | 2724 | defer block_scope.deinit(); |
| 2681 | 2725 | |
| 2682 | 2726 | // Note that we do not defer a deinit here; the switch_scope.pending_block field |
| 2683 | 2727 | // has its own memory management. This resource is freed inside `transCase` and |
| 2684 | 2728 | // then the final pending_block is freed at the bottom of this function with |
| 2685 | 2729 | // pending_block.deinit(). |
| 2686 | switch_scope.pending_block = try Scope.Block.init(rp.c, scope, null); | |
| 2730 | switch_scope.pending_block = try Scope.Block.init(rp.c, scope, false); | |
| 2687 | 2731 | try switch_scope.pending_block.statements.append(&switch_node.base); |
| 2688 | 2732 | |
| 2689 | 2733 | const last = try transStmt(rp, &block_scope.base, ZigClangSwitchStmt_getBody(stmt), .unused, .r_value); |
| ... | ... | @@ -2698,11 +2742,19 @@ fn transSwitch( |
| 2698 | 2742 | switch_scope.pending_block.statements.appendAssumeCapacity(n); |
| 2699 | 2743 | } |
| 2700 | 2744 | |
| 2701 | switch_scope.pending_block.label = try appendIdentifier(rp.c, "__switch"); | |
| 2702 | _ = try appendToken(rp.c, .Colon, ":"); | |
| 2703 | if (!switch_scope.has_default) { | |
| 2745 | if (switch_scope.default_label == null) { | |
| 2746 | switch_scope.switch_label = try block_scope.makeMangledName(rp.c, "switch"); | |
| 2747 | } | |
| 2748 | if (switch_scope.switch_label) |l| { | |
| 2749 | switch_scope.pending_block.label = try appendIdentifier(rp.c, l); | |
| 2750 | _ = try appendToken(rp.c, .Colon, ":"); | |
| 2751 | } | |
| 2752 | if (switch_scope.default_label == null) { | |
| 2704 | 2753 | const else_prong = try transCreateNodeSwitchCase(rp.c, try transCreateNodeSwitchElse(rp.c)); |
| 2705 | else_prong.expr = &(try transCreateNodeBreak(rp.c, "__switch", null)).base; | |
| 2754 | else_prong.expr = blk: { | |
| 2755 | var br = try CtrlFlow.init(rp.c, .Break, switch_scope.switch_label.?); | |
| 2756 | break :blk &(try br.finish(null)).base; | |
| 2757 | }; | |
| 2706 | 2758 | _ = try appendToken(rp.c, .Comma, ","); |
| 2707 | 2759 | |
| 2708 | 2760 | if (switch_scope.case_index >= switch_scope.cases.len) |
| ... | ... | @@ -2726,7 +2778,7 @@ fn transCase( |
| 2726 | 2778 | ) TransError!*ast.Node { |
| 2727 | 2779 | const block_scope = scope.findBlockScope(rp.c) catch unreachable; |
| 2728 | 2780 | const switch_scope = scope.getSwitch(); |
| 2729 | const label = try std.fmt.allocPrint(rp.c.arena, "__case_{}", .{switch_scope.case_index - @boolToInt(switch_scope.has_default)}); | |
| 2781 | const label = try block_scope.makeMangledName(rp.c, "case"); | |
| 2730 | 2782 | _ = try appendToken(rp.c, .Semicolon, ";"); |
| 2731 | 2783 | |
| 2732 | 2784 | const expr = if (ZigClangCaseStmt_getRHS(stmt)) |rhs| blk: { |
| ... | ... | @@ -2746,7 +2798,10 @@ fn transCase( |
| 2746 | 2798 | try transExpr(rp, scope, ZigClangCaseStmt_getLHS(stmt), .used, .r_value); |
| 2747 | 2799 | |
| 2748 | 2800 | const switch_prong = try transCreateNodeSwitchCase(rp.c, expr); |
| 2749 | switch_prong.expr = &(try transCreateNodeBreak(rp.c, label, null)).base; | |
| 2801 | switch_prong.expr = blk: { | |
| 2802 | var br = try CtrlFlow.init(rp.c, .Break, label); | |
| 2803 | break :blk &(try br.finish(null)).base; | |
| 2804 | }; | |
| 2750 | 2805 | _ = try appendToken(rp.c, .Comma, ","); |
| 2751 | 2806 | |
| 2752 | 2807 | if (switch_scope.case_index >= switch_scope.cases.len) |
| ... | ... | @@ -2763,7 +2818,7 @@ fn transCase( |
| 2763 | 2818 | |
| 2764 | 2819 | const pending_node = try switch_scope.pending_block.complete(rp.c); |
| 2765 | 2820 | switch_scope.pending_block.deinit(); |
| 2766 | switch_scope.pending_block = try Scope.Block.init(rp.c, scope, null); | |
| 2821 | switch_scope.pending_block = try Scope.Block.init(rp.c, scope, false); | |
| 2767 | 2822 | |
| 2768 | 2823 | try switch_scope.pending_block.statements.append(&pending_node.base); |
| 2769 | 2824 | |
| ... | ... | @@ -2777,12 +2832,14 @@ fn transDefault( |
| 2777 | 2832 | ) TransError!*ast.Node { |
| 2778 | 2833 | const block_scope = scope.findBlockScope(rp.c) catch unreachable; |
| 2779 | 2834 | const switch_scope = scope.getSwitch(); |
| 2780 | const label = "__default"; | |
| 2781 | switch_scope.has_default = true; | |
| 2835 | switch_scope.default_label = try block_scope.makeMangledName(rp.c, "default"); | |
| 2782 | 2836 | _ = try appendToken(rp.c, .Semicolon, ";"); |
| 2783 | 2837 | |
| 2784 | 2838 | const else_prong = try transCreateNodeSwitchCase(rp.c, try transCreateNodeSwitchElse(rp.c)); |
| 2785 | else_prong.expr = &(try transCreateNodeBreak(rp.c, label, null)).base; | |
| 2839 | else_prong.expr = blk: { | |
| 2840 | var br = try CtrlFlow.init(rp.c, .Break, switch_scope.default_label.?); | |
| 2841 | break :blk &(try br.finish(null)).base; | |
| 2842 | }; | |
| 2786 | 2843 | _ = try appendToken(rp.c, .Comma, ","); |
| 2787 | 2844 | |
| 2788 | 2845 | if (switch_scope.case_index >= switch_scope.cases.len) |
| ... | ... | @@ -2790,7 +2847,7 @@ fn transDefault( |
| 2790 | 2847 | switch_scope.cases[switch_scope.case_index] = &else_prong.base; |
| 2791 | 2848 | switch_scope.case_index += 1; |
| 2792 | 2849 | |
| 2793 | switch_scope.pending_block.label = try appendIdentifier(rp.c, label); | |
| 2850 | switch_scope.pending_block.label = try appendIdentifier(rp.c, switch_scope.default_label.?); | |
| 2794 | 2851 | _ = try appendToken(rp.c, .Colon, ":"); |
| 2795 | 2852 | |
| 2796 | 2853 | // take all pending statements |
| ... | ... | @@ -2799,7 +2856,7 @@ fn transDefault( |
| 2799 | 2856 | |
| 2800 | 2857 | const pending_node = try switch_scope.pending_block.complete(rp.c); |
| 2801 | 2858 | switch_scope.pending_block.deinit(); |
| 2802 | switch_scope.pending_block = try Scope.Block.init(rp.c, scope, null); | |
| 2859 | switch_scope.pending_block = try Scope.Block.init(rp.c, scope, false); | |
| 2803 | 2860 | try switch_scope.pending_block.statements.append(&pending_node.base); |
| 2804 | 2861 | |
| 2805 | 2862 | return transStmt(rp, scope, ZigClangDefaultStmt_getSubStmt(stmt), .unused, .r_value); |
| ... | ... | @@ -2894,7 +2951,7 @@ fn transStmtExpr(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangStmtExpr, |
| 2894 | 2951 | return transCompoundStmt(rp, scope, comp); |
| 2895 | 2952 | } |
| 2896 | 2953 | const lparen = try appendToken(rp.c, .LParen, "("); |
| 2897 | var block_scope = try Scope.Block.init(rp.c, scope, "blk"); | |
| 2954 | var block_scope = try Scope.Block.init(rp.c, scope, true); | |
| 2898 | 2955 | defer block_scope.deinit(); |
| 2899 | 2956 | |
| 2900 | 2957 | var it = ZigClangCompoundStmt_body_begin(comp); |
| ... | ... | @@ -3209,7 +3266,7 @@ fn transCreatePreCrement( |
| 3209 | 3266 | // zig: _ref.* += 1; |
| 3210 | 3267 | // zig: break :blk _ref.* |
| 3211 | 3268 | // zig: }) |
| 3212 | var block_scope = try Scope.Block.init(rp.c, scope, "blk"); | |
| 3269 | var block_scope = try Scope.Block.init(rp.c, scope, true); | |
| 3213 | 3270 | defer block_scope.deinit(); |
| 3214 | 3271 | const ref = try block_scope.makeMangledName(rp.c, "ref"); |
| 3215 | 3272 | |
| ... | ... | @@ -3239,7 +3296,7 @@ fn transCreatePreCrement( |
| 3239 | 3296 | const assign = try transCreateNodeInfixOp(rp, scope, ref_node, op, token, one, .used, false); |
| 3240 | 3297 | try block_scope.statements.append(assign); |
| 3241 | 3298 | |
| 3242 | const break_node = try transCreateNodeBreakToken(rp.c, block_scope.label, ref_node); | |
| 3299 | const break_node = try transCreateNodeBreak(rp.c, block_scope.label, ref_node); | |
| 3243 | 3300 | try block_scope.statements.append(&break_node.base); |
| 3244 | 3301 | const block_node = try block_scope.complete(rp.c); |
| 3245 | 3302 | // semicolon must immediately follow rbrace because it is the last token in a block |
| ... | ... | @@ -3283,7 +3340,7 @@ fn transCreatePostCrement( |
| 3283 | 3340 | // zig: _ref.* += 1; |
| 3284 | 3341 | // zig: break :blk _tmp |
| 3285 | 3342 | // zig: }) |
| 3286 | var block_scope = try Scope.Block.init(rp.c, scope, "blk"); | |
| 3343 | var block_scope = try Scope.Block.init(rp.c, scope, true); | |
| 3287 | 3344 | defer block_scope.deinit(); |
| 3288 | 3345 | const ref = try block_scope.makeMangledName(rp.c, "ref"); |
| 3289 | 3346 | |
| ... | ... | @@ -3458,7 +3515,7 @@ fn transCreateCompoundAssign( |
| 3458 | 3515 | // zig: _ref.* = _ref.* + rhs; |
| 3459 | 3516 | // zig: break :blk _ref.* |
| 3460 | 3517 | // zig: }) |
| 3461 | var block_scope = try Scope.Block.init(rp.c, scope, "blk"); | |
| 3518 | var block_scope = try Scope.Block.init(rp.c, scope, true); | |
| 3462 | 3519 | defer block_scope.deinit(); |
| 3463 | 3520 | const ref = try block_scope.makeMangledName(rp.c, "ref"); |
| 3464 | 3521 | |
| ... | ... | @@ -3526,7 +3583,7 @@ fn transCreateCompoundAssign( |
| 3526 | 3583 | try block_scope.statements.append(assign); |
| 3527 | 3584 | } |
| 3528 | 3585 | |
| 3529 | const break_node = try transCreateNodeBreakToken(rp.c, block_scope.label, ref_node); | |
| 3586 | const break_node = try transCreateNodeBreak(rp.c, block_scope.label, ref_node); | |
| 3530 | 3587 | try block_scope.statements.append(&break_node.base); |
| 3531 | 3588 | const block_node = try block_scope.complete(rp.c); |
| 3532 | 3589 | const grouped_expr = try rp.c.arena.create(ast.Node.GroupedExpression); |
| ... | ... | @@ -3602,8 +3659,16 @@ fn transCPtrCast( |
| 3602 | 3659 | |
| 3603 | 3660 | fn transBreak(rp: RestorePoint, scope: *Scope) TransError!*ast.Node { |
| 3604 | 3661 | const break_scope = scope.getBreakableScope(); |
| 3605 | const label_text: ?[]const u8 = if (break_scope.id == .Switch) "__switch" else null; | |
| 3606 | const br = try transCreateNodeBreak(rp.c, label_text, null); | |
| 3662 | const label_text: ?[]const u8 = if (break_scope.id == .Switch) blk: { | |
| 3663 | const swtch = @fieldParentPtr(Scope.Switch, "base", break_scope); | |
| 3664 | const block_scope = try scope.findBlockScope(rp.c); | |
| 3665 | swtch.switch_label = try block_scope.makeMangledName(rp.c, "switch"); | |
| 3666 | break :blk swtch.switch_label; | |
| 3667 | } else | |
| 3668 | null; | |
| 3669 | ||
| 3670 | var cf = try CtrlFlow.init(rp.c, .Break, label_text); | |
| 3671 | const br = try cf.finish(null); | |
| 3607 | 3672 | _ = try appendToken(rp.c, .Semicolon, ";"); |
| 3608 | 3673 | return &br.base; |
| 3609 | 3674 | } |
| ... | ... | @@ -3634,7 +3699,7 @@ fn transBinaryConditionalOperator(rp: RestorePoint, scope: *Scope, stmt: *const |
| 3634 | 3699 | // }) |
| 3635 | 3700 | const lparen = try appendToken(rp.c, .LParen, "("); |
| 3636 | 3701 | |
| 3637 | var block_scope = try Scope.Block.init(rp.c, scope, "blk"); | |
| 3702 | var block_scope = try Scope.Block.init(rp.c, scope, true); | |
| 3638 | 3703 | defer block_scope.deinit(); |
| 3639 | 3704 | |
| 3640 | 3705 | const mangled_name = try block_scope.makeMangledName(rp.c, "cond_temp"); |
| ... | ... | @@ -4082,8 +4147,7 @@ fn transCreateNodeAssign( |
| 4082 | 4147 | // zig: lhs = _tmp; |
| 4083 | 4148 | // zig: break :blk _tmp |
| 4084 | 4149 | // zig: }) |
| 4085 | const label_name = "blk"; | |
| 4086 | var block_scope = try Scope.Block.init(rp.c, scope, label_name); | |
| 4150 | var block_scope = try Scope.Block.init(rp.c, scope, true); | |
| 4087 | 4151 | defer block_scope.deinit(); |
| 4088 | 4152 | |
| 4089 | 4153 | const tmp = try block_scope.makeMangledName(rp.c, "tmp"); |
| ... | ... | @@ -4118,7 +4182,7 @@ fn transCreateNodeAssign( |
| 4118 | 4182 | try block_scope.statements.append(assign); |
| 4119 | 4183 | |
| 4120 | 4184 | const break_node = blk: { |
| 4121 | var tmp_ctrl_flow = try CtrlFlow.init(rp.c, .Break, label_name); | |
| 4185 | var tmp_ctrl_flow = try CtrlFlow.init(rp.c, .Break, tokenSlice(rp.c, block_scope.label.?)); | |
| 4122 | 4186 | const rhs_expr = try transCreateNodeIdentifier(rp.c, tmp); |
| 4123 | 4187 | break :blk try tmp_ctrl_flow.finish(rhs_expr); |
| 4124 | 4188 | }; |
| ... | ... | @@ -4495,23 +4559,12 @@ fn transCreateNodeElse(c: *Context) !*ast.Node.Else { |
| 4495 | 4559 | return node; |
| 4496 | 4560 | } |
| 4497 | 4561 | |
| 4498 | fn transCreateNodeBreakToken( | |
| 4499 | c: *Context, | |
| 4500 | label: ?ast.TokenIndex, | |
| 4501 | rhs: ?*ast.Node, | |
| 4502 | ) !*ast.Node.ControlFlowExpression { | |
| 4503 | const other_token = label orelse return transCreateNodeBreak(c, null, rhs); | |
| 4504 | const loc = c.token_locs.items[other_token]; | |
| 4505 | const label_name = c.source_buffer.items[loc.start..loc.end]; | |
| 4506 | return transCreateNodeBreak(c, label_name, rhs); | |
| 4507 | } | |
| 4508 | ||
| 4509 | 4562 | fn transCreateNodeBreak( |
| 4510 | 4563 | c: *Context, |
| 4511 | label: ?[]const u8, | |
| 4564 | label: ?ast.TokenIndex, | |
| 4512 | 4565 | rhs: ?*ast.Node, |
| 4513 | 4566 | ) !*ast.Node.ControlFlowExpression { |
| 4514 | var ctrl_flow = try CtrlFlow.init(c, .Break, label); | |
| 4567 | var ctrl_flow = try CtrlFlow.init(c, .Break, if (label) |l| tokenSlice(c, l) else null); | |
| 4515 | 4568 | return ctrl_flow.finish(rhs); |
| 4516 | 4569 | } |
| 4517 | 4570 | |
| ... | ... | @@ -5362,7 +5415,7 @@ fn transMacroDefine(c: *Context, m: *MacroCtx) ParseError!void { |
| 5362 | 5415 | } |
| 5363 | 5416 | |
| 5364 | 5417 | fn transMacroFnDefine(c: *Context, m: *MacroCtx) ParseError!void { |
| 5365 | var block_scope = try Scope.Block.init(c, &c.global_scope.base, null); | |
| 5418 | var block_scope = try Scope.Block.init(c, &c.global_scope.base, false); | |
| 5366 | 5419 | defer block_scope.deinit(); |
| 5367 | 5420 | const scope = &block_scope.base; |
| 5368 | 5421 | |
| ... | ... | @@ -5475,8 +5528,7 @@ fn parseCExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node { |
| 5475 | 5528 | }, |
| 5476 | 5529 | .Comma => { |
| 5477 | 5530 | _ = try appendToken(c, .Semicolon, ";"); |
| 5478 | const label_name = "blk"; | |
| 5479 | var block_scope = try Scope.Block.init(c, scope, label_name); | |
| 5531 | var block_scope = try Scope.Block.init(c, scope, true); | |
| 5480 | 5532 | defer block_scope.deinit(); |
| 5481 | 5533 | |
| 5482 | 5534 | var last = node; |
| ... | ... | @@ -5501,7 +5553,7 @@ fn parseCExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node { |
| 5501 | 5553 | } |
| 5502 | 5554 | } |
| 5503 | 5555 | |
| 5504 | const break_node = try transCreateNodeBreak(c, label_name, last); | |
| 5556 | const break_node = try transCreateNodeBreak(c, block_scope.label, last); | |
| 5505 | 5557 | try block_scope.statements.append(&break_node.base); |
| 5506 | 5558 | const block_node = try block_scope.complete(c); |
| 5507 | 5559 | return &block_node.base; |
src/all_types.hpp+3| ... | ... | @@ -2438,6 +2438,7 @@ struct ScopeBlock { |
| 2438 | 2438 | LVal lval; |
| 2439 | 2439 | bool safety_off; |
| 2440 | 2440 | bool fast_math_on; |
| 2441 | bool name_used; | |
| 2441 | 2442 | }; |
| 2442 | 2443 | |
| 2443 | 2444 | // This scope is created from every defer expression. |
| ... | ... | @@ -2488,6 +2489,8 @@ struct ScopeLoop { |
| 2488 | 2489 | ZigList<IrBasicBlockSrc *> *incoming_blocks; |
| 2489 | 2490 | ResultLocPeerParent *peer_parent; |
| 2490 | 2491 | ScopeExpr *spill_scope; |
| 2492 | ||
| 2493 | bool name_used; | |
| 2491 | 2494 | }; |
| 2492 | 2495 | |
| 2493 | 2496 | // This scope blocks certain things from working such as comptime continue |
src/ir.cpp+60| ... | ... | @@ -5476,6 +5476,25 @@ static ResultLocPeer *create_peer_result(ResultLocPeerParent *peer_parent) { |
| 5476 | 5476 | return result; |
| 5477 | 5477 | } |
| 5478 | 5478 | |
| 5479 | static bool is_duplicate_label(CodeGen *g, Scope *scope, AstNode *node, Buf *name) { | |
| 5480 | if (name == nullptr) return false; | |
| 5481 | ||
| 5482 | for (;;) { | |
| 5483 | if (scope == nullptr || scope->id == ScopeIdFnDef) { | |
| 5484 | break; | |
| 5485 | } else if (scope->id == ScopeIdBlock || scope->id == ScopeIdLoop) { | |
| 5486 | Buf *this_block_name = scope->id == ScopeIdBlock ? ((ScopeBlock *)scope)->name : ((ScopeLoop *)scope)->name; | |
| 5487 | if (this_block_name != nullptr && buf_eql_buf(name, this_block_name)) { | |
| 5488 | ErrorMsg *msg = add_node_error(g, node, buf_sprintf("redeclaration of label '%s'", buf_ptr(name))); | |
| 5489 | add_error_note(g, msg, scope->source_node, buf_sprintf("previous declaration is here")); | |
| 5490 | return true; | |
| 5491 | } | |
| 5492 | } | |
| 5493 | scope = scope->parent; | |
| 5494 | } | |
| 5495 | return false; | |
| 5496 | } | |
| 5497 | ||
| 5479 | 5498 | static IrInstSrc *ir_gen_block(IrBuilderSrc *irb, Scope *parent_scope, AstNode *block_node, LVal lval, |
| 5480 | 5499 | ResultLoc *result_loc) |
| 5481 | 5500 | { |
| ... | ... | @@ -5484,6 +5503,9 @@ static IrInstSrc *ir_gen_block(IrBuilderSrc *irb, Scope *parent_scope, AstNode * |
| 5484 | 5503 | ZigList<IrInstSrc *> incoming_values = {0}; |
| 5485 | 5504 | ZigList<IrBasicBlockSrc *> incoming_blocks = {0}; |
| 5486 | 5505 | |
| 5506 | if (is_duplicate_label(irb->codegen, parent_scope, block_node, block_node->data.block.name)) | |
| 5507 | return irb->codegen->invalid_inst_src; | |
| 5508 | ||
| 5487 | 5509 | ScopeBlock *scope_block = create_block_scope(irb->codegen, block_node, parent_scope); |
| 5488 | 5510 | |
| 5489 | 5511 | Scope *outer_block_scope = &scope_block->base; |
| ... | ... | @@ -5495,6 +5517,9 @@ static IrInstSrc *ir_gen_block(IrBuilderSrc *irb, Scope *parent_scope, AstNode * |
| 5495 | 5517 | } |
| 5496 | 5518 | |
| 5497 | 5519 | if (block_node->data.block.statements.length == 0) { |
| 5520 | if (scope_block->name != nullptr) { | |
| 5521 | add_node_error(irb->codegen, block_node, buf_sprintf("unused block label")); | |
| 5522 | } | |
| 5498 | 5523 | // {} |
| 5499 | 5524 | return ir_lval_wrap(irb, parent_scope, ir_build_const_void(irb, child_scope, block_node), lval, result_loc); |
| 5500 | 5525 | } |
| ... | ... | @@ -5552,6 +5577,10 @@ static IrInstSrc *ir_gen_block(IrBuilderSrc *irb, Scope *parent_scope, AstNode * |
| 5552 | 5577 | } |
| 5553 | 5578 | } |
| 5554 | 5579 | |
| 5580 | if (scope_block->name != nullptr && scope_block->name_used == false) { | |
| 5581 | add_node_error(irb->codegen, block_node, buf_sprintf("unused block label")); | |
| 5582 | } | |
| 5583 | ||
| 5555 | 5584 | if (found_invalid_inst) |
| 5556 | 5585 | return irb->codegen->invalid_inst_src; |
| 5557 | 5586 | |
| ... | ... | @@ -8152,6 +8181,9 @@ static IrInstSrc *ir_gen_while_expr(IrBuilderSrc *irb, Scope *scope, AstNode *no |
| 8152 | 8181 | ZigList<IrInstSrc *> incoming_values = {0}; |
| 8153 | 8182 | ZigList<IrBasicBlockSrc *> incoming_blocks = {0}; |
| 8154 | 8183 | |
| 8184 | if (is_duplicate_label(irb->codegen, payload_scope, node, node->data.while_expr.name)) | |
| 8185 | return irb->codegen->invalid_inst_src; | |
| 8186 | ||
| 8155 | 8187 | ScopeLoop *loop_scope = create_loop_scope(irb->codegen, node, payload_scope); |
| 8156 | 8188 | loop_scope->break_block = end_block; |
| 8157 | 8189 | loop_scope->continue_block = continue_block; |
| ... | ... | @@ -8169,6 +8201,10 @@ static IrInstSrc *ir_gen_while_expr(IrBuilderSrc *irb, Scope *scope, AstNode *no |
| 8169 | 8201 | if (body_result == irb->codegen->invalid_inst_src) |
| 8170 | 8202 | return body_result; |
| 8171 | 8203 | |
| 8204 | if (loop_scope->name != nullptr && loop_scope->name_used == false) { | |
| 8205 | add_node_error(irb->codegen, node, buf_sprintf("unused while label")); | |
| 8206 | } | |
| 8207 | ||
| 8172 | 8208 | if (!instr_is_unreachable(body_result)) { |
| 8173 | 8209 | ir_mark_gen(ir_build_check_statement_is_void(irb, payload_scope, node->data.while_expr.body, body_result)); |
| 8174 | 8210 | ir_mark_gen(ir_build_br(irb, payload_scope, node, continue_block, is_comptime)); |
| ... | ... | @@ -8263,6 +8299,9 @@ static IrInstSrc *ir_gen_while_expr(IrBuilderSrc *irb, Scope *scope, AstNode *no |
| 8263 | 8299 | ZigList<IrInstSrc *> incoming_values = {0}; |
| 8264 | 8300 | ZigList<IrBasicBlockSrc *> incoming_blocks = {0}; |
| 8265 | 8301 | |
| 8302 | if (is_duplicate_label(irb->codegen, child_scope, node, node->data.while_expr.name)) | |
| 8303 | return irb->codegen->invalid_inst_src; | |
| 8304 | ||
| 8266 | 8305 | ScopeLoop *loop_scope = create_loop_scope(irb->codegen, node, child_scope); |
| 8267 | 8306 | loop_scope->break_block = end_block; |
| 8268 | 8307 | loop_scope->continue_block = continue_block; |
| ... | ... | @@ -8280,6 +8319,10 @@ static IrInstSrc *ir_gen_while_expr(IrBuilderSrc *irb, Scope *scope, AstNode *no |
| 8280 | 8319 | if (body_result == irb->codegen->invalid_inst_src) |
| 8281 | 8320 | return body_result; |
| 8282 | 8321 | |
| 8322 | if (loop_scope->name != nullptr && loop_scope->name_used == false) { | |
| 8323 | add_node_error(irb->codegen, node, buf_sprintf("unused while label")); | |
| 8324 | } | |
| 8325 | ||
| 8283 | 8326 | if (!instr_is_unreachable(body_result)) { |
| 8284 | 8327 | ir_mark_gen(ir_build_check_statement_is_void(irb, child_scope, node->data.while_expr.body, body_result)); |
| 8285 | 8328 | ir_mark_gen(ir_build_br(irb, child_scope, node, continue_block, is_comptime)); |
| ... | ... | @@ -8353,6 +8396,9 @@ static IrInstSrc *ir_gen_while_expr(IrBuilderSrc *irb, Scope *scope, AstNode *no |
| 8353 | 8396 | |
| 8354 | 8397 | Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime); |
| 8355 | 8398 | |
| 8399 | if (is_duplicate_label(irb->codegen, subexpr_scope, node, node->data.while_expr.name)) | |
| 8400 | return irb->codegen->invalid_inst_src; | |
| 8401 | ||
| 8356 | 8402 | ScopeLoop *loop_scope = create_loop_scope(irb->codegen, node, subexpr_scope); |
| 8357 | 8403 | loop_scope->break_block = end_block; |
| 8358 | 8404 | loop_scope->continue_block = continue_block; |
| ... | ... | @@ -8369,6 +8415,10 @@ static IrInstSrc *ir_gen_while_expr(IrBuilderSrc *irb, Scope *scope, AstNode *no |
| 8369 | 8415 | if (body_result == irb->codegen->invalid_inst_src) |
| 8370 | 8416 | return body_result; |
| 8371 | 8417 | |
| 8418 | if (loop_scope->name != nullptr && loop_scope->name_used == false) { | |
| 8419 | add_node_error(irb->codegen, node, buf_sprintf("unused while label")); | |
| 8420 | } | |
| 8421 | ||
| 8372 | 8422 | if (!instr_is_unreachable(body_result)) { |
| 8373 | 8423 | ir_mark_gen(ir_build_check_statement_is_void(irb, scope, node->data.while_expr.body, body_result)); |
| 8374 | 8424 | ir_mark_gen(ir_build_br(irb, scope, node, continue_block, is_comptime)); |
| ... | ... | @@ -8501,6 +8551,9 @@ static IrInstSrc *ir_gen_for_expr(IrBuilderSrc *irb, Scope *parent_scope, AstNod |
| 8501 | 8551 | elem_ptr : ir_build_load_ptr(irb, &spill_scope->base, elem_node, elem_ptr); |
| 8502 | 8552 | build_decl_var_and_init(irb, parent_scope, elem_node, elem_var, elem_value, buf_ptr(elem_var_name), is_comptime); |
| 8503 | 8553 | |
| 8554 | if (is_duplicate_label(irb->codegen, child_scope, node, node->data.for_expr.name)) | |
| 8555 | return irb->codegen->invalid_inst_src; | |
| 8556 | ||
| 8504 | 8557 | ZigList<IrInstSrc *> incoming_values = {0}; |
| 8505 | 8558 | ZigList<IrBasicBlockSrc *> incoming_blocks = {0}; |
| 8506 | 8559 | ScopeLoop *loop_scope = create_loop_scope(irb->codegen, node, child_scope); |
| ... | ... | @@ -8520,6 +8573,10 @@ static IrInstSrc *ir_gen_for_expr(IrBuilderSrc *irb, Scope *parent_scope, AstNod |
| 8520 | 8573 | if (body_result == irb->codegen->invalid_inst_src) |
| 8521 | 8574 | return irb->codegen->invalid_inst_src; |
| 8522 | 8575 | |
| 8576 | if (loop_scope->name != nullptr && loop_scope->name_used == false) { | |
| 8577 | add_node_error(irb->codegen, node, buf_sprintf("unused for label")); | |
| 8578 | } | |
| 8579 | ||
| 8523 | 8580 | if (!instr_is_unreachable(body_result)) { |
| 8524 | 8581 | ir_mark_gen(ir_build_check_statement_is_void(irb, child_scope, node->data.for_expr.body, body_result)); |
| 8525 | 8582 | ir_mark_gen(ir_build_br(irb, child_scope, node, continue_block, is_comptime)); |
| ... | ... | @@ -9464,6 +9521,7 @@ static IrInstSrc *ir_gen_break(IrBuilderSrc *irb, Scope *break_scope, AstNode *n |
| 9464 | 9521 | if (node->data.break_expr.name == nullptr || |
| 9465 | 9522 | (this_loop_scope->name != nullptr && buf_eql_buf(node->data.break_expr.name, this_loop_scope->name))) |
| 9466 | 9523 | { |
| 9524 | this_loop_scope->name_used = true; | |
| 9467 | 9525 | loop_scope = this_loop_scope; |
| 9468 | 9526 | break; |
| 9469 | 9527 | } |
| ... | ... | @@ -9473,6 +9531,7 @@ static IrInstSrc *ir_gen_break(IrBuilderSrc *irb, Scope *break_scope, AstNode *n |
| 9473 | 9531 | (this_block_scope->name != nullptr && buf_eql_buf(node->data.break_expr.name, this_block_scope->name))) |
| 9474 | 9532 | { |
| 9475 | 9533 | assert(this_block_scope->end_block != nullptr); |
| 9534 | this_block_scope->name_used = true; | |
| 9476 | 9535 | return ir_gen_return_from_block(irb, break_scope, node, this_block_scope); |
| 9477 | 9536 | } |
| 9478 | 9537 | } else if (search_scope->id == ScopeIdSuspend) { |
| ... | ... | @@ -9540,6 +9599,7 @@ static IrInstSrc *ir_gen_continue(IrBuilderSrc *irb, Scope *continue_scope, AstN |
| 9540 | 9599 | if (node->data.continue_expr.name == nullptr || |
| 9541 | 9600 | (this_loop_scope->name != nullptr && buf_eql_buf(node->data.continue_expr.name, this_loop_scope->name))) |
| 9542 | 9601 | { |
| 9602 | this_loop_scope->name_used = true; | |
| 9543 | 9603 | loop_scope = this_loop_scope; |
| 9544 | 9604 | break; |
| 9545 | 9605 | } |
test/compile_errors.zig+23| ... | ... | @@ -2,6 +2,29 @@ const tests = @import("tests.zig"); |
| 2 | 2 | const std = @import("std"); |
| 3 | 3 | |
| 4 | 4 | pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 5 | cases.addTest("duplicate/unused labels", | |
| 6 | \\comptime { | |
| 7 | \\ blk: { blk: while (false) {} } | |
| 8 | \\ blk: while (false) { blk: for (@as([0]void, undefined)) |_| {} } | |
| 9 | \\ blk: for (@as([0]void, undefined)) |_| { blk: {} } | |
| 10 | \\} | |
| 11 | \\comptime { | |
| 12 | \\ blk: {} | |
| 13 | \\ blk: while(false) {} | |
| 14 | \\ blk: for(@as([0]void, undefined)) |_| {} | |
| 15 | \\} | |
| 16 | , &[_][]const u8{ | |
| 17 | "tmp.zig:2:17: error: redeclaration of label 'blk'", | |
| 18 | "tmp.zig:2:10: note: previous declaration is here", | |
| 19 | "tmp.zig:3:31: error: redeclaration of label 'blk'", | |
| 20 | "tmp.zig:3:10: note: previous declaration is here", | |
| 21 | "tmp.zig:4:51: error: redeclaration of label 'blk'", | |
| 22 | "tmp.zig:4:10: note: previous declaration is here", | |
| 23 | "tmp.zig:7:10: error: unused block label", | |
| 24 | "tmp.zig:8:10: error: unused while label", | |
| 25 | "tmp.zig:9:10: error: unused for label", | |
| 26 | }); | |
| 27 | ||
| 5 | 28 | cases.addTest("@alignCast of zero sized types", |
| 6 | 29 | \\export fn foo() void { |
| 7 | 30 | \\ const a: *void = undefined; |
test/run_translated_c.zig-1| ... | ... | @@ -15,7 +15,6 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void { |
| 15 | 15 | \\ } |
| 16 | 16 | \\ if (s0 != 1) abort(); |
| 17 | 17 | \\ if (s1 != 10) abort(); |
| 18 | \\ return 0; | |
| 19 | 18 | \\} |
| 20 | 19 | , ""); |
| 21 | 20 |
test/translate_c.zig+56-31| ... | ... | @@ -3,12 +3,33 @@ const std = @import("std"); |
| 3 | 3 | const CrossTarget = std.zig.CrossTarget; |
| 4 | 4 | |
| 5 | 5 | pub fn addCases(cases: *tests.TranslateCContext) void { |
| 6 | cases.add("missing return stmt", | |
| 7 | \\int foo() {} | |
| 8 | \\int bar() { | |
| 9 | \\ int a = 2; | |
| 10 | \\} | |
| 11 | \\int baz() { | |
| 12 | \\ return 0; | |
| 13 | \\} | |
| 14 | , &[_][]const u8{ | |
| 15 | \\pub export fn foo() c_int { | |
| 16 | \\ return 0; | |
| 17 | \\} | |
| 18 | \\pub export fn bar() c_int { | |
| 19 | \\ var a: c_int = 2; | |
| 20 | \\ return 0; | |
| 21 | \\} | |
| 22 | \\pub export fn baz() c_int { | |
| 23 | \\ return 0; | |
| 24 | \\} | |
| 25 | }); | |
| 26 | ||
| 6 | 27 | cases.add("alignof", |
| 7 | \\int main() { | |
| 28 | \\void main() { | |
| 8 | 29 | \\ int a = _Alignof(int); |
| 9 | 30 | \\} |
| 10 | 31 | , &[_][]const u8{ |
| 11 | \\pub export fn main() c_int { | |
| 32 | \\pub export fn main() void { | |
| 12 | 33 | \\ var a: c_int = @bitCast(c_int, @truncate(c_uint, @alignOf(c_int))); |
| 13 | 34 | \\} |
| 14 | 35 | }); |
| ... | ... | @@ -539,6 +560,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 539 | 560 | \\ c = (a * b); |
| 540 | 561 | \\ c = @divTrunc(a, b); |
| 541 | 562 | \\ c = @rem(a, b); |
| 563 | \\ return 0; | |
| 542 | 564 | \\} |
| 543 | 565 | \\pub export fn u() c_uint { |
| 544 | 566 | \\ var a: c_uint = undefined; |
| ... | ... | @@ -549,6 +571,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 549 | 571 | \\ c = (a *% b); |
| 550 | 572 | \\ c = (a / b); |
| 551 | 573 | \\ c = (a % b); |
| 574 | \\ return 0; | |
| 552 | 575 | \\} |
| 553 | 576 | }); |
| 554 | 577 | |
| ... | ... | @@ -1596,13 +1619,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1596 | 1619 | }); |
| 1597 | 1620 | |
| 1598 | 1621 | cases.add("worst-case assign", |
| 1599 | \\int foo() { | |
| 1622 | \\void foo() { | |
| 1600 | 1623 | \\ int a; |
| 1601 | 1624 | \\ int b; |
| 1602 | 1625 | \\ a = b = 2; |
| 1603 | 1626 | \\} |
| 1604 | 1627 | , &[_][]const u8{ |
| 1605 | \\pub export fn foo() c_int { | |
| 1628 | \\pub export fn foo() void { | |
| 1606 | 1629 | \\ var a: c_int = undefined; |
| 1607 | 1630 | \\ var b: c_int = undefined; |
| 1608 | 1631 | \\ a = blk: { |
| ... | ... | @@ -1650,11 +1673,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1650 | 1673 | \\ a = 7; |
| 1651 | 1674 | \\ if (!true) break; |
| 1652 | 1675 | \\ } |
| 1676 | \\ return 0; | |
| 1653 | 1677 | \\} |
| 1654 | 1678 | }); |
| 1655 | 1679 | |
| 1656 | 1680 | cases.add("for loops", |
| 1657 | \\int foo() { | |
| 1681 | \\void foo() { | |
| 1658 | 1682 | \\ for (int i = 2, b = 4; i + 2; i = 2) { |
| 1659 | 1683 | \\ int a = 2; |
| 1660 | 1684 | \\ a = 6, 5, 7; |
| ... | ... | @@ -1662,7 +1686,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1662 | 1686 | \\ char i = 2; |
| 1663 | 1687 | \\} |
| 1664 | 1688 | , &[_][]const u8{ |
| 1665 | \\pub export fn foo() c_int { | |
| 1689 | \\pub export fn foo() void { | |
| 1666 | 1690 | \\ { |
| 1667 | 1691 | \\ var i: c_int = 2; |
| 1668 | 1692 | \\ var b: c_int = 4; |
| ... | ... | @@ -1712,7 +1736,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1712 | 1736 | }); |
| 1713 | 1737 | |
| 1714 | 1738 | cases.add("switch on int", |
| 1715 | \\int switch_fn(int i) { | |
| 1739 | \\void switch_fn(int i) { | |
| 1716 | 1740 | \\ int res = 0; |
| 1717 | 1741 | \\ switch (i) { |
| 1718 | 1742 | \\ case 0: |
| ... | ... | @@ -1727,19 +1751,19 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1727 | 1751 | \\ } |
| 1728 | 1752 | \\} |
| 1729 | 1753 | , &[_][]const u8{ |
| 1730 | \\pub export fn switch_fn(arg_i: c_int) c_int { | |
| 1754 | \\pub export fn switch_fn(arg_i: c_int) void { | |
| 1731 | 1755 | \\ var i = arg_i; |
| 1732 | 1756 | \\ var res: c_int = 0; |
| 1733 | \\ __switch: { | |
| 1734 | \\ __case_2: { | |
| 1735 | \\ __default: { | |
| 1736 | \\ __case_1: { | |
| 1737 | \\ __case_0: { | |
| 1757 | \\ @"switch": { | |
| 1758 | \\ case_2: { | |
| 1759 | \\ default: { | |
| 1760 | \\ case_1: { | |
| 1761 | \\ case: { | |
| 1738 | 1762 | \\ switch (i) { |
| 1739 | \\ @as(c_int, 0) => break :__case_0, | |
| 1740 | \\ @as(c_int, 1)...@as(c_int, 3) => break :__case_1, | |
| 1741 | \\ else => break :__default, | |
| 1742 | \\ @as(c_int, 4) => break :__case_2, | |
| 1763 | \\ @as(c_int, 0) => break :case, | |
| 1764 | \\ @as(c_int, 1)...@as(c_int, 3) => break :case_1, | |
| 1765 | \\ else => break :default, | |
| 1766 | \\ @as(c_int, 4) => break :case_2, | |
| 1743 | 1767 | \\ } |
| 1744 | 1768 | \\ } |
| 1745 | 1769 | \\ res = 1; |
| ... | ... | @@ -1747,7 +1771,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1747 | 1771 | \\ res = 2; |
| 1748 | 1772 | \\ } |
| 1749 | 1773 | \\ res = (@as(c_int, 3) * i); |
| 1750 | \\ break :__switch; | |
| 1774 | \\ break :@"switch"; | |
| 1751 | 1775 | \\ } |
| 1752 | 1776 | \\ res = 5; |
| 1753 | 1777 | \\ } |
| ... | ... | @@ -1787,13 +1811,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1787 | 1811 | }); |
| 1788 | 1812 | |
| 1789 | 1813 | cases.add("assign", |
| 1790 | \\int max(int a) { | |
| 1814 | \\void max(int a) { | |
| 1791 | 1815 | \\ int tmp; |
| 1792 | 1816 | \\ tmp = a; |
| 1793 | 1817 | \\ a = tmp; |
| 1794 | 1818 | \\} |
| 1795 | 1819 | , &[_][]const u8{ |
| 1796 | \\pub export fn max(arg_a: c_int) c_int { | |
| 1820 | \\pub export fn max(arg_a: c_int) void { | |
| 1797 | 1821 | \\ var a = arg_a; |
| 1798 | 1822 | \\ var tmp: c_int = undefined; |
| 1799 | 1823 | \\ tmp = a; |
| ... | ... | @@ -2082,7 +2106,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 2082 | 2106 | \\ int b; |
| 2083 | 2107 | \\}a; |
| 2084 | 2108 | \\float b = 2.0f; |
| 2085 | \\int foo(void) { | |
| 2109 | \\void foo(void) { | |
| 2086 | 2110 | \\ struct Foo *c; |
| 2087 | 2111 | \\ a.b; |
| 2088 | 2112 | \\ c->b; |
| ... | ... | @@ -2093,7 +2117,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 2093 | 2117 | \\}; |
| 2094 | 2118 | \\pub extern var a: struct_Foo; |
| 2095 | 2119 | \\pub export var b: f32 = 2; |
| 2096 | \\pub export fn foo() c_int { | |
| 2120 | \\pub export fn foo() void { | |
| 2097 | 2121 | \\ var c: [*c]struct_Foo = undefined; |
| 2098 | 2122 | \\ _ = a.b; |
| 2099 | 2123 | \\ _ = c.*.b; |
| ... | ... | @@ -2204,11 +2228,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 2204 | 2228 | \\ if (a < b) return b; |
| 2205 | 2229 | \\ if (a < b) return b else return a; |
| 2206 | 2230 | \\ if (a < b) {} else {} |
| 2231 | \\ return 0; | |
| 2207 | 2232 | \\} |
| 2208 | 2233 | }); |
| 2209 | 2234 | |
| 2210 | 2235 | cases.add("if statements", |
| 2211 | \\int foo() { | |
| 2236 | \\void foo() { | |
| 2212 | 2237 | \\ if (2) { |
| 2213 | 2238 | \\ int a = 2; |
| 2214 | 2239 | \\ } |
| ... | ... | @@ -2217,7 +2242,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 2217 | 2242 | \\ } |
| 2218 | 2243 | \\} |
| 2219 | 2244 | , &[_][]const u8{ |
| 2220 | \\pub export fn foo() c_int { | |
| 2245 | \\pub export fn foo() void { | |
| 2221 | 2246 | \\ if (true) { |
| 2222 | 2247 | \\ var a: c_int = 2; |
| 2223 | 2248 | \\ } |
| ... | ... | @@ -2782,11 +2807,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 2782 | 2807 | \\ var x = arg_x; |
| 2783 | 2808 | \\ return blk: { |
| 2784 | 2809 | \\ const tmp = x; |
| 2785 | \\ (blk: { | |
| 2810 | \\ (blk_1: { | |
| 2786 | 2811 | \\ const ref = &p; |
| 2787 | \\ const tmp_1 = ref.*; | |
| 2812 | \\ const tmp_2 = ref.*; | |
| 2788 | 2813 | \\ ref.* += 1; |
| 2789 | \\ break :blk tmp_1; | |
| 2814 | \\ break :blk_1 tmp_2; | |
| 2790 | 2815 | \\ }).?.* = tmp; |
| 2791 | 2816 | \\ break :blk tmp; |
| 2792 | 2817 | \\ }; |
| ... | ... | @@ -2811,12 +2836,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 2811 | 2836 | }); |
| 2812 | 2837 | |
| 2813 | 2838 | cases.add("arg name aliasing decl which comes after", |
| 2814 | \\int foo(int bar) { | |
| 2839 | \\void foo(int bar) { | |
| 2815 | 2840 | \\ bar = 2; |
| 2816 | 2841 | \\} |
| 2817 | 2842 | \\int bar = 4; |
| 2818 | 2843 | , &[_][]const u8{ |
| 2819 | \\pub export fn foo(arg_bar_1: c_int) c_int { | |
| 2844 | \\pub export fn foo(arg_bar_1: c_int) void { | |
| 2820 | 2845 | \\ var bar_1 = arg_bar_1; |
| 2821 | 2846 | \\ bar_1 = 2; |
| 2822 | 2847 | \\} |
| ... | ... | @@ -2824,12 +2849,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 2824 | 2849 | }); |
| 2825 | 2850 | |
| 2826 | 2851 | cases.add("arg name aliasing macro which comes after", |
| 2827 | \\int foo(int bar) { | |
| 2852 | \\void foo(int bar) { | |
| 2828 | 2853 | \\ bar = 2; |
| 2829 | 2854 | \\} |
| 2830 | 2855 | \\#define bar 4 |
| 2831 | 2856 | , &[_][]const u8{ |
| 2832 | \\pub export fn foo(arg_bar_1: c_int) c_int { | |
| 2857 | \\pub export fn foo(arg_bar_1: c_int) void { | |
| 2833 | 2858 | \\ var bar_1 = arg_bar_1; |
| 2834 | 2859 | \\ bar_1 = 2; |
| 2835 | 2860 | \\} |