Commit e2a9f2ef98

raulgrell <raulgrell@gmail.com>
2018-08-27 17:37:37
Allow implicit cast from *T and [*]T to ?*c_void
1 parent c48be3a
Changed files (2)
src
test
cases
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