diff options
| author | raulgrell <raulgrell@gmail.com> | 2018-08-27 16:37:37 +0100 |
|---|---|---|
| committer | raulgrell <raulgrell@gmail.com> | 2018-08-27 23:13:57 +0100 |
| commit | e2a9f2ef988e6ff4ec9f943ead9285c67c56ffd7 (patch) | |
| tree | b61d37c78a9281d55959af5bf6de6d6a5412087a | |
| parent | c48be3a742cd82a8007512bfe145374e4b3750be (diff) | |
| download | zig-e2a9f2ef988e6ff4ec9f943ead9285c67c56ffd7.tar.gz zig-e2a9f2ef988e6ff4ec9f943ead9285c67c56ffd7.zip | |
Allow implicit cast from *T and [*]T to ?*c_void
| -rw-r--r-- | src/ir.cpp | 20 | ||||
| -rw-r--r-- | test/cases/cast.zig | 24 |
2 files changed, 40 insertions, 4 deletions
diff --git a/src/ir.cpp b/src/ir.cpp index 710456179c..b4af7f42e2 100644 --- a/src/ir.cpp +++ b/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, diff --git a/test/cases/cast.zig b/test/cases/cast.zig index df37bd1dd9..dde714b2be 100644 --- a/test/cases/cast.zig +++ b/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 |
