aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVeikka Tuominen <git@vexu.eu>2022-10-05 15:06:14 +0300
committerVeikka Tuominen <git@vexu.eu>2022-10-06 20:09:45 +0300
commit94039d66ed4fecb7defc5deeeedd7afa3b773f0c (patch)
tree59e0c2a2033972bdf2ba22a76db7b1236a82dcc5
parentcc89908e826882065eeaa23bb8827fb7d7cd6219 (diff)
downloadzig-94039d66ed4fecb7defc5deeeedd7afa3b773f0c.tar.gz
zig-94039d66ed4fecb7defc5deeeedd7afa3b773f0c.zip
Sema: disallow fieldParentPtr and offsetOf on comptime fields
Comptime fields are tied to the type and behave more like declarations so these operations cannot return anything useful for them.
-rw-r--r--src/Sema.zig8
-rw-r--r--src/type.zig22
-rw-r--r--test/cases/compile_errors/fieldParentPtr_on_comptime_field.zig16
3 files changed, 46 insertions, 0 deletions
diff --git a/src/Sema.zig b/src/Sema.zig
index 7b9f7da769..f2b3cee3e3 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -18749,6 +18749,10 @@ fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u6
break :blk try sema.tupleFieldIndex(block, ty, field_name, rhs_src);
} else try sema.structFieldIndex(block, ty, field_name, rhs_src);
+ if (ty.structFieldIsComptime(field_index)) {
+ return sema.fail(block, src, "no offset available for comptime field", .{});
+ }
+
switch (ty.containerLayout()) {
.Packed => {
var bit_sum: u64 = 0;
@@ -20132,6 +20136,10 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
break :blk try sema.tupleFieldIndex(block, struct_ty, field_name, name_src);
} else try sema.structFieldIndex(block, struct_ty, field_name, name_src);
+ if (struct_ty.structFieldIsComptime(field_index)) {
+ return sema.fail(block, src, "cannot get @fieldParentPtr of a comptime field", .{});
+ }
+
try sema.checkPtrOperand(block, ptr_src, field_ptr_ty);
const field_ptr_ty_info = field_ptr_ty.ptrInfo().data;
diff --git a/src/type.zig b/src/type.zig
index 1fef525062..7c35eccbe6 100644
--- a/src/type.zig
+++ b/src/type.zig
@@ -5664,6 +5664,28 @@ pub const Type = extern union {
}
}
+ pub fn structFieldIsComptime(ty: Type, index: usize) bool {
+ switch (ty.tag()) {
+ .@"struct" => {
+ const struct_obj = ty.castTag(.@"struct").?.data;
+ if (struct_obj.layout == .Packed) return false;
+ const field = struct_obj.fields.values()[index];
+ return field.is_comptime;
+ },
+ .tuple => {
+ const tuple = ty.castTag(.tuple).?.data;
+ const val = tuple.values[index];
+ return val.tag() != .unreachable_value;
+ },
+ .anon_struct => {
+ const anon_struct = ty.castTag(.anon_struct).?.data;
+ const val = anon_struct.values[index];
+ return val.tag() != .unreachable_value;
+ },
+ else => unreachable,
+ }
+ }
+
pub fn packedStructFieldByteOffset(ty: Type, field_index: usize, target: Target) u32 {
const struct_obj = ty.castTag(.@"struct").?.data;
assert(struct_obj.layout == .Packed);
diff --git a/test/cases/compile_errors/fieldParentPtr_on_comptime_field.zig b/test/cases/compile_errors/fieldParentPtr_on_comptime_field.zig
new file mode 100644
index 0000000000..fb95ea691c
--- /dev/null
+++ b/test/cases/compile_errors/fieldParentPtr_on_comptime_field.zig
@@ -0,0 +1,16 @@
+const T = struct {
+ comptime a: u32 = 2,
+};
+pub export fn entry1() void {
+ @offsetOf(T, "a");
+}
+pub export fn entry2() void {
+ @fieldParentPtr(T, "a", undefined);
+}
+
+// error
+// backend=stage2
+// target=native
+//
+// :5:5: error: no offset available for comptime field
+// :8:5: error: cannot get @fieldParentPtr of a comptime field