| ... | @@ -82,6 +82,7 @@ struct TransScopeSwitch { | ... | @@ -82,6 +82,7 @@ struct TransScopeSwitch { |
| 82 | AstNode *switch_node; | 82 | AstNode *switch_node; |
| 83 | uint32_t case_index; | 83 | uint32_t case_index; |
| 84 | bool found_default; | 84 | bool found_default; |
| | 85 | Buf *end_label_name; |
| 85 | }; | 86 | }; |
| 86 | | 87 | |
| 87 | struct TransScopeVar { | 88 | struct TransScopeVar { |
| ... | @@ -156,6 +157,19 @@ static void add_global_weak_alias(Context *c, Buf *new_name, Buf *canon_name) { | ... | @@ -156,6 +157,19 @@ static void add_global_weak_alias(Context *c, Buf *new_name, Buf *canon_name) { |
| 156 | alias->canon_name = canon_name; | 157 | alias->canon_name = canon_name; |
| 157 | } | 158 | } |
| 158 | | 159 | |
| | 160 | static Buf *trans_lookup_zig_symbol(Context *c, TransScope *scope, Buf *c_symbol_name) { |
| | 161 | while (scope != nullptr) { |
| | 162 | if (scope->id == TransScopeIdVar) { |
| | 163 | TransScopeVar *var_scope = (TransScopeVar *)scope; |
| | 164 | if (buf_eql_buf(var_scope->c_name, c_symbol_name)) { |
| | 165 | return var_scope->zig_name; |
| | 166 | } |
| | 167 | } |
| | 168 | scope = scope->parent; |
| | 169 | } |
| | 170 | return c_symbol_name; |
| | 171 | } |
| | 172 | |
| 159 | static AstNode * trans_create_node(Context *c, NodeType id) { | 173 | static AstNode * trans_create_node(Context *c, NodeType id) { |
| 160 | AstNode *node = allocate<AstNode>(1); | 174 | AstNode *node = allocate<AstNode>(1); |
| 161 | node->type = id; | 175 | node->type = id; |
| ... | @@ -248,6 +262,18 @@ static AstNode *trans_create_node_addr_of(Context *c, bool is_const, bool is_vol | ... | @@ -248,6 +262,18 @@ static AstNode *trans_create_node_addr_of(Context *c, bool is_const, bool is_vol |
| 248 | return node; | 262 | return node; |
| 249 | } | 263 | } |
| 250 | | 264 | |
| | 265 | static AstNode *trans_create_node_goto(Context *c, Buf *label_name) { |
| | 266 | AstNode *goto_node = trans_create_node(c, NodeTypeGoto); |
| | 267 | goto_node->data.goto_expr.name = label_name; |
| | 268 | return goto_node; |
| | 269 | } |
| | 270 | |
| | 271 | static AstNode *trans_create_node_label(Context *c, Buf *label_name) { |
| | 272 | AstNode *label_node = trans_create_node(c, NodeTypeLabel); |
| | 273 | label_node->data.label.name = label_name; |
| | 274 | return label_node; |
| | 275 | } |
| | 276 | |
| 251 | static AstNode *trans_create_node_bool(Context *c, bool value) { | 277 | static AstNode *trans_create_node_bool(Context *c, bool value) { |
| 252 | AstNode *bool_node = trans_create_node(c, NodeTypeBoolLiteral); | 278 | AstNode *bool_node = trans_create_node(c, NodeTypeBoolLiteral); |
| 253 | bool_node->data.bool_literal.value = value; | 279 | bool_node->data.bool_literal.value = value; |
| ... | @@ -414,6 +440,10 @@ static AstNode *trans_create_node_apint(Context *c, const llvm::APSInt &aps_int) | ... | @@ -414,6 +440,10 @@ static AstNode *trans_create_node_apint(Context *c, const llvm::APSInt &aps_int) |
| 414 | | 440 | |
| 415 | } | 441 | } |
| 416 | | 442 | |
| | 443 | static const Type *qual_type_canon(QualType qt) { |
| | 444 | return qt.getCanonicalType().getTypePtr(); |
| | 445 | } |
| | 446 | |
| 417 | static QualType get_expr_qual_type(Context *c, const Expr *expr) { | 447 | static QualType get_expr_qual_type(Context *c, const Expr *expr) { |
| 418 | // String literals in C are `char *` but they should really be `const char *`. | 448 | // String literals in C are `char *` but they should really be `const char *`. |
| 419 | if (expr->getStmtClass() == Stmt::ImplicitCastExprClass) { | 449 | if (expr->getStmtClass() == Stmt::ImplicitCastExprClass) { |
| ... | @@ -436,10 +466,7 @@ static AstNode *get_expr_type(Context *c, const Expr *expr) { | ... | @@ -436,10 +466,7 @@ static AstNode *get_expr_type(Context *c, const Expr *expr) { |
| 436 | return trans_qual_type(c, get_expr_qual_type(c, expr), expr->getLocStart()); | 466 | return trans_qual_type(c, get_expr_qual_type(c, expr), expr->getLocStart()); |
| 437 | } | 467 | } |
| 438 | | 468 | |
| 439 | static bool expr_types_equal(Context *c, const Expr *expr1, const Expr *expr2) { | 469 | static bool qual_types_equal(QualType t1, QualType t2) { |
| 440 | QualType t1 = get_expr_qual_type(c, expr1); | | |
| 441 | QualType t2 = get_expr_qual_type(c, expr2); | | |
| 442 | | | |
| 443 | if (t1.isConstQualified() != t2.isConstQualified()) { | 470 | if (t1.isConstQualified() != t2.isConstQualified()) { |
| 444 | return false; | 471 | return false; |
| 445 | } | 472 | } |
| ... | @@ -456,26 +483,27 @@ static bool is_c_void_type(AstNode *node) { | ... | @@ -456,26 +483,27 @@ static bool is_c_void_type(AstNode *node) { |
| 456 | return (node->type == NodeTypeSymbol && buf_eql_str(node->data.symbol_expr.symbol, "c_void")); | 483 | return (node->type == NodeTypeSymbol && buf_eql_str(node->data.symbol_expr.symbol, "c_void")); |
| 457 | } | 484 | } |
| 458 | | 485 | |
| 459 | static AstNode* trans_c_cast(Context *c, const SourceLocation &source_location, const QualType &qt, AstNode *expr) { | 486 | static bool expr_types_equal(Context *c, const Expr *expr1, const Expr *expr2) { |
| 460 | // TODO: maybe widen to increase size | 487 | QualType t1 = get_expr_qual_type(c, expr1); |
| 461 | // TODO: maybe bitcast to change sign | 488 | QualType t2 = get_expr_qual_type(c, expr2); |
| 462 | // TODO: maybe truncate to reduce size | 489 | |
| 463 | return trans_create_node_fn_call_1(c, trans_qual_type(c, qt, source_location), expr); | 490 | return qual_types_equal(t1, t2); |
| 464 | } | 491 | } |
| 465 | | 492 | |
| 466 | static bool qual_type_is_fn_ptr(Context *c, const QualType &qt) { | 493 | static bool qual_type_is_ptr(QualType qt) { |
| 467 | const Type *ty = qt.getTypePtr(); | 494 | const Type *ty = qual_type_canon(qt); |
| | 495 | return ty->getTypeClass() == Type::Pointer; |
| | 496 | } |
| | 497 | |
| | 498 | static bool qual_type_is_fn_ptr(Context *c, QualType qt) { |
| | 499 | const Type *ty = qual_type_canon(qt); |
| 468 | if (ty->getTypeClass() != Type::Pointer) { | 500 | if (ty->getTypeClass() != Type::Pointer) { |
| 469 | return false; | 501 | return false; |
| 470 | } | 502 | } |
| 471 | const PointerType *pointer_ty = static_cast<const PointerType*>(ty); | 503 | const PointerType *pointer_ty = static_cast<const PointerType*>(ty); |
| 472 | QualType child_qt = pointer_ty->getPointeeType(); | 504 | QualType child_qt = pointer_ty->getPointeeType(); |
| 473 | const Type *child_ty = child_qt.getTypePtr(); | 505 | const Type *child_ty = child_qt.getTypePtr(); |
| 474 | if (child_ty->getTypeClass() != Type::Paren) { | 506 | return child_ty->getTypeClass() == Type::FunctionProto; |
| 475 | return false; | | |
| 476 | } | | |
| 477 | const ParenType *paren_ty = static_cast<const ParenType *>(child_ty); | | |
| 478 | return paren_ty->getInnerType().getTypePtr()->getTypeClass() == Type::FunctionProto; | | |
| 479 | } | 507 | } |
| 480 | | 508 | |
| 481 | static uint32_t qual_type_int_bit_width(Context *c, const QualType &qt, const SourceLocation &source_loc) { | 509 | static uint32_t qual_type_int_bit_width(Context *c, const QualType &qt, const SourceLocation &source_loc) { |
| ... | @@ -568,17 +596,26 @@ static bool qual_type_child_is_fn_proto(const QualType &qt) { | ... | @@ -568,17 +596,26 @@ static bool qual_type_child_is_fn_proto(const QualType &qt) { |
| 568 | return false; | 596 | return false; |
| 569 | } | 597 | } |
| 570 | | 598 | |
| 571 | static QualType resolve_any_typedef(Context *c, QualType qt) { | 599 | static AstNode* trans_c_cast(Context *c, const SourceLocation &source_location, QualType dest_type, |
| 572 | const Type * ty = qt.getTypePtr(); | 600 | QualType src_type, AstNode *expr) |
| 573 | if (ty->getTypeClass() != Type::Typedef) | 601 | { |
| 574 | return qt; | 602 | if (qual_types_equal(dest_type, src_type)) { |
| 575 | const TypedefType *typedef_ty = static_cast<const TypedefType*>(ty); | 603 | return expr; |
| 576 | const TypedefNameDecl *typedef_decl = typedef_ty->getDecl(); | 604 | } |
| 577 | return typedef_decl->getUnderlyingType(); | 605 | if (qual_type_is_ptr(dest_type) && qual_type_is_ptr(src_type)) { |
| | 606 | AstNode *ptr_cast_node = trans_create_node_builtin_fn_call_str(c, "ptrCast"); |
| | 607 | ptr_cast_node->data.fn_call_expr.params.append(trans_qual_type(c, dest_type, source_location)); |
| | 608 | ptr_cast_node->data.fn_call_expr.params.append(expr); |
| | 609 | return ptr_cast_node; |
| | 610 | } |
| | 611 | // TODO: maybe widen to increase size |
| | 612 | // TODO: maybe bitcast to change sign |
| | 613 | // TODO: maybe truncate to reduce size |
| | 614 | return trans_create_node_fn_call_1(c, trans_qual_type(c, dest_type, source_location), expr); |
| 578 | } | 615 | } |
| 579 | | 616 | |
| 580 | static bool c_is_signed_integer(Context *c, QualType qt) { | 617 | static bool c_is_signed_integer(Context *c, QualType qt) { |
| 581 | const Type *c_type = resolve_any_typedef(c, qt).getTypePtr(); | 618 | const Type *c_type = qual_type_canon(qt); |
| 582 | if (c_type->getTypeClass() != Type::Builtin) | 619 | if (c_type->getTypeClass() != Type::Builtin) |
| 583 | return false; | 620 | return false; |
| 584 | const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(c_type); | 621 | const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(c_type); |
| ... | @@ -597,7 +634,7 @@ static bool c_is_signed_integer(Context *c, QualType qt) { | ... | @@ -597,7 +634,7 @@ static bool c_is_signed_integer(Context *c, QualType qt) { |
| 597 | } | 634 | } |
| 598 | | 635 | |
| 599 | static bool c_is_unsigned_integer(Context *c, QualType qt) { | 636 | static bool c_is_unsigned_integer(Context *c, QualType qt) { |
| 600 | const Type *c_type = resolve_any_typedef(c, qt).getTypePtr(); | 637 | const Type *c_type = qual_type_canon(qt); |
| 601 | if (c_type->getTypeClass() != Type::Builtin) | 638 | if (c_type->getTypeClass() != Type::Builtin) |
| 602 | return false; | 639 | return false; |
| 603 | const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(c_type); | 640 | const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(c_type); |
| ... | @@ -865,6 +902,11 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou | ... | @@ -865,6 +902,11 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou |
| 865 | return nullptr; | 902 | return nullptr; |
| 866 | } | 903 | } |
| 867 | // convert c_void to actual void (only for return type) | 904 | // convert c_void to actual void (only for return type) |
| | 905 | // we do want to look at the AstNode instead of QualType, because |
| | 906 | // if they do something like: |
| | 907 | // typedef Foo void; |
| | 908 | // void foo(void) -> Foo; |
| | 909 | // we want to keep the return type AST node. |
| 868 | if (is_c_void_type(proto_node->data.fn_proto.return_type)) { | 910 | if (is_c_void_type(proto_node->data.fn_proto.return_type)) { |
| 869 | proto_node->data.fn_proto.return_type = nullptr; | 911 | proto_node->data.fn_proto.return_type = nullptr; |
| 870 | } | 912 | } |
| ... | @@ -1291,19 +1333,28 @@ static AstNode *trans_create_compound_assign_shift(Context *c, ResultUsed result | ... | @@ -1291,19 +1333,28 @@ static AstNode *trans_create_compound_assign_shift(Context *c, ResultUsed result |
| 1291 | if (rhs == nullptr) return nullptr; | 1333 | if (rhs == nullptr) return nullptr; |
| 1292 | AstNode *coerced_rhs = trans_create_node_fn_call_1(c, rhs_type, rhs); | 1334 | AstNode *coerced_rhs = trans_create_node_fn_call_1(c, rhs_type, rhs); |
| 1293 | | 1335 | |
| | 1336 | // operation_type(*_ref) |
| | 1337 | AstNode *operation_type_cast = trans_c_cast(c, rhs_location, |
| | 1338 | stmt->getComputationLHSType(), |
| | 1339 | stmt->getLHS()->getType(), |
| | 1340 | trans_create_node_prefix_op(c, PrefixOpDereference, |
| | 1341 | trans_create_node_symbol(c, tmp_var_name))); |
| | 1342 | |
| | 1343 | // result_type(... >> u5(rhs)) |
| | 1344 | AstNode *result_type_cast = trans_c_cast(c, rhs_location, |
| | 1345 | stmt->getComputationResultType(), |
| | 1346 | stmt->getComputationLHSType(), |
| | 1347 | trans_create_node_bin_op(c, |
| | 1348 | operation_type_cast, |
| | 1349 | bin_op, |
| | 1350 | coerced_rhs)); |
| | 1351 | |
| | 1352 | // *_ref = ... |
| 1294 | AstNode *assign_statement = trans_create_node_bin_op(c, | 1353 | AstNode *assign_statement = trans_create_node_bin_op(c, |
| 1295 | trans_create_node_prefix_op(c, PrefixOpDereference, | 1354 | trans_create_node_prefix_op(c, PrefixOpDereference, |
| 1296 | trans_create_node_symbol(c, tmp_var_name)), | 1355 | trans_create_node_symbol(c, tmp_var_name)), |
| 1297 | BinOpTypeAssign, | 1356 | BinOpTypeAssign, result_type_cast); |
| 1298 | trans_c_cast(c, rhs_location, | 1357 | |
| 1299 | stmt->getComputationResultType(), | | |
| 1300 | trans_create_node_bin_op(c, | | |
| 1301 | trans_c_cast(c, rhs_location, | | |
| 1302 | stmt->getComputationLHSType(), | | |
| 1303 | trans_create_node_prefix_op(c, PrefixOpDereference, | | |
| 1304 | trans_create_node_symbol(c, tmp_var_name))), | | |
| 1305 | bin_op, | | |
| 1306 | coerced_rhs))); | | |
| 1307 | child_scope->node->data.block.statements.append(assign_statement); | 1358 | child_scope->node->data.block.statements.append(assign_statement); |
| 1308 | | 1359 | |
| 1309 | if (result_used == ResultUsedYes) { | 1360 | if (result_used == ResultUsedYes) { |
| ... | @@ -1448,7 +1499,8 @@ static AstNode *trans_implicit_cast_expr(Context *c, TransScope *scope, const Im | ... | @@ -1448,7 +1499,8 @@ static AstNode *trans_implicit_cast_expr(Context *c, TransScope *scope, const Im |
| 1448 | AstNode *target_node = trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue); | 1499 | AstNode *target_node = trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue); |
| 1449 | if (target_node == nullptr) | 1500 | if (target_node == nullptr) |
| 1450 | return nullptr; | 1501 | return nullptr; |
| 1451 | return trans_c_cast(c, stmt->getExprLoc(), stmt->getType(), target_node); | 1502 | return trans_c_cast(c, stmt->getExprLoc(), stmt->getType(), |
| | 1503 | stmt->getSubExpr()->getType(), target_node); |
| 1452 | } | 1504 | } |
| 1453 | case CK_FunctionToPointerDecay: | 1505 | case CK_FunctionToPointerDecay: |
| 1454 | case CK_ArrayToPointerDecay: | 1506 | case CK_ArrayToPointerDecay: |
| ... | @@ -1637,13 +1689,14 @@ static AstNode *trans_implicit_cast_expr(Context *c, TransScope *scope, const Im | ... | @@ -1637,13 +1689,14 @@ static AstNode *trans_implicit_cast_expr(Context *c, TransScope *scope, const Im |
| 1637 | zig_unreachable(); | 1689 | zig_unreachable(); |
| 1638 | } | 1690 | } |
| 1639 | | 1691 | |
| 1640 | static AstNode *trans_decl_ref_expr(Context *c, const DeclRefExpr *stmt, TransLRValue lrval) { | 1692 | static AstNode *trans_decl_ref_expr(Context *c, TransScope *scope, const DeclRefExpr *stmt, TransLRValue lrval) { |
| 1641 | const ValueDecl *value_decl = stmt->getDecl(); | 1693 | const ValueDecl *value_decl = stmt->getDecl(); |
| 1642 | Buf *symbol_name = buf_create_from_str(decl_name(value_decl)); | 1694 | Buf *c_symbol_name = buf_create_from_str(decl_name(value_decl)); |
| | 1695 | Buf *zig_symbol_name = trans_lookup_zig_symbol(c, scope, c_symbol_name); |
| 1643 | if (lrval == TransLValue) { | 1696 | if (lrval == TransLValue) { |
| 1644 | c->ptr_params.put(symbol_name, true); | 1697 | c->ptr_params.put(zig_symbol_name, true); |
| 1645 | } | 1698 | } |
| 1646 | return trans_create_node_symbol(c, symbol_name); | 1699 | return trans_create_node_symbol(c, zig_symbol_name); |
| 1647 | } | 1700 | } |
| 1648 | | 1701 | |
| 1649 | static AstNode *trans_create_post_crement(Context *c, ResultUsed result_used, TransScope *scope, | 1702 | static AstNode *trans_create_post_crement(Context *c, ResultUsed result_used, TransScope *scope, |
| ... | @@ -2150,9 +2203,23 @@ static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope * | ... | @@ -2150,9 +2203,23 @@ static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope * |
| 2150 | if (callee_raw_node == nullptr) | 2203 | if (callee_raw_node == nullptr) |
| 2151 | return nullptr; | 2204 | return nullptr; |
| 2152 | | 2205 | |
| 2153 | AstNode *callee_node; | 2206 | AstNode *callee_node = nullptr; |
| 2154 | if (qual_type_is_fn_ptr(c, stmt->getCallee()->getType())) { | 2207 | if (qual_type_is_fn_ptr(c, stmt->getCallee()->getType())) { |
| 2155 | callee_node = trans_create_node_prefix_op(c, PrefixOpUnwrapMaybe, callee_raw_node); | 2208 | if (stmt->getCallee()->getStmtClass() == Stmt::ImplicitCastExprClass) { |
| | 2209 | const ImplicitCastExpr *implicit_cast = static_cast<const ImplicitCastExpr *>(stmt->getCallee()); |
| | 2210 | if (implicit_cast->getCastKind() == CK_FunctionToPointerDecay) { |
| | 2211 | if (implicit_cast->getSubExpr()->getStmtClass() == Stmt::DeclRefExprClass) { |
| | 2212 | const DeclRefExpr *decl_ref = static_cast<const DeclRefExpr *>(implicit_cast->getSubExpr()); |
| | 2213 | const Decl *decl = decl_ref->getFoundDecl(); |
| | 2214 | if (decl->getKind() == Decl::Function) { |
| | 2215 | callee_node = callee_raw_node; |
| | 2216 | } |
| | 2217 | } |
| | 2218 | } |
| | 2219 | } |
| | 2220 | if (callee_node == nullptr) { |
| | 2221 | callee_node = trans_create_node_prefix_op(c, PrefixOpUnwrapMaybe, callee_raw_node); |
| | 2222 | } |
| 2156 | } else { | 2223 | } else { |
| 2157 | callee_node = callee_raw_node; | 2224 | callee_node = callee_raw_node; |
| 2158 | } | 2225 | } |
| ... | @@ -2210,7 +2277,7 @@ static AstNode *trans_c_style_cast_expr(Context *c, ResultUsed result_used, Tran | ... | @@ -2210,7 +2277,7 @@ static AstNode *trans_c_style_cast_expr(Context *c, ResultUsed result_used, Tran |
| 2210 | if (sub_expr_node == nullptr) | 2277 | if (sub_expr_node == nullptr) |
| 2211 | return nullptr; | 2278 | return nullptr; |
| 2212 | | 2279 | |
| 2213 | return trans_c_cast(c, stmt->getLocStart(), stmt->getType(), sub_expr_node); | 2280 | return trans_c_cast(c, stmt->getLocStart(), stmt->getType(), stmt->getSubExpr()->getType(), sub_expr_node); |
| 2214 | } | 2281 | } |
| 2215 | | 2282 | |
| 2216 | static AstNode *trans_unary_expr_or_type_trait_expr(Context *c, TransScope *scope, | 2283 | static AstNode *trans_unary_expr_or_type_trait_expr(Context *c, TransScope *scope, |
| ... | @@ -2283,11 +2350,7 @@ static AstNode *trans_do_loop(Context *c, TransScope *parent_scope, const DoStmt | ... | @@ -2283,11 +2350,7 @@ static AstNode *trans_do_loop(Context *c, TransScope *parent_scope, const DoStmt |
| 2283 | } | 2350 | } |
| 2284 | | 2351 | |
| 2285 | static AstNode *trans_switch_stmt(Context *c, TransScope *parent_scope, const SwitchStmt *stmt) { | 2352 | static AstNode *trans_switch_stmt(Context *c, TransScope *parent_scope, const SwitchStmt *stmt) { |
| 2286 | TransScopeWhile *while_scope = trans_scope_while_create(c, parent_scope); | 2353 | TransScopeBlock *block_scope = trans_scope_block_create(c, parent_scope); |
| 2287 | while_scope->node->data.while_expr.condition = trans_create_node_bool(c, true); | | |
| 2288 | | | |
| 2289 | TransScopeBlock *block_scope = trans_scope_block_create(c, &while_scope->base); | | |
| 2290 | while_scope->node->data.while_expr.body = block_scope->node; | | |
| 2291 | | 2354 | |
| 2292 | TransScopeSwitch *switch_scope; | 2355 | TransScopeSwitch *switch_scope; |
| 2293 | | 2356 | |
| ... | @@ -2305,6 +2368,10 @@ static AstNode *trans_switch_stmt(Context *c, TransScope *parent_scope, const Sw | ... | @@ -2305,6 +2368,10 @@ static AstNode *trans_switch_stmt(Context *c, TransScope *parent_scope, const Sw |
| 2305 | } | 2368 | } |
| 2306 | block_scope->node->data.block.statements.append(switch_scope->switch_node); | 2369 | block_scope->node->data.block.statements.append(switch_scope->switch_node); |
| 2307 | | 2370 | |
| | 2371 | // TODO avoid name collisions |
| | 2372 | Buf *end_label_name = buf_create_from_str("end"); |
| | 2373 | switch_scope->end_label_name = end_label_name; |
| | 2374 | |
| 2308 | const Expr *cond_expr = stmt->getCond(); | 2375 | const Expr *cond_expr = stmt->getCond(); |
| 2309 | assert(cond_expr != nullptr); | 2376 | assert(cond_expr != nullptr); |
| 2310 | | 2377 | |
| ... | @@ -2331,14 +2398,16 @@ static AstNode *trans_switch_stmt(Context *c, TransScope *parent_scope, const Sw | ... | @@ -2331,14 +2398,16 @@ static AstNode *trans_switch_stmt(Context *c, TransScope *parent_scope, const Sw |
| 2331 | | 2398 | |
| 2332 | if (!switch_scope->found_default && !stmt->isAllEnumCasesCovered()) { | 2399 | if (!switch_scope->found_default && !stmt->isAllEnumCasesCovered()) { |
| 2333 | AstNode *prong_node = trans_create_node(c, NodeTypeSwitchProng); | 2400 | AstNode *prong_node = trans_create_node(c, NodeTypeSwitchProng); |
| 2334 | prong_node->data.switch_prong.expr = trans_create_node(c, NodeTypeBreak); | 2401 | prong_node->data.switch_prong.expr = trans_create_node_goto(c, end_label_name); |
| 2335 | switch_scope->switch_node->data.switch_expr.prongs.append(prong_node); | 2402 | switch_scope->switch_node->data.switch_expr.prongs.append(prong_node); |
| 2336 | } | 2403 | } |
| 2337 | | 2404 | |
| 2338 | // This is necessary if the last switch case "falls through" the end of the switch block | 2405 | // This is necessary if the last switch case "falls through" the end of the switch block |
| 2339 | block_scope->node->data.block.statements.append(trans_create_node(c, NodeTypeBreak)); | 2406 | block_scope->node->data.block.statements.append(trans_create_node_goto(c, end_label_name)); |
| 2340 | | 2407 | |
| 2341 | return while_scope->node; | 2408 | block_scope->node->data.block.statements.append(trans_create_node_label(c, end_label_name)); |
| | 2409 | |
| | 2410 | return block_scope->node; |
| 2342 | } | 2411 | } |
| 2343 | | 2412 | |
| 2344 | static int trans_switch_case(Context *c, TransScope *parent_scope, const CaseStmt *stmt, AstNode **out_node, | 2413 | static int trans_switch_case(Context *c, TransScope *parent_scope, const CaseStmt *stmt, AstNode **out_node, |
| ... | @@ -2365,18 +2434,13 @@ static int trans_switch_case(Context *c, TransScope *parent_scope, const CaseStm | ... | @@ -2365,18 +2434,13 @@ static int trans_switch_case(Context *c, TransScope *parent_scope, const CaseStm |
| 2365 | return ErrorUnexpected; | 2434 | return ErrorUnexpected; |
| 2366 | prong_node->data.switch_prong.items.append(item_node); | 2435 | prong_node->data.switch_prong.items.append(item_node); |
| 2367 | | 2436 | |
| 2368 | AstNode *goto_node = trans_create_node(c, NodeTypeGoto); | 2437 | prong_node->data.switch_prong.expr = trans_create_node_goto(c, label_name); |
| 2369 | goto_node->data.goto_expr.name = label_name; | | |
| 2370 | prong_node->data.switch_prong.expr = goto_node; | | |
| 2371 | | 2438 | |
| 2372 | switch_scope->switch_node->data.switch_expr.prongs.append(prong_node); | 2439 | switch_scope->switch_node->data.switch_expr.prongs.append(prong_node); |
| 2373 | } | 2440 | } |
| 2374 | | 2441 | |
| 2375 | AstNode *label_node = trans_create_node(c, NodeTypeLabel); | | |
| 2376 | label_node->data.label.name = label_name; | | |
| 2377 | | | |
| 2378 | TransScopeBlock *scope_block = trans_scope_block_find(parent_scope); | 2442 | TransScopeBlock *scope_block = trans_scope_block_find(parent_scope); |
| 2379 | scope_block->node->data.block.statements.append(label_node); | 2443 | scope_block->node->data.block.statements.append(trans_create_node_label(c, label_name)); |
| 2380 | | 2444 | |
| 2381 | AstNode *sub_stmt_node; | 2445 | AstNode *sub_stmt_node; |
| 2382 | TransScope *new_scope = trans_stmt(c, parent_scope, stmt->getSubStmt(), &sub_stmt_node); | 2446 | TransScope *new_scope = trans_stmt(c, parent_scope, stmt->getSubStmt(), &sub_stmt_node); |
| ... | @@ -2399,23 +2463,19 @@ static int trans_switch_default(Context *c, TransScope *parent_scope, const Defa | ... | @@ -2399,23 +2463,19 @@ static int trans_switch_default(Context *c, TransScope *parent_scope, const Defa |
| 2399 | | 2463 | |
| 2400 | Buf *label_name = buf_sprintf("default"); | 2464 | Buf *label_name = buf_sprintf("default"); |
| 2401 | | 2465 | |
| 2402 | AstNode *label_node = trans_create_node(c, NodeTypeLabel); | | |
| 2403 | label_node->data.label.name = label_name; | | |
| 2404 | | | |
| 2405 | { | 2466 | { |
| 2406 | // Add the prong | 2467 | // Add the prong |
| 2407 | AstNode *prong_node = trans_create_node(c, NodeTypeSwitchProng); | 2468 | AstNode *prong_node = trans_create_node(c, NodeTypeSwitchProng); |
| 2408 | | 2469 | |
| 2409 | AstNode *goto_node = trans_create_node(c, NodeTypeGoto); | 2470 | prong_node->data.switch_prong.expr = trans_create_node_goto(c, label_name); |
| 2410 | goto_node->data.goto_expr.name = label_name; | | |
| 2411 | prong_node->data.switch_prong.expr = goto_node; | | |
| 2412 | | 2471 | |
| 2413 | switch_scope->switch_node->data.switch_expr.prongs.append(prong_node); | 2472 | switch_scope->switch_node->data.switch_expr.prongs.append(prong_node); |
| 2414 | switch_scope->found_default = true; | 2473 | switch_scope->found_default = true; |
| 2415 | } | 2474 | } |
| 2416 | | 2475 | |
| 2417 | TransScopeBlock *scope_block = trans_scope_block_find(parent_scope); | 2476 | TransScopeBlock *scope_block = trans_scope_block_find(parent_scope); |
| 2418 | scope_block->node->data.block.statements.append(label_node); | 2477 | scope_block->node->data.block.statements.append(trans_create_node_label(c, label_name)); |
| | 2478 | |
| 2419 | | 2479 | |
| 2420 | AstNode *sub_stmt_node; | 2480 | AstNode *sub_stmt_node; |
| 2421 | TransScope *new_scope = trans_stmt(c, parent_scope, stmt->getSubStmt(), &sub_stmt_node); | 2481 | TransScope *new_scope = trans_stmt(c, parent_scope, stmt->getSubStmt(), &sub_stmt_node); |
| ... | @@ -2500,7 +2560,17 @@ static AstNode *trans_string_literal(Context *c, TransScope *scope, const String | ... | @@ -2500,7 +2560,17 @@ static AstNode *trans_string_literal(Context *c, TransScope *scope, const String |
| 2500 | } | 2560 | } |
| 2501 | | 2561 | |
| 2502 | static AstNode *trans_break_stmt(Context *c, TransScope *scope, const BreakStmt *stmt) { | 2562 | static AstNode *trans_break_stmt(Context *c, TransScope *scope, const BreakStmt *stmt) { |
| 2503 | return trans_create_node(c, NodeTypeBreak); | 2563 | TransScope *cur_scope = scope; |
| | 2564 | while (cur_scope != nullptr) { |
| | 2565 | if (cur_scope->id == TransScopeIdWhile) { |
| | 2566 | return trans_create_node(c, NodeTypeBreak); |
| | 2567 | } else if (cur_scope->id == TransScopeIdSwitch) { |
| | 2568 | TransScopeSwitch *switch_scope = (TransScopeSwitch *)cur_scope; |
| | 2569 | return trans_create_node_goto(c, switch_scope->end_label_name); |
| | 2570 | } |
| | 2571 | cur_scope = cur_scope->parent; |
| | 2572 | } |
| | 2573 | zig_unreachable(); |
| 2504 | } | 2574 | } |
| 2505 | | 2575 | |
| 2506 | static AstNode *trans_continue_stmt(Context *c, TransScope *scope, const ContinueStmt *stmt) { | 2576 | static AstNode *trans_continue_stmt(Context *c, TransScope *scope, const ContinueStmt *stmt) { |
| ... | @@ -2546,7 +2616,7 @@ static int trans_stmt_extra(Context *c, TransScope *scope, const Stmt *stmt, | ... | @@ -2546,7 +2616,7 @@ static int trans_stmt_extra(Context *c, TransScope *scope, const Stmt *stmt, |
| 2546 | trans_implicit_cast_expr(c, scope, (const ImplicitCastExpr *)stmt)); | 2616 | trans_implicit_cast_expr(c, scope, (const ImplicitCastExpr *)stmt)); |
| 2547 | case Stmt::DeclRefExprClass: | 2617 | case Stmt::DeclRefExprClass: |
| 2548 | return wrap_stmt(out_node, out_child_scope, scope, | 2618 | return wrap_stmt(out_node, out_child_scope, scope, |
| 2549 | trans_decl_ref_expr(c, (const DeclRefExpr *)stmt, lrvalue)); | 2619 | trans_decl_ref_expr(c, scope, (const DeclRefExpr *)stmt, lrvalue)); |
| 2550 | case Stmt::UnaryOperatorClass: | 2620 | case Stmt::UnaryOperatorClass: |
| 2551 | return wrap_stmt(out_node, out_child_scope, scope, | 2621 | return wrap_stmt(out_node, out_child_scope, scope, |
| 2552 | trans_unary_operator(c, result_used, scope, (const UnaryOperator *)stmt)); | 2622 | trans_unary_operator(c, result_used, scope, (const UnaryOperator *)stmt)); |