mirror of
https://github.com/ziglang/zig.git
synced 2026-02-20 00:08:56 +00:00
translate-c: small miscellaneous improvements
This commit is contained in:
parent
7ca53bdfaa
commit
df5a8120df
@ -1219,8 +1219,10 @@ fn transCompoundStmtInline(
|
||||
const end_it = stmt.body_end();
|
||||
while (it != end_it) : (it += 1) {
|
||||
const result = try transStmt(c, &block.base, it[0], .unused);
|
||||
if (result.tag() == .declaration) continue;
|
||||
try block.statements.append(result);
|
||||
switch (result.tag()) {
|
||||
.declaration, .empty_block => {},
|
||||
else => try block.statements.append(result),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1395,6 +1397,10 @@ fn transImplicitCastExpr(
|
||||
.BuiltinFnToFnPtr => {
|
||||
return transExpr(c, scope, sub_expr, result_used);
|
||||
},
|
||||
.ToVoid => {
|
||||
// Should only appear in the rhs and lhs of a ConditionalOperator
|
||||
return transExpr(c, scope, sub_expr, .unused);
|
||||
},
|
||||
else => |kind| return fail(
|
||||
c,
|
||||
error.UnsupportedTranslation,
|
||||
@ -2032,10 +2038,8 @@ fn transZeroInitExpr(
|
||||
typedef_decl.getUnderlyingType().getTypePtr(),
|
||||
);
|
||||
},
|
||||
else => {},
|
||||
else => return Tag.std_mem_zeroes.create(c.arena, try transType(c, scope, ty, source_loc)),
|
||||
}
|
||||
|
||||
return fail(c, error.UnsupportedType, source_loc, "type does not have an implicit init value", .{});
|
||||
}
|
||||
|
||||
fn transImplicitValueInitExpr(
|
||||
@ -2118,7 +2122,7 @@ fn transDoWhileLoop(
|
||||
defer cond_scope.deinit();
|
||||
const cond = try transBoolExpr(c, &cond_scope.base, @ptrCast(*const clang.Expr, stmt.getCond()), .used);
|
||||
const if_not_break = switch (cond.tag()) {
|
||||
.false_literal => Tag.@"break".init(),
|
||||
.false_literal => return transStmt(c, scope, stmt.getBody(), .unused),
|
||||
.true_literal => {
|
||||
const body_node = try transStmt(c, scope, stmt.getBody(), .unused);
|
||||
return Tag.while_true.create(c.arena, body_node);
|
||||
@ -2396,8 +2400,10 @@ fn transSwitchProngStmtInline(
|
||||
},
|
||||
else => {
|
||||
const result = try transStmt(c, &block.base, it[0], .unused);
|
||||
if (result.tag() == .declaration) continue;
|
||||
try block.statements.append(result);
|
||||
switch (result.tag()) {
|
||||
.declaration, .empty_block => {},
|
||||
else => try block.statements.append(result),
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -2479,8 +2485,10 @@ fn transStmtExpr(c: *Context, scope: *Scope, stmt: *const clang.StmtExpr, used:
|
||||
const end_it = comp.body_end();
|
||||
while (it != end_it - 1) : (it += 1) {
|
||||
const result = try transStmt(c, &block_scope.base, it[0], .unused);
|
||||
if (result.tag() == .declaration) continue;
|
||||
try block_scope.statements.append(result);
|
||||
switch (result.tag()) {
|
||||
.declaration, .empty_block => {},
|
||||
else => try block_scope.statements.append(result),
|
||||
}
|
||||
}
|
||||
const break_node = try Tag.break_val.create(c.arena, .{
|
||||
.label = block_scope.label,
|
||||
@ -3126,12 +3134,12 @@ fn transConditionalOperator(c: *Context, scope: *Scope, stmt: *const clang.Condi
|
||||
|
||||
const cond = try transBoolExpr(c, &cond_scope.base, cond_expr, .used);
|
||||
|
||||
var then_body = try transExpr(c, scope, true_expr, .used);
|
||||
var then_body = try transExpr(c, scope, true_expr, used);
|
||||
if (!res_is_bool and isBoolRes(then_body)) {
|
||||
then_body = try Tag.bool_to_int.create(c.arena, then_body);
|
||||
}
|
||||
|
||||
var else_body = try transExpr(c, scope, false_expr, .used);
|
||||
var else_body = try transExpr(c, scope, false_expr, used);
|
||||
if (!res_is_bool and isBoolRes(else_body)) {
|
||||
else_body = try Tag.bool_to_int.create(c.arena, else_body);
|
||||
}
|
||||
@ -3141,7 +3149,8 @@ fn transConditionalOperator(c: *Context, scope: *Scope, stmt: *const clang.Condi
|
||||
.then = then_body,
|
||||
.@"else" = else_body,
|
||||
});
|
||||
return maybeSuppressResult(c, scope, used, if_node);
|
||||
// Clang inserts ImplicitCast(ToVoid)'s to both rhs and lhs so we don't need to supress the result here.
|
||||
return if_node;
|
||||
}
|
||||
|
||||
fn maybeSuppressResult(
|
||||
@ -4794,7 +4803,8 @@ fn parseCMulExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
|
||||
while (true) {
|
||||
switch (m.next().?) {
|
||||
.Asterisk => {
|
||||
if (m.peek().? == .RParen) {
|
||||
const next = m.peek().?;
|
||||
if (next == .RParen or next == .Nl or next == .Eof) {
|
||||
// type *)
|
||||
|
||||
// last token of `node`
|
||||
|
||||
@ -1891,30 +1891,35 @@ fn addSemicolonIfNeeded(c: *Context, node: Node) !void {
|
||||
.var_decl, .var_simple, .arg_redecl, .alias, .enum_redecl, .block, .empty_block, .block_single, .@"switch" => {},
|
||||
.while_true => {
|
||||
const payload = node.castTag(.while_true).?.data;
|
||||
return addSemicolonIfNotBlock(c, payload);
|
||||
return addSemicolonIfNotBlock(c, payload, .yes_if);
|
||||
},
|
||||
.@"while" => {
|
||||
const payload = node.castTag(.@"while").?.data;
|
||||
return addSemicolonIfNotBlock(c, payload.body);
|
||||
return addSemicolonIfNotBlock(c, payload.body, .yes_if);
|
||||
},
|
||||
.@"if" => {
|
||||
const payload = node.castTag(.@"if").?.data;
|
||||
if (payload.@"else") |some|
|
||||
return addSemicolonIfNotBlock(c, some);
|
||||
return addSemicolonIfNotBlock(c, payload.then);
|
||||
return addSemicolonIfNotBlock(c, some, .no_if);
|
||||
return addSemicolonIfNotBlock(c, payload.then, .no_if);
|
||||
},
|
||||
else => _ = try c.addToken(.semicolon, ";"),
|
||||
}
|
||||
}
|
||||
|
||||
fn addSemicolonIfNotBlock(c: *Context, node: Node) !void {
|
||||
fn addSemicolonIfNotBlock(c: *Context, node: Node, if_needs_semicolon: enum{ yes_if, no_if}) !void {
|
||||
switch (node.tag()) {
|
||||
.block, .empty_block, .block_single => {},
|
||||
.@"if" => {
|
||||
if (if_needs_semicolon == .yes_if) {
|
||||
_ = try c.addToken(.semicolon, ";");
|
||||
return;
|
||||
}
|
||||
|
||||
const payload = node.castTag(.@"if").?.data;
|
||||
if (payload.@"else") |some|
|
||||
return addSemicolonIfNotBlock(c, some);
|
||||
return addSemicolonIfNotBlock(c, payload.then);
|
||||
return addSemicolonIfNotBlock(c, some, .no_if);
|
||||
return addSemicolonIfNotBlock(c, payload.then, .no_if);
|
||||
},
|
||||
else => _ = try c.addToken(.semicolon, ";"),
|
||||
}
|
||||
|
||||
@ -3,6 +3,62 @@ const std = @import("std");
|
||||
const CrossTarget = std.zig.CrossTarget;
|
||||
|
||||
pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
cases.add("if as while stmt has semicolon",
|
||||
\\void foo() {
|
||||
\\ while (1) if (1) {
|
||||
\\ int a = 1;
|
||||
\\ } else {
|
||||
\\ int b = 2;
|
||||
\\ }
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub export fn foo() void {
|
||||
\\ while (true) if (true) {
|
||||
\\ var a: c_int = 1;
|
||||
\\ } else {
|
||||
\\ var b: c_int = 2;
|
||||
\\ };
|
||||
\\}
|
||||
});
|
||||
|
||||
cases.add("conditional operator cast to void",
|
||||
\\int bar();
|
||||
\\void foo() {
|
||||
\\ int a;
|
||||
\\ a ? a = 2 : bar();
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub extern fn bar(...) c_int;
|
||||
\\pub export fn foo() void {
|
||||
\\ var a: c_int = undefined;
|
||||
\\ if (a != 0) a = 2 else _ = bar();
|
||||
\\}
|
||||
});
|
||||
|
||||
cases.add("struct in struct init to zero",
|
||||
\\struct Foo {
|
||||
\\ int a;
|
||||
\\ struct Bar {
|
||||
\\ int a;
|
||||
\\ } b;
|
||||
\\} a = {};
|
||||
\\#define PTR void *
|
||||
, &[_][]const u8{
|
||||
\\pub const struct_Bar = extern struct {
|
||||
\\ a: c_int,
|
||||
\\};
|
||||
\\pub const struct_Foo = extern struct {
|
||||
\\ a: c_int,
|
||||
\\ b: struct_Bar,
|
||||
\\};
|
||||
\\pub export var a: struct_Foo = struct_Foo{
|
||||
\\ .a = 0,
|
||||
\\ .b = @import("std").mem.zeroes(struct_Bar),
|
||||
\\};
|
||||
,
|
||||
\\pub const PTR = ?*c_void;
|
||||
});
|
||||
|
||||
cases.add("scoped enum",
|
||||
\\void foo() {
|
||||
\\ enum Foo {
|
||||
@ -330,9 +386,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\pub export fn foo() void {
|
||||
\\ while (false) while (false) {};
|
||||
\\ while (true) while (false) {};
|
||||
\\ while (true) while (true) {
|
||||
\\ break;
|
||||
\\ };
|
||||
\\ while (true) {}
|
||||
\\}
|
||||
});
|
||||
|
||||
@ -1044,13 +1098,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\ ;;;;;
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub export fn foo() void {
|
||||
\\ {}
|
||||
\\ {}
|
||||
\\ {}
|
||||
\\ {}
|
||||
\\ {}
|
||||
\\}
|
||||
\\pub export fn foo() void {}
|
||||
});
|
||||
|
||||
if (std.Target.current.os.tag != .windows) {
|
||||
@ -3050,9 +3098,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub fn foo() callconv(.C) void {
|
||||
\\ if (true) while (true) {
|
||||
\\ break;
|
||||
\\ };
|
||||
\\ if (true) {}
|
||||
\\}
|
||||
});
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user