Skip to content

Commit 6f05e8d

Browse files
committed
implicit casting between C pointer and optional non-C pointer
See #1059
1 parent 285e2f6 commit 6f05e8d

File tree

2 files changed

+31
-13
lines changed

2 files changed

+31
-13
lines changed

src/ir.cpp

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
101+
test "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+
}

0 commit comments

Comments
 (0)