| ... | ... | @@ -1063,6 +1063,7 @@ fn transStmt( |
| 1063 | 1063 | const gen_sel = @ptrCast(*const clang.GenericSelectionExpr, stmt); |
| 1064 | 1064 | return transExpr(c, scope, gen_sel.getResultExpr(), result_used); |
| 1065 | 1065 | }, |
| 1066 | // When adding new cases here, see comment for maybeBlockify() |
| 1066 | 1067 | else => { |
| 1067 | 1068 | return fail(c, error.UnsupportedTranslation, stmt.getBeginLoc(), "TODO implement translation of stmt class {s}", .{@tagName(sc)}); |
| 1068 | 1069 | }, |
| ... | ... | @@ -2242,6 +2243,35 @@ fn transImplicitValueInitExpr( |
| 2242 | 2243 | return transZeroInitExpr(c, scope, source_loc, ty); |
| 2243 | 2244 | } |
| 2244 | 2245 | |
| 2246 | /// If a statement can possibly translate to a Zig assignment (either directly because it's |
| 2247 | /// an assignment in C or indirectly via result assignment to `_`) AND it's the sole statement |
| 2248 | /// in the body of an if statement or loop, then we need to put the statement into its own block. |
| 2249 | /// The `else` case here corresponds to statements that could result in an assignment. If a statement |
| 2250 | /// class never needs a block, add its enum to the top prong. |
| 2251 | fn maybeBlockify(c: *Context, scope: *Scope, stmt: *const clang.Stmt) TransError!Node { |
| 2252 | switch (stmt.getStmtClass()) { |
| 2253 | .BreakStmtClass, |
| 2254 | .CompoundStmtClass, |
| 2255 | .ContinueStmtClass, |
| 2256 | .DeclRefExprClass, |
| 2257 | .DeclStmtClass, |
| 2258 | .DoStmtClass, |
| 2259 | .ForStmtClass, |
| 2260 | .IfStmtClass, |
| 2261 | .ReturnStmtClass, |
| 2262 | .NullStmtClass, |
| 2263 | .WhileStmtClass, |
| 2264 | => return transStmt(c, scope, stmt, .unused), |
| 2265 | else => { |
| 2266 | var block_scope = try Scope.Block.init(c, scope, false); |
| 2267 | defer block_scope.deinit(); |
| 2268 | const result = try transStmt(c, &block_scope.base, stmt, .unused); |
| 2269 | try block_scope.statements.append(result); |
| 2270 | return block_scope.complete(c); |
| 2271 | }, |
| 2272 | } |
| 2273 | } |
| 2274 | |
| 2245 | 2275 | fn transIfStmt( |
| 2246 | 2276 | c: *Context, |
| 2247 | 2277 | scope: *Scope, |
| ... | ... | @@ -2259,9 +2289,10 @@ fn transIfStmt( |
| 2259 | 2289 | const cond_expr = @ptrCast(*const clang.Expr, stmt.getCond()); |
| 2260 | 2290 | const cond = try transBoolExpr(c, &cond_scope.base, cond_expr, .used); |
| 2261 | 2291 | |
| 2262 | | const then_body = try transStmt(c, scope, stmt.getThen(), .unused); |
| 2292 | const then_body = try maybeBlockify(c, scope, stmt.getThen()); |
| 2293 | |
| 2263 | 2294 | const else_body = if (stmt.getElse()) |expr| |
| 2264 | | try transStmt(c, scope, expr, .unused) |
| 2295 | try maybeBlockify(c, scope, expr) |
| 2265 | 2296 | else |
| 2266 | 2297 | null; |
| 2267 | 2298 | return Tag.@"if".create(c.arena, .{ .cond = cond, .then = then_body, .@"else" = else_body }); |
| ... | ... | @@ -2286,7 +2317,7 @@ fn transWhileLoop( |
| 2286 | 2317 | .parent = scope, |
| 2287 | 2318 | .id = .loop, |
| 2288 | 2319 | }; |
| 2289 | | const body = try transStmt(c, &loop_scope, stmt.getBody(), .unused); |
| 2320 | const body = try maybeBlockify(c, &loop_scope, stmt.getBody()); |
| 2290 | 2321 | return Tag.@"while".create(c.arena, .{ .cond = cond, .body = body, .cont_expr = null }); |
| 2291 | 2322 | } |
| 2292 | 2323 | |
| ... | ... | @@ -2312,7 +2343,7 @@ fn transDoWhileLoop( |
| 2312 | 2343 | const if_not_break = switch (cond.tag()) { |
| 2313 | 2344 | .false_literal => return transStmt(c, scope, stmt.getBody(), .unused), |
| 2314 | 2345 | .true_literal => { |
| 2315 | | const body_node = try transStmt(c, scope, stmt.getBody(), .unused); |
| 2346 | const body_node = try maybeBlockify(c, scope, stmt.getBody()); |
| 2316 | 2347 | return Tag.while_true.create(c.arena, body_node); |
| 2317 | 2348 | }, |
| 2318 | 2349 | else => try Tag.if_not_break.create(c.arena, cond), |
| ... | ... | @@ -2388,7 +2419,7 @@ fn transForLoop( |
| 2388 | 2419 | else |
| 2389 | 2420 | null; |
| 2390 | 2421 | |
| 2391 | | const body = try transStmt(c, &loop_scope, stmt.getBody(), .unused); |
| 2422 | const body = try maybeBlockify(c, &loop_scope, stmt.getBody()); |
| 2392 | 2423 | const while_node = try Tag.@"while".create(c.arena, .{ .cond = cond, .body = body, .cont_expr = cont_expr }); |
| 2393 | 2424 | if (block_scope) |*bs| { |
| 2394 | 2425 | try bs.statements.append(while_node); |