| ... | ... | @@ -1596,6 +1596,11 @@ fn transBinaryOperator( |
| 1596 | 1596 | // @divExact(@bitCast(<platform-ptrdiff_t>, @intFromPtr(lhs) -% @intFromPtr(rhs)), @sizeOf(<lhs target type>)) |
| 1597 | 1597 | const ptrdiff_type = try transQualTypeIntWidthOf(c, qt, true); |
| 1598 | 1598 | |
| 1599 | const bitcast = try Tag.as.create(c.arena, .{ |
| 1600 | .lhs = ptrdiff_type, |
| 1601 | .rhs = try Tag.bit_cast.create(c.arena, infixOpNode), |
| 1602 | }); |
| 1603 | |
| 1599 | 1604 | // C standard requires that pointer subtraction operands are of the same type, |
| 1600 | 1605 | // otherwise it is undefined behavior. So we can assume the left and right |
| 1601 | 1606 | // sides are the same QualType and arbitrarily choose left. |
| ... | ... | @@ -1603,18 +1608,19 @@ fn transBinaryOperator( |
| 1603 | 1608 | const lhs_qt = getExprQualType(c, lhs_expr); |
| 1604 | 1609 | const lhs_qt_translated = try transQualType(c, scope, lhs_qt, lhs_expr.getBeginLoc()); |
| 1605 | 1610 | const c_pointer = getContainer(c, lhs_qt_translated).?; |
| 1606 | | const elem_type = c_pointer.castTag(.c_pointer).?.data.elem_type; |
| 1607 | | const sizeof = try Tag.sizeof.create(c.arena, elem_type); |
| 1608 | | |
| 1609 | | const bitcast = try Tag.as.create(c.arena, .{ |
| 1610 | | .lhs = ptrdiff_type, |
| 1611 | | .rhs = try Tag.bit_cast.create(c.arena, infixOpNode), |
| 1612 | | }); |
| 1613 | 1611 | |
| 1614 | | return Tag.div_exact.create(c.arena, .{ |
| 1615 | | .lhs = bitcast, |
| 1616 | | .rhs = sizeof, |
| 1617 | | }); |
| 1612 | if (c_pointer.castTag(.c_pointer)) |c_pointer_payload| { |
| 1613 | const sizeof = try Tag.sizeof.create(c.arena, c_pointer_payload.data.elem_type); |
| 1614 | return Tag.div_exact.create(c.arena, .{ |
| 1615 | .lhs = bitcast, |
| 1616 | .rhs = sizeof, |
| 1617 | }); |
| 1618 | } else { |
| 1619 | // This is an opaque/incomplete type. This subtraction exhibits Undefined Behavior by the C99 spec. |
| 1620 | // However, allowing subtraction on `void *` and function pointers is a commonly used extension. |
| 1621 | // So, just return the value in byte units, mirroring the behavior of this language extension as implemented by GCC and Clang. |
| 1622 | return bitcast; |
| 1623 | } |
| 1618 | 1624 | } |
| 1619 | 1625 | return infixOpNode; |
| 1620 | 1626 | } |