authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2021-02-10 23:02:38+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2021-02-16 16:40:05+02:00
logcadd4483be80f73f192621f79eea41117183129c
treeec365d44270e50ab71670dc037b081436f5bd3a3
parent66dd64ec15d787bb43cb0ab1169e8bac6cfe762e
signature Commit is signed but in an unrecognized format.

translate-c: convert switch


2 files changed, 118 insertions(+), 195 deletions(-)

src/translate_c.zig+101-181
......@@ -43,7 +43,7 @@ const Scope = struct {
4343 const Switch = struct {
4444 base: Scope,
4545 pending_block: Block,
46 cases: []Node,
46 cases: std.ArrayList(Node),
4747 case_index: usize,
4848 switch_label: ?[]const u8,
4949 default_label: ?[]const u8,
......@@ -1087,7 +1087,7 @@ fn transStmt(
10871087 return maybeSuppressResult(c, scope, result_used, expr);
10881088 },
10891089 else => {
1090 return revertAndWarn(
1090 return fail(
10911091 rp,
10921092 error.UnsupportedTranslation,
10931093 stmt.getBeginLoc(),
......@@ -1348,7 +1348,7 @@ fn transDeclStmtOne(
13481348 return error.UnsupportedTranslation;
13491349 return node;
13501350 },
1351 else => |kind| return revertAndWarn(
1351 else => |kind| return fail(
13521352 rp,
13531353 error.UnsupportedTranslation,
13541354 decl.getLocation(),
......@@ -1440,7 +1440,7 @@ fn transImplicitCastExpr(
14401440 .BuiltinFnToFnPtr => {
14411441 return transExpr(rp, scope, sub_expr, result_used, .r_value);
14421442 },
1443 else => |kind| return revertAndWarn(
1443 else => |kind| return fail(
14441444 rp,
14451445 error.UnsupportedTranslation,
14461446 @ptrCast(*const clang.Stmt, expr).getBeginLoc(),
......@@ -1460,7 +1460,7 @@ fn transBoolExpr(
14601460 if (@ptrCast(*const clang.Stmt, expr).getStmtClass() == .IntegerLiteralClass) {
14611461 var is_zero: bool = undefined;
14621462 if (!(@ptrCast(*const clang.IntegerLiteral, expr).isZero(&is_zero, c.clang_context))) {
1463 return revertAndWarn(c, error.UnsupportedTranslation, expr.getBeginLoc(), "invalid integer literal", .{});
1463 return fail(c, error.UnsupportedTranslation, expr.getBeginLoc(), "invalid integer literal", .{});
14641464 }
14651465 return Node{ .tag = ([2]ast.Node.Tag{ .true_literal, .false_literal })[@boolToInt(is_zero)] };
14661466 }
......@@ -1605,7 +1605,7 @@ fn transIntegerLiteral(
16051605 var eval_result: clang.ExprEvalResult = undefined;
16061606 if (!expr.EvaluateAsInt(&eval_result, c.clang_context)) {
16071607 const loc = expr.getBeginLoc();
1608 return revertAndWarn(c, error.UnsupportedTranslation, loc, "invalid integer literal", .{});
1608 return fail(c, error.UnsupportedTranslation, loc, "invalid integer literal", .{});
16091609 }
16101610
16111611 if (suppress_as == .no_as) {
......@@ -2144,7 +2144,6 @@ fn transDoWhileLoop(
21442144 block.data.stmts.len += 1; // This is safe since we reserve one extra space in Scope.Block.complete.
21452145 block.data.stmts[block.data.stmts.len - 1] = if_not_break;
21462146 break :blk node;
2147
21482147 } else blk: {
21492148 // the C statement is without a block, so we need to create a block to contain it.
21502149 // c: do
......@@ -2209,27 +2208,11 @@ fn transForLoop(
22092208 }
22102209}
22112210
2212fn getSwitchCaseCount(stmt: *const clang.SwitchStmt) usize {
2213 const body = stmt.getBody();
2214 assert(body.getStmtClass() == .CompoundStmtClass);
2215 const comp = @ptrCast(*const clang.CompoundStmt, body);
2216 // TODO https://github.com/ziglang/zig/issues/1738
2217 // return comp.body_end() - comp.body_begin();
2218 const start_addr = @ptrToInt(comp.body_begin());
2219 const end_addr = @ptrToInt(comp.body_end());
2220 return (end_addr - start_addr) / @sizeOf(*clang.Stmt);
2221}
2222
22232211fn transSwitch(
2224 rp: RestorePoint,
2212 c: *Context,
22252213 scope: *Scope,
22262214 stmt: *const clang.SwitchStmt,
2227) TransError!*ast.Node {
2228 const switch_tok = try appendToken(rp.c, .Keyword_switch, "switch");
2229 _ = try appendToken(rp.c, .LParen, "(");
2230
2231 const cases_len = getSwitchCaseCount(stmt);
2232
2215) TransError!Node {
22332216 var cond_scope = Scope.Condition{
22342217 .base = .{
22352218 .parent = scope,
......@@ -2237,16 +2220,13 @@ fn transSwitch(
22372220 },
22382221 };
22392222 defer cond_scope.deinit();
2240 const switch_expr = try transExpr(rp, &cond_scope.base, stmt.getCond(), .used, .r_value);
2241 _ = try appendToken(rp.c, .RParen, ")");
2242 _ = try appendToken(rp.c, .LBrace, "{");
2243 // reserve +1 case in case there is no default case
2244 const switch_node = try ast.Node.Switch.alloc(rp.c.arena, cases_len + 1);
2223 const switch_expr = try transExpr(c, &cond_scope.base, stmt.getCond(), .used, .r_value);
2224 const switch_node = try c.arena.create(ast.Payload.Switch);
22452225 switch_node.* = .{
2246 .switch_token = switch_tok,
2247 .expr = switch_expr,
2248 .cases_len = cases_len + 1,
2249 .rbrace = try appendToken(rp.c, .RBrace, "}"),
2226 .data = .{
2227 .cond = switch_expr,
2228 .cases = undefined, // set later
2229 },
22502230 };
22512231
22522232 var switch_scope = Scope.Switch{
......@@ -2254,29 +2234,32 @@ fn transSwitch(
22542234 .id = .Switch,
22552235 .parent = scope,
22562236 },
2257 .cases = switch_node.cases(),
2258 .case_index = 0,
2237 .cases = std.ArrayList(Node).init(c.gpa),
22592238 .pending_block = undefined,
22602239 .default_label = null,
22612240 .switch_label = null,
22622241 };
2242 defer {
2243 switch_node.data.cases = try c.arena.dupe(Node, switch_scope.cases.items);
2244 switch_node.data.default = switch_scope.switch_label;
2245 switch_scope.cases.deinit();
2246 }
22632247
22642248 // tmp block that all statements will go before being picked up by a case or default
2265 var block_scope = try Scope.Block.init(rp.c, &switch_scope.base, false);
2249 var block_scope = try Scope.Block.init(c, &switch_scope.base, false);
22662250 defer block_scope.deinit();
22672251
22682252 // Note that we do not defer a deinit here; the switch_scope.pending_block field
22692253 // has its own memory management. This resource is freed inside `transCase` and
22702254 // then the final pending_block is freed at the bottom of this function with
22712255 // pending_block.deinit().
2272 switch_scope.pending_block = try Scope.Block.init(rp.c, scope, false);
2273 try switch_scope.pending_block.statements.append(&switch_node.base);
2256 switch_scope.pending_block = try Scope.Block.init(c, scope, false);
2257 try switch_scope.pending_block.statements.append(Node.initPayload(&switch_node.base));
22742258
2275 const last = try transStmt(rp, &block_scope.base, stmt.getBody(), .unused, .r_value);
2276 _ = try appendToken(rp.c, .Semicolon, ";");
2259 const last = try transStmt(c, &block_scope.base, stmt.getBody(), .unused, .r_value);
22772260
22782261 // take all pending statements
2279 const last_block_stmts = last.cast(ast.Node.Block).?.statements();
2262 const last_block_stmts = last.castTag(.block).?.data.stmts;
22802263 try switch_scope.pending_block.statements.ensureCapacity(
22812264 switch_scope.pending_block.statements.items.len + last_block_stmts.len,
22822265 );
......@@ -2285,213 +2268,159 @@ fn transSwitch(
22852268 }
22862269
22872270 if (switch_scope.default_label == null) {
2288 switch_scope.switch_label = try block_scope.makeMangledName(rp.c, "switch");
2271 switch_scope.switch_label = try block_scope.makeMangledName(c, "switch");
22892272 }
22902273 if (switch_scope.switch_label) |l| {
2291 switch_scope.pending_block.label = try appendIdentifier(rp.c, l);
2292 _ = try appendToken(rp.c, .Colon, ":");
2274 switch_scope.pending_block.label = l;
22932275 }
22942276 if (switch_scope.default_label == null) {
2295 const else_prong = try transCreateNodeSwitchCase(rp.c, try transCreateNodeSwitchElse(rp.c));
2296 else_prong.expr = blk: {
2297 var br = try CtrlFlow.init(rp.c, .Break, switch_scope.switch_label.?);
2298 break :blk &(try br.finish(null)).base;
2299 };
2300 _ = try appendToken(rp.c, .Comma, ",");
2301
2302 if (switch_scope.case_index >= switch_scope.cases.len)
2303 return revertAndWarn(rp, error.UnsupportedTranslation, @ptrCast(*const clang.Stmt, stmt).getBeginLoc(), "TODO complex switch cases", .{});
2304 switch_scope.cases[switch_scope.case_index] = &else_prong.base;
2305 switch_scope.case_index += 1;
2277 const else_prong = try Node.switch_else.create(
2278 c.arena,
2279 try Node.@"break".create(c.arena, switch_scope.switch_label.?),
2280 );
2281 switch_scope.cases.append(else_prong);
23062282 }
2307 // We overallocated in case there was no default, so now we correct
2308 // the number of cases in the AST node.
2309 switch_node.cases_len = switch_scope.case_index;
23102283
2311 const result_node = try switch_scope.pending_block.complete(rp.c);
2284 const result_node = try switch_scope.pending_block.complete(c);
23122285 switch_scope.pending_block.deinit();
23132286 return result_node;
23142287}
23152288
23162289fn transCase(
2317 rp: RestorePoint,
2290 c: *Context,
23182291 scope: *Scope,
23192292 stmt: *const clang.CaseStmt,
2320) TransError!*ast.Node {
2321 const block_scope = scope.findBlockScope(rp.c) catch unreachable;
2293) TransError!Node {
2294 const block_scope = scope.findBlockScope(c) catch unreachable;
23222295 const switch_scope = scope.getSwitch();
2323 const label = try block_scope.makeMangledName(rp.c, "case");
2324 _ = try appendToken(rp.c, .Semicolon, ";");
2296 const label = try block_scope.makeMangledName(c, "case");
23252297
23262298 const expr = if (stmt.getRHS()) |rhs| blk: {
2327 const lhs_node = try transExpr(rp, scope, stmt.getLHS(), .used, .r_value);
2328 const ellips = try appendToken(rp.c, .Ellipsis3, "...");
2329 const rhs_node = try transExpr(rp, scope, rhs, .used, .r_value);
2330
2331 const node = try rp.c.arena.create(ast.Node.SimpleInfixOp);
2332 node.* = .{
2333 .base = .{ .tag = .Range },
2334 .op_token = ellips,
2335 .lhs = lhs_node,
2336 .rhs = rhs_node,
2337 };
2338 break :blk &node.base;
2339 } else
2340 try transExpr(rp, scope, stmt.getLHS(), .used, .r_value);
2299 const lhs_node = try transExpr(c, scope, stmt.getLHS(), .used, .r_value);
2300 const rhs_node = try transExpr(c, scope, rhs, .used, .r_value);
23412301
2342 const switch_prong = try transCreateNodeSwitchCase(rp.c, expr);
2343 switch_prong.expr = blk: {
2344 var br = try CtrlFlow.init(rp.c, .Break, label);
2345 break :blk &(try br.finish(null)).base;
2346 };
2347 _ = try appendToken(rp.c, .Comma, ",");
2302 break :blk Node.ellipsis3.create(c.arena, .{ .lhs = lhs_node, .rhs = rhs_node });
2303 } else
2304 try transExpr(c, scope, stmt.getLHS(), .used, .r_value);
23482305
2349 if (switch_scope.case_index >= switch_scope.cases.len)
2350 return revertAndWarn(rp, error.UnsupportedTranslation, @ptrCast(*const clang.Stmt, stmt).getBeginLoc(), "TODO complex switch cases", .{});
2351 switch_scope.cases[switch_scope.case_index] = &switch_prong.base;
2352 switch_scope.case_index += 1;
2306 const switch_prong = try Node.switch_prong.create(
2307 c.arena,
2308 try Node.@"break".create(c.arena, label),
2309 );
2310 switch_scope.cases.append(switch_prong);
23532311
2354 switch_scope.pending_block.label = try appendIdentifier(rp.c, label);
2355 _ = try appendToken(rp.c, .Colon, ":");
2312 switch_scope.pending_block.label = label;
23562313
23572314 // take all pending statements
23582315 try switch_scope.pending_block.statements.appendSlice(block_scope.statements.items);
23592316 block_scope.statements.shrinkAndFree(0);
23602317
2361 const pending_node = try switch_scope.pending_block.complete(rp.c);
2318 const pending_node = try switch_scope.pending_block.complete(c);
23622319 switch_scope.pending_block.deinit();
2363 switch_scope.pending_block = try Scope.Block.init(rp.c, scope, false);
2320 switch_scope.pending_block = try Scope.Block.init(c, scope, false);
23642321
23652322 try switch_scope.pending_block.statements.append(pending_node);
23662323
2367 return transStmt(rp, scope, stmt.getSubStmt(), .unused, .r_value);
2324 return transStmt(c, scope, stmt.getSubStmt(), .unused, .r_value);
23682325}
23692326
23702327fn transDefault(
2371 rp: RestorePoint,
2328 c: *Context,
23722329 scope: *Scope,
23732330 stmt: *const clang.DefaultStmt,
2374) TransError!*ast.Node {
2375 const block_scope = scope.findBlockScope(rp.c) catch unreachable;
2331) TransError!Node {
2332 const block_scope = scope.findBlockScope(c) catch unreachable;
23762333 const switch_scope = scope.getSwitch();
2377 switch_scope.default_label = try block_scope.makeMangledName(rp.c, "default");
2378 _ = try appendToken(rp.c, .Semicolon, ";");
2379
2380 const else_prong = try transCreateNodeSwitchCase(rp.c, try transCreateNodeSwitchElse(rp.c));
2381 else_prong.expr = blk: {
2382 var br = try CtrlFlow.init(rp.c, .Break, switch_scope.default_label.?);
2383 break :blk &(try br.finish(null)).base;
2384 };
2385 _ = try appendToken(rp.c, .Comma, ",");
2334 switch_scope.default_label = try block_scope.makeMangledName(c, "default");
23862335
2387 if (switch_scope.case_index >= switch_scope.cases.len)
2388 return revertAndWarn(rp, error.UnsupportedTranslation, @ptrCast(*const clang.Stmt, stmt).getBeginLoc(), "TODO complex switch cases", .{});
2389 switch_scope.cases[switch_scope.case_index] = &else_prong.base;
2390 switch_scope.case_index += 1;
2391
2392 switch_scope.pending_block.label = try appendIdentifier(rp.c, switch_scope.default_label.?);
2393 _ = try appendToken(rp.c, .Colon, ":");
2336 const else_prong = try Node.switch_else.create(
2337 c.arena,
2338 try Node.@"break".create(c.arena, switch_scope.default_label.?),
2339 );
2340 switch_scope.cases.append(else_prong);
2341 switch_scope.pending_block.label = try appendIdentifier(c, switch_scope.default_label.?);
23942342
23952343 // take all pending statements
23962344 try switch_scope.pending_block.statements.appendSlice(block_scope.statements.items);
23972345 block_scope.statements.shrinkAndFree(0);
23982346
2399 const pending_node = try switch_scope.pending_block.complete(rp.c);
2347 const pending_node = try switch_scope.pending_block.complete(c);
24002348 switch_scope.pending_block.deinit();
2401 switch_scope.pending_block = try Scope.Block.init(rp.c, scope, false);
2349 switch_scope.pending_block = try Scope.Block.init(c, scope, false);
24022350 try switch_scope.pending_block.statements.append(pending_node);
24032351
2404 return transStmt(rp, scope, stmt.getSubStmt(), .unused, .r_value);
2352 return transStmt(c, scope, stmt.getSubStmt(), .unused, .r_value);
24052353}
24062354
2407fn transConstantExpr(rp: RestorePoint, scope: *Scope, expr: *const clang.Expr, used: ResultUsed) TransError!*ast.Node {
2355fn transConstantExpr(c: *Context, scope: *Scope, expr: *const clang.Expr, used: ResultUsed) TransError!Node {
24082356 var result: clang.ExprEvalResult = undefined;
2409 if (!expr.EvaluateAsConstantExpr(&result, .EvaluateForCodeGen, rp.c.clang_context))
2410 return revertAndWarn(rp, error.UnsupportedTranslation, expr.getBeginLoc(), "invalid constant expression", .{});
2357 if (!expr.EvaluateAsConstantExpr(&result, .EvaluateForCodeGen, c.clang_context))
2358 return fail(c, error.UnsupportedTranslation, expr.getBeginLoc(), "invalid constant expression", .{});
24112359
2412 var val_node: ?*ast.Node = null;
24132360 switch (result.Val.getKind()) {
24142361 .Int => {
24152362 // See comment in `transIntegerLiteral` for why this code is here.
24162363 // @as(T, x)
24172364 const expr_base = @ptrCast(*const clang.Expr, expr);
2418 const as_node = try rp.c.createBuiltinCall("@as", 2);
2419 const ty_node = try transQualType(rp, expr_base.getType(), expr_base.getBeginLoc());
2420 as_node.params()[0] = ty_node;
2421 _ = try appendToken(rp.c, .Comma, ",");
2422
2423 const int_lit_node = try transCreateNodeAPInt(rp.c, result.Val.getInt());
2424 as_node.params()[1] = int_lit_node;
2425
2426 as_node.rparen_token = try appendToken(rp.c, .RParen, ")");
2427
2428 return maybeSuppressResult(rp, scope, used, &as_node.base);
2365 const as_node = try Node.as.create(c.arena, .{
2366 .lhs = try transQualType(c, expr_base.getType(), expr_base.getBeginLoc()),
2367 .rhs = try transCreateNodeAPInt(c, result.Val.getInt()),
2368 });
2369 return maybeSuppressResult(c, scope, used, as_node);
24292370 },
24302371 else => {
2431 return revertAndWarn(rp, error.UnsupportedTranslation, expr.getBeginLoc(), "unsupported constant expression kind", .{});
2372 return fail(c, error.UnsupportedTranslation, expr.getBeginLoc(), "unsupported constant expression kind", .{});
24322373 },
24332374 }
24342375}
24352376
2436fn transPredefinedExpr(rp: RestorePoint, scope: *Scope, expr: *const clang.PredefinedExpr, used: ResultUsed) TransError!*ast.Node {
2437 return transStringLiteral(rp, scope, expr.getFunctionName(), used);
2377fn transPredefinedExpr(c: *Context, scope: *Scope, expr: *const clang.PredefinedExpr, used: ResultUsed) TransError!Node {
2378 return transStringLiteral(c, scope, expr.getFunctionName(), used);
24382379}
24392380
2440fn transCreateCharLitNode(c: *Context, narrow: bool, val: u32) TransError!*ast.Node {
2441 const node = try c.arena.create(ast.Node.OneToken);
2442 node.* = .{
2443 .base = .{ .tag = .CharLiteral },
2444 .token = undefined,
2445 };
2446 if (narrow) {
2447 const val_array = [_]u8{@intCast(u8, val)};
2448 node.token = try appendTokenFmt(c, .CharLiteral, "'{}'", .{std.zig.fmtEscapes(&val_array)});
2449 } else {
2450 node.token = try appendTokenFmt(c, .CharLiteral, "'\\u{{{x}}}'", .{val});
2451 }
2452 return &node.base;
2381fn transCreateCharLitNode(c: *Context, narrow: bool, val: u32) TransError!Node {
2382 return Node.char_literal.create(c.arena, if (narrow)
2383 try std.fmt.bufPrint(c.arena, "'{}'", .{std.zig.fmtEscapes(&.{@intCast(u8, val)})})
2384 else
2385 try std.fmt.bufPrint(c.arena, "'\\u{{{x}}}'", .{val}));
24532386}
24542387
24552388fn transCharLiteral(
2456 rp: RestorePoint,
2389 c: *Context,
24572390 scope: *Scope,
24582391 stmt: *const clang.CharacterLiteral,
24592392 result_used: ResultUsed,
24602393 suppress_as: SuppressCast,
2461) TransError!*ast.Node {
2394) TransError!Node {
24622395 const kind = stmt.getKind();
24632396 const val = stmt.getValue();
24642397 const narrow = kind == .Ascii or kind == .UTF8;
24652398 // C has a somewhat obscure feature called multi-character character constant
24662399 // e.g. 'abcd'
24672400 const int_lit_node = if (kind == .Ascii and val > 255)
2468 try transCreateNodeInt(rp.c, val)
2401 try transCreateNodeInt(c, val)
24692402 else
2470 try transCreateCharLitNode(rp.c, narrow, val);
2403 try transCreateCharLitNode(c, narrow, val);
24712404
24722405 if (suppress_as == .no_as) {
2473 return maybeSuppressResult(rp, scope, result_used, int_lit_node);
2406 return maybeSuppressResult(c, scope, result_used, int_lit_node);
24742407 }
24752408 // See comment in `transIntegerLiteral` for why this code is here.
24762409 // @as(T, x)
24772410 const expr_base = @ptrCast(*const clang.Expr, stmt);
2478 const as_node = try rp.c.createBuiltinCall("@as", 2);
2479 const ty_node = try transQualType(rp, expr_base.getType(), expr_base.getBeginLoc());
2480 as_node.params()[0] = ty_node;
2481 _ = try appendToken(rp.c, .Comma, ",");
2482 as_node.params()[1] = int_lit_node;
2483
2484 as_node.rparen_token = try appendToken(rp.c, .RParen, ")");
2485 return maybeSuppressResult(rp, scope, result_used, &as_node.base);
2411 const as_node = Node.as.create(c.arena, .{
2412 .lhs = try transQualType(c, expr_base.getType(), expr_base.getBeginLoc()),
2413 .rhs = int_lit_node,
2414 });
2415 return maybeSuppressResult(c, scope, result_used, as_node);
24862416}
24872417
2488fn transStmtExpr(rp: RestorePoint, scope: *Scope, stmt: *const clang.StmtExpr, used: ResultUsed) TransError!*ast.Node {
2418fn transStmtExpr(c: *Context, scope: *Scope, stmt: *const clang.StmtExpr, used: ResultUsed) TransError!Node {
24892419 const comp = stmt.getSubStmt();
24902420 if (used == .unused) {
2491 return transCompoundStmt(rp, scope, comp);
2421 return transCompoundStmt(c, scope, comp);
24922422 }
2493 const lparen = try appendToken(rp.c, .LParen, "(");
2494 var block_scope = try Scope.Block.init(rp.c, scope, true);
2423 var block_scope = try Scope.Block.init(c, scope, true);
24952424 defer block_scope.deinit();
24962425
24972426 var it = comp.body_begin();
......@@ -2500,22 +2429,13 @@ fn transStmtExpr(rp: RestorePoint, scope: *Scope, stmt: *const clang.StmtExpr, u
25002429 const result = try transStmt(rp, &block_scope.base, it[0], .unused, .r_value);
25012430 try block_scope.statements.append(result);
25022431 }
2503 const break_node = blk: {
2504 var tmp = try CtrlFlow.init(rp.c, .Break, "blk");
2505 const rhs = try transStmt(rp, &block_scope.base, it[0], .used, .r_value);
2506 break :blk try tmp.finish(rhs);
2507 };
2508 _ = try appendToken(rp.c, .Semicolon, ";");
2509 try block_scope.statements.append(&break_node.base);
2510 const block_node = try block_scope.complete(rp.c);
2511 const rparen = try appendToken(rp.c, .RParen, ")");
2512 const grouped_expr = try rp.c.arena.create(ast.Node.GroupedExpression);
2513 grouped_expr.* = .{
2514 .lparen = lparen,
2515 .expr = block_node,
2516 .rparen = rparen,
2517 };
2518 return maybeSuppressResult(rp, scope, used, &grouped_expr.base);
2432 const break_node = try Node.break_val.create(c.arena, .{
2433 .label = block_scope.label,
2434 .val = try transStmt(c, &block_scope.base, it[0], .used, .r_value),
2435 });
2436 try block_scope.statements.append(break_node);
2437
2438 return block_scope.complete(c);
25192439}
25202440
25212441fn transMemberExpr(rp: RestorePoint, scope: *Scope, stmt: *const clang.MemberExpr, result_used: ResultUsed) TransError!*ast.Node {
......@@ -4581,7 +4501,7 @@ fn fail(
45814501 comptime format: []const u8,
45824502 args: anytype,
45834503) (@TypeOf(err) || error{OutOfMemory}) {
4584 try emitWarning(c, source_loc, format, args);
4504 try warn(c, source_loc, format, args);
45854505 return err;
45864506}
45874507
src/translate_c/ast.zig+17-14
......@@ -35,8 +35,13 @@ pub const Node = extern union {
3535 /// while (true) operand
3636 while_true,
3737 @"switch",
38 /// else => operand,
39 switch_else,
40 /// lhs => rhs,
41 switch_prong,
3842 @"continue",
3943 @"break",
44 break_val,
4045 @"return",
4146 field_access,
4247 field_access_arrow,
......@@ -109,6 +114,7 @@ pub const Node = extern union {
109114 bit_or,
110115 bit_xor,
111116 array_cat,
117 ellipsis3,
112118
113119 log2_int_type,
114120 /// @import("std").math.Log2Int(operand)
......@@ -217,6 +223,7 @@ pub const Node = extern union {
217223 .empty_array,
218224 .while_true,
219225 .if_not_break,
226 .switch_else,
220227 => Payload.UnOp,
221228
222229 .add,
......@@ -280,6 +287,8 @@ pub const Node = extern union {
280287 .int_to_enum,
281288 .int_to_ptr,
282289 .array_cat,
290 .ellipsis3,
291 .switch_prong,
283292 => Payload.BinOp,
284293
285294 .int,
......@@ -300,6 +309,7 @@ pub const Node = extern union {
300309 .@"while" => Payload.While,
301310 .@"switch" => Payload.Switch,
302311 .@"break" => Payload.Break,
312 .break_val => Payload.BreakVal,
303313 .call => Payload.Call,
304314 .var_decl => Payload.VarDecl,
305315 .func => Payload.Func,
......@@ -413,22 +423,20 @@ pub const Payload = struct {
413423 base: Node = .{ .tag = .@"switch" },
414424 data: struct {
415425 cond: Node,
416 cases: []Prong,
417 default: ?[]const u8,
418
419 pub const Prong = struct {
420 lhs: Node,
421 rhs: ?Node,
422 label: []const u8,
423 };
426 cases: []Node,
424427 },
425428 };
426429
427430 pub const Break = struct {
428431 base: Node = .{ .tag = .@"break" },
432 data: ?[]const u8,
433 };
434
435 pub const BreakVal = struct {
436 base: Node = .{ .tag = .break_val },
429437 data: struct {
430438 label: ?[]const u8,
431 rhs: ?Node,
439 val: Node,
432440 },
433441 };
434442
......@@ -525,11 +533,6 @@ pub const Payload = struct {
525533 },
526534 };
527535
528 pub const Break = struct {
529 base: Node = .{ .tag = .@"break" },
530 data: *Block
531 };
532
533536 pub const Array = struct {
534537 base: Node,
535538 data: struct {