authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-02-12 01:38:11-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-02-12 01:38:11-05:00
log6f05e8d1be083a429673e717e8b3c736c7ddb8d2
tree3b4004ef1afaab617282b33eff3a4a45729c0f23
parent285e2f62ba0648d6d8e7ff64d1ee7d2900481e2f
signature Commit is signed but in an unrecognized format.

implicit casting between C pointer and optional non-C pointer

See #1059

2 files changed, 31 insertions(+), 13 deletions(-)

src/ir.cpp+21-13
......@@ -8669,33 +8669,41 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
86698669 }
86708670
86718671 // pointer const
8672 if (wanted_type->id == ZigTypeIdPointer && actual_type->id == ZigTypeIdPointer) {
8673 ConstCastOnly child = types_match_const_cast_only(ira, wanted_type->data.pointer.child_type,
8674 actual_type->data.pointer.child_type, source_node, !wanted_type->data.pointer.is_const);
8672 ZigType *wanted_ptr_type = get_src_ptr_type(wanted_type);
8673 ZigType *actual_ptr_type = get_src_ptr_type(actual_type);
8674 bool wanted_is_c_ptr = wanted_type->id == ZigTypeIdPointer && wanted_type->data.pointer.ptr_len == PtrLenC;
8675 bool actual_is_c_ptr = actual_type->id == ZigTypeIdPointer && actual_type->data.pointer.ptr_len == PtrLenC;
8676 if ((wanted_type->id == ZigTypeIdPointer && actual_type->id == ZigTypeIdPointer) ||
8677 (wanted_ptr_type != nullptr && actual_is_c_ptr) ||
8678 (actual_ptr_type != nullptr && wanted_is_c_ptr))
8679 {
8680 ConstCastOnly child = types_match_const_cast_only(ira, wanted_ptr_type->data.pointer.child_type,
8681 actual_ptr_type->data.pointer.child_type, source_node, !wanted_ptr_type->data.pointer.is_const);
86758682 if (child.id == ConstCastResultIdInvalid)
86768683 return child;
86778684 if (child.id != ConstCastResultIdOk) {
86788685 result.id = ConstCastResultIdPointerChild;
86798686 result.data.pointer_mismatch = allocate_nonzero<ConstCastPointerMismatch>(1);
86808687 result.data.pointer_mismatch->child = child;
8681 result.data.pointer_mismatch->wanted_child = wanted_type->data.pointer.child_type;
8682 result.data.pointer_mismatch->actual_child = actual_type->data.pointer.child_type;
8688 result.data.pointer_mismatch->wanted_child = wanted_ptr_type->data.pointer.child_type;
8689 result.data.pointer_mismatch->actual_child = actual_ptr_type->data.pointer.child_type;
86838690 return result;
86848691 }
8685 if ((err = type_resolve(g, actual_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) {
8692 if ((err = type_resolve(g, actual_ptr_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) {
86868693 result.id = ConstCastResultIdInvalid;
86878694 return result;
86888695 }
8689 if ((err = type_resolve(g, wanted_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) {
8696 if ((err = type_resolve(g, wanted_ptr_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) {
86908697 result.id = ConstCastResultIdInvalid;
86918698 return result;
86928699 }
8693 if ((actual_type->data.pointer.ptr_len == wanted_type->data.pointer.ptr_len) &&
8694 (!actual_type->data.pointer.is_const || wanted_type->data.pointer.is_const) &&
8695 (!actual_type->data.pointer.is_volatile || wanted_type->data.pointer.is_volatile) &&
8696 actual_type->data.pointer.bit_offset_in_host == wanted_type->data.pointer.bit_offset_in_host &&
8697 actual_type->data.pointer.host_int_bytes == wanted_type->data.pointer.host_int_bytes &&
8698 get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, wanted_type))
8700 bool ptr_lens_equal = actual_ptr_type->data.pointer.ptr_len == wanted_ptr_type->data.pointer.ptr_len;
8701 if ((ptr_lens_equal || wanted_is_c_ptr || actual_is_c_ptr) &&
8702 (!actual_ptr_type->data.pointer.is_const || wanted_ptr_type->data.pointer.is_const) &&
8703 (!actual_ptr_type->data.pointer.is_volatile || wanted_ptr_type->data.pointer.is_volatile) &&
8704 actual_ptr_type->data.pointer.bit_offset_in_host == wanted_ptr_type->data.pointer.bit_offset_in_host &&
8705 actual_ptr_type->data.pointer.host_int_bytes == wanted_ptr_type->data.pointer.host_int_bytes &&
8706 get_ptr_align(ira->codegen, actual_ptr_type) >= get_ptr_align(ira->codegen, wanted_ptr_type))
86998707 {
87008708 return result;
87018709 }
test/stage1/behavior/pointers.zig+10
......@@ -97,3 +97,13 @@ test "peer type resolution with C pointers" {
9797 expect(@typeOf(x3) == [*c]u8);
9898 expect(@typeOf(x4) == [*c]u8);
9999}
100
101test "implicit casting between C pointer and optional non-C pointer" {
102 var slice: []const u8 = "aoeu";
103 const opt_many_ptr: ?[*]const u8 = slice.ptr;
104 var ptr_opt_many_ptr = &opt_many_ptr;
105 var c_ptr: [*c]const [*c]const u8 = ptr_opt_many_ptr;
106 expect(c_ptr.*.* == 'a');
107 ptr_opt_many_ptr = c_ptr;
108 expect(ptr_opt_many_ptr.*.?[1] == 'o');
109}