@@ -3416,19 +3416,12 @@ fn indexablePtrLenOrNone(
3416
3416
sema: *Sema,
3417
3417
block: *Block,
3418
3418
src: LazySrcLoc,
3419
- object : Air.Inst.Ref,
3419
+ operand : Air.Inst.Ref,
3420
3420
) CompileError!Air.Inst.Ref {
3421
- const object_ty = sema.typeOf(object);
3422
- const indexable_ty = t: {
3423
- const ptr_size = object_ty.ptrSizeOrNull() orelse break :t object_ty;
3424
- break :t switch (ptr_size) {
3425
- .Many => return .none,
3426
- .One => object_ty.childType(),
3427
- else => object_ty,
3428
- };
3429
- };
3430
- try checkIndexable(sema, block, src, indexable_ty);
3431
- return sema.fieldVal(block, src, object, "len", src);
3421
+ const operand_ty = sema.typeOf(operand);
3422
+ try checkMemOperand(sema, block, src, operand_ty);
3423
+ if (operand_ty.ptrSize() == .Many) return .none;
3424
+ return sema.fieldVal(block, src, operand, "len", src);
3432
3425
}
3433
3426
3434
3427
fn zirAllocExtended(
@@ -22080,19 +22073,25 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
22080
22073
const src_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };
22081
22074
const dest_ptr = try sema.resolveInst(extra.lhs);
22082
22075
const src_ptr = try sema.resolveInst(extra.rhs);
22076
+ const dest_ty = sema.typeOf(dest_ptr);
22077
+ const src_ty = sema.typeOf(src_ptr);
22083
22078
const dest_len = try indexablePtrLenOrNone(sema, block, dest_src, dest_ptr);
22084
22079
const src_len = try indexablePtrLenOrNone(sema, block, src_src, src_ptr);
22085
22080
const target = sema.mod.getTarget();
22086
22081
22082
+ if (dest_ty.isConstPtr()) {
22083
+ return sema.fail(block, dest_src, "cannot memcpy to constant pointer", .{});
22084
+ }
22085
+
22087
22086
if (dest_len == .none and src_len == .none) {
22088
22087
const msg = msg: {
22089
22088
const msg = try sema.errMsg(block, src, "unknown @memcpy length", .{});
22090
22089
errdefer msg.destroy(sema.gpa);
22091
22090
try sema.errNote(block, dest_src, msg, "destination type '{}' provides no length", .{
22092
- sema.typeOf(dest_ptr) .fmt(sema.mod),
22091
+ dest_ty .fmt(sema.mod),
22093
22092
});
22094
22093
try sema.errNote(block, src_src, msg, "source type '{}' provides no length", .{
22095
- sema.typeOf(src_ptr) .fmt(sema.mod),
22094
+ src_ty .fmt(sema.mod),
22096
22095
});
22097
22096
break :msg msg;
22098
22097
};
@@ -22130,6 +22129,14 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
22130
22129
const ok = try block.addBinOp(.cmp_eq, dest_len, src_len);
22131
22130
try sema.addSafetyCheck(block, ok, .memcpy_len_mismatch);
22132
22131
}
22132
+ } else if (dest_len != .none) {
22133
+ if (try sema.resolveDefinedValue(block, dest_src, dest_len)) |dest_len_val| {
22134
+ len_val = dest_len_val;
22135
+ }
22136
+ } else if (src_len != .none) {
22137
+ if (try sema.resolveDefinedValue(block, src_src, src_len)) |src_len_val| {
22138
+ len_val = src_len_val;
22139
+ }
22133
22140
}
22134
22141
22135
22142
const runtime_src = if (try sema.resolveDefinedValue(block, dest_src, dest_ptr)) |dest_ptr_val| rs: {
@@ -22139,7 +22146,7 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
22139
22146
const len = try sema.usizeCast(block, dest_src, len_u64);
22140
22147
for (0..len) |i| {
22141
22148
const elem_index = try sema.addIntUnsigned(Type.usize, i);
22142
- const dest_elem_ptr = try sema.elemPtr (
22149
+ const dest_elem_ptr = try sema.elemPtrOneLayerOnly (
22143
22150
block,
22144
22151
src,
22145
22152
dest_ptr,
@@ -22148,7 +22155,7 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
22148
22155
true, // init
22149
22156
false, // oob_safety
22150
22157
);
22151
- const src_elem_ptr = try sema.elemPtr (
22158
+ const src_elem_ptr = try sema.elemPtrOneLayerOnly (
22152
22159
block,
22153
22160
src,
22154
22161
src_ptr,
@@ -22172,9 +22179,6 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
22172
22179
} else break :rs src_src;
22173
22180
} else dest_src;
22174
22181
22175
- const dest_ty = sema.typeOf(dest_ptr);
22176
- const src_ty = sema.typeOf(src_ptr);
22177
-
22178
22182
// If in-memory coercion is not allowed, explode this memcpy call into a
22179
22183
// for loop that copies element-wise.
22180
22184
// Likewise if this is an iterable rather than a pointer, do the same
@@ -22213,6 +22217,10 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
22213
22217
if (new_src_ptr_ty.isSlice()) {
22214
22218
new_src_ptr = try sema.analyzeSlicePtr(block, src_src, new_src_ptr, new_src_ptr_ty);
22215
22219
}
22220
+ } else if (dest_len == .none and len_val == null) {
22221
+ // Change the dest to a slice, since its type must have the length.
22222
+ const dest_ptr_ptr = try sema.analyzeRef(block, dest_src, new_dest_ptr);
22223
+ new_dest_ptr = try sema.analyzeSlice(block, dest_src, dest_ptr_ptr, .zero, src_len, .none, .unneeded, dest_src, dest_src, dest_src, false);
22216
22224
}
22217
22225
22218
22226
try sema.requireRuntimeBlock(block, src, runtime_src);
@@ -22262,7 +22270,11 @@ fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
22262
22270
const dest_ptr = try sema.resolveInst(extra.lhs);
22263
22271
const uncoerced_elem = try sema.resolveInst(extra.rhs);
22264
22272
const dest_ptr_ty = sema.typeOf(dest_ptr);
22265
- try checkIndexable(sema, block, dest_src, dest_ptr_ty);
22273
+ try checkMemOperand(sema, block, dest_src, dest_ptr_ty);
22274
+
22275
+ if (dest_ptr_ty.isConstPtr()) {
22276
+ return sema.fail(block, dest_src, "cannot memset constant pointer", .{});
22277
+ }
22266
22278
22267
22279
const dest_elem_ty = dest_ptr_ty.elemType2();
22268
22280
const target = sema.mod.getTarget();
@@ -31100,6 +31112,27 @@ fn checkIndexable(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void {
31100
31112
}
31101
31113
}
31102
31114
31115
+ fn checkMemOperand(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void {
31116
+ if (ty.zigTypeTag() == .Pointer) {
31117
+ switch (ty.ptrSize()) {
31118
+ .Slice, .Many, .C => return,
31119
+ .One => {
31120
+ const elem_ty = ty.childType();
31121
+ if (elem_ty.zigTypeTag() == .Array) return;
31122
+ // TODO https://github.com/ziglang/zig/issues/15479
31123
+ // if (elem_ty.isTuple()) return;
31124
+ },
31125
+ }
31126
+ }
31127
+ const msg = msg: {
31128
+ const msg = try sema.errMsg(block, src, "type '{}' is not an indexable pointer", .{ty.fmt(sema.mod)});
31129
+ errdefer msg.destroy(sema.gpa);
31130
+ try sema.errNote(block, src, msg, "operand must be a slice, a many pointer or a pointer to an array", .{});
31131
+ break :msg msg;
31132
+ };
31133
+ return sema.failWithOwnedErrorMsg(msg);
31134
+ }
31135
+
31103
31136
fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void {
31104
31137
const resolved_ty = try sema.resolveTypeFields(ty);
31105
31138
const union_obj = resolved_ty.cast(Type.Payload.Union).?.data;
0 commit comments