authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-08-14 01:04:05+03:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2020-08-14 01:04:05+03:00
logf5b99abc93b44239e95378d9958e72999abb6b44
treed18a9199d13c761b986d885dc7e4105559c13541
parent50139aa23245c7b6b6a5faff95f1a2c854051a38
parent13e472aa2a8113df6417c09727297a6106127f8e
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #6045 from Vexu/block

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,7 +322,7 @@ fn parseFormValue(allocator: *mem.Allocator, in_stream: anytype, form_id: u64, e
322 FORM_block1 => parseFormValueBlock(allocator, in_stream, endian, 1),322 FORM_block1 => parseFormValueBlock(allocator, in_stream, endian, 1),
323 FORM_block2 => parseFormValueBlock(allocator, in_stream, endian, 2),323 FORM_block2 => parseFormValueBlock(allocator, in_stream, endian, 2),
324 FORM_block4 => parseFormValueBlock(allocator, in_stream, endian, 4),324 FORM_block4 => parseFormValueBlock(allocator, in_stream, endian, 4),
325 FORM_block => x: {325 FORM_block => {
326 const block_len = try nosuspend leb.readULEB128(usize, in_stream);326 const block_len = try nosuspend leb.readULEB128(usize, in_stream);
327 return parseFormValueBlockLen(allocator, in_stream, block_len);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,7 +129,7 @@ pub fn hash(hasher: anytype, key: anytype, comptime strat: HashStrategy) void {
129 }129 }
130 },130 },
131131
132 .Union => |info| blk: {132 .Union => |info| {
133 if (info.tag_type) |tag_type| {133 if (info.tag_type) |tag_type| {
134 const tag = meta.activeTag(key);134 const tag = meta.activeTag(key);
135 const s = hash(hasher, tag, strat);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,7 +536,7 @@ fn generic_fmod(comptime T: type, x: T, y: T) T {
536 // normalize x and y536 // normalize x and y
537 if (ex == 0) {537 if (ex == 0) {
538 i = ux << exp_bits;538 i = ux << exp_bits;
539 while (i >> bits_minus_1 == 0) : (b: {539 while (i >> bits_minus_1 == 0) : ({
540 ex -= 1;540 ex -= 1;
541 i <<= 1;541 i <<= 1;
542 }) {}542 }) {}
...@@ -547,7 +547,7 @@ fn generic_fmod(comptime T: type, x: T, y: T) T {...@@ -547,7 +547,7 @@ fn generic_fmod(comptime T: type, x: T, y: T) T {
547 }547 }
548 if (ey == 0) {548 if (ey == 0) {
549 i = uy << exp_bits;549 i = uy << exp_bits;
550 while (i >> bits_minus_1 == 0) : (b: {550 while (i >> bits_minus_1 == 0) : ({
551 ey -= 1;551 ey -= 1;
552 i <<= 1;552 i <<= 1;
553 }) {}553 }) {}
...@@ -573,7 +573,7 @@ fn generic_fmod(comptime T: type, x: T, y: T) T {...@@ -573,7 +573,7 @@ fn generic_fmod(comptime T: type, x: T, y: T) T {
573 return 0 * x;573 return 0 * x;
574 ux = i;574 ux = i;
575 }575 }
576 while (ux >> digits == 0) : (b: {576 while (ux >> digits == 0) : ({
577 ux <<= 1;577 ux <<= 1;
578 ex -= 1;578 ex -= 1;
579 }) {}579 }) {}
lib/std/zig/render.zig+1-1
...@@ -2385,7 +2385,7 @@ fn renderTokenOffset(...@@ -2385,7 +2385,7 @@ fn renderTokenOffset(
2385 }2385 }
2386 }2386 }
23872387
2388 if (next_token_id != .LineComment) blk: {2388 if (next_token_id != .LineComment) {
2389 switch (space) {2389 switch (space) {
2390 Space.None, Space.NoNewline => return,2390 Space.None, Space.NoNewline => return,
2391 Space.Newline => {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,7 +2811,7 @@ pub fn floatAdd(self: *Module, scope: *Scope, float_type: Type, src: usize, lhs:
2811 val_payload.* = .{ .val = lhs_val + rhs_val };2811 val_payload.* = .{ .val = lhs_val + rhs_val };
2812 break :blk &val_payload.base;2812 break :blk &val_payload.base;
2813 },2813 },
2814 128 => blk: {2814 128 => {
2815 return self.fail(scope, src, "TODO Implement addition for big floats", .{});2815 return self.fail(scope, src, "TODO Implement addition for big floats", .{});
2816 },2816 },
2817 else => unreachable,2817 else => unreachable,
...@@ -2845,7 +2845,7 @@ pub fn floatSub(self: *Module, scope: *Scope, float_type: Type, src: usize, lhs:...@@ -2845,7 +2845,7 @@ pub fn floatSub(self: *Module, scope: *Scope, float_type: Type, src: usize, lhs:
2845 val_payload.* = .{ .val = lhs_val - rhs_val };2845 val_payload.* = .{ .val = lhs_val - rhs_val };
2846 break :blk &val_payload.base;2846 break :blk &val_payload.base;
2847 },2847 },
2848 128 => blk: {2848 128 => {
2849 return self.fail(scope, src, "TODO Implement substraction for big floats", .{});2849 return self.fail(scope, src, "TODO Implement substraction for big floats", .{});
2850 },2850 },
2851 else => unreachable,2851 else => unreachable,
src-self-hosted/translate_c.zig+114-62
...@@ -61,7 +61,8 @@ const Scope = struct {...@@ -61,7 +61,8 @@ const Scope = struct {
61 pending_block: Block,61 pending_block: Block,
62 cases: []*ast.Node,62 cases: []*ast.Node,
63 case_index: usize,63 case_index: usize,
64 has_default: bool = false,64 switch_label: ?[]const u8,
65 default_label: ?[]const u8,
65 };66 };
6667
67 /// Used for the scope of condition expressions, for example `if (cond)`.68 /// Used for the scope of condition expressions, for example `if (cond)`.
...@@ -73,7 +74,7 @@ const Scope = struct {...@@ -73,7 +74,7 @@ const Scope = struct {
7374
74 fn getBlockScope(self: *Condition, c: *Context) !*Block {75 fn getBlockScope(self: *Condition, c: *Context) !*Block {
75 if (self.block) |*b| return b;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 return &self.block.?;78 return &self.block.?;
78 }79 }
7980
...@@ -93,21 +94,22 @@ const Scope = struct {...@@ -93,21 +94,22 @@ const Scope = struct {
93 mangle_count: u32 = 0,94 mangle_count: u32 = 0,
94 lbrace: ast.TokenIndex,95 lbrace: ast.TokenIndex,
9596
96 fn init(c: *Context, parent: *Scope, label: ?[]const u8) !Block {97 fn init(c: *Context, parent: *Scope, labeled: bool) !Block {
97 return Block{98 var blk = Block{
98 .base = .{99 .base = .{
99 .id = .Block,100 .id = .Block,
100 .parent = parent,101 .parent = parent,
101 },102 },
102 .statements = std.ArrayList(*ast.Node).init(c.gpa),103 .statements = std.ArrayList(*ast.Node).init(c.gpa),
103 .variables = AliasList.init(c.gpa),104 .variables = AliasList.init(c.gpa),
104 .label = if (label) |l| blk: {105 .label = null,
105 const ll = try appendIdentifier(c, l);
106 _ = try appendToken(c, .Colon, ":");
107 break :blk ll;
108 } else null,
109 .lbrace = try appendToken(c, .LBrace, "{"),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 }
112114
113 fn deinit(self: *Block) void {115 fn deinit(self: *Block) void {
...@@ -577,7 +579,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {...@@ -577,7 +579,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {
577579
578 // actual function definition with body580 // actual function definition with body
579 const body_stmt = ZigClangFunctionDecl_getBody(fn_decl);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 defer block_scope.deinit();583 defer block_scope.deinit();
582 var scope = &block_scope.base;584 var scope = &block_scope.base;
583585
...@@ -626,6 +628,46 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {...@@ -626,6 +628,46 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {
626 error.UnsupportedType,628 error.UnsupportedType,
627 => return failDecl(c, fn_decl_loc, fn_name, "unable to translate function", .{}),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 const body_node = try block_scope.complete(rp.c);671 const body_node = try block_scope.complete(rp.c);
630 proto_node.setTrailer("body_node", &body_node.base);672 proto_node.setTrailer("body_node", &body_node.base);
631 return addTopLevelDecl(c, fn_name, &proto_node.base);673 return addTopLevelDecl(c, fn_name, &proto_node.base);
...@@ -931,7 +973,7 @@ fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!?*...@@ -931,7 +973,7 @@ fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!?*
931 else => |e| return e,973 else => |e| return e,
932 };974 };
933975
934 const align_expr = blk: {976 const align_expr = blk_2: {
935 const alignment = ZigClangFieldDecl_getAlignedAttribute(field_decl, rp.c.clang_context);977 const alignment = ZigClangFieldDecl_getAlignedAttribute(field_decl, rp.c.clang_context);
936 if (alignment != 0) {978 if (alignment != 0) {
937 _ = try appendToken(rp.c, .Keyword_align, "align");979 _ = try appendToken(rp.c, .Keyword_align, "align");
...@@ -940,9 +982,9 @@ fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!?*...@@ -940,9 +982,9 @@ fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!?*
940 const expr = try transCreateNodeInt(rp.c, alignment / 8);982 const expr = try transCreateNodeInt(rp.c, alignment / 8);
941 _ = try appendToken(rp.c, .RParen, ")");983 _ = try appendToken(rp.c, .RParen, ")");
942984
943 break :blk expr;985 break :blk_2 expr;
944 }986 }
945 break :blk null;987 break :blk_2 null;
946 };988 };
947989
948 const field_node = try c.arena.create(ast.Node.ContainerField);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,9 +1115,9 @@ fn transEnumDecl(c: *Context, enum_decl: *const ZigClangEnumDecl) Error!?*ast.No
10731115
1074 const field_name_tok = try appendIdentifier(c, field_name);1116 const field_name_tok = try appendIdentifier(c, field_name);
10751117
1076 const int_node = if (!pure_enum) blk: {1118 const int_node = if (!pure_enum) blk_2: {
1077 _ = try appendToken(c, .Colon, "=");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 } else1121 } else
1080 null;1122 null;
10811123
...@@ -1307,7 +1349,7 @@ fn transBinaryOperator(...@@ -1307,7 +1349,7 @@ fn transBinaryOperator(
1307 const rhs = try transExpr(rp, &block_scope.base, ZigClangBinaryOperator_getRHS(stmt), .used, .r_value);1349 const rhs = try transExpr(rp, &block_scope.base, ZigClangBinaryOperator_getRHS(stmt), .used, .r_value);
1308 if (expr) {1350 if (expr) {
1309 _ = try appendToken(rp.c, .Semicolon, ";");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 try block_scope.statements.append(&break_node.base);1353 try block_scope.statements.append(&break_node.base);
1312 const block_node = try block_scope.complete(rp.c);1354 const block_node = try block_scope.complete(rp.c);
1313 const rparen = try appendToken(rp.c, .RParen, ")");1355 const rparen = try appendToken(rp.c, .RParen, ")");
...@@ -1476,7 +1518,7 @@ fn transCompoundStmtInline(...@@ -1476,7 +1518,7 @@ fn transCompoundStmtInline(
1476}1518}
14771519
1478fn transCompoundStmt(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangCompoundStmt) TransError!*ast.Node {1520fn 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 defer block_scope.deinit();1522 defer block_scope.deinit();
1481 try transCompoundStmtInline(rp, &block_scope.base, stmt, &block_scope);1523 try transCompoundStmtInline(rp, &block_scope.base, stmt, &block_scope);
1482 const node = try block_scope.complete(rp.c);1524 const node = try block_scope.complete(rp.c);
...@@ -2388,7 +2430,7 @@ fn transZeroInitExpr(...@@ -2388,7 +2430,7 @@ fn transZeroInitExpr(
2388 ty: *const ZigClangType,2430 ty: *const ZigClangType,
2389) TransError!*ast.Node {2431) TransError!*ast.Node {
2390 switch (ZigClangType_getTypeClass(ty)) {2432 switch (ZigClangType_getTypeClass(ty)) {
2391 .Builtin => blk: {2433 .Builtin => {
2392 const builtin_ty = @ptrCast(*const ZigClangBuiltinType, ty);2434 const builtin_ty = @ptrCast(*const ZigClangBuiltinType, ty);
2393 switch (ZigClangBuiltinType_getKind(builtin_ty)) {2435 switch (ZigClangBuiltinType_getKind(builtin_ty)) {
2394 .Bool => return try transCreateNodeBoolLiteral(rp.c, false),2436 .Bool => return try transCreateNodeBoolLiteral(rp.c, false),
...@@ -2587,7 +2629,7 @@ fn transForLoop(...@@ -2587,7 +2629,7 @@ fn transForLoop(
2587 defer if (block_scope) |*bs| bs.deinit();2629 defer if (block_scope) |*bs| bs.deinit();
25882630
2589 if (ZigClangForStmt_getInit(stmt)) |init| {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 loop_scope.parent = &block_scope.?.base;2633 loop_scope.parent = &block_scope.?.base;
2592 const init_node = try transStmt(rp, &block_scope.?.base, init, .unused, .r_value);2634 const init_node = try transStmt(rp, &block_scope.?.base, init, .unused, .r_value);
2593 try block_scope.?.statements.append(init_node);2635 try block_scope.?.statements.append(init_node);
...@@ -2673,17 +2715,19 @@ fn transSwitch(...@@ -2673,17 +2715,19 @@ fn transSwitch(
2673 .cases = switch_node.cases(),2715 .cases = switch_node.cases(),
2674 .case_index = 0,2716 .case_index = 0,
2675 .pending_block = undefined,2717 .pending_block = undefined,
2718 .default_label = null,
2719 .switch_label = null,
2676 };2720 };
26772721
2678 // tmp block that all statements will go before being picked up by a case or default2722 // 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 defer block_scope.deinit();2724 defer block_scope.deinit();
26812725
2682 // Note that we do not defer a deinit here; the switch_scope.pending_block field2726 // Note that we do not defer a deinit here; the switch_scope.pending_block field
2683 // has its own memory management. This resource is freed inside `transCase` and2727 // has its own memory management. This resource is freed inside `transCase` and
2684 // then the final pending_block is freed at the bottom of this function with2728 // then the final pending_block is freed at the bottom of this function with
2685 // pending_block.deinit().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 try switch_scope.pending_block.statements.append(&switch_node.base);2731 try switch_scope.pending_block.statements.append(&switch_node.base);
26882732
2689 const last = try transStmt(rp, &block_scope.base, ZigClangSwitchStmt_getBody(stmt), .unused, .r_value);2733 const last = try transStmt(rp, &block_scope.base, ZigClangSwitchStmt_getBody(stmt), .unused, .r_value);
...@@ -2698,11 +2742,19 @@ fn transSwitch(...@@ -2698,11 +2742,19 @@ fn transSwitch(
2698 switch_scope.pending_block.statements.appendAssumeCapacity(n);2742 switch_scope.pending_block.statements.appendAssumeCapacity(n);
2699 }2743 }
27002744
2701 switch_scope.pending_block.label = try appendIdentifier(rp.c, "__switch");2745 if (switch_scope.default_label == null) {
2702 _ = try appendToken(rp.c, .Colon, ":");2746 switch_scope.switch_label = try block_scope.makeMangledName(rp.c, "switch");
2703 if (!switch_scope.has_default) {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 const else_prong = try transCreateNodeSwitchCase(rp.c, try transCreateNodeSwitchElse(rp.c));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 _ = try appendToken(rp.c, .Comma, ",");2758 _ = try appendToken(rp.c, .Comma, ",");
27072759
2708 if (switch_scope.case_index >= switch_scope.cases.len)2760 if (switch_scope.case_index >= switch_scope.cases.len)
...@@ -2726,7 +2778,7 @@ fn transCase(...@@ -2726,7 +2778,7 @@ fn transCase(
2726) TransError!*ast.Node {2778) TransError!*ast.Node {
2727 const block_scope = scope.findBlockScope(rp.c) catch unreachable;2779 const block_scope = scope.findBlockScope(rp.c) catch unreachable;
2728 const switch_scope = scope.getSwitch();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 _ = try appendToken(rp.c, .Semicolon, ";");2782 _ = try appendToken(rp.c, .Semicolon, ";");
27312783
2732 const expr = if (ZigClangCaseStmt_getRHS(stmt)) |rhs| blk: {2784 const expr = if (ZigClangCaseStmt_getRHS(stmt)) |rhs| blk: {
...@@ -2746,7 +2798,10 @@ fn transCase(...@@ -2746,7 +2798,10 @@ fn transCase(
2746 try transExpr(rp, scope, ZigClangCaseStmt_getLHS(stmt), .used, .r_value);2798 try transExpr(rp, scope, ZigClangCaseStmt_getLHS(stmt), .used, .r_value);
27472799
2748 const switch_prong = try transCreateNodeSwitchCase(rp.c, expr);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 _ = try appendToken(rp.c, .Comma, ",");2805 _ = try appendToken(rp.c, .Comma, ",");
27512806
2752 if (switch_scope.case_index >= switch_scope.cases.len)2807 if (switch_scope.case_index >= switch_scope.cases.len)
...@@ -2763,7 +2818,7 @@ fn transCase(...@@ -2763,7 +2818,7 @@ fn transCase(
27632818
2764 const pending_node = try switch_scope.pending_block.complete(rp.c);2819 const pending_node = try switch_scope.pending_block.complete(rp.c);
2765 switch_scope.pending_block.deinit();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);
27672822
2768 try switch_scope.pending_block.statements.append(&pending_node.base);2823 try switch_scope.pending_block.statements.append(&pending_node.base);
27692824
...@@ -2777,12 +2832,14 @@ fn transDefault(...@@ -2777,12 +2832,14 @@ fn transDefault(
2777) TransError!*ast.Node {2832) TransError!*ast.Node {
2778 const block_scope = scope.findBlockScope(rp.c) catch unreachable;2833 const block_scope = scope.findBlockScope(rp.c) catch unreachable;
2779 const switch_scope = scope.getSwitch();2834 const switch_scope = scope.getSwitch();
2780 const label = "__default";2835 switch_scope.default_label = try block_scope.makeMangledName(rp.c, "default");
2781 switch_scope.has_default = true;
2782 _ = try appendToken(rp.c, .Semicolon, ";");2836 _ = try appendToken(rp.c, .Semicolon, ";");
27832837
2784 const else_prong = try transCreateNodeSwitchCase(rp.c, try transCreateNodeSwitchElse(rp.c));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 _ = try appendToken(rp.c, .Comma, ",");2843 _ = try appendToken(rp.c, .Comma, ",");
27872844
2788 if (switch_scope.case_index >= switch_scope.cases.len)2845 if (switch_scope.case_index >= switch_scope.cases.len)
...@@ -2790,7 +2847,7 @@ fn transDefault(...@@ -2790,7 +2847,7 @@ fn transDefault(
2790 switch_scope.cases[switch_scope.case_index] = &else_prong.base;2847 switch_scope.cases[switch_scope.case_index] = &else_prong.base;
2791 switch_scope.case_index += 1;2848 switch_scope.case_index += 1;
27922849
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 _ = try appendToken(rp.c, .Colon, ":");2851 _ = try appendToken(rp.c, .Colon, ":");
27952852
2796 // take all pending statements2853 // take all pending statements
...@@ -2799,7 +2856,7 @@ fn transDefault(...@@ -2799,7 +2856,7 @@ fn transDefault(
27992856
2800 const pending_node = try switch_scope.pending_block.complete(rp.c);2857 const pending_node = try switch_scope.pending_block.complete(rp.c);
2801 switch_scope.pending_block.deinit();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 try switch_scope.pending_block.statements.append(&pending_node.base);2860 try switch_scope.pending_block.statements.append(&pending_node.base);
28042861
2805 return transStmt(rp, scope, ZigClangDefaultStmt_getSubStmt(stmt), .unused, .r_value);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,7 +2951,7 @@ fn transStmtExpr(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangStmtExpr,
2894 return transCompoundStmt(rp, scope, comp);2951 return transCompoundStmt(rp, scope, comp);
2895 }2952 }
2896 const lparen = try appendToken(rp.c, .LParen, "(");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 defer block_scope.deinit();2955 defer block_scope.deinit();
28992956
2900 var it = ZigClangCompoundStmt_body_begin(comp);2957 var it = ZigClangCompoundStmt_body_begin(comp);
...@@ -3209,7 +3266,7 @@ fn transCreatePreCrement(...@@ -3209,7 +3266,7 @@ fn transCreatePreCrement(
3209 // zig: _ref.* += 1;3266 // zig: _ref.* += 1;
3210 // zig: break :blk _ref.*3267 // zig: break :blk _ref.*
3211 // zig: })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 defer block_scope.deinit();3270 defer block_scope.deinit();
3214 const ref = try block_scope.makeMangledName(rp.c, "ref");3271 const ref = try block_scope.makeMangledName(rp.c, "ref");
32153272
...@@ -3239,7 +3296,7 @@ fn transCreatePreCrement(...@@ -3239,7 +3296,7 @@ fn transCreatePreCrement(
3239 const assign = try transCreateNodeInfixOp(rp, scope, ref_node, op, token, one, .used, false);3296 const assign = try transCreateNodeInfixOp(rp, scope, ref_node, op, token, one, .used, false);
3240 try block_scope.statements.append(assign);3297 try block_scope.statements.append(assign);
32413298
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 try block_scope.statements.append(&break_node.base);3300 try block_scope.statements.append(&break_node.base);
3244 const block_node = try block_scope.complete(rp.c);3301 const block_node = try block_scope.complete(rp.c);
3245 // semicolon must immediately follow rbrace because it is the last token in a block3302 // semicolon must immediately follow rbrace because it is the last token in a block
...@@ -3283,7 +3340,7 @@ fn transCreatePostCrement(...@@ -3283,7 +3340,7 @@ fn transCreatePostCrement(
3283 // zig: _ref.* += 1;3340 // zig: _ref.* += 1;
3284 // zig: break :blk _tmp3341 // zig: break :blk _tmp
3285 // zig: })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 defer block_scope.deinit();3344 defer block_scope.deinit();
3288 const ref = try block_scope.makeMangledName(rp.c, "ref");3345 const ref = try block_scope.makeMangledName(rp.c, "ref");
32893346
...@@ -3458,7 +3515,7 @@ fn transCreateCompoundAssign(...@@ -3458,7 +3515,7 @@ fn transCreateCompoundAssign(
3458 // zig: _ref.* = _ref.* + rhs;3515 // zig: _ref.* = _ref.* + rhs;
3459 // zig: break :blk _ref.*3516 // zig: break :blk _ref.*
3460 // zig: })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 defer block_scope.deinit();3519 defer block_scope.deinit();
3463 const ref = try block_scope.makeMangledName(rp.c, "ref");3520 const ref = try block_scope.makeMangledName(rp.c, "ref");
34643521
...@@ -3526,7 +3583,7 @@ fn transCreateCompoundAssign(...@@ -3526,7 +3583,7 @@ fn transCreateCompoundAssign(
3526 try block_scope.statements.append(assign);3583 try block_scope.statements.append(assign);
3527 }3584 }
35283585
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 try block_scope.statements.append(&break_node.base);3587 try block_scope.statements.append(&break_node.base);
3531 const block_node = try block_scope.complete(rp.c);3588 const block_node = try block_scope.complete(rp.c);
3532 const grouped_expr = try rp.c.arena.create(ast.Node.GroupedExpression);3589 const grouped_expr = try rp.c.arena.create(ast.Node.GroupedExpression);
...@@ -3602,8 +3659,16 @@ fn transCPtrCast(...@@ -3602,8 +3659,16 @@ fn transCPtrCast(
36023659
3603fn transBreak(rp: RestorePoint, scope: *Scope) TransError!*ast.Node {3660fn transBreak(rp: RestorePoint, scope: *Scope) TransError!*ast.Node {
3604 const break_scope = scope.getBreakableScope();3661 const break_scope = scope.getBreakableScope();
3605 const label_text: ?[]const u8 = if (break_scope.id == .Switch) "__switch" else null;3662 const label_text: ?[]const u8 = if (break_scope.id == .Switch) blk: {
3606 const br = try transCreateNodeBreak(rp.c, label_text, null);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 _ = try appendToken(rp.c, .Semicolon, ";");3672 _ = try appendToken(rp.c, .Semicolon, ";");
3608 return &br.base;3673 return &br.base;
3609}3674}
...@@ -3634,7 +3699,7 @@ fn transBinaryConditionalOperator(rp: RestorePoint, scope: *Scope, stmt: *const...@@ -3634,7 +3699,7 @@ fn transBinaryConditionalOperator(rp: RestorePoint, scope: *Scope, stmt: *const
3634 // })3699 // })
3635 const lparen = try appendToken(rp.c, .LParen, "(");3700 const lparen = try appendToken(rp.c, .LParen, "(");
36363701
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 defer block_scope.deinit();3703 defer block_scope.deinit();
36393704
3640 const mangled_name = try block_scope.makeMangledName(rp.c, "cond_temp");3705 const mangled_name = try block_scope.makeMangledName(rp.c, "cond_temp");
...@@ -4082,8 +4147,7 @@ fn transCreateNodeAssign(...@@ -4082,8 +4147,7 @@ fn transCreateNodeAssign(
4082 // zig: lhs = _tmp;4147 // zig: lhs = _tmp;
4083 // zig: break :blk _tmp4148 // zig: break :blk _tmp
4084 // zig: })4149 // zig: })
4085 const label_name = "blk";4150 var block_scope = try Scope.Block.init(rp.c, scope, true);
4086 var block_scope = try Scope.Block.init(rp.c, scope, label_name);
4087 defer block_scope.deinit();4151 defer block_scope.deinit();
40884152
4089 const tmp = try block_scope.makeMangledName(rp.c, "tmp");4153 const tmp = try block_scope.makeMangledName(rp.c, "tmp");
...@@ -4118,7 +4182,7 @@ fn transCreateNodeAssign(...@@ -4118,7 +4182,7 @@ fn transCreateNodeAssign(
4118 try block_scope.statements.append(assign);4182 try block_scope.statements.append(assign);
41194183
4120 const break_node = blk: {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 const rhs_expr = try transCreateNodeIdentifier(rp.c, tmp);4186 const rhs_expr = try transCreateNodeIdentifier(rp.c, tmp);
4123 break :blk try tmp_ctrl_flow.finish(rhs_expr);4187 break :blk try tmp_ctrl_flow.finish(rhs_expr);
4124 };4188 };
...@@ -4495,23 +4559,12 @@ fn transCreateNodeElse(c: *Context) !*ast.Node.Else {...@@ -4495,23 +4559,12 @@ fn transCreateNodeElse(c: *Context) !*ast.Node.Else {
4495 return node;4559 return node;
4496}4560}
44974561
4498fn 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
4509fn transCreateNodeBreak(4562fn transCreateNodeBreak(
4510 c: *Context,4563 c: *Context,
4511 label: ?[]const u8,4564 label: ?ast.TokenIndex,
4512 rhs: ?*ast.Node,4565 rhs: ?*ast.Node,
4513) !*ast.Node.ControlFlowExpression {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 return ctrl_flow.finish(rhs);4568 return ctrl_flow.finish(rhs);
4516}4569}
45174570
...@@ -5362,7 +5415,7 @@ fn transMacroDefine(c: *Context, m: *MacroCtx) ParseError!void {...@@ -5362,7 +5415,7 @@ fn transMacroDefine(c: *Context, m: *MacroCtx) ParseError!void {
5362}5415}
53635416
5364fn transMacroFnDefine(c: *Context, m: *MacroCtx) ParseError!void {5417fn 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 defer block_scope.deinit();5419 defer block_scope.deinit();
5367 const scope = &block_scope.base;5420 const scope = &block_scope.base;
53685421
...@@ -5475,8 +5528,7 @@ fn parseCExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node {...@@ -5475,8 +5528,7 @@ fn parseCExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node {
5475 },5528 },
5476 .Comma => {5529 .Comma => {
5477 _ = try appendToken(c, .Semicolon, ";");5530 _ = try appendToken(c, .Semicolon, ";");
5478 const label_name = "blk";5531 var block_scope = try Scope.Block.init(c, scope, true);
5479 var block_scope = try Scope.Block.init(c, scope, label_name);
5480 defer block_scope.deinit();5532 defer block_scope.deinit();
54815533
5482 var last = node;5534 var last = node;
...@@ -5501,7 +5553,7 @@ fn parseCExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node {...@@ -5501,7 +5553,7 @@ fn parseCExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node {
5501 }5553 }
5502 }5554 }
55035555
5504 const break_node = try transCreateNodeBreak(c, label_name, last);5556 const break_node = try transCreateNodeBreak(c, block_scope.label, last);
5505 try block_scope.statements.append(&break_node.base);5557 try block_scope.statements.append(&break_node.base);
5506 const block_node = try block_scope.complete(c);5558 const block_node = try block_scope.complete(c);
5507 return &block_node.base;5559 return &block_node.base;
src/all_types.hpp+3
...@@ -2438,6 +2438,7 @@ struct ScopeBlock {...@@ -2438,6 +2438,7 @@ struct ScopeBlock {
2438 LVal lval;2438 LVal lval;
2439 bool safety_off;2439 bool safety_off;
2440 bool fast_math_on;2440 bool fast_math_on;
2441 bool name_used;
2441};2442};
24422443
2443// This scope is created from every defer expression.2444// This scope is created from every defer expression.
...@@ -2488,6 +2489,8 @@ struct ScopeLoop {...@@ -2488,6 +2489,8 @@ struct ScopeLoop {
2488 ZigList<IrBasicBlockSrc *> *incoming_blocks;2489 ZigList<IrBasicBlockSrc *> *incoming_blocks;
2489 ResultLocPeerParent *peer_parent;2490 ResultLocPeerParent *peer_parent;
2490 ScopeExpr *spill_scope;2491 ScopeExpr *spill_scope;
2492
2493 bool name_used;
2491};2494};
24922495
2493// This scope blocks certain things from working such as comptime continue2496// 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,6 +5476,25 @@ static ResultLocPeer *create_peer_result(ResultLocPeerParent *peer_parent) {
5476 return result;5476 return result;
5477}5477}
54785478
5479static 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
5479static IrInstSrc *ir_gen_block(IrBuilderSrc *irb, Scope *parent_scope, AstNode *block_node, LVal lval,5498static IrInstSrc *ir_gen_block(IrBuilderSrc *irb, Scope *parent_scope, AstNode *block_node, LVal lval,
5480 ResultLoc *result_loc)5499 ResultLoc *result_loc)
5481{5500{
...@@ -5484,6 +5503,9 @@ static IrInstSrc *ir_gen_block(IrBuilderSrc *irb, Scope *parent_scope, AstNode *...@@ -5484,6 +5503,9 @@ static IrInstSrc *ir_gen_block(IrBuilderSrc *irb, Scope *parent_scope, AstNode *
5484 ZigList<IrInstSrc *> incoming_values = {0};5503 ZigList<IrInstSrc *> incoming_values = {0};
5485 ZigList<IrBasicBlockSrc *> incoming_blocks = {0};5504 ZigList<IrBasicBlockSrc *> incoming_blocks = {0};
54865505
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 ScopeBlock *scope_block = create_block_scope(irb->codegen, block_node, parent_scope);5509 ScopeBlock *scope_block = create_block_scope(irb->codegen, block_node, parent_scope);
54885510
5489 Scope *outer_block_scope = &scope_block->base;5511 Scope *outer_block_scope = &scope_block->base;
...@@ -5495,6 +5517,9 @@ static IrInstSrc *ir_gen_block(IrBuilderSrc *irb, Scope *parent_scope, AstNode *...@@ -5495,6 +5517,9 @@ static IrInstSrc *ir_gen_block(IrBuilderSrc *irb, Scope *parent_scope, AstNode *
5495 }5517 }
54965518
5497 if (block_node->data.block.statements.length == 0) {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 return ir_lval_wrap(irb, parent_scope, ir_build_const_void(irb, child_scope, block_node), lval, result_loc);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,6 +5577,10 @@ static IrInstSrc *ir_gen_block(IrBuilderSrc *irb, Scope *parent_scope, AstNode *
5552 }5577 }
5553 }5578 }
55545579
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 if (found_invalid_inst)5584 if (found_invalid_inst)
5556 return irb->codegen->invalid_inst_src;5585 return irb->codegen->invalid_inst_src;
55575586
...@@ -8152,6 +8181,9 @@ static IrInstSrc *ir_gen_while_expr(IrBuilderSrc *irb, Scope *scope, AstNode *no...@@ -8152,6 +8181,9 @@ static IrInstSrc *ir_gen_while_expr(IrBuilderSrc *irb, Scope *scope, AstNode *no
8152 ZigList<IrInstSrc *> incoming_values = {0};8181 ZigList<IrInstSrc *> incoming_values = {0};
8153 ZigList<IrBasicBlockSrc *> incoming_blocks = {0};8182 ZigList<IrBasicBlockSrc *> incoming_blocks = {0};
81548183
8184 if (is_duplicate_label(irb->codegen, payload_scope, node, node->data.while_expr.name))
8185 return irb->codegen->invalid_inst_src;
8186
8155 ScopeLoop *loop_scope = create_loop_scope(irb->codegen, node, payload_scope);8187 ScopeLoop *loop_scope = create_loop_scope(irb->codegen, node, payload_scope);
8156 loop_scope->break_block = end_block;8188 loop_scope->break_block = end_block;
8157 loop_scope->continue_block = continue_block;8189 loop_scope->continue_block = continue_block;
...@@ -8169,6 +8201,10 @@ static IrInstSrc *ir_gen_while_expr(IrBuilderSrc *irb, Scope *scope, AstNode *no...@@ -8169,6 +8201,10 @@ static IrInstSrc *ir_gen_while_expr(IrBuilderSrc *irb, Scope *scope, AstNode *no
8169 if (body_result == irb->codegen->invalid_inst_src)8201 if (body_result == irb->codegen->invalid_inst_src)
8170 return body_result;8202 return body_result;
81718203
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 if (!instr_is_unreachable(body_result)) {8208 if (!instr_is_unreachable(body_result)) {
8173 ir_mark_gen(ir_build_check_statement_is_void(irb, payload_scope, node->data.while_expr.body, body_result));8209 ir_mark_gen(ir_build_check_statement_is_void(irb, payload_scope, node->data.while_expr.body, body_result));
8174 ir_mark_gen(ir_build_br(irb, payload_scope, node, continue_block, is_comptime));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,6 +8299,9 @@ static IrInstSrc *ir_gen_while_expr(IrBuilderSrc *irb, Scope *scope, AstNode *no
8263 ZigList<IrInstSrc *> incoming_values = {0};8299 ZigList<IrInstSrc *> incoming_values = {0};
8264 ZigList<IrBasicBlockSrc *> incoming_blocks = {0};8300 ZigList<IrBasicBlockSrc *> incoming_blocks = {0};
82658301
8302 if (is_duplicate_label(irb->codegen, child_scope, node, node->data.while_expr.name))
8303 return irb->codegen->invalid_inst_src;
8304
8266 ScopeLoop *loop_scope = create_loop_scope(irb->codegen, node, child_scope);8305 ScopeLoop *loop_scope = create_loop_scope(irb->codegen, node, child_scope);
8267 loop_scope->break_block = end_block;8306 loop_scope->break_block = end_block;
8268 loop_scope->continue_block = continue_block;8307 loop_scope->continue_block = continue_block;
...@@ -8280,6 +8319,10 @@ static IrInstSrc *ir_gen_while_expr(IrBuilderSrc *irb, Scope *scope, AstNode *no...@@ -8280,6 +8319,10 @@ static IrInstSrc *ir_gen_while_expr(IrBuilderSrc *irb, Scope *scope, AstNode *no
8280 if (body_result == irb->codegen->invalid_inst_src)8319 if (body_result == irb->codegen->invalid_inst_src)
8281 return body_result;8320 return body_result;
82828321
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 if (!instr_is_unreachable(body_result)) {8326 if (!instr_is_unreachable(body_result)) {
8284 ir_mark_gen(ir_build_check_statement_is_void(irb, child_scope, node->data.while_expr.body, body_result));8327 ir_mark_gen(ir_build_check_statement_is_void(irb, child_scope, node->data.while_expr.body, body_result));
8285 ir_mark_gen(ir_build_br(irb, child_scope, node, continue_block, is_comptime));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,6 +8396,9 @@ static IrInstSrc *ir_gen_while_expr(IrBuilderSrc *irb, Scope *scope, AstNode *no
83538396
8354 Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime);8397 Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime);
83558398
8399 if (is_duplicate_label(irb->codegen, subexpr_scope, node, node->data.while_expr.name))
8400 return irb->codegen->invalid_inst_src;
8401
8356 ScopeLoop *loop_scope = create_loop_scope(irb->codegen, node, subexpr_scope);8402 ScopeLoop *loop_scope = create_loop_scope(irb->codegen, node, subexpr_scope);
8357 loop_scope->break_block = end_block;8403 loop_scope->break_block = end_block;
8358 loop_scope->continue_block = continue_block;8404 loop_scope->continue_block = continue_block;
...@@ -8369,6 +8415,10 @@ static IrInstSrc *ir_gen_while_expr(IrBuilderSrc *irb, Scope *scope, AstNode *no...@@ -8369,6 +8415,10 @@ static IrInstSrc *ir_gen_while_expr(IrBuilderSrc *irb, Scope *scope, AstNode *no
8369 if (body_result == irb->codegen->invalid_inst_src)8415 if (body_result == irb->codegen->invalid_inst_src)
8370 return body_result;8416 return body_result;
83718417
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 if (!instr_is_unreachable(body_result)) {8422 if (!instr_is_unreachable(body_result)) {
8373 ir_mark_gen(ir_build_check_statement_is_void(irb, scope, node->data.while_expr.body, body_result));8423 ir_mark_gen(ir_build_check_statement_is_void(irb, scope, node->data.while_expr.body, body_result));
8374 ir_mark_gen(ir_build_br(irb, scope, node, continue_block, is_comptime));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,6 +8551,9 @@ static IrInstSrc *ir_gen_for_expr(IrBuilderSrc *irb, Scope *parent_scope, AstNod
8501 elem_ptr : ir_build_load_ptr(irb, &spill_scope->base, elem_node, elem_ptr);8551 elem_ptr : ir_build_load_ptr(irb, &spill_scope->base, elem_node, elem_ptr);
8502 build_decl_var_and_init(irb, parent_scope, elem_node, elem_var, elem_value, buf_ptr(elem_var_name), is_comptime);8552 build_decl_var_and_init(irb, parent_scope, elem_node, elem_var, elem_value, buf_ptr(elem_var_name), is_comptime);
85038553
8554 if (is_duplicate_label(irb->codegen, child_scope, node, node->data.for_expr.name))
8555 return irb->codegen->invalid_inst_src;
8556
8504 ZigList<IrInstSrc *> incoming_values = {0};8557 ZigList<IrInstSrc *> incoming_values = {0};
8505 ZigList<IrBasicBlockSrc *> incoming_blocks = {0};8558 ZigList<IrBasicBlockSrc *> incoming_blocks = {0};
8506 ScopeLoop *loop_scope = create_loop_scope(irb->codegen, node, child_scope);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,6 +8573,10 @@ static IrInstSrc *ir_gen_for_expr(IrBuilderSrc *irb, Scope *parent_scope, AstNod
8520 if (body_result == irb->codegen->invalid_inst_src)8573 if (body_result == irb->codegen->invalid_inst_src)
8521 return irb->codegen->invalid_inst_src;8574 return irb->codegen->invalid_inst_src;
85228575
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 if (!instr_is_unreachable(body_result)) {8580 if (!instr_is_unreachable(body_result)) {
8524 ir_mark_gen(ir_build_check_statement_is_void(irb, child_scope, node->data.for_expr.body, body_result));8581 ir_mark_gen(ir_build_check_statement_is_void(irb, child_scope, node->data.for_expr.body, body_result));
8525 ir_mark_gen(ir_build_br(irb, child_scope, node, continue_block, is_comptime));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,6 +9521,7 @@ static IrInstSrc *ir_gen_break(IrBuilderSrc *irb, Scope *break_scope, AstNode *n
9464 if (node->data.break_expr.name == nullptr ||9521 if (node->data.break_expr.name == nullptr ||
9465 (this_loop_scope->name != nullptr && buf_eql_buf(node->data.break_expr.name, this_loop_scope->name)))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 loop_scope = this_loop_scope;9525 loop_scope = this_loop_scope;
9468 break;9526 break;
9469 }9527 }
...@@ -9473,6 +9531,7 @@ static IrInstSrc *ir_gen_break(IrBuilderSrc *irb, Scope *break_scope, AstNode *n...@@ -9473,6 +9531,7 @@ static IrInstSrc *ir_gen_break(IrBuilderSrc *irb, Scope *break_scope, AstNode *n
9473 (this_block_scope->name != nullptr && buf_eql_buf(node->data.break_expr.name, this_block_scope->name)))9531 (this_block_scope->name != nullptr && buf_eql_buf(node->data.break_expr.name, this_block_scope->name)))
9474 {9532 {
9475 assert(this_block_scope->end_block != nullptr);9533 assert(this_block_scope->end_block != nullptr);
9534 this_block_scope->name_used = true;
9476 return ir_gen_return_from_block(irb, break_scope, node, this_block_scope);9535 return ir_gen_return_from_block(irb, break_scope, node, this_block_scope);
9477 }9536 }
9478 } else if (search_scope->id == ScopeIdSuspend) {9537 } else if (search_scope->id == ScopeIdSuspend) {
...@@ -9540,6 +9599,7 @@ static IrInstSrc *ir_gen_continue(IrBuilderSrc *irb, Scope *continue_scope, AstN...@@ -9540,6 +9599,7 @@ static IrInstSrc *ir_gen_continue(IrBuilderSrc *irb, Scope *continue_scope, AstN
9540 if (node->data.continue_expr.name == nullptr ||9599 if (node->data.continue_expr.name == nullptr ||
9541 (this_loop_scope->name != nullptr && buf_eql_buf(node->data.continue_expr.name, this_loop_scope->name)))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 loop_scope = this_loop_scope;9603 loop_scope = this_loop_scope;
9544 break;9604 break;
9545 }9605 }
test/compile_errors.zig+23
...@@ -2,6 +2,29 @@ const tests = @import("tests.zig");...@@ -2,6 +2,29 @@ const tests = @import("tests.zig");
2const std = @import("std");2const std = @import("std");
33
4pub fn addCases(cases: *tests.CompileErrorContext) void {4pub 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 cases.addTest("@alignCast of zero sized types",28 cases.addTest("@alignCast of zero sized types",
6 \\export fn foo() void {29 \\export fn foo() void {
7 \\ const a: *void = undefined;30 \\ const a: *void = undefined;
test/run_translated_c.zig-1
...@@ -15,7 +15,6 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void {...@@ -15,7 +15,6 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void {
15 \\ }15 \\ }
16 \\ if (s0 != 1) abort();16 \\ if (s0 != 1) abort();
17 \\ if (s1 != 10) abort();17 \\ if (s1 != 10) abort();
18 \\ return 0;
19 \\}18 \\}
20 , "");19 , "");
2120
test/translate_c.zig+56-31
...@@ -3,12 +3,33 @@ const std = @import("std");...@@ -3,12 +3,33 @@ const std = @import("std");
3const CrossTarget = std.zig.CrossTarget;3const CrossTarget = std.zig.CrossTarget;
44
5pub fn addCases(cases: *tests.TranslateCContext) void {5pub 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 cases.add("alignof",27 cases.add("alignof",
7 \\int main() {28 \\void main() {
8 \\ int a = _Alignof(int);29 \\ int a = _Alignof(int);
9 \\}30 \\}
10 , &[_][]const u8{31 , &[_][]const u8{
11 \\pub export fn main() c_int {32 \\pub export fn main() void {
12 \\ var a: c_int = @bitCast(c_int, @truncate(c_uint, @alignOf(c_int)));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,6 +560,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
539 \\ c = (a * b);560 \\ c = (a * b);
540 \\ c = @divTrunc(a, b);561 \\ c = @divTrunc(a, b);
541 \\ c = @rem(a, b);562 \\ c = @rem(a, b);
563 \\ return 0;
542 \\}564 \\}
543 \\pub export fn u() c_uint {565 \\pub export fn u() c_uint {
544 \\ var a: c_uint = undefined;566 \\ var a: c_uint = undefined;
...@@ -549,6 +571,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -549,6 +571,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
549 \\ c = (a *% b);571 \\ c = (a *% b);
550 \\ c = (a / b);572 \\ c = (a / b);
551 \\ c = (a % b);573 \\ c = (a % b);
574 \\ return 0;
552 \\}575 \\}
553 });576 });
554577
...@@ -1596,13 +1619,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1596,13 +1619,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1596 });1619 });
15971620
1598 cases.add("worst-case assign",1621 cases.add("worst-case assign",
1599 \\int foo() {1622 \\void foo() {
1600 \\ int a;1623 \\ int a;
1601 \\ int b;1624 \\ int b;
1602 \\ a = b = 2;1625 \\ a = b = 2;
1603 \\}1626 \\}
1604 , &[_][]const u8{1627 , &[_][]const u8{
1605 \\pub export fn foo() c_int {1628 \\pub export fn foo() void {
1606 \\ var a: c_int = undefined;1629 \\ var a: c_int = undefined;
1607 \\ var b: c_int = undefined;1630 \\ var b: c_int = undefined;
1608 \\ a = blk: {1631 \\ a = blk: {
...@@ -1650,11 +1673,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1650,11 +1673,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1650 \\ a = 7;1673 \\ a = 7;
1651 \\ if (!true) break;1674 \\ if (!true) break;
1652 \\ }1675 \\ }
1676 \\ return 0;
1653 \\}1677 \\}
1654 });1678 });
16551679
1656 cases.add("for loops",1680 cases.add("for loops",
1657 \\int foo() {1681 \\void foo() {
1658 \\ for (int i = 2, b = 4; i + 2; i = 2) {1682 \\ for (int i = 2, b = 4; i + 2; i = 2) {
1659 \\ int a = 2;1683 \\ int a = 2;
1660 \\ a = 6, 5, 7;1684 \\ a = 6, 5, 7;
...@@ -1662,7 +1686,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1662,7 +1686,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1662 \\ char i = 2;1686 \\ char i = 2;
1663 \\}1687 \\}
1664 , &[_][]const u8{1688 , &[_][]const u8{
1665 \\pub export fn foo() c_int {1689 \\pub export fn foo() void {
1666 \\ {1690 \\ {
1667 \\ var i: c_int = 2;1691 \\ var i: c_int = 2;
1668 \\ var b: c_int = 4;1692 \\ var b: c_int = 4;
...@@ -1712,7 +1736,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1712,7 +1736,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1712 });1736 });
17131737
1714 cases.add("switch on int",1738 cases.add("switch on int",
1715 \\int switch_fn(int i) {1739 \\void switch_fn(int i) {
1716 \\ int res = 0;1740 \\ int res = 0;
1717 \\ switch (i) {1741 \\ switch (i) {
1718 \\ case 0:1742 \\ case 0:
...@@ -1727,19 +1751,19 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1727,19 +1751,19 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1727 \\ }1751 \\ }
1728 \\}1752 \\}
1729 , &[_][]const u8{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 \\ var i = arg_i;1755 \\ var i = arg_i;
1732 \\ var res: c_int = 0;1756 \\ var res: c_int = 0;
1733 \\ __switch: {1757 \\ @"switch": {
1734 \\ __case_2: {1758 \\ case_2: {
1735 \\ __default: {1759 \\ default: {
1736 \\ __case_1: {1760 \\ case_1: {
1737 \\ __case_0: {1761 \\ case: {
1738 \\ switch (i) {1762 \\ switch (i) {
1739 \\ @as(c_int, 0) => break :__case_0,1763 \\ @as(c_int, 0) => break :case,
1740 \\ @as(c_int, 1)...@as(c_int, 3) => break :__case_1,1764 \\ @as(c_int, 1)...@as(c_int, 3) => break :case_1,
1741 \\ else => break :__default,1765 \\ else => break :default,
1742 \\ @as(c_int, 4) => break :__case_2,1766 \\ @as(c_int, 4) => break :case_2,
1743 \\ }1767 \\ }
1744 \\ }1768 \\ }
1745 \\ res = 1;1769 \\ res = 1;
...@@ -1747,7 +1771,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1747,7 +1771,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1747 \\ res = 2;1771 \\ res = 2;
1748 \\ }1772 \\ }
1749 \\ res = (@as(c_int, 3) * i);1773 \\ res = (@as(c_int, 3) * i);
1750 \\ break :__switch;1774 \\ break :@"switch";
1751 \\ }1775 \\ }
1752 \\ res = 5;1776 \\ res = 5;
1753 \\ }1777 \\ }
...@@ -1787,13 +1811,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1787,13 +1811,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1787 });1811 });
17881812
1789 cases.add("assign",1813 cases.add("assign",
1790 \\int max(int a) {1814 \\void max(int a) {
1791 \\ int tmp;1815 \\ int tmp;
1792 \\ tmp = a;1816 \\ tmp = a;
1793 \\ a = tmp;1817 \\ a = tmp;
1794 \\}1818 \\}
1795 , &[_][]const u8{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 \\ var a = arg_a;1821 \\ var a = arg_a;
1798 \\ var tmp: c_int = undefined;1822 \\ var tmp: c_int = undefined;
1799 \\ tmp = a;1823 \\ tmp = a;
...@@ -2082,7 +2106,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -2082,7 +2106,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
2082 \\ int b;2106 \\ int b;
2083 \\}a;2107 \\}a;
2084 \\float b = 2.0f;2108 \\float b = 2.0f;
2085 \\int foo(void) {2109 \\void foo(void) {
2086 \\ struct Foo *c;2110 \\ struct Foo *c;
2087 \\ a.b;2111 \\ a.b;
2088 \\ c->b;2112 \\ c->b;
...@@ -2093,7 +2117,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -2093,7 +2117,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
2093 \\};2117 \\};
2094 \\pub extern var a: struct_Foo;2118 \\pub extern var a: struct_Foo;
2095 \\pub export var b: f32 = 2;2119 \\pub export var b: f32 = 2;
2096 \\pub export fn foo() c_int {2120 \\pub export fn foo() void {
2097 \\ var c: [*c]struct_Foo = undefined;2121 \\ var c: [*c]struct_Foo = undefined;
2098 \\ _ = a.b;2122 \\ _ = a.b;
2099 \\ _ = c.*.b;2123 \\ _ = c.*.b;
...@@ -2204,11 +2228,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -2204,11 +2228,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
2204 \\ if (a < b) return b;2228 \\ if (a < b) return b;
2205 \\ if (a < b) return b else return a;2229 \\ if (a < b) return b else return a;
2206 \\ if (a < b) {} else {}2230 \\ if (a < b) {} else {}
2231 \\ return 0;
2207 \\}2232 \\}
2208 });2233 });
22092234
2210 cases.add("if statements",2235 cases.add("if statements",
2211 \\int foo() {2236 \\void foo() {
2212 \\ if (2) {2237 \\ if (2) {
2213 \\ int a = 2;2238 \\ int a = 2;
2214 \\ }2239 \\ }
...@@ -2217,7 +2242,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -2217,7 +2242,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
2217 \\ }2242 \\ }
2218 \\}2243 \\}
2219 , &[_][]const u8{2244 , &[_][]const u8{
2220 \\pub export fn foo() c_int {2245 \\pub export fn foo() void {
2221 \\ if (true) {2246 \\ if (true) {
2222 \\ var a: c_int = 2;2247 \\ var a: c_int = 2;
2223 \\ }2248 \\ }
...@@ -2782,11 +2807,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -2782,11 +2807,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
2782 \\ var x = arg_x;2807 \\ var x = arg_x;
2783 \\ return blk: {2808 \\ return blk: {
2784 \\ const tmp = x;2809 \\ const tmp = x;
2785 \\ (blk: {2810 \\ (blk_1: {
2786 \\ const ref = &p;2811 \\ const ref = &p;
2787 \\ const tmp_1 = ref.*;2812 \\ const tmp_2 = ref.*;
2788 \\ ref.* += 1;2813 \\ ref.* += 1;
2789 \\ break :blk tmp_1;2814 \\ break :blk_1 tmp_2;
2790 \\ }).?.* = tmp;2815 \\ }).?.* = tmp;
2791 \\ break :blk tmp;2816 \\ break :blk tmp;
2792 \\ };2817 \\ };
...@@ -2811,12 +2836,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -2811,12 +2836,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
2811 });2836 });
28122837
2813 cases.add("arg name aliasing decl which comes after",2838 cases.add("arg name aliasing decl which comes after",
2814 \\int foo(int bar) {2839 \\void foo(int bar) {
2815 \\ bar = 2;2840 \\ bar = 2;
2816 \\}2841 \\}
2817 \\int bar = 4;2842 \\int bar = 4;
2818 , &[_][]const u8{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 \\ var bar_1 = arg_bar_1;2845 \\ var bar_1 = arg_bar_1;
2821 \\ bar_1 = 2;2846 \\ bar_1 = 2;
2822 \\}2847 \\}
...@@ -2824,12 +2849,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -2824,12 +2849,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
2824 });2849 });
28252850
2826 cases.add("arg name aliasing macro which comes after",2851 cases.add("arg name aliasing macro which comes after",
2827 \\int foo(int bar) {2852 \\void foo(int bar) {
2828 \\ bar = 2;2853 \\ bar = 2;
2829 \\}2854 \\}
2830 \\#define bar 42855 \\#define bar 4
2831 , &[_][]const u8{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 \\ var bar_1 = arg_bar_1;2858 \\ var bar_1 = arg_bar_1;
2834 \\ bar_1 = 2;2859 \\ bar_1 = 2;
2835 \\}2860 \\}