Commit e2a9f2ef98
src/ir.cpp
@@ -60,7 +60,7 @@ enum ConstCastResultId {
ConstCastResultIdType,
ConstCastResultIdUnresolvedInferredErrSet,
ConstCastResultIdAsyncAllocatorType,
- ConstCastResultIdNullWrapPtr,
+ ConstCastResultIdNullWrapPtr
};
struct ConstCastOnly;
@@ -8471,9 +8471,9 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, TypeTableEntry
if (wanted_type == actual_type)
return result;
- // * and [*] can do a const-cast-only to ?* and ?[*], respectively
- // but not if there is a mutable parent pointer
- // and not if the pointer is zero bits
+ // *T and [*]T may const-cast-only to ?*U and ?[*]U, respectively
+ // but not if we want a mutable pointer
+ // and not if the actual pointer has zero bits
if (!wanted_is_mutable && wanted_type->id == TypeTableEntryIdOptional &&
wanted_type->data.maybe.child_type->id == TypeTableEntryIdPointer &&
actual_type->id == TypeTableEntryIdPointer && type_has_bits(actual_type))
@@ -8488,6 +8488,18 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, TypeTableEntry
return result;
}
+ // *T and [*]T can always cast to ?*c_void
+ if (wanted_type->id == TypeTableEntryIdPointer &&
+ wanted_type->data.pointer.ptr_len == PtrLenSingle &&
+ wanted_type->data.pointer.child_type == g->builtin_types.entry_c_void &&
+ actual_type->id == TypeTableEntryIdPointer &&
+ (!actual_type->data.pointer.is_const || wanted_type->data.pointer.is_const) &&
+ (!actual_type->data.pointer.is_volatile || wanted_type->data.pointer.is_volatile))
+ {
+ assert(actual_type->data.pointer.alignment >= wanted_type->data.pointer.alignment);
+ return result;
+ }
+
// pointer const
if (wanted_type->id == TypeTableEntryIdPointer && actual_type->id == TypeTableEntryIdPointer) {
ConstCastOnly child = types_match_const_cast_only(ira, wanted_type->data.pointer.child_type,
test/cases/cast.zig
@@ -495,4 +495,28 @@ test "implicit cast from *[N]T to ?[*]T" {
x.?[0] = 8;
y[3] = 6;
assert(std.mem.eql(u16, x.?[0..4], y[0..4]));
+}
+
+test "implicit cast from *T to ?*c_void" {
+ var a: u8 = 1;
+ incrementVoidPtrValue(&a);
+ std.debug.assert(a == 2);
+}
+
+fn incrementVoidPtrValue(value: ?*c_void) void {
+ @ptrCast(*u8, value.?).* += 1;
+}
+
+test "implicit cast from [*]T to ?*c_void" {
+ var a = []u8{3, 2, 1};
+ incrementVoidPtrArray(a[0..].ptr, 3);
+ std.debug.assert(std.mem.eql(u8, a, []u8{4, 3, 2}));
+}
+
+fn incrementVoidPtrArray(array: ?*c_void, len: usize) void {
+ var n: usize = 0;
+ while(n < len) : (n += 1) {
+ std.debug.warn("{}", n);
+ @ptrCast([*]u8, array.?)[n] += 1;
+ }
}
\ No newline at end of file