Merge pull request #4561 from LemonBoy/fix-4536-1

Resend of #4552
This commit is contained in:
Andrew Kelley 2020-02-26 11:11:28 -05:00 committed by GitHub
commit c4a2734aa0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 68 additions and 8 deletions

View File

@ -1131,18 +1131,26 @@ Error type_val_resolve_zero_bits(CodeGen *g, ZigValue *type_val, ZigType *parent
Error err;
if (type_val->special != ConstValSpecialLazy) {
assert(type_val->special == ConstValSpecialStatic);
if ((type_val->data.x_type->id == ZigTypeIdStruct &&
type_val->data.x_type->data.structure.resolve_loop_flag_zero_bits) ||
(type_val->data.x_type->id == ZigTypeIdUnion &&
type_val->data.x_type->data.unionation.resolve_loop_flag_zero_bits) ||
type_val->data.x_type->id == ZigTypeIdPointer)
// Self-referencing types via pointers are allowed and have non-zero size
ZigType *ty = type_val->data.x_type;
while (ty->id == ZigTypeIdPointer &&
!ty->data.unionation.resolve_loop_flag_zero_bits)
{
ty = ty->data.pointer.child_type;
}
if ((ty->id == ZigTypeIdStruct && ty->data.structure.resolve_loop_flag_zero_bits) ||
(ty->id == ZigTypeIdUnion && ty->data.unionation.resolve_loop_flag_zero_bits) ||
(ty->id == ZigTypeIdPointer && ty->data.pointer.resolve_loop_flag_zero_bits))
{
// Does a struct/union which contains a pointer field to itself have bits? Yes.
*is_zero_bits = false;
return ErrorNone;
}
if ((err = type_resolve(g, type_val->data.x_type, ResolveStatusZeroBitsKnown)))
return err;
*is_zero_bits = (type_val->data.x_type->abi_size == 0);
return ErrorNone;
}

View File

@ -1,5 +1,7 @@
const builtin = @import("builtin");
const expect = @import("std").testing.expect;
const std = @import("std");
const builtin = std.builtin;
const expect = std.testing.expect;
const expectEqual = std.testing.expectEqual;
test "@sizeOf and @TypeOf" {
const y: @TypeOf(x) = 120;
@ -135,3 +137,53 @@ test "@bitSizeOf" {
a: u2
}) == 2);
}
test "@sizeOf comparison against zero" {
const S0 = struct {
f: *@This(),
};
const U0 = union {
f: *@This(),
};
const S1 = struct {
fn H(comptime T: type) type {
return struct {
x: T,
};
}
f0: H(*@This()),
f1: H(**@This()),
f2: H(***@This()),
};
const U1 = union {
fn H(comptime T: type) type {
return struct {
x: T,
};
}
f0: H(*@This()),
f1: H(**@This()),
f2: H(***@This()),
};
const S = struct {
fn doTheTest(comptime T: type, comptime result: bool) void {
expectEqual(result, @sizeOf(T) > 0);
}
};
// Zero-sized type
S.doTheTest(u0, false);
S.doTheTest(*u0, false);
// Non byte-sized type
S.doTheTest(u1, true);
S.doTheTest(*u1, true);
// Regular type
S.doTheTest(u8, true);
S.doTheTest(*u8, true);
S.doTheTest(f32, true);
S.doTheTest(*f32, true);
// Container with ptr pointing to themselves
S.doTheTest(S0, true);
S.doTheTest(U0, true);
S.doTheTest(S1, true);
S.doTheTest(U1, true);
}