Commit d2535c003c
Changed files (2)
src
test
stage1
behavior
src/analyze.cpp
@@ -1131,17 +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))
+
+ // 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;
}
test/stage1/behavior/sizeof_and_typeof.zig
@@ -145,6 +145,26 @@ test "@sizeOf comparison against zero" {
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);
@@ -164,4 +184,6 @@ test "@sizeOf comparison against zero" {
// Container with ptr pointing to themselves
S.doTheTest(S0, true);
S.doTheTest(U0, true);
+ S.doTheTest(S1, true);
+ S.doTheTest(U1, true);
}