| ... | ... | @@ -1170,7 +1170,7 @@ fn transBinaryOperator( |
| 1170 | 1170 | } |
| 1171 | 1171 | }, |
| 1172 | 1172 | .Div => { |
| 1173 | | if (!cIsUnsignedInteger(qt)) { |
| 1173 | if (cIsSignedInteger(qt)) { |
| 1174 | 1174 | // signed integer division uses @divTrunc |
| 1175 | 1175 | const div_trunc_node = try transCreateNodeBuiltinFnCall(rp.c, "@divTrunc"); |
| 1176 | 1176 | try div_trunc_node.params.push(try transExpr(rp, scope, ZigClangBinaryOperator_getLHS(stmt), .used, .l_value)); |
| ... | ... | @@ -1182,7 +1182,7 @@ fn transBinaryOperator( |
| 1182 | 1182 | } |
| 1183 | 1183 | }, |
| 1184 | 1184 | .Rem => { |
| 1185 | | if (!cIsUnsignedInteger(qt)) { |
| 1185 | if (cIsSignedInteger(qt)) { |
| 1186 | 1186 | // signed integer division uses @rem |
| 1187 | 1187 | const rem_node = try transCreateNodeBuiltinFnCall(rp.c, "@rem"); |
| 1188 | 1188 | try rem_node.params.push(try transExpr(rp, scope, ZigClangBinaryOperator_getLHS(stmt), .used, .l_value)); |
| ... | ... | @@ -3048,13 +3048,37 @@ fn transCreateCompoundAssign( |
| 3048 | 3048 | used: ResultUsed, |
| 3049 | 3049 | ) TransError!*ast.Node { |
| 3050 | 3050 | const is_shift = bin_op == .BitShiftLeft or bin_op == .BitShiftRight; |
| 3051 | const is_div = bin_op == .Div; |
| 3052 | const is_mod = bin_op == .Mod; |
| 3051 | 3053 | const lhs = ZigClangCompoundAssignOperator_getLHS(stmt); |
| 3052 | 3054 | const rhs = ZigClangCompoundAssignOperator_getRHS(stmt); |
| 3053 | 3055 | const loc = ZigClangCompoundAssignOperator_getBeginLoc(stmt); |
| 3056 | const is_signed = cIsSignedInteger(getExprQualType(rp.c, lhs)); |
| 3054 | 3057 | if (used == .unused) { |
| 3055 | 3058 | // common case |
| 3056 | 3059 | // c: lhs += rhs |
| 3057 | 3060 | // zig: lhs += rhs |
| 3061 | |
| 3062 | if ((is_mod or is_div) and is_signed) { |
| 3063 | const op_token = try appendToken(rp.c, .Equal, "="); |
| 3064 | const op_node = try rp.c.a().create(ast.Node.InfixOp); |
| 3065 | const builtin = if (is_mod) "@rem" else "@divTrunc"; |
| 3066 | const builtin_node = try transCreateNodeBuiltinFnCall(rp.c, builtin); |
| 3067 | const lhs_node = try transExpr(rp, scope, lhs, .used, .l_value); |
| 3068 | try builtin_node.params.push(lhs_node); |
| 3069 | _ = try appendToken(rp.c, .Comma, ","); |
| 3070 | try builtin_node.params.push(try transExpr(rp, scope, rhs, .used, .r_value)); |
| 3071 | builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")"); |
| 3072 | op_node.* = .{ |
| 3073 | .op_token = op_token, |
| 3074 | .lhs = lhs_node, |
| 3075 | .op = .Assign, |
| 3076 | .rhs = &builtin_node.base, |
| 3077 | }; |
| 3078 | _ = try appendToken(rp.c, .Semicolon, ";"); |
| 3079 | return &op_node.base; |
| 3080 | } |
| 3081 | |
| 3058 | 3082 | const lhs_node = try transExpr(rp, scope, lhs, .used, .l_value); |
| 3059 | 3083 | const eq_token = try appendToken(rp.c, assign_tok_id, assign_bytes); |
| 3060 | 3084 | var rhs_node = if (is_shift) |
| ... | ... | @@ -3097,31 +3121,53 @@ fn transCreateCompoundAssign( |
| 3097 | 3121 | const lhs_node = try transCreateNodeIdentifier(rp.c, ref); |
| 3098 | 3122 | const ref_node = try transCreateNodePtrDeref(rp.c, lhs_node); |
| 3099 | 3123 | _ = try appendToken(rp.c, .Semicolon, ";"); |
| 3100 | | const bin_token = try appendToken(rp.c, bin_tok_id, bin_bytes); |
| 3101 | | var rhs_node = try transExpr(rp, scope, rhs, .used, .r_value); |
| 3102 | | if (is_shift) { |
| 3103 | | const cast_node = try transCreateNodeBuiltinFnCall(rp.c, "@intCast"); |
| 3104 | | const rhs_type = try qualTypeToLog2IntRef(rp, getExprQualType(rp.c, rhs), loc); |
| 3105 | | try cast_node.params.push(rhs_type); |
| 3124 | |
| 3125 | if ((is_mod or is_div) and is_signed) { |
| 3126 | const op_token = try appendToken(rp.c, .Equal, "="); |
| 3127 | const op_node = try rp.c.a().create(ast.Node.InfixOp); |
| 3128 | const builtin = if (is_mod) "@rem" else "@divTrunc"; |
| 3129 | const builtin_node = try transCreateNodeBuiltinFnCall(rp.c, builtin); |
| 3130 | try builtin_node.params.push(try transCreateNodePtrDeref(rp.c, lhs_node)); |
| 3106 | 3131 | _ = try appendToken(rp.c, .Comma, ","); |
| 3107 | | try cast_node.params.push(rhs_node); |
| 3108 | | cast_node.rparen_token = try appendToken(rp.c, .RParen, ")"); |
| 3109 | | rhs_node = &cast_node.base; |
| 3110 | | } |
| 3111 | | const rhs_bin = try transCreateNodeInfixOp(rp, scope, ref_node, bin_op, bin_token, rhs_node, .used, false); |
| 3132 | try builtin_node.params.push(try transExpr(rp, scope, rhs, .used, .r_value)); |
| 3133 | builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")"); |
| 3134 | _ = try appendToken(rp.c, .Semicolon, ";"); |
| 3135 | op_node.* = .{ |
| 3136 | .op_token = op_token, |
| 3137 | .lhs = ref_node, |
| 3138 | .op = .Assign, |
| 3139 | .rhs = &builtin_node.base, |
| 3140 | }; |
| 3141 | _ = try appendToken(rp.c, .Semicolon, ";"); |
| 3142 | try block_scope.block_node.statements.push(&op_node.base); |
| 3143 | } else { |
| 3144 | const bin_token = try appendToken(rp.c, bin_tok_id, bin_bytes); |
| 3145 | var rhs_node = try transExpr(rp, scope, rhs, .used, .r_value); |
| 3112 | 3146 | |
| 3113 | | _ = try appendToken(rp.c, .Semicolon, ";"); |
| 3147 | if (is_shift) { |
| 3148 | const cast_node = try transCreateNodeBuiltinFnCall(rp.c, "@intCast"); |
| 3149 | const rhs_type = try qualTypeToLog2IntRef(rp, getExprQualType(rp.c, rhs), loc); |
| 3150 | try cast_node.params.push(rhs_type); |
| 3151 | _ = try appendToken(rp.c, .Comma, ","); |
| 3152 | try cast_node.params.push(rhs_node); |
| 3153 | cast_node.rparen_token = try appendToken(rp.c, .RParen, ")"); |
| 3154 | rhs_node = &cast_node.base; |
| 3155 | } |
| 3114 | 3156 | |
| 3115 | | const eq_token = try appendToken(rp.c, .Equal, "="); |
| 3116 | | const assign = try transCreateNodeInfixOp(rp, scope, ref_node, .Assign, eq_token, rhs_bin, .used, false); |
| 3117 | | try block_scope.block_node.statements.push(assign); |
| 3157 | const rhs_bin = try transCreateNodeInfixOp(rp, scope, ref_node, bin_op, bin_token, rhs_node, .used, false); |
| 3158 | _ = try appendToken(rp.c, .Semicolon, ";"); |
| 3159 | |
| 3160 | const eq_token = try appendToken(rp.c, .Equal, "="); |
| 3161 | const assign = try transCreateNodeInfixOp(rp, scope, ref_node, .Assign, eq_token, rhs_bin, .used, false); |
| 3162 | try block_scope.block_node.statements.push(assign); |
| 3163 | } |
| 3118 | 3164 | |
| 3119 | 3165 | const break_node = try transCreateNodeBreak(rp.c, block_scope.label); |
| 3120 | 3166 | break_node.rhs = ref_node; |
| 3121 | 3167 | try block_scope.block_node.statements.push(&break_node.base); |
| 3122 | 3168 | block_scope.block_node.rbrace = try appendToken(rp.c, .RBrace, "}"); |
| 3123 | 3169 | // semicolon must immediately follow rbrace because it is the last token in a block |
| 3124 | | _ = try appendToken(rp.c, .Semicolon, ";"); |
| 3170 | _ = try appendToken(rp.c, .Semicolon, ";4"); |
| 3125 | 3171 | const grouped_expr = try rp.c.a().create(ast.Node.GroupedExpression); |
| 3126 | 3172 | grouped_expr.* = .{ |
| 3127 | 3173 | .lparen = try appendToken(rp.c, .LParen, "("), |