From 373488157751dbaa22415ce842c4f5616fc845ff Mon Sep 17 00:00:00 2001 From: Vexu Date: Wed, 12 Aug 2020 23:35:11 +0300 Subject: add error for unused/duplicate block labels --- lib/std/dwarf.zig | 2 +- lib/std/special/c.zig | 6 +++--- lib/std/zig/render.zig | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'lib/std') diff --git a/lib/std/dwarf.zig b/lib/std/dwarf.zig index c5802240d4..085e394a8f 100644 --- a/lib/std/dwarf.zig +++ b/lib/std/dwarf.zig @@ -322,7 +322,7 @@ fn parseFormValue(allocator: *mem.Allocator, in_stream: anytype, form_id: u64, e FORM_block1 => parseFormValueBlock(allocator, in_stream, endian, 1), FORM_block2 => parseFormValueBlock(allocator, in_stream, endian, 2), FORM_block4 => parseFormValueBlock(allocator, in_stream, endian, 4), - FORM_block => x: { + FORM_block => { const block_len = try nosuspend leb.readULEB128(usize, in_stream); return parseFormValueBlockLen(allocator, in_stream, block_len); }, diff --git a/lib/std/special/c.zig b/lib/std/special/c.zig index c769bc358b..170bb98620 100644 --- a/lib/std/special/c.zig +++ b/lib/std/special/c.zig @@ -536,7 +536,7 @@ fn generic_fmod(comptime T: type, x: T, y: T) T { // normalize x and y if (ex == 0) { i = ux << exp_bits; - while (i >> bits_minus_1 == 0) : (b: { + while (i >> bits_minus_1 == 0) : ({ ex -= 1; i <<= 1; }) {} @@ -547,7 +547,7 @@ fn generic_fmod(comptime T: type, x: T, y: T) T { } if (ey == 0) { i = uy << exp_bits; - while (i >> bits_minus_1 == 0) : (b: { + while (i >> bits_minus_1 == 0) : ({ ey -= 1; i <<= 1; }) {} @@ -573,7 +573,7 @@ fn generic_fmod(comptime T: type, x: T, y: T) T { return 0 * x; ux = i; } - while (ux >> digits == 0) : (b: { + while (ux >> digits == 0) : ({ ux <<= 1; ex -= 1; }) {} diff --git a/lib/std/zig/render.zig b/lib/std/zig/render.zig index 454ddde160..c516250a17 100644 --- a/lib/std/zig/render.zig +++ b/lib/std/zig/render.zig @@ -2385,7 +2385,7 @@ fn renderTokenOffset( } } - if (next_token_id != .LineComment) blk: { + if (next_token_id != .LineComment) { switch (space) { Space.None, Space.NoNewline => return, Space.Newline => { -- cgit v1.2.3 From 13e472aa2a8113df6417c09727297a6106127f8e Mon Sep 17 00:00:00 2001 From: Vexu Date: Thu, 13 Aug 2020 16:06:42 +0300 Subject: translate-c: add return if one is needed --- lib/std/hash/auto_hash.zig | 2 +- src-self-hosted/Module.zig | 4 +-- src-self-hosted/translate_c.zig | 40 +++++++++++++++++++++++++++ test/run_translated_c.zig | 1 - test/translate_c.zig | 61 +++++++++++++++++++++++++++++------------ 5 files changed, 86 insertions(+), 22 deletions(-) (limited to 'lib/std') diff --git a/lib/std/hash/auto_hash.zig b/lib/std/hash/auto_hash.zig index 85f8e4b0d2..996d6ede38 100644 --- a/lib/std/hash/auto_hash.zig +++ b/lib/std/hash/auto_hash.zig @@ -129,7 +129,7 @@ pub fn hash(hasher: anytype, key: anytype, comptime strat: HashStrategy) void { } }, - .Union => |info| blk: { + .Union => |info| { if (info.tag_type) |tag_type| { const tag = meta.activeTag(key); const s = hash(hasher, tag, strat); diff --git a/src-self-hosted/Module.zig b/src-self-hosted/Module.zig index 6abd4f51e1..88e59b5a2f 100644 --- a/src-self-hosted/Module.zig +++ b/src-self-hosted/Module.zig @@ -2798,7 +2798,7 @@ pub fn floatAdd(self: *Module, scope: *Scope, float_type: Type, src: usize, lhs: val_payload.* = .{ .val = lhs_val + rhs_val }; break :blk &val_payload.base; }, - 128 => blk: { + 128 => { return self.fail(scope, src, "TODO Implement addition for big floats", .{}); }, else => unreachable, @@ -2832,7 +2832,7 @@ pub fn floatSub(self: *Module, scope: *Scope, float_type: Type, src: usize, lhs: val_payload.* = .{ .val = lhs_val - rhs_val }; break :blk &val_payload.base; }, - 128 => blk: { + 128 => { return self.fail(scope, src, "TODO Implement substraction for big floats", .{}); }, else => unreachable, diff --git a/src-self-hosted/translate_c.zig b/src-self-hosted/translate_c.zig index de8f633076..2382375fc5 100644 --- a/src-self-hosted/translate_c.zig +++ b/src-self-hosted/translate_c.zig @@ -628,6 +628,46 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void { error.UnsupportedType, => return failDecl(c, fn_decl_loc, fn_name, "unable to translate function", .{}), }; + // add return statement if the function didn't have one + blk: { + const fn_ty = @ptrCast(*const ZigClangFunctionType, fn_type); + + if (ZigClangFunctionType_getNoReturnAttr(fn_ty)) break :blk; + const return_qt = ZigClangFunctionType_getReturnType(fn_ty); + if (isCVoid(return_qt)) break :blk; + + if (block_scope.statements.items.len > 0) { + var last = block_scope.statements.items[block_scope.statements.items.len - 1]; + while (true) { + switch (last.tag) { + .Block => { + const stmts = last.castTag(.Block).?.statements(); + if (stmts.len == 0) break; + + last = stmts[stmts.len - 1]; + }, + // no extra return needed + .Return => break :blk, + else => break, + } + } + } + + const return_expr = try ast.Node.ControlFlowExpression.create(rp.c.arena, .{ + .ltoken = try appendToken(rp.c, .Keyword_return, "return"), + .tag = .Return, + }, .{ + .rhs = transZeroInitExpr(rp, scope, fn_decl_loc, ZigClangQualType_getTypePtr(return_qt)) catch |err| switch (err) { + error.OutOfMemory => |e| return e, + error.UnsupportedTranslation, + error.UnsupportedType, + => return failDecl(c, fn_decl_loc, fn_name, "unable to create a return value for function", .{}), + }, + }); + _ = try appendToken(rp.c, .Semicolon, ";"); + try block_scope.statements.append(&return_expr.base); + } + const body_node = try block_scope.complete(rp.c); proto_node.setTrailer("body_node", &body_node.base); return addTopLevelDecl(c, fn_name, &proto_node.base); diff --git a/test/run_translated_c.zig b/test/run_translated_c.zig index efdc9702a4..3fa183ce3b 100644 --- a/test/run_translated_c.zig +++ b/test/run_translated_c.zig @@ -15,7 +15,6 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void { \\ } \\ if (s0 != 1) abort(); \\ if (s1 != 10) abort(); - \\ return 0; \\} , ""); diff --git a/test/translate_c.zig b/test/translate_c.zig index c632700bc5..f7e983276e 100644 --- a/test/translate_c.zig +++ b/test/translate_c.zig @@ -3,12 +3,33 @@ const std = @import("std"); const CrossTarget = std.zig.CrossTarget; pub fn addCases(cases: *tests.TranslateCContext) void { + cases.add("missing return stmt", + \\int foo() {} + \\int bar() { + \\ int a = 2; + \\} + \\int baz() { + \\ return 0; + \\} + , &[_][]const u8{ + \\pub export fn foo() c_int { + \\ return 0; + \\} + \\pub export fn bar() c_int { + \\ var a: c_int = 2; + \\ return 0; + \\} + \\pub export fn baz() c_int { + \\ return 0; + \\} + }); + cases.add("alignof", - \\int main() { + \\void main() { \\ int a = _Alignof(int); \\} , &[_][]const u8{ - \\pub export fn main() c_int { + \\pub export fn main() void { \\ var a: c_int = @bitCast(c_int, @truncate(c_uint, @alignOf(c_int))); \\} }); @@ -539,6 +560,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ c = (a * b); \\ c = @divTrunc(a, b); \\ c = @rem(a, b); + \\ return 0; \\} \\pub export fn u() c_uint { \\ var a: c_uint = undefined; @@ -549,6 +571,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ c = (a *% b); \\ c = (a / b); \\ c = (a % b); + \\ return 0; \\} }); @@ -1596,13 +1619,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void { }); cases.add("worst-case assign", - \\int foo() { + \\void foo() { \\ int a; \\ int b; \\ a = b = 2; \\} , &[_][]const u8{ - \\pub export fn foo() c_int { + \\pub export fn foo() void { \\ var a: c_int = undefined; \\ var b: c_int = undefined; \\ a = blk: { @@ -1650,11 +1673,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ a = 7; \\ if (!true) break; \\ } + \\ return 0; \\} }); cases.add("for loops", - \\int foo() { + \\void foo() { \\ for (int i = 2, b = 4; i + 2; i = 2) { \\ int a = 2; \\ a = 6, 5, 7; @@ -1662,7 +1686,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ char i = 2; \\} , &[_][]const u8{ - \\pub export fn foo() c_int { + \\pub export fn foo() void { \\ { \\ var i: c_int = 2; \\ var b: c_int = 4; @@ -1712,7 +1736,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { }); cases.add("switch on int", - \\int switch_fn(int i) { + \\void switch_fn(int i) { \\ int res = 0; \\ switch (i) { \\ case 0: @@ -1727,7 +1751,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ } \\} , &[_][]const u8{ - \\pub export fn switch_fn(arg_i: c_int) c_int { + \\pub export fn switch_fn(arg_i: c_int) void { \\ var i = arg_i; \\ var res: c_int = 0; \\ @"switch": { @@ -1787,13 +1811,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void { }); cases.add("assign", - \\int max(int a) { + \\void max(int a) { \\ int tmp; \\ tmp = a; \\ a = tmp; \\} , &[_][]const u8{ - \\pub export fn max(arg_a: c_int) c_int { + \\pub export fn max(arg_a: c_int) void { \\ var a = arg_a; \\ var tmp: c_int = undefined; \\ tmp = a; @@ -2082,7 +2106,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ int b; \\}a; \\float b = 2.0f; - \\int foo(void) { + \\void foo(void) { \\ struct Foo *c; \\ a.b; \\ c->b; @@ -2093,7 +2117,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\}; \\pub extern var a: struct_Foo; \\pub export var b: f32 = 2; - \\pub export fn foo() c_int { + \\pub export fn foo() void { \\ var c: [*c]struct_Foo = undefined; \\ _ = a.b; \\ _ = c.*.b; @@ -2204,11 +2228,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ if (a < b) return b; \\ if (a < b) return b else return a; \\ if (a < b) {} else {} + \\ return 0; \\} }); cases.add("if statements", - \\int foo() { + \\void foo() { \\ if (2) { \\ int a = 2; \\ } @@ -2217,7 +2242,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ } \\} , &[_][]const u8{ - \\pub export fn foo() c_int { + \\pub export fn foo() void { \\ if (true) { \\ var a: c_int = 2; \\ } @@ -2811,12 +2836,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void { }); cases.add("arg name aliasing decl which comes after", - \\int foo(int bar) { + \\void foo(int bar) { \\ bar = 2; \\} \\int bar = 4; , &[_][]const u8{ - \\pub export fn foo(arg_bar_1: c_int) c_int { + \\pub export fn foo(arg_bar_1: c_int) void { \\ var bar_1 = arg_bar_1; \\ bar_1 = 2; \\} @@ -2824,12 +2849,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void { }); cases.add("arg name aliasing macro which comes after", - \\int foo(int bar) { + \\void foo(int bar) { \\ bar = 2; \\} \\#define bar 4 , &[_][]const u8{ - \\pub export fn foo(arg_bar_1: c_int) c_int { + \\pub export fn foo(arg_bar_1: c_int) void { \\ var bar_1 = arg_bar_1; \\ bar_1 = 2; \\} -- cgit v1.2.3