Commit e3f1bfe483
Changed files (3)
src-self-hosted
test
src-self-hosted/clang.zig
@@ -1036,3 +1036,7 @@ pub extern fn ZigClangPreprocessedEntity_getKind(*const ZigClangPreprocessedEnti
pub extern fn ZigClangMacroDefinitionRecord_getName_getNameStart(*const ZigClangMacroDefinitionRecord) [*:0]const u8;
pub extern fn ZigClangMacroDefinitionRecord_getSourceRange_getBegin(*const ZigClangMacroDefinitionRecord) ZigClangSourceLocation;
pub extern fn ZigClangMacroDefinitionRecord_getSourceRange_getEnd(*const ZigClangMacroDefinitionRecord) ZigClangSourceLocation;
+
+pub extern fn ZigClangIfStmt_getThen(*const ZigClangIfStmt) *const ZigClangStmt;
+pub extern fn ZigClangIfStmt_getElse(*const ZigClangIfStmt) ?*const ZigClangStmt;
+pub extern fn ZigClangIfStmt_getCond(*const ZigClangIfStmt) *const ZigClangStmt;
src-self-hosted/translate_c.zig
@@ -67,18 +67,17 @@ const Scope = struct {
variables: AliasList,
label: ?[]const u8,
- /// Don't forget to set rbrace token later
+ /// Don't forget to set rbrace token and block_node later
fn init(c: *Context, parent: *Scope, want_label: bool) !*Block {
// TODO removing `?[]const u8` here causes LLVM error
const label: ?[]const u8 = if (want_label) try std.fmt.allocPrint(c.a(), "blk_{}", .{c.getMangle()}) else null;
- const block_node = try transCreateNodeBlock(c, label);
const block = try c.a().create(Block);
block.* = .{
.base = .{
.id = .Block,
.parent = parent,
},
- .block_node = block_node,
+ .block_node = undefined,
.variables = AliasList.init(c.a()),
.label = label,
};
@@ -126,7 +125,6 @@ const Scope = struct {
};
const Condition = struct {
- expr: *ast.Node,
base: Scope,
};
@@ -612,6 +610,7 @@ fn transStmt(
.ParenExprClass => return transExpr(rp, scope, ZigClangParenExpr_getSubExpr(@ptrCast(*const ZigClangParenExpr, stmt)), result_used, lrvalue),
.InitListExprClass => return transInitListExpr(rp, scope, @ptrCast(*const ZigClangInitListExpr, stmt), result_used),
.ImplicitValueInitExprClass => return transImplicitValueInitExpr(rp, scope, @ptrCast(*const ZigClangExpr, stmt), result_used),
+ .IfStmtClass => return transIfStmt(rp, scope, @ptrCast(*const ZigClangIfStmt, stmt), result_used),
else => {
return revertAndWarn(
rp,
@@ -718,18 +717,31 @@ fn transBinaryOperator(
),
.Comma => {
const block_scope = try scope.findBlockScope(rp.c);
+ const expr = block_scope.base.parent == scope;
+ const lparen = if (expr) blk: {
+ const l = try appendToken(rp.c, .LParen, "(");
+ block_scope.block_node = try transCreateNodeBlock(rp.c, block_scope.label);
+ break :blk l;
+ } else undefined;
const lhs = try transExpr(rp, &block_scope.base, ZigClangBinaryOperator_getLHS(stmt), .unused, .r_value);
try block_scope.block_node.statements.push(lhs);
const rhs = try transExpr(rp, &block_scope.base, ZigClangBinaryOperator_getRHS(stmt), .used, .r_value);
- if (block_scope.base.parent == scope) {
+ if (expr) {
+ _ = try appendToken(rp.c, .Semicolon, ";");
const break_node = try transCreateNodeBreak(rp.c, block_scope.label);
break_node.rhs = rhs;
- _ = try appendToken(rp.c, .Semicolon, ";");
try block_scope.block_node.statements.push(&break_node.base);
block_scope.block_node.rbrace = try appendToken(rp.c, .RBrace, "}");
- return maybeSuppressResult(rp, scope, result_used, &block_scope.block_node.base);
+ const rparen = try appendToken(rp.c, .RParen, ")");
+ const grouped_expr = try rp.c.a().create(ast.Node.GroupedExpression);
+ grouped_expr.* = .{
+ .lparen = lparen,
+ .expr = &block_scope.block_node.base,
+ .rparen = rparen,
+ };
+ return maybeSuppressResult(rp, scope, result_used, &grouped_expr.base);
} else {
return maybeSuppressResult(rp, scope, result_used, rhs);
}
@@ -766,6 +778,7 @@ fn transCompoundStmtInline(
fn transCompoundStmt(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangCompoundStmt) TransError!*ast.Node {
const block_scope = try Scope.Block.init(rp.c, scope, false);
+ block_scope.block_node = try transCreateNodeBlock(rp.c, block_scope.label);
try transCompoundStmtInline(rp, &block_scope.base, stmt, block_scope.block_node);
block_scope.block_node.rbrace = try appendToken(rp.c, .RBrace, "}");
return &block_scope.block_node.base;
@@ -792,7 +805,7 @@ fn transCStyleCastExprClass(
fn transDeclStmt(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangDeclStmt) TransError!*ast.Node {
const c = rp.c;
- const block_scope = try scope.findBlockScope(c);
+ const block_scope = scope.findBlockScope(c) catch unreachable;
var it = ZigClangDeclStmt_decl_begin(stmt);
const end_it = ZigClangDeclStmt_decl_end(stmt);
@@ -1167,6 +1180,35 @@ fn transImplicitValueInitExpr(
};
}
+fn transIfStmt(
+ rp: RestorePoint,
+ scope: *Scope,
+ stmt: *const ZigClangIfStmt,
+ used: ResultUsed,
+) TransError!*ast.Node {
+ // if (c) t
+ // if (c) t else e
+ const if_node = try transCreateNodeIf(rp.c);
+
+ var cond_scope = Scope.Condition{
+ .base = .{
+ .parent = scope,
+ .id = .Condition,
+ },
+ };
+ if_node.condition = try transBoolExpr(rp, &cond_scope.base, @ptrCast(*const ZigClangExpr, ZigClangIfStmt_getCond(stmt)), .used, .r_value);
+ _ = try appendToken(rp.c, .RParen, ")");
+
+ if_node.body = try transStmt(rp, scope, ZigClangIfStmt_getThen(stmt), .used, .r_value);
+
+ if (ZigClangIfStmt_getElse(stmt)) |expr| {
+ if_node.@"else" = try transCreateNodeElse(rp.c);
+ if_node.@"else".?.body = try transStmt(rp, scope, expr, .used, .r_value);
+ }
+ _ = try appendToken(rp.c, .Semicolon, ";");
+ return &if_node.base;
+}
+
fn transCPtrCast(
rp: RestorePoint,
loc: ZigClangSourceLocation,
@@ -1602,6 +1644,7 @@ fn transCreateNodeAssign(
// zig: })
_ = try appendToken(rp.c, .LParen, "(");
const block_scope = try Scope.Block.init(rp.c, scope, true);
+ block_scope.block_node = try transCreateNodeBlock(rp.c, block_scope.label);
const tmp = try std.fmt.allocPrint(rp.c.a(), "_tmp_{}", .{rp.c.getMangle()});
const node = try transCreateNodeVarDecl(rp.c, false, true, tmp);
test/translate_c.zig
@@ -732,6 +732,29 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\}
});
+ cases.add_2("if statements",
+ \\int foo(char c) {
+ \\ if (2) {
+ \\ int a = 2;
+ \\ }
+ \\ if (2, 5) {
+ \\ int a = 2;
+ \\ }
+ \\}
+ , &[_][]const u8{
+ \\pub export fn foo(c: u8) c_int {
+ \\ if (2 != 0) {
+ \\ var a: c_int = 2;
+ \\ }
+ \\ if ((blk_1: {
+ \\ _ = 2;
+ \\ break :blk_1 5;
+ \\ }) != 0) {
+ \\ var a: c_int = 2;
+ \\ }
+ \\}
+ });
+
/////////////// Cases for only stage1 which are TODO items for stage2 ////////////////
if (builtin.os != builtin.Os.windows) {