feature. See also
. The project being documented here (as the example) is the Zig library itself.
Translator.transPtrDiffExpr
fn transPtrDiffExpr(t: *Translator, scope: *Scope, bin: Node.Binary) TransError!ZigNode
File
Code
fn transPtrDiffExpr(t: *Translator, scope: *Scope, bin: Node.Binary) TransError!ZigNode {
const lhs_uncasted = try t.transExpr(scope, bin.lhs, .used);
const rhs_uncasted = try t.transExpr(scope, bin.rhs, .used);
const lhs = try ZigTag.int_from_ptr.create(t.arena, lhs_uncasted);
const rhs = try ZigTag.int_from_ptr.create(t.arena, rhs_uncasted);
const sub_res = try t.createBinOpNode(.sub_wrap, lhs, rhs);
const ptrdiff_type = try t.transTypeIntWidthOf(bin.qt, true);
const bitcast = try ZigTag.as.create(t.arena, .{
.lhs = ptrdiff_type,
.rhs = try ZigTag.bit_cast.create(t.arena, sub_res),
});
// otherwise it is undefined behavior. So we can assume the left and right
// sides are the same Type and arbitrarily choose left.
const lhs_ty = try t.transType(scope, bin.lhs.qt(t.tree), bin.lhs.tok(t.tree));
const c_pointer = t.getContainer(lhs_ty).?;
if (c_pointer.castTag(.c_pointer)) |c_pointer_payload| {
const sizeof = try ZigTag.sizeof.create(t.arena, c_pointer_payload.data.elem_type);
return ZigTag.div_exact.create(t.arena, .{
.lhs = bitcast,
.rhs = sizeof,
});
} else {
// However, allowing subtraction on `void *` and function pointers is a commonly used extension.
// So, just return the value in byte units, mirroring the behavior of this language extension as implemented by GCC and Clang.
return bitcast;
}
}