| ... | ... | @@ -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)); |
| ... | ... | @@ -3018,6 +3018,8 @@ fn transCompoundAssignOperator(rp: RestorePoint, scope: *Scope, stmt: *const Zig |
| 3018 | 3018 | return transCreateCompoundAssign(rp, scope, stmt, .AssignSubWrap, .MinusPercentEqual, "-%=", .SubWrap, .MinusPercent, "-%", used) |
| 3019 | 3019 | else |
| 3020 | 3020 | return transCreateCompoundAssign(rp, scope, stmt, .AssignSub, .MinusPercentEqual, "-=", .Sub, .Minus, "-", used), |
| 3021 | .DivAssign => return transCreateCompoundAssign(rp, scope, stmt, .AssignDiv, .SlashEqual, "/=", .Div, .Slash, "/", used), |
| 3022 | .RemAssign => return transCreateCompoundAssign(rp, scope, stmt, .AssignMod, .PercentEqual, "%=", .Mod, .Percent, "%", used), |
| 3021 | 3023 | .ShlAssign => return transCreateCompoundAssign(rp, scope, stmt, .AssignBitShiftLeft, .AngleBracketAngleBracketLeftEqual, "<<=", .BitShiftLeft, .AngleBracketAngleBracketLeft, "<<", used), |
| 3022 | 3024 | .ShrAssign => return transCreateCompoundAssign(rp, scope, stmt, .AssignBitShiftRight, .AngleBracketAngleBracketRightEqual, ">>=", .BitShiftRight, .AngleBracketAngleBracketRight, ">>", used), |
| 3023 | 3025 | .AndAssign => return transCreateCompoundAssign(rp, scope, stmt, .AssignBitAnd, .AmpersandEqual, "&=", .BitAnd, .Ampersand, "&", used), |
| ... | ... | @@ -3046,13 +3048,37 @@ fn transCreateCompoundAssign( |
| 3046 | 3048 | used: ResultUsed, |
| 3047 | 3049 | ) TransError!*ast.Node { |
| 3048 | 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; |
| 3049 | 3053 | const lhs = ZigClangCompoundAssignOperator_getLHS(stmt); |
| 3050 | 3054 | const rhs = ZigClangCompoundAssignOperator_getRHS(stmt); |
| 3051 | 3055 | const loc = ZigClangCompoundAssignOperator_getBeginLoc(stmt); |
| 3056 | const is_signed = cIsSignedInteger(getExprQualType(rp.c, lhs)); |
| 3052 | 3057 | if (used == .unused) { |
| 3053 | 3058 | // common case |
| 3054 | 3059 | // c: lhs += rhs |
| 3055 | 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 | |
| 3056 | 3082 | const lhs_node = try transExpr(rp, scope, lhs, .used, .l_value); |
| 3057 | 3083 | const eq_token = try appendToken(rp.c, assign_tok_id, assign_bytes); |
| 3058 | 3084 | var rhs_node = if (is_shift) |
| ... | ... | @@ -3095,31 +3121,51 @@ fn transCreateCompoundAssign( |
| 3095 | 3121 | const lhs_node = try transCreateNodeIdentifier(rp.c, ref); |
| 3096 | 3122 | const ref_node = try transCreateNodePtrDeref(rp.c, lhs_node); |
| 3097 | 3123 | _ = try appendToken(rp.c, .Semicolon, ";"); |
| 3098 | | const bin_token = try appendToken(rp.c, bin_tok_id, bin_bytes); |
| 3099 | | var rhs_node = try transExpr(rp, scope, rhs, .used, .r_value); |
| 3100 | | if (is_shift) { |
| 3101 | | const cast_node = try transCreateNodeBuiltinFnCall(rp.c, "@intCast"); |
| 3102 | | const rhs_type = try qualTypeToLog2IntRef(rp, getExprQualType(rp.c, rhs), loc); |
| 3103 | | 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)); |
| 3104 | 3131 | _ = try appendToken(rp.c, .Comma, ","); |
| 3105 | | try cast_node.params.push(rhs_node); |
| 3106 | | cast_node.rparen_token = try appendToken(rp.c, .RParen, ")"); |
| 3107 | | rhs_node = &cast_node.base; |
| 3108 | | } |
| 3109 | | 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); |
| 3110 | 3146 | |
| 3111 | | _ = 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 | } |
| 3112 | 3156 | |
| 3113 | | const eq_token = try appendToken(rp.c, .Equal, "="); |
| 3114 | | const assign = try transCreateNodeInfixOp(rp, scope, ref_node, .Assign, eq_token, rhs_bin, .used, false); |
| 3115 | | 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 | } |
| 3116 | 3164 | |
| 3117 | 3165 | const break_node = try transCreateNodeBreak(rp.c, block_scope.label); |
| 3118 | 3166 | break_node.rhs = ref_node; |
| 3119 | 3167 | try block_scope.block_node.statements.push(&break_node.base); |
| 3120 | 3168 | block_scope.block_node.rbrace = try appendToken(rp.c, .RBrace, "}"); |
| 3121 | | // semicolon must immediately follow rbrace because it is the last token in a block |
| 3122 | | _ = try appendToken(rp.c, .Semicolon, ";"); |
| 3123 | 3169 | const grouped_expr = try rp.c.a().create(ast.Node.GroupedExpression); |
| 3124 | 3170 | grouped_expr.* = .{ |
| 3125 | 3171 | .lparen = try appendToken(rp.c, .LParen, "("), |