| 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,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 | }, |
| 131 | 131 | ||
| 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 y | 536 | // 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 | } |
| 2387 | 2387 | ||
| 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 | }; |
| 66 | 67 | ||
| 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 { |
| 73 | 74 | ||
| 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 | } |
| 79 | 80 | ||
| ... | @@ -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, |
| 95 | 96 | ||
| 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 | } |
| 112 | 114 | ||
| 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 { |
| 577 | 579 | ||
| 578 | // actual function definition with body | 580 | // 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; |
| 583 | 585 | ||
| ... | @@ -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 | }; |
| 933 | 975 | ||
| 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, ")"); |
| 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 | 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 |
| 1073 | 1115 | ||
| 1074 | const field_name_tok = try appendIdentifier(c, field_name); | 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 | _ = 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 | } else | 1121 | } else |
| 1080 | null; | 1122 | null; |
| 1081 | 1123 | ||
| ... | @@ -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 | } |
| 1477 | 1519 | ||
| 1478 | fn transCompoundStmt(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangCompoundStmt) TransError!*ast.Node { | 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 | 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(); |
| 2588 | 2630 | ||
| 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 | }; |
| 2677 | 2721 | ||
| 2678 | // tmp block that all statements will go before being picked up by a case or default | 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 | defer block_scope.deinit(); | 2724 | defer block_scope.deinit(); |
| 2681 | 2725 | ||
| 2682 | // Note that we do not defer a deinit here; the switch_scope.pending_block field | 2726 | // 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` and | 2727 | // 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 with | 2728 | // 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); |
| 2688 | 2732 | ||
| 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 | } |
| 2700 | 2744 | ||
| 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, ","); |
| 2707 | 2759 | ||
| 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, ";"); |
| 2731 | 2783 | ||
| 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); |
| 2747 | 2799 | ||
| 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, ","); |
| 2751 | 2806 | ||
| 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( |
| 2763 | 2818 | ||
| 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); |
| 2767 | 2822 | ||
| 2768 | try switch_scope.pending_block.statements.append(&pending_node.base); | 2823 | try switch_scope.pending_block.statements.append(&pending_node.base); |
| 2769 | 2824 | ||
| ... | @@ -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, ";"); |
| 2783 | 2837 | ||
| 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, ","); |
| 2787 | 2844 | ||
| 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; |
| 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 | _ = try appendToken(rp.c, .Colon, ":"); | 2851 | _ = try appendToken(rp.c, .Colon, ":"); |
| 2795 | 2852 | ||
| 2796 | // take all pending statements | 2853 | // take all pending statements |
| ... | @@ -2799,7 +2856,7 @@ fn transDefault( | ... | @@ -2799,7 +2856,7 @@ fn transDefault( |
| 2799 | 2856 | ||
| 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); |
| 2804 | 2861 | ||
| 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(); |
| 2899 | 2956 | ||
| 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"); |
| 3215 | 3272 | ||
| ... | @@ -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); |
| 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 | 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 block | 3302 | // 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 _tmp | 3341 | // 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"); |
| 3289 | 3346 | ||
| ... | @@ -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"); |
| 3464 | 3521 | ||
| ... | @@ -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 | } |
| 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 | 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( |
| 3602 | 3659 | ||
| 3603 | fn transBreak(rp: RestorePoint, scope: *Scope) TransError!*ast.Node { | 3660 | fn 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, "("); |
| 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 | defer block_scope.deinit(); | 3703 | defer block_scope.deinit(); |
| 3639 | 3704 | ||
| 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 _tmp | 4148 | // 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(); |
| 4088 | 4152 | ||
| 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); |
| 4119 | 4183 | ||
| 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 | } |
| 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 | fn transCreateNodeBreak( | 4562 | fn 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 | } |
| 4517 | 4570 | ||
| ... | @@ -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 | } |
| 5363 | 5416 | ||
| 5364 | fn transMacroFnDefine(c: *Context, m: *MacroCtx) ParseError!void { | 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 | defer block_scope.deinit(); | 5419 | defer block_scope.deinit(); |
| 5367 | const scope = &block_scope.base; | 5420 | const scope = &block_scope.base; |
| 5368 | 5421 | ||
| ... | @@ -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(); |
| 5481 | 5533 | ||
| 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 | } |
| 5503 | 5555 | ||
| 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 | }; |
| 2442 | 2443 | ||
| 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 | }; |
| 2492 | 2495 | ||
| 2493 | // This scope blocks certain things from working such as comptime continue | 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,6 +5476,25 @@ static ResultLocPeer *create_peer_result(ResultLocPeerParent *peer_parent) { |
| 5476 | return result; | 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 | static IrInstSrc *ir_gen_block(IrBuilderSrc *irb, Scope *parent_scope, AstNode *block_node, LVal lval, | 5498 | static 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}; |
| 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 | 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); |
| 5488 | 5510 | ||
| 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 | } |
| 5496 | 5518 | ||
| 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 | } |
| 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 | if (found_invalid_inst) | 5584 | if (found_invalid_inst) |
| 5556 | return irb->codegen->invalid_inst_src; | 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,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}; |
| 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 | 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; |
| 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 | 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}; |
| 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 | 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; |
| 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 | 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 |
| 8353 | 8396 | ||
| 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); |
| 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 | 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; |
| 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 | 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); |
| 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 | 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; |
| 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 | 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"); |
| 2 | const std = @import("std"); | 2 | const std = @import("std"); |
| 3 | 3 | ||
| 4 | pub fn addCases(cases: *tests.CompileErrorContext) void { | 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 | 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 | , ""); |
| 21 | 20 |
test/translate_c.zig+56-31| ... | @@ -3,12 +3,33 @@ const std = @import("std"); | ... | @@ -3,12 +3,33 @@ const std = @import("std"); |
| 3 | const CrossTarget = std.zig.CrossTarget; | 3 | const CrossTarget = std.zig.CrossTarget; |
| 4 | 4 | ||
| 5 | pub fn addCases(cases: *tests.TranslateCContext) void { | 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 | 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 | }); |
| 554 | 577 | ||
| ... | @@ -1596,13 +1619,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -1596,13 +1619,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1596 | }); | 1619 | }); |
| 1597 | 1620 | ||
| 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 | }); |
| 1655 | 1679 | ||
| 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 | }); |
| 1713 | 1737 | ||
| 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 | }); |
| 1788 | 1812 | ||
| 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 | }); |
| 2209 | 2234 | ||
| 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 | }); |
| 2812 | 2837 | ||
| 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 | }); |
| 2825 | 2850 | ||
| 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 4 | 2855 | \\#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 | \\} |