| ... | @@ -23,6 +23,8 @@ | ... | @@ -23,6 +23,8 @@ |
| 23 | | 23 | |
| 24 | using namespace clang; | 24 | using namespace clang; |
| 25 | | 25 | |
| | 26 | struct TransScope; |
| | 27 | |
| 26 | struct MacroSymbol { | 28 | struct MacroSymbol { |
| 27 | Buf *name; | 29 | Buf *name; |
| 28 | Buf *value; | 30 | Buf *value; |
| ... | @@ -52,12 +54,59 @@ struct Context { | ... | @@ -52,12 +54,59 @@ struct Context { |
| 52 | ASTContext *ctx; | 54 | ASTContext *ctx; |
| 53 | | 55 | |
| 54 | HashMap<Buf *, bool, buf_hash, buf_eql_buf> ptr_params; | 56 | HashMap<Buf *, bool, buf_hash, buf_eql_buf> ptr_params; |
| | 57 | TransScope *child_scope; // TODO refactor out |
| | 58 | }; |
| | 59 | |
| | 60 | enum ResultUsed { |
| | 61 | ResultUsedNo, |
| | 62 | ResultUsedYes, |
| | 63 | }; |
| | 64 | |
| | 65 | enum TransLRValue { |
| | 66 | TransLValue, |
| | 67 | TransRValue, |
| | 68 | }; |
| | 69 | |
| | 70 | enum TransScopeId { |
| | 71 | TransScopeIdSwitch, |
| | 72 | TransScopeIdVar, |
| | 73 | TransScopeIdBlock, |
| 55 | }; | 74 | }; |
| 56 | | 75 | |
| | 76 | struct TransScope { |
| | 77 | TransScopeId id; |
| | 78 | TransScope *parent; |
| | 79 | }; |
| | 80 | |
| | 81 | struct TransScopeSwitch { |
| | 82 | TransScope base; |
| | 83 | AstNode *switch_node; |
| | 84 | }; |
| | 85 | |
| | 86 | struct TransScopeVar { |
| | 87 | TransScope base; |
| | 88 | Buf *c_name; |
| | 89 | Buf *zig_name; |
| | 90 | }; |
| | 91 | |
| | 92 | struct TransScopeBlock { |
| | 93 | TransScope base; |
| | 94 | AstNode *node; |
| | 95 | }; |
| | 96 | |
| | 97 | static AstNode *const skip_add_to_block_node = (AstNode *) 0x2; |
| | 98 | |
| | 99 | static TransScopeBlock *trans_scope_block_create(Context *c, TransScope *parent_scope); |
| | 100 | static TransScopeVar *trans_scope_var_create(Context *c, TransScope *parent_scope, Buf *wanted_name); |
| | 101 | //static TransScopeSwitch *trans_scope_switch_create(Context *c, TransScope *parent_scope); |
| | 102 | |
| 57 | static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl); | 103 | static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl); |
| 58 | static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl); | 104 | static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl); |
| 59 | static AstNode *resolve_typedef_decl(Context *c, const TypedefNameDecl *typedef_decl); | 105 | static AstNode *resolve_typedef_decl(Context *c, const TypedefNameDecl *typedef_decl); |
| 60 | | 106 | |
| | 107 | static AstNode *trans_stmt(Context *c, ResultUsed result_used, TransScope *scope, const Stmt *stmt, TransLRValue lrval); |
| | 108 | static AstNode *trans_qual_type(Context *c, QualType qt, const SourceLocation &source_loc); |
| | 109 | |
| 61 | | 110 | |
| 62 | ATTRIBUTE_PRINTF(3, 4) | 111 | ATTRIBUTE_PRINTF(3, 4) |
| 63 | static void emit_warning(Context *c, const SourceLocation &sl, const char *format, ...) { | 112 | static void emit_warning(Context *c, const SourceLocation &sl, const char *format, ...) { |
| ... | @@ -165,8 +214,8 @@ static AstNode *trans_create_node_bin_op(Context *c, AstNode *lhs_node, BinOpTyp | ... | @@ -165,8 +214,8 @@ static AstNode *trans_create_node_bin_op(Context *c, AstNode *lhs_node, BinOpTyp |
| 165 | return node; | 214 | return node; |
| 166 | } | 215 | } |
| 167 | | 216 | |
| 168 | static AstNode *maybe_suppress_result(Context *c, bool result_used, AstNode *node) { | 217 | static AstNode *maybe_suppress_result(Context *c, ResultUsed result_used, AstNode *node) { |
| 169 | if (result_used) return node; | 218 | if (result_used == ResultUsedYes) return node; |
| 170 | return trans_create_node_bin_op(c, | 219 | return trans_create_node_bin_op(c, |
| 171 | trans_create_node_symbol_str(c, "_"), | 220 | trans_create_node_symbol_str(c, "_"), |
| 172 | BinOpTypeAssign, | 221 | BinOpTypeAssign, |
| ... | @@ -341,8 +390,6 @@ static AstNode *trans_create_node_apint(Context *c, const llvm::APSInt &aps_int) | ... | @@ -341,8 +390,6 @@ static AstNode *trans_create_node_apint(Context *c, const llvm::APSInt &aps_int) |
| 341 | | 390 | |
| 342 | } | 391 | } |
| 343 | | 392 | |
| 344 | static AstNode *trans_qual_type(Context *c, QualType qt, const SourceLocation &source_loc); | | |
| 345 | | | |
| 346 | static QualType get_expr_qual_type(Context *c, const Expr *expr) { | 393 | static QualType get_expr_qual_type(Context *c, const Expr *expr) { |
| 347 | // String literals in C are `char *` but they should really be `const char *`. | 394 | // String literals in C are `char *` but they should really be `const char *`. |
| 348 | if (expr->getStmtClass() == Stmt::ImplicitCastExprClass) { | 395 | if (expr->getStmtClass() == Stmt::ImplicitCastExprClass) { |
| ... | @@ -573,16 +620,8 @@ static bool qual_type_has_wrapping_overflow(Context *c, QualType qt) { | ... | @@ -573,16 +620,8 @@ static bool qual_type_has_wrapping_overflow(Context *c, QualType qt) { |
| 573 | } | 620 | } |
| 574 | } | 621 | } |
| 575 | | 622 | |
| 576 | enum TransLRValue { | 623 | static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope, const Expr *expr, TransLRValue lrval) { |
| 577 | TransLValue, | 624 | return trans_stmt(c, result_used, scope, expr, lrval); |
| 578 | TransRValue, | | |
| 579 | }; | | |
| 580 | | | |
| 581 | static AstNode *trans_stmt(Context *c, bool result_used, AstNode *block, Stmt *stmt, TransLRValue lrval); | | |
| 582 | static AstNode *const skip_add_to_block_node = (AstNode *) 0x2; | | |
| 583 | | | |
| 584 | static AstNode *trans_expr(Context *c, bool result_used, AstNode *block, Expr *expr, TransLRValue lrval) { | | |
| 585 | return trans_stmt(c, result_used, block, expr, lrval); | | |
| 586 | } | 625 | } |
| 587 | | 626 | |
| 588 | static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &source_loc) { | 627 | static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &source_loc) { |
| ... | @@ -922,32 +961,33 @@ static AstNode *trans_qual_type(Context *c, QualType qt, const SourceLocation &s | ... | @@ -922,32 +961,33 @@ static AstNode *trans_qual_type(Context *c, QualType qt, const SourceLocation &s |
| 922 | return trans_type(c, qt.getTypePtr(), source_loc); | 961 | return trans_type(c, qt.getTypePtr(), source_loc); |
| 923 | } | 962 | } |
| 924 | | 963 | |
| 925 | static AstNode *trans_compound_stmt(Context *c, AstNode *parent, CompoundStmt *stmt) { | 964 | static AstNode *trans_compound_stmt(Context *c, TransScope *parent_scope, const CompoundStmt *stmt) { |
| 926 | AstNode *child_block = trans_create_node(c, NodeTypeBlock); | 965 | TransScopeBlock *child_scope_block = trans_scope_block_create(c, parent_scope); |
| 927 | for (CompoundStmt::body_iterator it = stmt->body_begin(), end_it = stmt->body_end(); it != end_it; ++it) { | 966 | for (CompoundStmt::const_body_iterator it = stmt->body_begin(), end_it = stmt->body_end(); it != end_it; ++it) { |
| 928 | AstNode *child_node = trans_stmt(c, false, child_block, *it, TransRValue); | 967 | AstNode *child_node = trans_stmt(c, ResultUsedNo, &child_scope_block->base, *it, TransRValue); |
| 929 | if (child_node == nullptr) | 968 | if (child_node == nullptr) |
| 930 | return nullptr; | 969 | return nullptr; |
| 931 | if (child_node != skip_add_to_block_node) | 970 | if (child_node != skip_add_to_block_node) |
| 932 | child_block->data.block.statements.append(child_node); | 971 | child_scope_block->node->data.block.statements.append(child_node); |
| 933 | } | 972 | } |
| 934 | return child_block; | 973 | c->child_scope = &child_scope_block->base; |
| | 974 | return child_scope_block->node; |
| 935 | } | 975 | } |
| 936 | | 976 | |
| 937 | static AstNode *trans_return_stmt(Context *c, AstNode *block, ReturnStmt *stmt) { | 977 | static AstNode *trans_return_stmt(Context *c, TransScope *scope, const ReturnStmt *stmt) { |
| 938 | Expr *value_expr = stmt->getRetValue(); | 978 | const Expr *value_expr = stmt->getRetValue(); |
| 939 | if (value_expr == nullptr) { | 979 | if (value_expr == nullptr) { |
| 940 | return trans_create_node(c, NodeTypeReturnExpr); | 980 | return trans_create_node(c, NodeTypeReturnExpr); |
| 941 | } else { | 981 | } else { |
| 942 | AstNode *return_node = trans_create_node(c, NodeTypeReturnExpr); | 982 | AstNode *return_node = trans_create_node(c, NodeTypeReturnExpr); |
| 943 | return_node->data.return_expr.expr = trans_expr(c, true, block, value_expr, TransRValue); | 983 | return_node->data.return_expr.expr = trans_expr(c, ResultUsedYes, scope, value_expr, TransRValue); |
| 944 | if (return_node->data.return_expr.expr == nullptr) | 984 | if (return_node->data.return_expr.expr == nullptr) |
| 945 | return nullptr; | 985 | return nullptr; |
| 946 | return return_node; | 986 | return return_node; |
| 947 | } | 987 | } |
| 948 | } | 988 | } |
| 949 | | 989 | |
| 950 | static AstNode *trans_integer_literal(Context *c, IntegerLiteral *stmt) { | 990 | static AstNode *trans_integer_literal(Context *c, const IntegerLiteral *stmt) { |
| 951 | llvm::APSInt result; | 991 | llvm::APSInt result; |
| 952 | if (!stmt->EvaluateAsInt(result, *c->ctx)) { | 992 | if (!stmt->EvaluateAsInt(result, *c->ctx)) { |
| 953 | emit_warning(c, stmt->getLocStart(), "invalid integer literal"); | 993 | emit_warning(c, stmt->getLocStart(), "invalid integer literal"); |
| ... | @@ -956,54 +996,56 @@ static AstNode *trans_integer_literal(Context *c, IntegerLiteral *stmt) { | ... | @@ -956,54 +996,56 @@ static AstNode *trans_integer_literal(Context *c, IntegerLiteral *stmt) { |
| 956 | return trans_create_node_apint(c, result); | 996 | return trans_create_node_apint(c, result); |
| 957 | } | 997 | } |
| 958 | | 998 | |
| 959 | static AstNode *trans_conditional_operator(Context *c, bool result_used, AstNode *block, ConditionalOperator *stmt) { | 999 | static AstNode *trans_conditional_operator(Context *c, ResultUsed result_used, TransScope *scope, |
| | 1000 | const ConditionalOperator *stmt) |
| | 1001 | { |
| 960 | AstNode *node = trans_create_node(c, NodeTypeIfBoolExpr); | 1002 | AstNode *node = trans_create_node(c, NodeTypeIfBoolExpr); |
| 961 | | 1003 | |
| 962 | Expr *cond_expr = stmt->getCond(); | 1004 | Expr *cond_expr = stmt->getCond(); |
| 963 | Expr *true_expr = stmt->getTrueExpr(); | 1005 | Expr *true_expr = stmt->getTrueExpr(); |
| 964 | Expr *false_expr = stmt->getFalseExpr(); | 1006 | Expr *false_expr = stmt->getFalseExpr(); |
| 965 | | 1007 | |
| 966 | node->data.if_bool_expr.condition = trans_expr(c, true, block, cond_expr, TransRValue); | 1008 | node->data.if_bool_expr.condition = trans_expr(c, ResultUsedYes, scope, cond_expr, TransRValue); |
| 967 | if (node->data.if_bool_expr.condition == nullptr) | 1009 | if (node->data.if_bool_expr.condition == nullptr) |
| 968 | return nullptr; | 1010 | return nullptr; |
| 969 | | 1011 | |
| 970 | node->data.if_bool_expr.then_block = trans_expr(c, result_used, block, true_expr, TransRValue); | 1012 | node->data.if_bool_expr.then_block = trans_expr(c, result_used, scope, true_expr, TransRValue); |
| 971 | if (node->data.if_bool_expr.then_block == nullptr) | 1013 | if (node->data.if_bool_expr.then_block == nullptr) |
| 972 | return nullptr; | 1014 | return nullptr; |
| 973 | | 1015 | |
| 974 | node->data.if_bool_expr.else_node = trans_expr(c, result_used, block, false_expr, TransRValue); | 1016 | node->data.if_bool_expr.else_node = trans_expr(c, result_used, scope, false_expr, TransRValue); |
| 975 | if (node->data.if_bool_expr.else_node == nullptr) | 1017 | if (node->data.if_bool_expr.else_node == nullptr) |
| 976 | return nullptr; | 1018 | return nullptr; |
| 977 | | 1019 | |
| 978 | return maybe_suppress_result(c, result_used, node); | 1020 | return maybe_suppress_result(c, result_used, node); |
| 979 | } | 1021 | } |
| 980 | | 1022 | |
| 981 | static AstNode *trans_create_bin_op(Context *c, AstNode *block, Expr *lhs, BinOpType bin_op, Expr *rhs) { | 1023 | static AstNode *trans_create_bin_op(Context *c, TransScope *scope, Expr *lhs, BinOpType bin_op, Expr *rhs) { |
| 982 | AstNode *node = trans_create_node(c, NodeTypeBinOpExpr); | 1024 | AstNode *node = trans_create_node(c, NodeTypeBinOpExpr); |
| 983 | node->data.bin_op_expr.bin_op = bin_op; | 1025 | node->data.bin_op_expr.bin_op = bin_op; |
| 984 | | 1026 | |
| 985 | node->data.bin_op_expr.op1 = trans_expr(c, true, block, lhs, TransRValue); | 1027 | node->data.bin_op_expr.op1 = trans_expr(c, ResultUsedYes, scope, lhs, TransRValue); |
| 986 | if (node->data.bin_op_expr.op1 == nullptr) | 1028 | if (node->data.bin_op_expr.op1 == nullptr) |
| 987 | return nullptr; | 1029 | return nullptr; |
| 988 | | 1030 | |
| 989 | node->data.bin_op_expr.op2 = trans_expr(c, true, block, rhs, TransRValue); | 1031 | node->data.bin_op_expr.op2 = trans_expr(c, ResultUsedYes, scope, rhs, TransRValue); |
| 990 | if (node->data.bin_op_expr.op2 == nullptr) | 1032 | if (node->data.bin_op_expr.op2 == nullptr) |
| 991 | return nullptr; | 1033 | return nullptr; |
| 992 | | 1034 | |
| 993 | return node; | 1035 | return node; |
| 994 | } | 1036 | } |
| 995 | | 1037 | |
| 996 | static AstNode *trans_create_assign(Context *c, bool result_used, AstNode *block, Expr *lhs, Expr *rhs) { | 1038 | static AstNode *trans_create_assign(Context *c, ResultUsed result_used, TransScope *scope, Expr *lhs, Expr *rhs) { |
| 997 | if (!result_used) { | 1039 | if (result_used == ResultUsedNo) { |
| 998 | // common case | 1040 | // common case |
| 999 | AstNode *node = trans_create_node(c, NodeTypeBinOpExpr); | 1041 | AstNode *node = trans_create_node(c, NodeTypeBinOpExpr); |
| 1000 | node->data.bin_op_expr.bin_op = BinOpTypeAssign; | 1042 | node->data.bin_op_expr.bin_op = BinOpTypeAssign; |
| 1001 | | 1043 | |
| 1002 | node->data.bin_op_expr.op1 = trans_expr(c, true, block, lhs, TransLValue); | 1044 | node->data.bin_op_expr.op1 = trans_expr(c, ResultUsedYes, scope, lhs, TransLValue); |
| 1003 | if (node->data.bin_op_expr.op1 == nullptr) | 1045 | if (node->data.bin_op_expr.op1 == nullptr) |
| 1004 | return nullptr; | 1046 | return nullptr; |
| 1005 | | 1047 | |
| 1006 | node->data.bin_op_expr.op2 = trans_expr(c, true, block, rhs, TransRValue); | 1048 | node->data.bin_op_expr.op2 = trans_expr(c, ResultUsedYes, scope, rhs, TransRValue); |
| 1007 | if (node->data.bin_op_expr.op2 == nullptr) | 1049 | if (node->data.bin_op_expr.op2 == nullptr) |
| 1008 | return nullptr; | 1050 | return nullptr; |
| 1009 | | 1051 | |
| ... | @@ -1017,47 +1059,49 @@ static AstNode *trans_create_assign(Context *c, bool result_used, AstNode *block | ... | @@ -1017,47 +1059,49 @@ static AstNode *trans_create_assign(Context *c, bool result_used, AstNode *block |
| 1017 | // zig: _tmp | 1059 | // zig: _tmp |
| 1018 | // zig: } | 1060 | // zig: } |
| 1019 | | 1061 | |
| 1020 | AstNode *child_block = trans_create_node(c, NodeTypeBlock); | 1062 | TransScopeBlock *child_scope = trans_scope_block_create(c, scope); |
| 1021 | | 1063 | |
| 1022 | // const _tmp = rhs; | 1064 | // const _tmp = rhs; |
| 1023 | AstNode *rhs_node = trans_expr(c, true, child_block, rhs, TransRValue); | 1065 | AstNode *rhs_node = trans_expr(c, ResultUsedYes, &child_scope->base, rhs, TransRValue); |
| 1024 | if (rhs_node == nullptr) return nullptr; | 1066 | if (rhs_node == nullptr) return nullptr; |
| 1025 | // TODO: avoid name collisions with generated variable names | 1067 | // TODO: avoid name collisions with generated variable names |
| 1026 | Buf* tmp_var_name = buf_create_from_str("_tmp"); | 1068 | Buf* tmp_var_name = buf_create_from_str("_tmp"); |
| 1027 | AstNode *tmp_var_decl = trans_create_node_var_decl_local(c, true, tmp_var_name, nullptr, rhs_node); | 1069 | AstNode *tmp_var_decl = trans_create_node_var_decl_local(c, true, tmp_var_name, nullptr, rhs_node); |
| 1028 | child_block->data.block.statements.append(tmp_var_decl); | 1070 | child_scope->node->data.block.statements.append(tmp_var_decl); |
| 1029 | | 1071 | |
| 1030 | // lhs = _tmp; | 1072 | // lhs = _tmp; |
| 1031 | AstNode *lhs_node = trans_expr(c, true, child_block, lhs, TransLValue); | 1073 | AstNode *lhs_node = trans_expr(c, ResultUsedYes, &child_scope->base, lhs, TransLValue); |
| 1032 | if (lhs_node == nullptr) return nullptr; | 1074 | if (lhs_node == nullptr) return nullptr; |
| 1033 | child_block->data.block.statements.append( | 1075 | child_scope->node->data.block.statements.append( |
| 1034 | trans_create_node_bin_op(c, lhs_node, BinOpTypeAssign, | 1076 | trans_create_node_bin_op(c, lhs_node, BinOpTypeAssign, |
| 1035 | trans_create_node_symbol(c, tmp_var_name))); | 1077 | trans_create_node_symbol(c, tmp_var_name))); |
| 1036 | | 1078 | |
| 1037 | // _tmp | 1079 | // _tmp |
| 1038 | child_block->data.block.statements.append(trans_create_node_symbol(c, tmp_var_name)); | 1080 | child_scope->node->data.block.statements.append(trans_create_node_symbol(c, tmp_var_name)); |
| 1039 | child_block->data.block.last_statement_is_result_expression = true; | 1081 | child_scope->node->data.block.last_statement_is_result_expression = true; |
| 1040 | | 1082 | |
| 1041 | return child_block; | 1083 | return child_scope->node; |
| 1042 | } | 1084 | } |
| 1043 | } | 1085 | } |
| 1044 | | 1086 | |
| 1045 | static AstNode *trans_create_shift_op(Context *c, AstNode *block, QualType result_type, Expr *lhs_expr, BinOpType bin_op, Expr *rhs_expr) { | 1087 | static AstNode *trans_create_shift_op(Context *c, TransScope *scope, QualType result_type, |
| | 1088 | Expr *lhs_expr, BinOpType bin_op, Expr *rhs_expr) |
| | 1089 | { |
| 1046 | const SourceLocation &rhs_location = rhs_expr->getLocStart(); | 1090 | const SourceLocation &rhs_location = rhs_expr->getLocStart(); |
| 1047 | AstNode *rhs_type = qual_type_to_log2_int_ref(c, result_type, rhs_location); | 1091 | AstNode *rhs_type = qual_type_to_log2_int_ref(c, result_type, rhs_location); |
| 1048 | // lhs >> u5(rh) | 1092 | // lhs >> u5(rh) |
| 1049 | | 1093 | |
| 1050 | AstNode *lhs = trans_expr(c, true, block, lhs_expr, TransLValue); | 1094 | AstNode *lhs = trans_expr(c, ResultUsedYes, scope, lhs_expr, TransLValue); |
| 1051 | if (lhs == nullptr) return nullptr; | 1095 | if (lhs == nullptr) return nullptr; |
| 1052 | | 1096 | |
| 1053 | AstNode *rhs = trans_expr(c, true, block, rhs_expr, TransRValue); | 1097 | AstNode *rhs = trans_expr(c, ResultUsedYes, scope, rhs_expr, TransRValue); |
| 1054 | if (rhs == nullptr) return nullptr; | 1098 | if (rhs == nullptr) return nullptr; |
| 1055 | AstNode *coerced_rhs = trans_create_node_fn_call_1(c, rhs_type, rhs); | 1099 | AstNode *coerced_rhs = trans_create_node_fn_call_1(c, rhs_type, rhs); |
| 1056 | | 1100 | |
| 1057 | return trans_create_node_bin_op(c, lhs, bin_op, coerced_rhs); | 1101 | return trans_create_node_bin_op(c, lhs, bin_op, coerced_rhs); |
| 1058 | } | 1102 | } |
| 1059 | | 1103 | |
| 1060 | static AstNode *trans_binary_operator(Context *c, bool result_used, AstNode *block, BinaryOperator *stmt) { | 1104 | static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransScope *scope, const BinaryOperator *stmt) { |
| 1061 | switch (stmt->getOpcode()) { | 1105 | switch (stmt->getOpcode()) { |
| 1062 | case BO_PtrMemD: | 1106 | case BO_PtrMemD: |
| 1063 | emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_PtrMemD"); | 1107 | emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_PtrMemD"); |
| ... | @@ -1066,20 +1110,20 @@ static AstNode *trans_binary_operator(Context *c, bool result_used, AstNode *blo | ... | @@ -1066,20 +1110,20 @@ static AstNode *trans_binary_operator(Context *c, bool result_used, AstNode *blo |
| 1066 | emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_PtrMemI"); | 1110 | emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_PtrMemI"); |
| 1067 | return nullptr; | 1111 | return nullptr; |
| 1068 | case BO_Mul: | 1112 | case BO_Mul: |
| 1069 | return trans_create_bin_op(c, block, stmt->getLHS(), | 1113 | return trans_create_bin_op(c, scope, stmt->getLHS(), |
| 1070 | qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeMultWrap : BinOpTypeMult, | 1114 | qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeMultWrap : BinOpTypeMult, |
| 1071 | stmt->getRHS()); | 1115 | stmt->getRHS()); |
| 1072 | case BO_Div: | 1116 | case BO_Div: |
| 1073 | if (qual_type_has_wrapping_overflow(c, stmt->getType())) { | 1117 | if (qual_type_has_wrapping_overflow(c, stmt->getType())) { |
| 1074 | // unsigned/float division uses the operator | 1118 | // unsigned/float division uses the operator |
| 1075 | return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeDiv, stmt->getRHS()); | 1119 | return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeDiv, stmt->getRHS()); |
| 1076 | } else { | 1120 | } else { |
| 1077 | // signed integer division uses @divTrunc | 1121 | // signed integer division uses @divTrunc |
| 1078 | AstNode *fn_call = trans_create_node_builtin_fn_call_str(c, "divTrunc"); | 1122 | AstNode *fn_call = trans_create_node_builtin_fn_call_str(c, "divTrunc"); |
| 1079 | AstNode *lhs = trans_expr(c, true, block, stmt->getLHS(), TransLValue); | 1123 | AstNode *lhs = trans_expr(c, ResultUsedYes, scope, stmt->getLHS(), TransLValue); |
| 1080 | if (lhs == nullptr) return nullptr; | 1124 | if (lhs == nullptr) return nullptr; |
| 1081 | fn_call->data.fn_call_expr.params.append(lhs); | 1125 | fn_call->data.fn_call_expr.params.append(lhs); |
| 1082 | AstNode *rhs = trans_expr(c, true, block, stmt->getRHS(), TransLValue); | 1126 | AstNode *rhs = trans_expr(c, ResultUsedYes, scope, stmt->getRHS(), TransLValue); |
| 1083 | if (rhs == nullptr) return nullptr; | 1127 | if (rhs == nullptr) return nullptr; |
| 1084 | fn_call->data.fn_call_expr.params.append(rhs); | 1128 | fn_call->data.fn_call_expr.params.append(rhs); |
| 1085 | return fn_call; | 1129 | return fn_call; |
| ... | @@ -1087,66 +1131,70 @@ static AstNode *trans_binary_operator(Context *c, bool result_used, AstNode *blo | ... | @@ -1087,66 +1131,70 @@ static AstNode *trans_binary_operator(Context *c, bool result_used, AstNode *blo |
| 1087 | case BO_Rem: | 1131 | case BO_Rem: |
| 1088 | if (qual_type_has_wrapping_overflow(c, stmt->getType())) { | 1132 | if (qual_type_has_wrapping_overflow(c, stmt->getType())) { |
| 1089 | // unsigned/float division uses the operator | 1133 | // unsigned/float division uses the operator |
| 1090 | return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeMod, stmt->getRHS()); | 1134 | return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeMod, stmt->getRHS()); |
| 1091 | } else { | 1135 | } else { |
| 1092 | // signed integer division uses @rem | 1136 | // signed integer division uses @rem |
| 1093 | AstNode *fn_call = trans_create_node_builtin_fn_call_str(c, "rem"); | 1137 | AstNode *fn_call = trans_create_node_builtin_fn_call_str(c, "rem"); |
| 1094 | AstNode *lhs = trans_expr(c, true, block, stmt->getLHS(), TransLValue); | 1138 | AstNode *lhs = trans_expr(c, ResultUsedYes, scope, stmt->getLHS(), TransLValue); |
| 1095 | if (lhs == nullptr) return nullptr; | 1139 | if (lhs == nullptr) return nullptr; |
| 1096 | fn_call->data.fn_call_expr.params.append(lhs); | 1140 | fn_call->data.fn_call_expr.params.append(lhs); |
| 1097 | AstNode *rhs = trans_expr(c, true, block, stmt->getRHS(), TransLValue); | 1141 | AstNode *rhs = trans_expr(c, ResultUsedYes, scope, stmt->getRHS(), TransLValue); |
| 1098 | if (rhs == nullptr) return nullptr; | 1142 | if (rhs == nullptr) return nullptr; |
| 1099 | fn_call->data.fn_call_expr.params.append(rhs); | 1143 | fn_call->data.fn_call_expr.params.append(rhs); |
| 1100 | return fn_call; | 1144 | return fn_call; |
| 1101 | } | 1145 | } |
| 1102 | case BO_Add: | 1146 | case BO_Add: |
| 1103 | return trans_create_bin_op(c, block, stmt->getLHS(), | 1147 | return trans_create_bin_op(c, scope, stmt->getLHS(), |
| 1104 | qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeAddWrap : BinOpTypeAdd, | 1148 | qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeAddWrap : BinOpTypeAdd, |
| 1105 | stmt->getRHS()); | 1149 | stmt->getRHS()); |
| 1106 | case BO_Sub: | 1150 | case BO_Sub: |
| 1107 | return trans_create_bin_op(c, block, stmt->getLHS(), | 1151 | return trans_create_bin_op(c, scope, stmt->getLHS(), |
| 1108 | qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeSubWrap : BinOpTypeSub, | 1152 | qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeSubWrap : BinOpTypeSub, |
| 1109 | stmt->getRHS()); | 1153 | stmt->getRHS()); |
| 1110 | case BO_Shl: | 1154 | case BO_Shl: |
| 1111 | return trans_create_shift_op(c, block, stmt->getType(), stmt->getLHS(), BinOpTypeBitShiftLeft, stmt->getRHS()); | 1155 | return trans_create_shift_op(c, scope, stmt->getType(), stmt->getLHS(), BinOpTypeBitShiftLeft, stmt->getRHS()); |
| 1112 | case BO_Shr: | 1156 | case BO_Shr: |
| 1113 | return trans_create_shift_op(c, block, stmt->getType(), stmt->getLHS(), BinOpTypeBitShiftRight, stmt->getRHS()); | 1157 | return trans_create_shift_op(c, scope, stmt->getType(), stmt->getLHS(), BinOpTypeBitShiftRight, stmt->getRHS()); |
| 1114 | case BO_LT: | 1158 | case BO_LT: |
| 1115 | return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeCmpLessThan, stmt->getRHS()); | 1159 | return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpLessThan, stmt->getRHS()); |
| 1116 | case BO_GT: | 1160 | case BO_GT: |
| 1117 | return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeCmpGreaterThan, stmt->getRHS()); | 1161 | return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpGreaterThan, stmt->getRHS()); |
| 1118 | case BO_LE: | 1162 | case BO_LE: |
| 1119 | return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeCmpLessOrEq, stmt->getRHS()); | 1163 | return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpLessOrEq, stmt->getRHS()); |
| 1120 | case BO_GE: | 1164 | case BO_GE: |
| 1121 | return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeCmpGreaterOrEq, stmt->getRHS()); | 1165 | return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpGreaterOrEq, stmt->getRHS()); |
| 1122 | case BO_EQ: | 1166 | case BO_EQ: |
| 1123 | return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeCmpEq, stmt->getRHS()); | 1167 | return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpEq, stmt->getRHS()); |
| 1124 | case BO_NE: | 1168 | case BO_NE: |
| 1125 | return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeCmpNotEq, stmt->getRHS()); | 1169 | return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpNotEq, stmt->getRHS()); |
| 1126 | case BO_And: | 1170 | case BO_And: |
| 1127 | return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeBinAnd, stmt->getRHS()); | 1171 | return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBinAnd, stmt->getRHS()); |
| 1128 | case BO_Xor: | 1172 | case BO_Xor: |
| 1129 | return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeBinXor, stmt->getRHS()); | 1173 | return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBinXor, stmt->getRHS()); |
| 1130 | case BO_Or: | 1174 | case BO_Or: |
| 1131 | return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeBinOr, stmt->getRHS()); | 1175 | return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBinOr, stmt->getRHS()); |
| 1132 | case BO_LAnd: | 1176 | case BO_LAnd: |
| 1133 | return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeBoolAnd, stmt->getRHS()); | 1177 | return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBoolAnd, stmt->getRHS()); |
| 1134 | case BO_LOr: | 1178 | case BO_LOr: |
| 1135 | // TODO: int vs bool | 1179 | // TODO: int vs bool |
| 1136 | return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeBoolOr, stmt->getRHS()); | 1180 | return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBoolOr, stmt->getRHS()); |
| 1137 | case BO_Assign: | 1181 | case BO_Assign: |
| 1138 | return trans_create_assign(c, result_used, block, stmt->getLHS(), stmt->getRHS()); | 1182 | return trans_create_assign(c, result_used, scope, stmt->getLHS(), stmt->getRHS()); |
| 1139 | case BO_Comma: | 1183 | case BO_Comma: |
| 1140 | { | 1184 | { |
| 1141 | block = trans_create_node(c, NodeTypeBlock); | 1185 | TransScopeBlock *scope_block = trans_scope_block_create(c, scope); |
| 1142 | AstNode *lhs = trans_expr(c, false, block, stmt->getLHS(), TransRValue); | 1186 | AstNode *lhs = trans_expr(c, ResultUsedNo, &scope_block->base, stmt->getLHS(), TransRValue); |
| 1143 | if (lhs == nullptr) return nullptr; | 1187 | if (lhs == nullptr) |
| 1144 | block->data.block.statements.append(maybe_suppress_result(c, false, lhs)); | 1188 | return nullptr; |
| 1145 | AstNode *rhs = trans_expr(c, result_used, block, stmt->getRHS(), TransRValue); | 1189 | scope_block->node->data.block.statements.append(maybe_suppress_result(c, ResultUsedNo, lhs)); |
| 1146 | if (rhs == nullptr) return nullptr; | 1190 | |
| 1147 | block->data.block.statements.append(maybe_suppress_result(c, result_used, rhs)); | 1191 | AstNode *rhs = trans_expr(c, result_used, &scope_block->base, stmt->getRHS(), TransRValue); |
| 1148 | block->data.block.last_statement_is_result_expression = true; | 1192 | if (rhs == nullptr) |
| 1149 | return block; | 1193 | return nullptr; |
| | 1194 | scope_block->node->data.block.statements.append(maybe_suppress_result(c, result_used, rhs)); |
| | 1195 | |
| | 1196 | scope_block->node->data.block.last_statement_is_result_expression = true; |
| | 1197 | return scope_block->node; |
| 1150 | } | 1198 | } |
| 1151 | case BO_MulAssign: | 1199 | case BO_MulAssign: |
| 1152 | case BO_DivAssign: | 1200 | case BO_DivAssign: |
| ... | @@ -1164,18 +1212,20 @@ static AstNode *trans_binary_operator(Context *c, bool result_used, AstNode *blo | ... | @@ -1164,18 +1212,20 @@ static AstNode *trans_binary_operator(Context *c, bool result_used, AstNode *blo |
| 1164 | zig_unreachable(); | 1212 | zig_unreachable(); |
| 1165 | } | 1213 | } |
| 1166 | | 1214 | |
| 1167 | static AstNode *trans_create_compound_assign_shift(Context *c, bool result_used, AstNode *block, CompoundAssignOperator *stmt, BinOpType assign_op, BinOpType bin_op) { | 1215 | static AstNode *trans_create_compound_assign_shift(Context *c, ResultUsed result_used, TransScope *scope, |
| | 1216 | const CompoundAssignOperator *stmt, BinOpType assign_op, BinOpType bin_op) |
| | 1217 | { |
| 1168 | const SourceLocation &rhs_location = stmt->getRHS()->getLocStart(); | 1218 | const SourceLocation &rhs_location = stmt->getRHS()->getLocStart(); |
| 1169 | AstNode *rhs_type = qual_type_to_log2_int_ref(c, stmt->getComputationLHSType(), rhs_location); | 1219 | AstNode *rhs_type = qual_type_to_log2_int_ref(c, stmt->getComputationLHSType(), rhs_location); |
| 1170 | | 1220 | |
| 1171 | bool use_intermediate_casts = stmt->getComputationLHSType().getTypePtr() != stmt->getComputationResultType().getTypePtr(); | 1221 | bool use_intermediate_casts = stmt->getComputationLHSType().getTypePtr() != stmt->getComputationResultType().getTypePtr(); |
| 1172 | if (!use_intermediate_casts && !result_used) { | 1222 | if (!use_intermediate_casts && result_used == ResultUsedNo) { |
| 1173 | // simple common case, where the C and Zig are identical: | 1223 | // simple common case, where the C and Zig are identical: |
| 1174 | // lhs >>= rhs | 1224 | // lhs >>= rhs |
| 1175 | AstNode *lhs = trans_expr(c, true, block, stmt->getLHS(), TransLValue); | 1225 | AstNode *lhs = trans_expr(c, ResultUsedYes, scope, stmt->getLHS(), TransLValue); |
| 1176 | if (lhs == nullptr) return nullptr; | 1226 | if (lhs == nullptr) return nullptr; |
| 1177 | | 1227 | |
| 1178 | AstNode *rhs = trans_expr(c, true, block, stmt->getRHS(), TransRValue); | 1228 | AstNode *rhs = trans_expr(c, ResultUsedYes, scope, stmt->getRHS(), TransRValue); |
| 1179 | if (rhs == nullptr) return nullptr; | 1229 | if (rhs == nullptr) return nullptr; |
| 1180 | AstNode *coerced_rhs = trans_create_node_fn_call_1(c, rhs_type, rhs); | 1230 | AstNode *coerced_rhs = trans_create_node_fn_call_1(c, rhs_type, rhs); |
| 1181 | | 1231 | |
| ... | @@ -1190,20 +1240,20 @@ static AstNode *trans_create_compound_assign_shift(Context *c, bool result_used, | ... | @@ -1190,20 +1240,20 @@ static AstNode *trans_create_compound_assign_shift(Context *c, bool result_used, |
| 1190 | // zig: } | 1240 | // zig: } |
| 1191 | // where u5 is the appropriate type | 1241 | // where u5 is the appropriate type |
| 1192 | | 1242 | |
| 1193 | AstNode *child_block = trans_create_node(c, NodeTypeBlock); | 1243 | TransScopeBlock *child_scope = trans_scope_block_create(c, scope); |
| 1194 | | 1244 | |
| 1195 | // const _ref = &lhs; | 1245 | // const _ref = &lhs; |
| 1196 | AstNode *lhs = trans_expr(c, true, child_block, stmt->getLHS(), TransLValue); | 1246 | AstNode *lhs = trans_expr(c, ResultUsedYes, &child_scope->base, stmt->getLHS(), TransLValue); |
| 1197 | if (lhs == nullptr) return nullptr; | 1247 | if (lhs == nullptr) return nullptr; |
| 1198 | AstNode *addr_of_lhs = trans_create_node_addr_of(c, false, false, lhs); | 1248 | AstNode *addr_of_lhs = trans_create_node_addr_of(c, false, false, lhs); |
| 1199 | // TODO: avoid name collisions with generated variable names | 1249 | // TODO: avoid name collisions with generated variable names |
| 1200 | Buf* tmp_var_name = buf_create_from_str("_ref"); | 1250 | Buf* tmp_var_name = buf_create_from_str("_ref"); |
| 1201 | AstNode *tmp_var_decl = trans_create_node_var_decl_local(c, true, tmp_var_name, nullptr, addr_of_lhs); | 1251 | AstNode *tmp_var_decl = trans_create_node_var_decl_local(c, true, tmp_var_name, nullptr, addr_of_lhs); |
| 1202 | child_block->data.block.statements.append(tmp_var_decl); | 1252 | child_scope->node->data.block.statements.append(tmp_var_decl); |
| 1203 | | 1253 | |
| 1204 | // *_ref = result_type(operation_type(*_ref) >> u5(rhs)); | 1254 | // *_ref = result_type(operation_type(*_ref) >> u5(rhs)); |
| 1205 | | 1255 | |
| 1206 | AstNode *rhs = trans_expr(c, true, child_block, stmt->getRHS(), TransRValue); | 1256 | AstNode *rhs = trans_expr(c, ResultUsedYes, &child_scope->base, stmt->getRHS(), TransRValue); |
| 1207 | if (rhs == nullptr) return nullptr; | 1257 | if (rhs == nullptr) return nullptr; |
| 1208 | AstNode *coerced_rhs = trans_create_node_fn_call_1(c, rhs_type, rhs); | 1258 | AstNode *coerced_rhs = trans_create_node_fn_call_1(c, rhs_type, rhs); |
| 1209 | | 1259 | |
| ... | @@ -1220,27 +1270,29 @@ static AstNode *trans_create_compound_assign_shift(Context *c, bool result_used, | ... | @@ -1220,27 +1270,29 @@ static AstNode *trans_create_compound_assign_shift(Context *c, bool result_used, |
| 1220 | trans_create_node_symbol(c, tmp_var_name))), | 1270 | trans_create_node_symbol(c, tmp_var_name))), |
| 1221 | bin_op, | 1271 | bin_op, |
| 1222 | coerced_rhs))); | 1272 | coerced_rhs))); |
| 1223 | child_block->data.block.statements.append(assign_statement); | 1273 | child_scope->node->data.block.statements.append(assign_statement); |
| 1224 | | 1274 | |
| 1225 | if (result_used) { | 1275 | if (result_used == ResultUsedYes) { |
| 1226 | // *_ref | 1276 | // *_ref |
| 1227 | child_block->data.block.statements.append( | 1277 | child_scope->node->data.block.statements.append( |
| 1228 | trans_create_node_prefix_op(c, PrefixOpDereference, | 1278 | trans_create_node_prefix_op(c, PrefixOpDereference, |
| 1229 | trans_create_node_symbol(c, tmp_var_name))); | 1279 | trans_create_node_symbol(c, tmp_var_name))); |
| 1230 | child_block->data.block.last_statement_is_result_expression = true; | 1280 | child_scope->node->data.block.last_statement_is_result_expression = true; |
| 1231 | } | 1281 | } |
| 1232 | | 1282 | |
| 1233 | return child_block; | 1283 | return child_scope->node; |
| 1234 | } | 1284 | } |
| 1235 | } | 1285 | } |
| 1236 | | 1286 | |
| 1237 | static AstNode *trans_create_compound_assign(Context *c, bool result_used, AstNode *block, CompoundAssignOperator *stmt, BinOpType assign_op, BinOpType bin_op) { | 1287 | static AstNode *trans_create_compound_assign(Context *c, ResultUsed result_used, TransScope *scope, |
| 1238 | if (!result_used) { | 1288 | const CompoundAssignOperator *stmt, BinOpType assign_op, BinOpType bin_op) |
| | 1289 | { |
| | 1290 | if (result_used == ResultUsedNo) { |
| 1239 | // simple common case, where the C and Zig are identical: | 1291 | // simple common case, where the C and Zig are identical: |
| 1240 | // lhs += rhs | 1292 | // lhs += rhs |
| 1241 | AstNode *lhs = trans_expr(c, true, block, stmt->getLHS(), TransLValue); | 1293 | AstNode *lhs = trans_expr(c, ResultUsedYes, scope, stmt->getLHS(), TransLValue); |
| 1242 | if (lhs == nullptr) return nullptr; | 1294 | if (lhs == nullptr) return nullptr; |
| 1243 | AstNode *rhs = trans_expr(c, true, block, stmt->getRHS(), TransRValue); | 1295 | AstNode *rhs = trans_expr(c, ResultUsedYes, scope, stmt->getRHS(), TransRValue); |
| 1244 | if (rhs == nullptr) return nullptr; | 1296 | if (rhs == nullptr) return nullptr; |
| 1245 | return trans_create_node_bin_op(c, lhs, assign_op, rhs); | 1297 | return trans_create_node_bin_op(c, lhs, assign_op, rhs); |
| 1246 | } else { | 1298 | } else { |
| ... | @@ -1252,20 +1304,20 @@ static AstNode *trans_create_compound_assign(Context *c, bool result_used, AstNo | ... | @@ -1252,20 +1304,20 @@ static AstNode *trans_create_compound_assign(Context *c, bool result_used, AstNo |
| 1252 | // zig: *_ref | 1304 | // zig: *_ref |
| 1253 | // zig: } | 1305 | // zig: } |
| 1254 | | 1306 | |
| 1255 | AstNode *child_block = trans_create_node(c, NodeTypeBlock); | 1307 | TransScopeBlock *child_scope = trans_scope_block_create(c, scope); |
| 1256 | | 1308 | |
| 1257 | // const _ref = &lhs; | 1309 | // const _ref = &lhs; |
| 1258 | AstNode *lhs = trans_expr(c, true, child_block, stmt->getLHS(), TransLValue); | 1310 | AstNode *lhs = trans_expr(c, ResultUsedYes, &child_scope->base, stmt->getLHS(), TransLValue); |
| 1259 | if (lhs == nullptr) return nullptr; | 1311 | if (lhs == nullptr) return nullptr; |
| 1260 | AstNode *addr_of_lhs = trans_create_node_addr_of(c, false, false, lhs); | 1312 | AstNode *addr_of_lhs = trans_create_node_addr_of(c, false, false, lhs); |
| 1261 | // TODO: avoid name collisions with generated variable names | 1313 | // TODO: avoid name collisions with generated variable names |
| 1262 | Buf* tmp_var_name = buf_create_from_str("_ref"); | 1314 | Buf* tmp_var_name = buf_create_from_str("_ref"); |
| 1263 | AstNode *tmp_var_decl = trans_create_node_var_decl_local(c, true, tmp_var_name, nullptr, addr_of_lhs); | 1315 | AstNode *tmp_var_decl = trans_create_node_var_decl_local(c, true, tmp_var_name, nullptr, addr_of_lhs); |
| 1264 | child_block->data.block.statements.append(tmp_var_decl); | 1316 | child_scope->node->data.block.statements.append(tmp_var_decl); |
| 1265 | | 1317 | |
| 1266 | // *_ref = *_ref + rhs; | 1318 | // *_ref = *_ref + rhs; |
| 1267 | | 1319 | |
| 1268 | AstNode *rhs = trans_expr(c, true, child_block, stmt->getRHS(), TransRValue); | 1320 | AstNode *rhs = trans_expr(c, ResultUsedYes, &child_scope->base, stmt->getRHS(), TransRValue); |
| 1269 | if (rhs == nullptr) return nullptr; | 1321 | if (rhs == nullptr) return nullptr; |
| 1270 | | 1322 | |
| 1271 | AstNode *assign_statement = trans_create_node_bin_op(c, | 1323 | AstNode *assign_statement = trans_create_node_bin_op(c, |
| ... | @@ -1277,26 +1329,28 @@ static AstNode *trans_create_compound_assign(Context *c, bool result_used, AstNo | ... | @@ -1277,26 +1329,28 @@ static AstNode *trans_create_compound_assign(Context *c, bool result_used, AstNo |
| 1277 | trans_create_node_symbol(c, tmp_var_name)), | 1329 | trans_create_node_symbol(c, tmp_var_name)), |
| 1278 | bin_op, | 1330 | bin_op, |
| 1279 | rhs)); | 1331 | rhs)); |
| 1280 | child_block->data.block.statements.append(assign_statement); | 1332 | child_scope->node->data.block.statements.append(assign_statement); |
| 1281 | | 1333 | |
| 1282 | // *_ref | 1334 | // *_ref |
| 1283 | child_block->data.block.statements.append( | 1335 | child_scope->node->data.block.statements.append( |
| 1284 | trans_create_node_prefix_op(c, PrefixOpDereference, | 1336 | trans_create_node_prefix_op(c, PrefixOpDereference, |
| 1285 | trans_create_node_symbol(c, tmp_var_name))); | 1337 | trans_create_node_symbol(c, tmp_var_name))); |
| 1286 | child_block->data.block.last_statement_is_result_expression = true; | 1338 | child_scope->node->data.block.last_statement_is_result_expression = true; |
| 1287 | | 1339 | |
| 1288 | return child_block; | 1340 | return child_scope->node; |
| 1289 | } | 1341 | } |
| 1290 | } | 1342 | } |
| 1291 | | 1343 | |
| 1292 | | 1344 | |
| 1293 | static AstNode *trans_compound_assign_operator(Context *c, bool result_used, AstNode *block, CompoundAssignOperator *stmt) { | 1345 | static AstNode *trans_compound_assign_operator(Context *c, ResultUsed result_used, TransScope *scope, |
| | 1346 | const CompoundAssignOperator *stmt) |
| | 1347 | { |
| 1294 | switch (stmt->getOpcode()) { | 1348 | switch (stmt->getOpcode()) { |
| 1295 | case BO_MulAssign: | 1349 | case BO_MulAssign: |
| 1296 | if (qual_type_has_wrapping_overflow(c, stmt->getType())) | 1350 | if (qual_type_has_wrapping_overflow(c, stmt->getType())) |
| 1297 | return trans_create_compound_assign(c, result_used, block, stmt, BinOpTypeAssignTimesWrap, BinOpTypeMultWrap); | 1351 | return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignTimesWrap, BinOpTypeMultWrap); |
| 1298 | else | 1352 | else |
| 1299 | return trans_create_compound_assign(c, result_used, block, stmt, BinOpTypeAssignTimes, BinOpTypeMult); | 1353 | return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignTimes, BinOpTypeMult); |
| 1300 | case BO_DivAssign: | 1354 | case BO_DivAssign: |
| 1301 | emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_DivAssign"); | 1355 | emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_DivAssign"); |
| 1302 | return nullptr; | 1356 | return nullptr; |
| ... | @@ -1305,24 +1359,24 @@ static AstNode *trans_compound_assign_operator(Context *c, bool result_used, Ast | ... | @@ -1305,24 +1359,24 @@ static AstNode *trans_compound_assign_operator(Context *c, bool result_used, Ast |
| 1305 | return nullptr; | 1359 | return nullptr; |
| 1306 | case BO_AddAssign: | 1360 | case BO_AddAssign: |
| 1307 | if (qual_type_has_wrapping_overflow(c, stmt->getType())) | 1361 | if (qual_type_has_wrapping_overflow(c, stmt->getType())) |
| 1308 | return trans_create_compound_assign(c, result_used, block, stmt, BinOpTypeAssignPlusWrap, BinOpTypeAddWrap); | 1362 | return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignPlusWrap, BinOpTypeAddWrap); |
| 1309 | else | 1363 | else |
| 1310 | return trans_create_compound_assign(c, result_used, block, stmt, BinOpTypeAssignPlus, BinOpTypeAdd); | 1364 | return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignPlus, BinOpTypeAdd); |
| 1311 | case BO_SubAssign: | 1365 | case BO_SubAssign: |
| 1312 | if (qual_type_has_wrapping_overflow(c, stmt->getType())) | 1366 | if (qual_type_has_wrapping_overflow(c, stmt->getType())) |
| 1313 | return trans_create_compound_assign(c, result_used, block, stmt, BinOpTypeAssignMinusWrap, BinOpTypeSubWrap); | 1367 | return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignMinusWrap, BinOpTypeSubWrap); |
| 1314 | else | 1368 | else |
| 1315 | return trans_create_compound_assign(c, result_used, block, stmt, BinOpTypeAssignMinus, BinOpTypeSub); | 1369 | return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignMinus, BinOpTypeSub); |
| 1316 | case BO_ShlAssign: | 1370 | case BO_ShlAssign: |
| 1317 | return trans_create_compound_assign_shift(c, result_used, block, stmt, BinOpTypeAssignBitShiftLeft, BinOpTypeBitShiftLeft); | 1371 | return trans_create_compound_assign_shift(c, result_used, scope, stmt, BinOpTypeAssignBitShiftLeft, BinOpTypeBitShiftLeft); |
| 1318 | case BO_ShrAssign: | 1372 | case BO_ShrAssign: |
| 1319 | return trans_create_compound_assign_shift(c, result_used, block, stmt, BinOpTypeAssignBitShiftRight, BinOpTypeBitShiftRight); | 1373 | return trans_create_compound_assign_shift(c, result_used, scope, stmt, BinOpTypeAssignBitShiftRight, BinOpTypeBitShiftRight); |
| 1320 | case BO_AndAssign: | 1374 | case BO_AndAssign: |
| 1321 | return trans_create_compound_assign(c, result_used, block, stmt, BinOpTypeAssignBitAnd, BinOpTypeBinAnd); | 1375 | return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignBitAnd, BinOpTypeBinAnd); |
| 1322 | case BO_XorAssign: | 1376 | case BO_XorAssign: |
| 1323 | return trans_create_compound_assign(c, result_used, block, stmt, BinOpTypeAssignBitXor, BinOpTypeBinXor); | 1377 | return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignBitXor, BinOpTypeBinXor); |
| 1324 | case BO_OrAssign: | 1378 | case BO_OrAssign: |
| 1325 | return trans_create_compound_assign(c, result_used, block, stmt, BinOpTypeAssignBitOr, BinOpTypeBinOr); | 1379 | return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignBitOr, BinOpTypeBinOr); |
| 1326 | case BO_PtrMemD: | 1380 | case BO_PtrMemD: |
| 1327 | case BO_PtrMemI: | 1381 | case BO_PtrMemI: |
| 1328 | case BO_Assign: | 1382 | case BO_Assign: |
| ... | @@ -1351,13 +1405,13 @@ static AstNode *trans_compound_assign_operator(Context *c, bool result_used, Ast | ... | @@ -1351,13 +1405,13 @@ static AstNode *trans_compound_assign_operator(Context *c, bool result_used, Ast |
| 1351 | zig_unreachable(); | 1405 | zig_unreachable(); |
| 1352 | } | 1406 | } |
| 1353 | | 1407 | |
| 1354 | static AstNode *trans_implicit_cast_expr(Context *c, AstNode *block, ImplicitCastExpr *stmt) { | 1408 | static AstNode *trans_implicit_cast_expr(Context *c, TransScope *scope, const ImplicitCastExpr *stmt) { |
| 1355 | switch (stmt->getCastKind()) { | 1409 | switch (stmt->getCastKind()) { |
| 1356 | case CK_LValueToRValue: | 1410 | case CK_LValueToRValue: |
| 1357 | return trans_expr(c, true, block, stmt->getSubExpr(), TransRValue); | 1411 | return trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue); |
| 1358 | case CK_IntegralCast: | 1412 | case CK_IntegralCast: |
| 1359 | { | 1413 | { |
| 1360 | AstNode *target_node = trans_expr(c, true, block, stmt->getSubExpr(), TransRValue); | 1414 | AstNode *target_node = trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue); |
| 1361 | if (target_node == nullptr) | 1415 | if (target_node == nullptr) |
| 1362 | return nullptr; | 1416 | return nullptr; |
| 1363 | return trans_c_cast(c, stmt->getExprLoc(), stmt->getType(), target_node); | 1417 | return trans_c_cast(c, stmt->getExprLoc(), stmt->getType(), target_node); |
| ... | @@ -1365,14 +1419,14 @@ static AstNode *trans_implicit_cast_expr(Context *c, AstNode *block, ImplicitCas | ... | @@ -1365,14 +1419,14 @@ static AstNode *trans_implicit_cast_expr(Context *c, AstNode *block, ImplicitCas |
| 1365 | case CK_FunctionToPointerDecay: | 1419 | case CK_FunctionToPointerDecay: |
| 1366 | case CK_ArrayToPointerDecay: | 1420 | case CK_ArrayToPointerDecay: |
| 1367 | { | 1421 | { |
| 1368 | AstNode *target_node = trans_expr(c, true, block, stmt->getSubExpr(), TransRValue); | 1422 | AstNode *target_node = trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue); |
| 1369 | if (target_node == nullptr) | 1423 | if (target_node == nullptr) |
| 1370 | return nullptr; | 1424 | return nullptr; |
| 1371 | return target_node; | 1425 | return target_node; |
| 1372 | } | 1426 | } |
| 1373 | case CK_BitCast: | 1427 | case CK_BitCast: |
| 1374 | { | 1428 | { |
| 1375 | AstNode *target_node = trans_expr(c, true, block, stmt->getSubExpr(), TransRValue); | 1429 | AstNode *target_node = trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue); |
| 1376 | if (target_node == nullptr) | 1430 | if (target_node == nullptr) |
| 1377 | return nullptr; | 1431 | return nullptr; |
| 1378 | | 1432 | |
| ... | @@ -1549,8 +1603,8 @@ static AstNode *trans_implicit_cast_expr(Context *c, AstNode *block, ImplicitCas | ... | @@ -1549,8 +1603,8 @@ static AstNode *trans_implicit_cast_expr(Context *c, AstNode *block, ImplicitCas |
| 1549 | zig_unreachable(); | 1603 | zig_unreachable(); |
| 1550 | } | 1604 | } |
| 1551 | | 1605 | |
| 1552 | static AstNode *trans_decl_ref_expr(Context *c, DeclRefExpr *stmt, TransLRValue lrval) { | 1606 | static AstNode *trans_decl_ref_expr(Context *c, const DeclRefExpr *stmt, TransLRValue lrval) { |
| 1553 | ValueDecl *value_decl = stmt->getDecl(); | 1607 | const ValueDecl *value_decl = stmt->getDecl(); |
| 1554 | Buf *symbol_name = buf_create_from_str(decl_name(value_decl)); | 1608 | Buf *symbol_name = buf_create_from_str(decl_name(value_decl)); |
| 1555 | if (lrval == TransLValue) { | 1609 | if (lrval == TransLValue) { |
| 1556 | c->ptr_params.put(symbol_name, true); | 1610 | c->ptr_params.put(symbol_name, true); |
| ... | @@ -1558,15 +1612,17 @@ static AstNode *trans_decl_ref_expr(Context *c, DeclRefExpr *stmt, TransLRValue | ... | @@ -1558,15 +1612,17 @@ static AstNode *trans_decl_ref_expr(Context *c, DeclRefExpr *stmt, TransLRValue |
| 1558 | return trans_create_node_symbol(c, symbol_name); | 1612 | return trans_create_node_symbol(c, symbol_name); |
| 1559 | } | 1613 | } |
| 1560 | | 1614 | |
| 1561 | static AstNode *trans_create_post_crement(Context *c, bool result_used, AstNode *block, UnaryOperator *stmt, BinOpType assign_op) { | 1615 | static AstNode *trans_create_post_crement(Context *c, ResultUsed result_used, TransScope *scope, |
| | 1616 | const UnaryOperator *stmt, BinOpType assign_op) |
| | 1617 | { |
| 1562 | Expr *op_expr = stmt->getSubExpr(); | 1618 | Expr *op_expr = stmt->getSubExpr(); |
| 1563 | | 1619 | |
| 1564 | if (!result_used) { | 1620 | if (result_used == ResultUsedNo) { |
| 1565 | // common case | 1621 | // common case |
| 1566 | // c: expr++ | 1622 | // c: expr++ |
| 1567 | // zig: expr += 1 | 1623 | // zig: expr += 1 |
| 1568 | return trans_create_node_bin_op(c, | 1624 | return trans_create_node_bin_op(c, |
| 1569 | trans_expr(c, true, block, op_expr, TransLValue), | 1625 | trans_expr(c, ResultUsedYes, scope, op_expr, TransLValue), |
| 1570 | assign_op, | 1626 | assign_op, |
| 1571 | trans_create_node_unsigned(c, 1)); | 1627 | trans_create_node_unsigned(c, 1)); |
| 1572 | } | 1628 | } |
| ... | @@ -1578,23 +1634,23 @@ static AstNode *trans_create_post_crement(Context *c, bool result_used, AstNode | ... | @@ -1578,23 +1634,23 @@ static AstNode *trans_create_post_crement(Context *c, bool result_used, AstNode |
| 1578 | // zig: *_ref += 1; | 1634 | // zig: *_ref += 1; |
| 1579 | // zig: _tmp | 1635 | // zig: _tmp |
| 1580 | // zig: } | 1636 | // zig: } |
| 1581 | AstNode *child_block = trans_create_node(c, NodeTypeBlock); | 1637 | TransScopeBlock *child_scope = trans_scope_block_create(c, scope); |
| 1582 | | 1638 | |
| 1583 | // const _ref = &expr; | 1639 | // const _ref = &expr; |
| 1584 | AstNode *expr = trans_expr(c, true, child_block, op_expr, TransLValue); | 1640 | AstNode *expr = trans_expr(c, ResultUsedYes, &child_scope->base, op_expr, TransLValue); |
| 1585 | if (expr == nullptr) return nullptr; | 1641 | if (expr == nullptr) return nullptr; |
| 1586 | AstNode *addr_of_expr = trans_create_node_addr_of(c, false, false, expr); | 1642 | AstNode *addr_of_expr = trans_create_node_addr_of(c, false, false, expr); |
| 1587 | // TODO: avoid name collisions with generated variable names | 1643 | // TODO: avoid name collisions with generated variable names |
| 1588 | Buf* ref_var_name = buf_create_from_str("_ref"); | 1644 | Buf* ref_var_name = buf_create_from_str("_ref"); |
| 1589 | AstNode *ref_var_decl = trans_create_node_var_decl_local(c, true, ref_var_name, nullptr, addr_of_expr); | 1645 | AstNode *ref_var_decl = trans_create_node_var_decl_local(c, true, ref_var_name, nullptr, addr_of_expr); |
| 1590 | child_block->data.block.statements.append(ref_var_decl); | 1646 | child_scope->node->data.block.statements.append(ref_var_decl); |
| 1591 | | 1647 | |
| 1592 | // const _tmp = *_ref; | 1648 | // const _tmp = *_ref; |
| 1593 | Buf* tmp_var_name = buf_create_from_str("_tmp"); | 1649 | Buf* tmp_var_name = buf_create_from_str("_tmp"); |
| 1594 | AstNode *tmp_var_decl = trans_create_node_var_decl_local(c, true, tmp_var_name, nullptr, | 1650 | AstNode *tmp_var_decl = trans_create_node_var_decl_local(c, true, tmp_var_name, nullptr, |
| 1595 | trans_create_node_prefix_op(c, PrefixOpDereference, | 1651 | trans_create_node_prefix_op(c, PrefixOpDereference, |
| 1596 | trans_create_node_symbol(c, ref_var_name))); | 1652 | trans_create_node_symbol(c, ref_var_name))); |
| 1597 | child_block->data.block.statements.append(tmp_var_decl); | 1653 | child_scope->node->data.block.statements.append(tmp_var_decl); |
| 1598 | | 1654 | |
| 1599 | // *_ref += 1; | 1655 | // *_ref += 1; |
| 1600 | AstNode *assign_statement = trans_create_node_bin_op(c, | 1656 | AstNode *assign_statement = trans_create_node_bin_op(c, |
| ... | @@ -1602,24 +1658,26 @@ static AstNode *trans_create_post_crement(Context *c, bool result_used, AstNode | ... | @@ -1602,24 +1658,26 @@ static AstNode *trans_create_post_crement(Context *c, bool result_used, AstNode |
| 1602 | trans_create_node_symbol(c, ref_var_name)), | 1658 | trans_create_node_symbol(c, ref_var_name)), |
| 1603 | assign_op, | 1659 | assign_op, |
| 1604 | trans_create_node_unsigned(c, 1)); | 1660 | trans_create_node_unsigned(c, 1)); |
| 1605 | child_block->data.block.statements.append(assign_statement); | 1661 | child_scope->node->data.block.statements.append(assign_statement); |
| 1606 | | 1662 | |
| 1607 | // _tmp | 1663 | // _tmp |
| 1608 | child_block->data.block.statements.append(trans_create_node_symbol(c, tmp_var_name)); | 1664 | child_scope->node->data.block.statements.append(trans_create_node_symbol(c, tmp_var_name)); |
| 1609 | child_block->data.block.last_statement_is_result_expression = true; | 1665 | child_scope->node->data.block.last_statement_is_result_expression = true; |
| 1610 | | 1666 | |
| 1611 | return child_block; | 1667 | return child_scope->node; |
| 1612 | } | 1668 | } |
| 1613 | | 1669 | |
| 1614 | static AstNode *trans_create_pre_crement(Context *c, bool result_used, AstNode *block, UnaryOperator *stmt, BinOpType assign_op) { | 1670 | static AstNode *trans_create_pre_crement(Context *c, ResultUsed result_used, TransScope *scope, |
| | 1671 | const UnaryOperator *stmt, BinOpType assign_op) |
| | 1672 | { |
| 1615 | Expr *op_expr = stmt->getSubExpr(); | 1673 | Expr *op_expr = stmt->getSubExpr(); |
| 1616 | | 1674 | |
| 1617 | if (!result_used) { | 1675 | if (result_used == ResultUsedNo) { |
| 1618 | // common case | 1676 | // common case |
| 1619 | // c: ++expr | 1677 | // c: ++expr |
| 1620 | // zig: expr += 1 | 1678 | // zig: expr += 1 |
| 1621 | return trans_create_node_bin_op(c, | 1679 | return trans_create_node_bin_op(c, |
| 1622 | trans_expr(c, true, block, op_expr, TransLValue), | 1680 | trans_expr(c, ResultUsedYes, scope, op_expr, TransLValue), |
| 1623 | assign_op, | 1681 | assign_op, |
| 1624 | trans_create_node_unsigned(c, 1)); | 1682 | trans_create_node_unsigned(c, 1)); |
| 1625 | } | 1683 | } |
| ... | @@ -1630,16 +1688,16 @@ static AstNode *trans_create_pre_crement(Context *c, bool result_used, AstNode * | ... | @@ -1630,16 +1688,16 @@ static AstNode *trans_create_pre_crement(Context *c, bool result_used, AstNode * |
| 1630 | // zig: *_ref += 1; | 1688 | // zig: *_ref += 1; |
| 1631 | // zig: *_ref | 1689 | // zig: *_ref |
| 1632 | // zig: } | 1690 | // zig: } |
| 1633 | AstNode *child_block = trans_create_node(c, NodeTypeBlock); | 1691 | TransScopeBlock *child_scope = trans_scope_block_create(c, scope); |
| 1634 | | 1692 | |
| 1635 | // const _ref = &expr; | 1693 | // const _ref = &expr; |
| 1636 | AstNode *expr = trans_expr(c, true, child_block, op_expr, TransLValue); | 1694 | AstNode *expr = trans_expr(c, ResultUsedYes, &child_scope->base, op_expr, TransLValue); |
| 1637 | if (expr == nullptr) return nullptr; | 1695 | if (expr == nullptr) return nullptr; |
| 1638 | AstNode *addr_of_expr = trans_create_node_addr_of(c, false, false, expr); | 1696 | AstNode *addr_of_expr = trans_create_node_addr_of(c, false, false, expr); |
| 1639 | // TODO: avoid name collisions with generated variable names | 1697 | // TODO: avoid name collisions with generated variable names |
| 1640 | Buf* ref_var_name = buf_create_from_str("_ref"); | 1698 | Buf* ref_var_name = buf_create_from_str("_ref"); |
| 1641 | AstNode *ref_var_decl = trans_create_node_var_decl_local(c, true, ref_var_name, nullptr, addr_of_expr); | 1699 | AstNode *ref_var_decl = trans_create_node_var_decl_local(c, true, ref_var_name, nullptr, addr_of_expr); |
| 1642 | child_block->data.block.statements.append(ref_var_decl); | 1700 | child_scope->node->data.block.statements.append(ref_var_decl); |
| 1643 | | 1701 | |
| 1644 | // *_ref += 1; | 1702 | // *_ref += 1; |
| 1645 | AstNode *assign_statement = trans_create_node_bin_op(c, | 1703 | AstNode *assign_statement = trans_create_node_bin_op(c, |
| ... | @@ -1647,49 +1705,49 @@ static AstNode *trans_create_pre_crement(Context *c, bool result_used, AstNode * | ... | @@ -1647,49 +1705,49 @@ static AstNode *trans_create_pre_crement(Context *c, bool result_used, AstNode * |
| 1647 | trans_create_node_symbol(c, ref_var_name)), | 1705 | trans_create_node_symbol(c, ref_var_name)), |
| 1648 | assign_op, | 1706 | assign_op, |
| 1649 | trans_create_node_unsigned(c, 1)); | 1707 | trans_create_node_unsigned(c, 1)); |
| 1650 | child_block->data.block.statements.append(assign_statement); | 1708 | child_scope->node->data.block.statements.append(assign_statement); |
| 1651 | | 1709 | |
| 1652 | // *_ref | 1710 | // *_ref |
| 1653 | AstNode *deref_expr = trans_create_node_prefix_op(c, PrefixOpDereference, | 1711 | AstNode *deref_expr = trans_create_node_prefix_op(c, PrefixOpDereference, |
| 1654 | trans_create_node_symbol(c, ref_var_name)); | 1712 | trans_create_node_symbol(c, ref_var_name)); |
| 1655 | child_block->data.block.statements.append(deref_expr); | 1713 | child_scope->node->data.block.statements.append(deref_expr); |
| 1656 | child_block->data.block.last_statement_is_result_expression = true; | 1714 | child_scope->node->data.block.last_statement_is_result_expression = true; |
| 1657 | | 1715 | |
| 1658 | return child_block; | 1716 | return child_scope->node; |
| 1659 | } | 1717 | } |
| 1660 | | 1718 | |
| 1661 | static AstNode *trans_unary_operator(Context *c, bool result_used, AstNode *block, UnaryOperator *stmt) { | 1719 | static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransScope *scope, const UnaryOperator *stmt) { |
| 1662 | switch (stmt->getOpcode()) { | 1720 | switch (stmt->getOpcode()) { |
| 1663 | case UO_PostInc: | 1721 | case UO_PostInc: |
| 1664 | if (qual_type_has_wrapping_overflow(c, stmt->getType())) | 1722 | if (qual_type_has_wrapping_overflow(c, stmt->getType())) |
| 1665 | return trans_create_post_crement(c, result_used, block, stmt, BinOpTypeAssignPlusWrap); | 1723 | return trans_create_post_crement(c, result_used, scope, stmt, BinOpTypeAssignPlusWrap); |
| 1666 | else | 1724 | else |
| 1667 | return trans_create_post_crement(c, result_used, block, stmt, BinOpTypeAssignPlus); | 1725 | return trans_create_post_crement(c, result_used, scope, stmt, BinOpTypeAssignPlus); |
| 1668 | case UO_PostDec: | 1726 | case UO_PostDec: |
| 1669 | if (qual_type_has_wrapping_overflow(c, stmt->getType())) | 1727 | if (qual_type_has_wrapping_overflow(c, stmt->getType())) |
| 1670 | return trans_create_post_crement(c, result_used, block, stmt, BinOpTypeAssignMinusWrap); | 1728 | return trans_create_post_crement(c, result_used, scope, stmt, BinOpTypeAssignMinusWrap); |
| 1671 | else | 1729 | else |
| 1672 | return trans_create_post_crement(c, result_used, block, stmt, BinOpTypeAssignMinus); | 1730 | return trans_create_post_crement(c, result_used, scope, stmt, BinOpTypeAssignMinus); |
| 1673 | case UO_PreInc: | 1731 | case UO_PreInc: |
| 1674 | if (qual_type_has_wrapping_overflow(c, stmt->getType())) | 1732 | if (qual_type_has_wrapping_overflow(c, stmt->getType())) |
| 1675 | return trans_create_pre_crement(c, result_used, block, stmt, BinOpTypeAssignPlusWrap); | 1733 | return trans_create_pre_crement(c, result_used, scope, stmt, BinOpTypeAssignPlusWrap); |
| 1676 | else | 1734 | else |
| 1677 | return trans_create_pre_crement(c, result_used, block, stmt, BinOpTypeAssignPlus); | 1735 | return trans_create_pre_crement(c, result_used, scope, stmt, BinOpTypeAssignPlus); |
| 1678 | case UO_PreDec: | 1736 | case UO_PreDec: |
| 1679 | if (qual_type_has_wrapping_overflow(c, stmt->getType())) | 1737 | if (qual_type_has_wrapping_overflow(c, stmt->getType())) |
| 1680 | return trans_create_pre_crement(c, result_used, block, stmt, BinOpTypeAssignMinusWrap); | 1738 | return trans_create_pre_crement(c, result_used, scope, stmt, BinOpTypeAssignMinusWrap); |
| 1681 | else | 1739 | else |
| 1682 | return trans_create_pre_crement(c, result_used, block, stmt, BinOpTypeAssignMinus); | 1740 | return trans_create_pre_crement(c, result_used, scope, stmt, BinOpTypeAssignMinus); |
| 1683 | case UO_AddrOf: | 1741 | case UO_AddrOf: |
| 1684 | { | 1742 | { |
| 1685 | AstNode *value_node = trans_expr(c, result_used, block, stmt->getSubExpr(), TransLValue); | 1743 | AstNode *value_node = trans_expr(c, result_used, scope, stmt->getSubExpr(), TransLValue); |
| 1686 | if (value_node == nullptr) | 1744 | if (value_node == nullptr) |
| 1687 | return value_node; | 1745 | return value_node; |
| 1688 | return trans_create_node_addr_of(c, false, false, value_node); | 1746 | return trans_create_node_addr_of(c, false, false, value_node); |
| 1689 | } | 1747 | } |
| 1690 | case UO_Deref: | 1748 | case UO_Deref: |
| 1691 | { | 1749 | { |
| 1692 | AstNode *value_node = trans_expr(c, result_used, block, stmt->getSubExpr(), TransRValue); | 1750 | AstNode *value_node = trans_expr(c, result_used, scope, stmt->getSubExpr(), TransRValue); |
| 1693 | if (value_node == nullptr) | 1751 | if (value_node == nullptr) |
| 1694 | return nullptr; | 1752 | return nullptr; |
| 1695 | bool is_fn_ptr = qual_type_is_fn_ptr(c, stmt->getSubExpr()->getType()); | 1753 | bool is_fn_ptr = qual_type_is_fn_ptr(c, stmt->getSubExpr()->getType()); |
| ... | @@ -1708,7 +1766,7 @@ static AstNode *trans_unary_operator(Context *c, bool result_used, AstNode *bloc | ... | @@ -1708,7 +1766,7 @@ static AstNode *trans_unary_operator(Context *c, bool result_used, AstNode *bloc |
| 1708 | AstNode *node = trans_create_node(c, NodeTypePrefixOpExpr); | 1766 | AstNode *node = trans_create_node(c, NodeTypePrefixOpExpr); |
| 1709 | node->data.prefix_op_expr.prefix_op = PrefixOpNegation; | 1767 | node->data.prefix_op_expr.prefix_op = PrefixOpNegation; |
| 1710 | | 1768 | |
| 1711 | node->data.prefix_op_expr.primary_expr = trans_expr(c, true, block, op_expr, TransRValue); | 1769 | node->data.prefix_op_expr.primary_expr = trans_expr(c, ResultUsedYes, scope, op_expr, TransRValue); |
| 1712 | if (node->data.prefix_op_expr.primary_expr == nullptr) | 1770 | if (node->data.prefix_op_expr.primary_expr == nullptr) |
| 1713 | return nullptr; | 1771 | return nullptr; |
| 1714 | | 1772 | |
| ... | @@ -1718,7 +1776,7 @@ static AstNode *trans_unary_operator(Context *c, bool result_used, AstNode *bloc | ... | @@ -1718,7 +1776,7 @@ static AstNode *trans_unary_operator(Context *c, bool result_used, AstNode *bloc |
| 1718 | AstNode *node = trans_create_node(c, NodeTypeBinOpExpr); | 1776 | AstNode *node = trans_create_node(c, NodeTypeBinOpExpr); |
| 1719 | node->data.bin_op_expr.op1 = trans_create_node_unsigned(c, 0); | 1777 | node->data.bin_op_expr.op1 = trans_create_node_unsigned(c, 0); |
| 1720 | | 1778 | |
| 1721 | node->data.bin_op_expr.op2 = trans_expr(c, true, block, op_expr, TransRValue); | 1779 | node->data.bin_op_expr.op2 = trans_expr(c, ResultUsedYes, scope, op_expr, TransRValue); |
| 1722 | if (node->data.bin_op_expr.op2 == nullptr) | 1780 | if (node->data.bin_op_expr.op2 == nullptr) |
| 1723 | return nullptr; | 1781 | return nullptr; |
| 1724 | | 1782 | |
| ... | @@ -1751,7 +1809,7 @@ static AstNode *trans_unary_operator(Context *c, bool result_used, AstNode *bloc | ... | @@ -1751,7 +1809,7 @@ static AstNode *trans_unary_operator(Context *c, bool result_used, AstNode *bloc |
| 1751 | zig_unreachable(); | 1809 | zig_unreachable(); |
| 1752 | } | 1810 | } |
| 1753 | | 1811 | |
| 1754 | static AstNode *trans_local_declaration(Context *c, AstNode *block, DeclStmt *stmt) { | 1812 | static AstNode *trans_local_declaration(Context *c, TransScope *scope, const DeclStmt *stmt) { |
| 1755 | for (auto iter = stmt->decl_begin(); iter != stmt->decl_end(); iter++) { | 1813 | for (auto iter = stmt->decl_begin(); iter != stmt->decl_end(); iter++) { |
| 1756 | Decl *decl = *iter; | 1814 | Decl *decl = *iter; |
| 1757 | switch (decl->getKind()) { | 1815 | switch (decl->getKind()) { |
| ... | @@ -1760,7 +1818,7 @@ static AstNode *trans_local_declaration(Context *c, AstNode *block, DeclStmt *st | ... | @@ -1760,7 +1818,7 @@ static AstNode *trans_local_declaration(Context *c, AstNode *block, DeclStmt *st |
| 1760 | QualType qual_type = var_decl->getTypeSourceInfo()->getType(); | 1818 | QualType qual_type = var_decl->getTypeSourceInfo()->getType(); |
| 1761 | AstNode *init_node = nullptr; | 1819 | AstNode *init_node = nullptr; |
| 1762 | if (var_decl->hasInit()) { | 1820 | if (var_decl->hasInit()) { |
| 1763 | init_node = trans_expr(c, true, block, var_decl->getInit(), TransRValue); | 1821 | init_node = trans_expr(c, ResultUsedYes, scope, var_decl->getInit(), TransRValue); |
| 1764 | if (init_node == nullptr) | 1822 | if (init_node == nullptr) |
| 1765 | return nullptr; | 1823 | return nullptr; |
| 1766 | | 1824 | |
| ... | @@ -1773,7 +1831,10 @@ static AstNode *trans_local_declaration(Context *c, AstNode *block, DeclStmt *st | ... | @@ -1773,7 +1831,10 @@ static AstNode *trans_local_declaration(Context *c, AstNode *block, DeclStmt *st |
| 1773 | | 1831 | |
| 1774 | AstNode *node = trans_create_node_var_decl_local(c, qual_type.isConstQualified(), | 1832 | AstNode *node = trans_create_node_var_decl_local(c, qual_type.isConstQualified(), |
| 1775 | symbol_name, type_node, init_node); | 1833 | symbol_name, type_node, init_node); |
| 1776 | block->data.block.statements.append(node); | 1834 | |
| | 1835 | assert(scope->id == TransScopeIdBlock); |
| | 1836 | TransScopeBlock *scope_block = (TransScopeBlock *)scope; |
| | 1837 | scope_block->node->data.block.statements.append(node); |
| 1777 | continue; | 1838 | continue; |
| 1778 | } | 1839 | } |
| 1779 | case Decl::AccessSpec: | 1840 | case Decl::AccessSpec: |
| ... | @@ -2000,37 +2061,37 @@ static AstNode *trans_local_declaration(Context *c, AstNode *block, DeclStmt *st | ... | @@ -2000,37 +2061,37 @@ static AstNode *trans_local_declaration(Context *c, AstNode *block, DeclStmt *st |
| 2000 | return skip_add_to_block_node; | 2061 | return skip_add_to_block_node; |
| 2001 | } | 2062 | } |
| 2002 | | 2063 | |
| 2003 | static AstNode *trans_while_loop(Context *c, AstNode *block, WhileStmt *stmt) { | 2064 | static AstNode *trans_while_loop(Context *c, TransScope *scope, const WhileStmt *stmt) { |
| 2004 | AstNode *while_node = trans_create_node(c, NodeTypeWhileExpr); | 2065 | AstNode *while_node = trans_create_node(c, NodeTypeWhileExpr); |
| 2005 | | 2066 | |
| 2006 | while_node->data.while_expr.condition = trans_expr(c, true, block, stmt->getCond(), TransRValue); | 2067 | while_node->data.while_expr.condition = trans_expr(c, ResultUsedYes, scope, stmt->getCond(), TransRValue); |
| 2007 | if (while_node->data.while_expr.condition == nullptr) | 2068 | if (while_node->data.while_expr.condition == nullptr) |
| 2008 | return nullptr; | 2069 | return nullptr; |
| 2009 | | 2070 | |
| 2010 | while_node->data.while_expr.body = trans_stmt(c, false, block, stmt->getBody(), TransRValue); | 2071 | while_node->data.while_expr.body = trans_stmt(c, ResultUsedNo, scope, stmt->getBody(), TransRValue); |
| 2011 | if (while_node->data.while_expr.body == nullptr) | 2072 | if (while_node->data.while_expr.body == nullptr) |
| 2012 | return nullptr; | 2073 | return nullptr; |
| 2013 | | 2074 | |
| 2014 | return while_node; | 2075 | return while_node; |
| 2015 | } | 2076 | } |
| 2016 | | 2077 | |
| 2017 | static AstNode *trans_if_statement(Context *c, AstNode *block, IfStmt *stmt) { | 2078 | static AstNode *trans_if_statement(Context *c, TransScope *scope, const IfStmt *stmt) { |
| 2018 | // if (c) t | 2079 | // if (c) t |
| 2019 | // if (c) t else e | 2080 | // if (c) t else e |
| 2020 | AstNode *if_node = trans_create_node(c, NodeTypeIfBoolExpr); | 2081 | AstNode *if_node = trans_create_node(c, NodeTypeIfBoolExpr); |
| 2021 | | 2082 | |
| 2022 | // TODO: condition != 0 | 2083 | // TODO: condition != 0 |
| 2023 | AstNode *condition_node = trans_expr(c, true, block, stmt->getCond(), TransRValue); | 2084 | AstNode *condition_node = trans_expr(c, ResultUsedYes, scope, stmt->getCond(), TransRValue); |
| 2024 | if (condition_node == nullptr) | 2085 | if (condition_node == nullptr) |
| 2025 | return nullptr; | 2086 | return nullptr; |
| 2026 | if_node->data.if_bool_expr.condition = condition_node; | 2087 | if_node->data.if_bool_expr.condition = condition_node; |
| 2027 | | 2088 | |
| 2028 | if_node->data.if_bool_expr.then_block = trans_stmt(c, false, block, stmt->getThen(), TransRValue); | 2089 | if_node->data.if_bool_expr.then_block = trans_stmt(c, ResultUsedNo, scope, stmt->getThen(), TransRValue); |
| 2029 | if (if_node->data.if_bool_expr.then_block == nullptr) | 2090 | if (if_node->data.if_bool_expr.then_block == nullptr) |
| 2030 | return nullptr; | 2091 | return nullptr; |
| 2031 | | 2092 | |
| 2032 | if (stmt->getElse() != nullptr) { | 2093 | if (stmt->getElse() != nullptr) { |
| 2033 | if_node->data.if_bool_expr.else_node = trans_stmt(c, false, block, stmt->getElse(), TransRValue); | 2094 | if_node->data.if_bool_expr.else_node = trans_stmt(c, ResultUsedNo, scope, stmt->getElse(), TransRValue); |
| 2034 | if (if_node->data.if_bool_expr.else_node == nullptr) | 2095 | if (if_node->data.if_bool_expr.else_node == nullptr) |
| 2035 | return nullptr; | 2096 | return nullptr; |
| 2036 | } | 2097 | } |
| ... | @@ -2038,10 +2099,10 @@ static AstNode *trans_if_statement(Context *c, AstNode *block, IfStmt *stmt) { | ... | @@ -2038,10 +2099,10 @@ static AstNode *trans_if_statement(Context *c, AstNode *block, IfStmt *stmt) { |
| 2038 | return if_node; | 2099 | return if_node; |
| 2039 | } | 2100 | } |
| 2040 | | 2101 | |
| 2041 | static AstNode *trans_call_expr(Context *c, bool result_used, AstNode *block, CallExpr *stmt) { | 2102 | static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope *scope, const CallExpr *stmt) { |
| 2042 | AstNode *node = trans_create_node(c, NodeTypeFnCallExpr); | 2103 | AstNode *node = trans_create_node(c, NodeTypeFnCallExpr); |
| 2043 | | 2104 | |
| 2044 | AstNode *callee_raw_node = trans_expr(c, true, block, stmt->getCallee(), TransRValue); | 2105 | AstNode *callee_raw_node = trans_expr(c, ResultUsedYes, scope, stmt->getCallee(), TransRValue); |
| 2045 | if (callee_raw_node == nullptr) | 2106 | if (callee_raw_node == nullptr) |
| 2046 | return nullptr; | 2107 | return nullptr; |
| 2047 | | 2108 | |
| ... | @@ -2055,9 +2116,9 @@ static AstNode *trans_call_expr(Context *c, bool result_used, AstNode *block, Ca | ... | @@ -2055,9 +2116,9 @@ static AstNode *trans_call_expr(Context *c, bool result_used, AstNode *block, Ca |
| 2055 | node->data.fn_call_expr.fn_ref_expr = callee_node; | 2116 | node->data.fn_call_expr.fn_ref_expr = callee_node; |
| 2056 | | 2117 | |
| 2057 | unsigned num_args = stmt->getNumArgs(); | 2118 | unsigned num_args = stmt->getNumArgs(); |
| 2058 | Expr **args = stmt->getArgs(); | 2119 | const Expr * const* args = stmt->getArgs(); |
| 2059 | for (unsigned i = 0; i < num_args; i += 1) { | 2120 | for (unsigned i = 0; i < num_args; i += 1) { |
| 2060 | AstNode *arg_node = trans_expr(c, true, block, args[i], TransRValue); | 2121 | AstNode *arg_node = trans_expr(c, ResultUsedYes, scope, args[i], TransRValue); |
| 2061 | if (arg_node == nullptr) | 2122 | if (arg_node == nullptr) |
| 2062 | return nullptr; | 2123 | return nullptr; |
| 2063 | | 2124 | |
| ... | @@ -2067,8 +2128,8 @@ static AstNode *trans_call_expr(Context *c, bool result_used, AstNode *block, Ca | ... | @@ -2067,8 +2128,8 @@ static AstNode *trans_call_expr(Context *c, bool result_used, AstNode *block, Ca |
| 2067 | return node; | 2128 | return node; |
| 2068 | } | 2129 | } |
| 2069 | | 2130 | |
| 2070 | static AstNode *trans_member_expr(Context *c, AstNode *block, MemberExpr *stmt) { | 2131 | static AstNode *trans_member_expr(Context *c, TransScope *scope, const MemberExpr *stmt) { |
| 2071 | AstNode *container_node = trans_expr(c, true, block, stmt->getBase(), TransRValue); | 2132 | AstNode *container_node = trans_expr(c, ResultUsedYes, scope, stmt->getBase(), TransRValue); |
| 2072 | if (container_node == nullptr) | 2133 | if (container_node == nullptr) |
| 2073 | return nullptr; | 2134 | return nullptr; |
| 2074 | | 2135 | |
| ... | @@ -2082,12 +2143,12 @@ static AstNode *trans_member_expr(Context *c, AstNode *block, MemberExpr *stmt) | ... | @@ -2082,12 +2143,12 @@ static AstNode *trans_member_expr(Context *c, AstNode *block, MemberExpr *stmt) |
| 2082 | return node; | 2143 | return node; |
| 2083 | } | 2144 | } |
| 2084 | | 2145 | |
| 2085 | static AstNode *trans_array_subscript_expr(Context *c, AstNode *block, ArraySubscriptExpr *stmt) { | 2146 | static AstNode *trans_array_subscript_expr(Context *c, TransScope *scope, const ArraySubscriptExpr *stmt) { |
| 2086 | AstNode *container_node = trans_expr(c, true, block, stmt->getBase(), TransRValue); | 2147 | AstNode *container_node = trans_expr(c, ResultUsedYes, scope, stmt->getBase(), TransRValue); |
| 2087 | if (container_node == nullptr) | 2148 | if (container_node == nullptr) |
| 2088 | return nullptr; | 2149 | return nullptr; |
| 2089 | | 2150 | |
| 2090 | AstNode *idx_node = trans_expr(c, true, block, stmt->getIdx(), TransRValue); | 2151 | AstNode *idx_node = trans_expr(c, ResultUsedYes, scope, stmt->getIdx(), TransRValue); |
| 2091 | if (idx_node == nullptr) | 2152 | if (idx_node == nullptr) |
| 2092 | return nullptr; | 2153 | return nullptr; |
| 2093 | | 2154 | |
| ... | @@ -2098,17 +2159,19 @@ static AstNode *trans_array_subscript_expr(Context *c, AstNode *block, ArraySubs | ... | @@ -2098,17 +2159,19 @@ static AstNode *trans_array_subscript_expr(Context *c, AstNode *block, ArraySubs |
| 2098 | return node; | 2159 | return node; |
| 2099 | } | 2160 | } |
| 2100 | | 2161 | |
| 2101 | static AstNode *trans_c_style_cast_expr(Context *c, bool result_used, AstNode *block, | 2162 | static AstNode *trans_c_style_cast_expr(Context *c, ResultUsed result_used, TransScope *scope, |
| 2102 | CStyleCastExpr *stmt, TransLRValue lrvalue) | 2163 | const CStyleCastExpr *stmt, TransLRValue lrvalue) |
| 2103 | { | 2164 | { |
| 2104 | AstNode *sub_expr_node = trans_expr(c, result_used, block, stmt->getSubExpr(), lrvalue); | 2165 | AstNode *sub_expr_node = trans_expr(c, result_used, scope, stmt->getSubExpr(), lrvalue); |
| 2105 | if (sub_expr_node == nullptr) | 2166 | if (sub_expr_node == nullptr) |
| 2106 | return nullptr; | 2167 | return nullptr; |
| 2107 | | 2168 | |
| 2108 | return trans_c_cast(c, stmt->getLocStart(), stmt->getType(), sub_expr_node); | 2169 | return trans_c_cast(c, stmt->getLocStart(), stmt->getType(), sub_expr_node); |
| 2109 | } | 2170 | } |
| 2110 | | 2171 | |
| 2111 | static AstNode *trans_unary_expr_or_type_trait_expr(Context *c, AstNode *block, UnaryExprOrTypeTraitExpr *stmt) { | 2172 | static AstNode *trans_unary_expr_or_type_trait_expr(Context *c, TransScope *scope, |
| | 2173 | const UnaryExprOrTypeTraitExpr *stmt) |
| | 2174 | { |
| 2112 | AstNode *type_node = trans_qual_type(c, stmt->getTypeOfArgument(), stmt->getLocStart()); | 2175 | AstNode *type_node = trans_qual_type(c, stmt->getTypeOfArgument(), stmt->getLocStart()); |
| 2113 | if (type_node == nullptr) | 2176 | if (type_node == nullptr) |
| 2114 | return nullptr; | 2177 | return nullptr; |
| ... | @@ -2118,7 +2181,7 @@ static AstNode *trans_unary_expr_or_type_trait_expr(Context *c, AstNode *block, | ... | @@ -2118,7 +2181,7 @@ static AstNode *trans_unary_expr_or_type_trait_expr(Context *c, AstNode *block, |
| 2118 | return node; | 2181 | return node; |
| 2119 | } | 2182 | } |
| 2120 | | 2183 | |
| 2121 | static AstNode *trans_do_loop(Context *c, AstNode *block, DoStmt *stmt) { | 2184 | static AstNode *trans_do_loop(Context *c, TransScope *parent_scope, const DoStmt *stmt) { |
| 2122 | AstNode *while_node = trans_create_node(c, NodeTypeWhileExpr); | 2185 | AstNode *while_node = trans_create_node(c, NodeTypeWhileExpr); |
| 2123 | | 2186 | |
| 2124 | AstNode *true_node = trans_create_node(c, NodeTypeBoolLiteral); | 2187 | AstNode *true_node = trans_create_node(c, NodeTypeBoolLiteral); |
| ... | @@ -2126,6 +2189,7 @@ static AstNode *trans_do_loop(Context *c, AstNode *block, DoStmt *stmt) { | ... | @@ -2126,6 +2189,7 @@ static AstNode *trans_do_loop(Context *c, AstNode *block, DoStmt *stmt) { |
| 2126 | while_node->data.while_expr.condition = true_node; | 2189 | while_node->data.while_expr.condition = true_node; |
| 2127 | | 2190 | |
| 2128 | AstNode *body_node; | 2191 | AstNode *body_node; |
| | 2192 | TransScope *child_scope; |
| 2129 | if (stmt->getBody()->getStmtClass() == Stmt::CompoundStmtClass) { | 2193 | if (stmt->getBody()->getStmtClass() == Stmt::CompoundStmtClass) { |
| 2130 | // there's already a block in C, so we'll append our condition to it. | 2194 | // there's already a block in C, so we'll append our condition to it. |
| 2131 | // c: do { | 2195 | // c: do { |
| ... | @@ -2137,9 +2201,10 @@ static AstNode *trans_do_loop(Context *c, AstNode *block, DoStmt *stmt) { | ... | @@ -2137,9 +2201,10 @@ static AstNode *trans_do_loop(Context *c, AstNode *block, DoStmt *stmt) { |
| 2137 | // zig: b; | 2201 | // zig: b; |
| 2138 | // zig: if (!cond) break; | 2202 | // zig: if (!cond) break; |
| 2139 | // zig: } | 2203 | // zig: } |
| 2140 | body_node = trans_stmt(c, false, block, stmt->getBody(), TransRValue); | 2204 | body_node = trans_stmt(c, ResultUsedNo, parent_scope, stmt->getBody(), TransRValue); |
| 2141 | if (body_node == nullptr) return nullptr; | 2205 | if (body_node == nullptr) return nullptr; |
| 2142 | assert(body_node->type == NodeTypeBlock); | 2206 | assert(body_node->type == NodeTypeBlock); |
| | 2207 | child_scope = c->child_scope; |
| 2143 | } else { | 2208 | } else { |
| 2144 | // the C statement is without a block, so we need to create a block to contain it. | 2209 | // the C statement is without a block, so we need to create a block to contain it. |
| 2145 | // c: do | 2210 | // c: do |
| ... | @@ -2149,63 +2214,103 @@ static AstNode *trans_do_loop(Context *c, AstNode *block, DoStmt *stmt) { | ... | @@ -2149,63 +2214,103 @@ static AstNode *trans_do_loop(Context *c, AstNode *block, DoStmt *stmt) { |
| 2149 | // zig: a; | 2214 | // zig: a; |
| 2150 | // zig: if (!cond) break; | 2215 | // zig: if (!cond) break; |
| 2151 | // zig: } | 2216 | // zig: } |
| 2152 | body_node = trans_create_node(c, NodeTypeBlock); | 2217 | TransScopeBlock *child_block_scope = trans_scope_block_create(c, parent_scope); |
| 2153 | AstNode *child_statement = trans_stmt(c, false, body_node, stmt->getBody(), TransRValue); | 2218 | body_node = child_block_scope->node; |
| | 2219 | child_scope = &child_block_scope->base; |
| | 2220 | AstNode *child_statement = trans_stmt(c, ResultUsedNo, child_scope, stmt->getBody(), TransRValue); |
| 2154 | if (child_statement == nullptr) return nullptr; | 2221 | if (child_statement == nullptr) return nullptr; |
| 2155 | body_node->data.block.statements.append(child_statement); | 2222 | child_block_scope->node->data.block.statements.append(child_statement); |
| 2156 | } | 2223 | } |
| 2157 | | 2224 | |
| 2158 | // if (!cond) break; | 2225 | // if (!cond) break; |
| 2159 | AstNode *condition_node = trans_expr(c, true, body_node, stmt->getCond(), TransRValue); | 2226 | AstNode *condition_node = trans_expr(c, ResultUsedYes, child_scope, stmt->getCond(), TransRValue); |
| 2160 | if (condition_node == nullptr) return nullptr; | 2227 | if (condition_node == nullptr) return nullptr; |
| 2161 | AstNode *terminator_node = trans_create_node(c, NodeTypeIfBoolExpr); | 2228 | AstNode *terminator_node = trans_create_node(c, NodeTypeIfBoolExpr); |
| 2162 | terminator_node->data.if_bool_expr.condition = trans_create_node_prefix_op(c, PrefixOpBoolNot, condition_node); | 2229 | terminator_node->data.if_bool_expr.condition = trans_create_node_prefix_op(c, PrefixOpBoolNot, condition_node); |
| 2163 | terminator_node->data.if_bool_expr.then_block = trans_create_node(c, NodeTypeBreak); | 2230 | terminator_node->data.if_bool_expr.then_block = trans_create_node(c, NodeTypeBreak); |
| 2164 | body_node->data.block.statements.append(terminator_node); | 2231 | |
| | 2232 | assert(child_scope->id == TransScopeIdBlock); |
| | 2233 | TransScopeBlock *child_block_scope = (TransScopeBlock *)child_scope; |
| | 2234 | |
| | 2235 | child_block_scope->node->data.block.statements.append(terminator_node); |
| 2165 | | 2236 | |
| 2166 | while_node->data.while_expr.body = body_node; | 2237 | while_node->data.while_expr.body = body_node; |
| 2167 | | 2238 | |
| 2168 | return while_node; | 2239 | return while_node; |
| 2169 | } | 2240 | } |
| 2170 | | 2241 | |
| 2171 | static AstNode *trans_for_loop(Context *c, AstNode *block, ForStmt *stmt) { | 2242 | //static AstNode *trans_switch_stmt(Context *c, TransScope *scope, const SwitchStmt *stmt) { |
| | 2243 | // AstNode *switch_block_node = trans_create_node(c, NodeTypeBlock); |
| | 2244 | // AstNode *switch_node = trans_create_node(c, NodeTypeSwitchExpr); |
| | 2245 | // const DeclStmt *var_decl_stmt = stmt->getConditionVariableDeclStmt(); |
| | 2246 | // if (var_decl_stmt != nullptr) { |
| | 2247 | // AstNode *vars_node = trans_stmt(c, ResultUsedNo, switch_block_node, var_decl_stmt, TransRValue); |
| | 2248 | // if (vars_node == nullptr) |
| | 2249 | // return nullptr; |
| | 2250 | // if (vars_node != skip_add_to_block_node) |
| | 2251 | // switch_block_node->data.block.statements.append(vars_node); |
| | 2252 | // } |
| | 2253 | // switch_block_node->data.block.statements.append(switch_node); |
| | 2254 | // |
| | 2255 | // const Expr *cond_expr = stmt->getCond(); |
| | 2256 | // assert(cond_expr != nullptr); |
| | 2257 | // |
| | 2258 | // AstNode *expr_node = trans_expr(c, ResultUsedYes, switch_block_node, cond_expr, TransRValue); |
| | 2259 | // if (expr_node == nullptr) |
| | 2260 | // return nullptr; |
| | 2261 | // switch_node->data.switch_expr.expr = expr_node; |
| | 2262 | // |
| | 2263 | // AstNode *body_node = trans_stmt(c, ResultUsedNo, switch_block_node, stmt->getBody(), TransRValue); |
| | 2264 | // if (body_node == nullptr) |
| | 2265 | // return nullptr; |
| | 2266 | // if (body_node != skip_add_to_block_node) |
| | 2267 | // switch_block_node->data.block.statements.append(body_node); |
| | 2268 | // |
| | 2269 | // return switch_block_node; |
| | 2270 | //} |
| | 2271 | |
| | 2272 | static AstNode *trans_for_loop(Context *c, TransScope *parent_scope, const ForStmt *stmt) { |
| 2172 | AstNode *loop_block_node; | 2273 | AstNode *loop_block_node; |
| | 2274 | TransScope *condition_scope; |
| 2173 | AstNode *while_node = trans_create_node(c, NodeTypeWhileExpr); | 2275 | AstNode *while_node = trans_create_node(c, NodeTypeWhileExpr); |
| 2174 | Stmt *init_stmt = stmt->getInit(); | 2276 | const Stmt *init_stmt = stmt->getInit(); |
| 2175 | if (init_stmt == nullptr) { | 2277 | if (init_stmt == nullptr) { |
| 2176 | loop_block_node = while_node; | 2278 | loop_block_node = while_node; |
| | 2279 | condition_scope = parent_scope; |
| 2177 | } else { | 2280 | } else { |
| 2178 | loop_block_node = trans_create_node(c, NodeTypeBlock); | 2281 | TransScopeBlock *child_scope = trans_scope_block_create(c, parent_scope); |
| | 2282 | loop_block_node = child_scope->node; |
| | 2283 | condition_scope = &child_scope->base; |
| 2179 | | 2284 | |
| 2180 | AstNode *vars_node = trans_stmt(c, false, loop_block_node, init_stmt, TransRValue); | 2285 | AstNode *vars_node = trans_stmt(c, ResultUsedNo, &child_scope->base, init_stmt, TransRValue); |
| 2181 | if (vars_node == nullptr) | 2286 | if (vars_node == nullptr) |
| 2182 | return nullptr; | 2287 | return nullptr; |
| 2183 | if (vars_node != skip_add_to_block_node) | 2288 | if (vars_node != skip_add_to_block_node) |
| 2184 | loop_block_node->data.block.statements.append(vars_node); | 2289 | child_scope->node->data.block.statements.append(vars_node); |
| 2185 | | 2290 | |
| 2186 | loop_block_node->data.block.statements.append(while_node); | 2291 | child_scope->node->data.block.statements.append(while_node); |
| 2187 | } | 2292 | } |
| 2188 | | 2293 | |
| 2189 | Stmt *cond_stmt = stmt->getCond(); | 2294 | const Stmt *cond_stmt = stmt->getCond(); |
| 2190 | if (cond_stmt == nullptr) { | 2295 | if (cond_stmt == nullptr) { |
| 2191 | AstNode *true_node = trans_create_node(c, NodeTypeBoolLiteral); | 2296 | AstNode *true_node = trans_create_node(c, NodeTypeBoolLiteral); |
| 2192 | true_node->data.bool_literal.value = true; | 2297 | true_node->data.bool_literal.value = true; |
| 2193 | while_node->data.while_expr.condition = true_node; | 2298 | while_node->data.while_expr.condition = true_node; |
| 2194 | } else { | 2299 | } else { |
| 2195 | while_node->data.while_expr.condition = trans_stmt(c, false, loop_block_node, cond_stmt, TransRValue); | 2300 | while_node->data.while_expr.condition = trans_stmt(c, ResultUsedNo, condition_scope, cond_stmt, TransRValue); |
| 2196 | if (while_node->data.while_expr.condition == nullptr) | 2301 | if (while_node->data.while_expr.condition == nullptr) |
| 2197 | return nullptr; | 2302 | return nullptr; |
| 2198 | } | 2303 | } |
| 2199 | | 2304 | |
| 2200 | Stmt *inc_stmt = stmt->getInc(); | 2305 | const Stmt *inc_stmt = stmt->getInc(); |
| 2201 | if (inc_stmt != nullptr) { | 2306 | if (inc_stmt != nullptr) { |
| 2202 | AstNode *inc_node = trans_stmt(c, false, loop_block_node, inc_stmt, TransRValue); | 2307 | AstNode *inc_node = trans_stmt(c, ResultUsedNo, condition_scope, inc_stmt, TransRValue); |
| 2203 | if (inc_node == nullptr) | 2308 | if (inc_node == nullptr) |
| 2204 | return nullptr; | 2309 | return nullptr; |
| 2205 | while_node->data.while_expr.continue_expr = inc_node; | 2310 | while_node->data.while_expr.continue_expr = inc_node; |
| 2206 | } | 2311 | } |
| 2207 | | 2312 | |
| 2208 | AstNode *child_statement = trans_stmt(c, false, loop_block_node, stmt->getBody(), TransRValue); | 2313 | AstNode *child_statement = trans_stmt(c, ResultUsedNo, condition_scope, stmt->getBody(), TransRValue); |
| 2209 | if (child_statement == nullptr) | 2314 | if (child_statement == nullptr) |
| 2210 | return nullptr; | 2315 | return nullptr; |
| 2211 | while_node->data.while_expr.body = child_statement; | 2316 | while_node->data.while_expr.body = child_statement; |
| ... | @@ -2213,7 +2318,7 @@ static AstNode *trans_for_loop(Context *c, AstNode *block, ForStmt *stmt) { | ... | @@ -2213,7 +2318,7 @@ static AstNode *trans_for_loop(Context *c, AstNode *block, ForStmt *stmt) { |
| 2213 | return loop_block_node; | 2318 | return loop_block_node; |
| 2214 | } | 2319 | } |
| 2215 | | 2320 | |
| 2216 | static AstNode *trans_string_literal(Context *c, AstNode *block, StringLiteral *stmt) { | 2321 | static AstNode *trans_string_literal(Context *c, TransScope *scope, const StringLiteral *stmt) { |
| 2217 | switch (stmt->getKind()) { | 2322 | switch (stmt->getKind()) { |
| 2218 | case StringLiteral::Ascii: | 2323 | case StringLiteral::Ascii: |
| 2219 | case StringLiteral::UTF8: | 2324 | case StringLiteral::UTF8: |
| ... | @@ -2231,72 +2336,75 @@ static AstNode *trans_string_literal(Context *c, AstNode *block, StringLiteral * | ... | @@ -2231,72 +2336,75 @@ static AstNode *trans_string_literal(Context *c, AstNode *block, StringLiteral * |
| 2231 | zig_unreachable(); | 2336 | zig_unreachable(); |
| 2232 | } | 2337 | } |
| 2233 | | 2338 | |
| 2234 | static AstNode *trans_break_stmt(Context *c, AstNode *block, BreakStmt *stmt) { | 2339 | static AstNode *trans_break_stmt(Context *c, TransScope *scope, const BreakStmt *stmt) { |
| 2235 | return trans_create_node(c, NodeTypeBreak); | 2340 | return trans_create_node(c, NodeTypeBreak); |
| 2236 | } | 2341 | } |
| 2237 | | 2342 | |
| 2238 | static AstNode *trans_continue_stmt(Context *c, AstNode *block, ContinueStmt *stmt) { | 2343 | static AstNode *trans_continue_stmt(Context *c, TransScope *scope, const ContinueStmt *stmt) { |
| 2239 | return trans_create_node(c, NodeTypeContinue); | 2344 | return trans_create_node(c, NodeTypeContinue); |
| 2240 | } | 2345 | } |
| 2241 | | 2346 | |
| 2242 | static AstNode *trans_stmt(Context *c, bool result_used, AstNode *block, Stmt *stmt, TransLRValue lrvalue) { | 2347 | static AstNode *trans_stmt(Context *c, ResultUsed result_used, TransScope *scope, const Stmt *stmt, TransLRValue lrvalue) { |
| | 2348 | c->child_scope = scope; // TODO refactor out |
| 2243 | Stmt::StmtClass sc = stmt->getStmtClass(); | 2349 | Stmt::StmtClass sc = stmt->getStmtClass(); |
| 2244 | switch (sc) { | 2350 | switch (sc) { |
| 2245 | case Stmt::ReturnStmtClass: | 2351 | case Stmt::ReturnStmtClass: |
| 2246 | return trans_return_stmt(c, block, (ReturnStmt *)stmt); | 2352 | return trans_return_stmt(c, scope, (const ReturnStmt *)stmt); |
| 2247 | case Stmt::CompoundStmtClass: | 2353 | case Stmt::CompoundStmtClass: |
| 2248 | return trans_compound_stmt(c, block, (CompoundStmt *)stmt); | 2354 | return trans_compound_stmt(c, scope, (const CompoundStmt *)stmt); |
| 2249 | case Stmt::IntegerLiteralClass: | 2355 | case Stmt::IntegerLiteralClass: |
| 2250 | return trans_integer_literal(c, (IntegerLiteral *)stmt); | 2356 | return trans_integer_literal(c, (const IntegerLiteral *)stmt); |
| 2251 | case Stmt::ConditionalOperatorClass: | 2357 | case Stmt::ConditionalOperatorClass: |
| 2252 | return trans_conditional_operator(c, result_used, block, (ConditionalOperator *)stmt); | 2358 | return trans_conditional_operator(c, result_used, scope, (const ConditionalOperator *)stmt); |
| 2253 | case Stmt::BinaryOperatorClass: | 2359 | case Stmt::BinaryOperatorClass: |
| 2254 | return trans_binary_operator(c, result_used, block, (BinaryOperator *)stmt); | 2360 | return trans_binary_operator(c, result_used, scope, (const BinaryOperator *)stmt); |
| 2255 | case Stmt::CompoundAssignOperatorClass: | 2361 | case Stmt::CompoundAssignOperatorClass: |
| 2256 | return trans_compound_assign_operator(c, result_used, block, (CompoundAssignOperator *)stmt); | 2362 | return trans_compound_assign_operator(c, result_used, scope, (const CompoundAssignOperator *)stmt); |
| 2257 | case Stmt::ImplicitCastExprClass: | 2363 | case Stmt::ImplicitCastExprClass: |
| 2258 | return trans_implicit_cast_expr(c, block, (ImplicitCastExpr *)stmt); | 2364 | return trans_implicit_cast_expr(c, scope, (const ImplicitCastExpr *)stmt); |
| 2259 | case Stmt::DeclRefExprClass: | 2365 | case Stmt::DeclRefExprClass: |
| 2260 | return trans_decl_ref_expr(c, (DeclRefExpr *)stmt, lrvalue); | 2366 | return trans_decl_ref_expr(c, (const DeclRefExpr *)stmt, lrvalue); |
| 2261 | case Stmt::UnaryOperatorClass: | 2367 | case Stmt::UnaryOperatorClass: |
| 2262 | return trans_unary_operator(c, result_used, block, (UnaryOperator *)stmt); | 2368 | return trans_unary_operator(c, result_used, scope, (const UnaryOperator *)stmt); |
| 2263 | case Stmt::DeclStmtClass: | 2369 | case Stmt::DeclStmtClass: |
| 2264 | return trans_local_declaration(c, block, (DeclStmt *)stmt); | 2370 | return trans_local_declaration(c, scope, (const DeclStmt *)stmt); |
| 2265 | case Stmt::WhileStmtClass: | 2371 | case Stmt::WhileStmtClass: |
| 2266 | return trans_while_loop(c, block, (WhileStmt *)stmt); | 2372 | return trans_while_loop(c, scope, (const WhileStmt *)stmt); |
| 2267 | case Stmt::IfStmtClass: | 2373 | case Stmt::IfStmtClass: |
| 2268 | return trans_if_statement(c, block, (IfStmt *)stmt); | 2374 | return trans_if_statement(c, scope, (const IfStmt *)stmt); |
| 2269 | case Stmt::CallExprClass: | 2375 | case Stmt::CallExprClass: |
| 2270 | return trans_call_expr(c, result_used, block, (CallExpr *)stmt); | 2376 | return trans_call_expr(c, result_used, scope, (const CallExpr *)stmt); |
| 2271 | case Stmt::NullStmtClass: | 2377 | case Stmt::NullStmtClass: |
| 2272 | return skip_add_to_block_node; | 2378 | return skip_add_to_block_node; |
| 2273 | case Stmt::MemberExprClass: | 2379 | case Stmt::MemberExprClass: |
| 2274 | return trans_member_expr(c, block, (MemberExpr *)stmt); | 2380 | return trans_member_expr(c, scope, (const MemberExpr *)stmt); |
| 2275 | case Stmt::ArraySubscriptExprClass: | 2381 | case Stmt::ArraySubscriptExprClass: |
| 2276 | return trans_array_subscript_expr(c, block, (ArraySubscriptExpr *)stmt); | 2382 | return trans_array_subscript_expr(c, scope, (const ArraySubscriptExpr *)stmt); |
| 2277 | case Stmt::CStyleCastExprClass: | 2383 | case Stmt::CStyleCastExprClass: |
| 2278 | return trans_c_style_cast_expr(c, result_used, block, (CStyleCastExpr *)stmt, lrvalue); | 2384 | return trans_c_style_cast_expr(c, result_used, scope, (const CStyleCastExpr *)stmt, lrvalue); |
| 2279 | case Stmt::UnaryExprOrTypeTraitExprClass: | 2385 | case Stmt::UnaryExprOrTypeTraitExprClass: |
| 2280 | return trans_unary_expr_or_type_trait_expr(c, block, (UnaryExprOrTypeTraitExpr *)stmt); | 2386 | return trans_unary_expr_or_type_trait_expr(c, scope, (const UnaryExprOrTypeTraitExpr *)stmt); |
| 2281 | case Stmt::DoStmtClass: | 2387 | case Stmt::DoStmtClass: |
| 2282 | return trans_do_loop(c, block, (DoStmt *)stmt); | 2388 | return trans_do_loop(c, scope, (const DoStmt *)stmt); |
| 2283 | case Stmt::ForStmtClass: | 2389 | case Stmt::ForStmtClass: |
| 2284 | return trans_for_loop(c, block, (ForStmt *)stmt); | 2390 | return trans_for_loop(c, scope, (const ForStmt *)stmt); |
| 2285 | case Stmt::StringLiteralClass: | 2391 | case Stmt::StringLiteralClass: |
| 2286 | return trans_string_literal(c, block, (StringLiteral *)stmt); | 2392 | return trans_string_literal(c, scope, (const StringLiteral *)stmt); |
| 2287 | case Stmt::BreakStmtClass: | 2393 | case Stmt::BreakStmtClass: |
| 2288 | return trans_break_stmt(c, block, (BreakStmt *)stmt); | 2394 | return trans_break_stmt(c, scope, (const BreakStmt *)stmt); |
| 2289 | case Stmt::ContinueStmtClass: | 2395 | case Stmt::ContinueStmtClass: |
| 2290 | return trans_continue_stmt(c, block, (ContinueStmt *)stmt); | 2396 | return trans_continue_stmt(c, scope, (const ContinueStmt *)stmt); |
| | 2397 | // case Stmt::SwitchStmtClass: |
| | 2398 | // return trans_switch_stmt(c, scope, (const SwitchStmt *)stmt); |
| | 2399 | case Stmt::SwitchStmtClass: |
| | 2400 | emit_warning(c, stmt->getLocStart(), "TODO handle C SwitchStmtClass"); |
| | 2401 | return nullptr; |
| 2291 | case Stmt::CaseStmtClass: | 2402 | case Stmt::CaseStmtClass: |
| 2292 | emit_warning(c, stmt->getLocStart(), "TODO handle C CaseStmtClass"); | 2403 | emit_warning(c, stmt->getLocStart(), "TODO handle C CaseStmtClass"); |
| 2293 | return nullptr; | 2404 | return nullptr; |
| 2294 | case Stmt::DefaultStmtClass: | 2405 | case Stmt::DefaultStmtClass: |
| 2295 | emit_warning(c, stmt->getLocStart(), "TODO handle C DefaultStmtClass"); | 2406 | emit_warning(c, stmt->getLocStart(), "TODO handle C DefaultStmtClass"); |
| 2296 | return nullptr; | 2407 | return nullptr; |
| 2297 | case Stmt::SwitchStmtClass: | | |
| 2298 | emit_warning(c, stmt->getLocStart(), "TODO handle C SwitchStmtClass"); | | |
| 2299 | return nullptr; | | |
| 2300 | case Stmt::NoStmtClass: | 2408 | case Stmt::NoStmtClass: |
| 2301 | emit_warning(c, stmt->getLocStart(), "TODO handle C NoStmtClass"); | 2409 | emit_warning(c, stmt->getLocStart(), "TODO handle C NoStmtClass"); |
| 2302 | return nullptr; | 2410 | return nullptr; |
| ... | @@ -2584,7 +2692,7 @@ static AstNode *trans_stmt(Context *c, bool result_used, AstNode *block, Stmt *s | ... | @@ -2584,7 +2692,7 @@ static AstNode *trans_stmt(Context *c, bool result_used, AstNode *block, Stmt *s |
| 2584 | emit_warning(c, stmt->getLocStart(), "TODO handle C PackExpansionExprClass"); | 2692 | emit_warning(c, stmt->getLocStart(), "TODO handle C PackExpansionExprClass"); |
| 2585 | return nullptr; | 2693 | return nullptr; |
| 2586 | case Stmt::ParenExprClass: | 2694 | case Stmt::ParenExprClass: |
| 2587 | return trans_expr(c, result_used, block, ((ParenExpr*)stmt)->getSubExpr(), lrvalue); | 2695 | return trans_expr(c, result_used, scope, ((const ParenExpr*)stmt)->getSubExpr(), lrvalue); |
| 2588 | case Stmt::ParenListExprClass: | 2696 | case Stmt::ParenListExprClass: |
| 2589 | emit_warning(c, stmt->getLocStart(), "TODO handle C ParenListExprClass"); | 2697 | emit_warning(c, stmt->getLocStart(), "TODO handle C ParenListExprClass"); |
| 2590 | return nullptr; | 2698 | return nullptr; |
| ... | @@ -2838,10 +2946,13 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) { | ... | @@ -2838,10 +2946,13 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) { |
| 2838 | return; | 2946 | return; |
| 2839 | } | 2947 | } |
| 2840 | | 2948 | |
| | 2949 | TransScope *scope = nullptr; |
| | 2950 | |
| 2841 | for (size_t i = 0; i < proto_node->data.fn_proto.params.length; i += 1) { | 2951 | for (size_t i = 0; i < proto_node->data.fn_proto.params.length; i += 1) { |
| 2842 | AstNode *param_node = proto_node->data.fn_proto.params.at(i); | 2952 | AstNode *param_node = proto_node->data.fn_proto.params.at(i); |
| 2843 | const ParmVarDecl *param = fn_decl->getParamDecl(i); | 2953 | const ParmVarDecl *param = fn_decl->getParamDecl(i); |
| 2844 | const char *name = decl_name(param); | 2954 | const char *name = decl_name(param); |
| | 2955 | |
| 2845 | Buf *proto_param_name; | 2956 | Buf *proto_param_name; |
| 2846 | if (strlen(name) != 0) { | 2957 | if (strlen(name) != 0) { |
| 2847 | proto_param_name = buf_create_from_str(name); | 2958 | proto_param_name = buf_create_from_str(name); |
| ... | @@ -2851,7 +2962,11 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) { | ... | @@ -2851,7 +2962,11 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) { |
| 2851 | proto_param_name = buf_sprintf("arg%" ZIG_PRI_usize "", i); | 2962 | proto_param_name = buf_sprintf("arg%" ZIG_PRI_usize "", i); |
| 2852 | } | 2963 | } |
| 2853 | } | 2964 | } |
| 2854 | param_node->data.param_decl.name = proto_param_name; | 2965 | |
| | 2966 | TransScopeVar *scope_var = trans_scope_var_create(c, scope, proto_param_name); |
| | 2967 | scope = &scope_var->base; |
| | 2968 | |
| | 2969 | param_node->data.param_decl.name = scope_var->zig_name; |
| 2855 | } | 2970 | } |
| 2856 | | 2971 | |
| 2857 | if (!fn_decl->hasBody()) { | 2972 | if (!fn_decl->hasBody()) { |
| ... | @@ -2863,7 +2978,7 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) { | ... | @@ -2863,7 +2978,7 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) { |
| 2863 | // actual function definition with body | 2978 | // actual function definition with body |
| 2864 | c->ptr_params.clear(); | 2979 | c->ptr_params.clear(); |
| 2865 | Stmt *body = fn_decl->getBody(); | 2980 | Stmt *body = fn_decl->getBody(); |
| 2866 | AstNode *actual_body_node = trans_stmt(c, false, nullptr, body, TransRValue); | 2981 | AstNode *actual_body_node = trans_stmt(c, ResultUsedNo, scope, body, TransRValue); |
| 2867 | assert(actual_body_node != skip_add_to_block_node); | 2982 | assert(actual_body_node != skip_add_to_block_node); |
| 2868 | if (actual_body_node == nullptr) { | 2983 | if (actual_body_node == nullptr) { |
| 2869 | emit_warning(c, fn_decl->getLocation(), "unable to translate function"); | 2984 | emit_warning(c, fn_decl->getLocation(), "unable to translate function"); |
| ... | @@ -3301,14 +3416,66 @@ static bool decl_visitor(void *context, const Decl *decl) { | ... | @@ -3301,14 +3416,66 @@ static bool decl_visitor(void *context, const Decl *decl) { |
| 3301 | return true; | 3416 | return true; |
| 3302 | } | 3417 | } |
| 3303 | | 3418 | |
| 3304 | static bool name_exists(Context *c, Buf *name) { | 3419 | static bool name_exists_global(Context *c, Buf *name) { |
| 3305 | return get_global(c, name) != nullptr; | 3420 | return get_global(c, name) != nullptr; |
| 3306 | } | 3421 | } |
| 3307 | | 3422 | |
| | 3423 | static bool name_exists_scope(Context *c, Buf *name, TransScope *scope) { |
| | 3424 | while (scope != nullptr) { |
| | 3425 | if (scope->id == TransScopeIdVar) { |
| | 3426 | TransScopeVar *var_scope = (TransScopeVar *)scope; |
| | 3427 | if (buf_eql_buf(name, var_scope->zig_name)) { |
| | 3428 | return true; |
| | 3429 | } |
| | 3430 | } |
| | 3431 | scope = scope->parent; |
| | 3432 | } |
| | 3433 | return name_exists_global(c, name); |
| | 3434 | } |
| | 3435 | |
| | 3436 | static Buf *get_unique_name(Context *c, Buf *name, TransScope *scope) { |
| | 3437 | Buf *proposed_name = name; |
| | 3438 | int count = 0; |
| | 3439 | while (name_exists_scope(c, proposed_name, scope)) { |
| | 3440 | if (proposed_name == name) { |
| | 3441 | proposed_name = buf_alloc(); |
| | 3442 | } |
| | 3443 | buf_resize(proposed_name, 0); |
| | 3444 | buf_appendf(proposed_name, "%s_%d", buf_ptr(name), count); |
| | 3445 | count += 1; |
| | 3446 | } |
| | 3447 | return proposed_name; |
| | 3448 | } |
| | 3449 | |
| | 3450 | static TransScopeBlock *trans_scope_block_create(Context *c, TransScope *parent_scope) { |
| | 3451 | TransScopeBlock *result = allocate<TransScopeBlock>(1); |
| | 3452 | result->base.id = TransScopeIdBlock; |
| | 3453 | result->base.parent = parent_scope; |
| | 3454 | result->node = trans_create_node(c, NodeTypeBlock); |
| | 3455 | return result; |
| | 3456 | } |
| | 3457 | |
| | 3458 | static TransScopeVar *trans_scope_var_create(Context *c, TransScope *parent_scope, Buf *wanted_name) { |
| | 3459 | TransScopeVar *result = allocate<TransScopeVar>(1); |
| | 3460 | result->base.id = TransScopeIdVar; |
| | 3461 | result->base.parent = parent_scope; |
| | 3462 | result->c_name = wanted_name; |
| | 3463 | result->zig_name = get_unique_name(c, wanted_name, parent_scope); |
| | 3464 | return result; |
| | 3465 | } |
| | 3466 | |
| | 3467 | //static TransScopeSwitch *trans_scope_switch_create(Context *c, TransScope *parent_scope) { |
| | 3468 | // TransScopeSwitch *result = allocate<TransScopeSwitch>(1); |
| | 3469 | // result->base.id = TransScopeIdSwitch; |
| | 3470 | // result->base.parent = parent_scope; |
| | 3471 | // result->switch_node = trans_create_node(c, NodeTypeSwitchExpr); |
| | 3472 | // return result; |
| | 3473 | //} |
| | 3474 | |
| 3308 | static void render_aliases(Context *c) { | 3475 | static void render_aliases(Context *c) { |
| 3309 | for (size_t i = 0; i < c->aliases.length; i += 1) { | 3476 | for (size_t i = 0; i < c->aliases.length; i += 1) { |
| 3310 | Alias *alias = &c->aliases.at(i); | 3477 | Alias *alias = &c->aliases.at(i); |
| 3311 | if (name_exists(c, alias->new_name)) | 3478 | if (name_exists_global(c, alias->new_name)) |
| 3312 | continue; | 3479 | continue; |
| 3313 | | 3480 | |
| 3314 | add_global_var(c, alias->new_name, trans_create_node_symbol(c, alias->canon_name)); | 3481 | add_global_var(c, alias->new_name, trans_create_node_symbol(c, alias->canon_name)); |
| ... | @@ -3438,7 +3605,7 @@ static void process_symbol_macros(Context *c) { | ... | @@ -3438,7 +3605,7 @@ static void process_symbol_macros(Context *c) { |
| 3438 | | 3605 | |
| 3439 | // Check if this macro aliases another top level declaration | 3606 | // Check if this macro aliases another top level declaration |
| 3440 | AstNode *existing_node = get_global(c, ms.value); | 3607 | AstNode *existing_node = get_global(c, ms.value); |
| 3441 | if (!existing_node || name_exists(c, ms.name)) | 3608 | if (!existing_node || name_exists_global(c, ms.name)) |
| 3442 | continue; | 3609 | continue; |
| 3443 | | 3610 | |
| 3444 | // If a macro aliases a global variable which is a function pointer, we conclude that | 3611 | // If a macro aliases a global variable which is a function pointer, we conclude that |
| ... | @@ -3487,7 +3654,7 @@ static void process_preprocessor_entities(Context *c, ASTUnit &unit) { | ... | @@ -3487,7 +3654,7 @@ static void process_preprocessor_entities(Context *c, ASTUnit &unit) { |
| 3487 | continue; | 3654 | continue; |
| 3488 | } | 3655 | } |
| 3489 | Buf *name = buf_create_from_str(raw_name); | 3656 | Buf *name = buf_create_from_str(raw_name); |
| 3490 | if (name_exists(c, name)) { | 3657 | if (name_exists_global(c, name)) { |
| 3491 | continue; | 3658 | continue; |
| 3492 | } | 3659 | } |
| 3493 | | 3660 | |