diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2019-05-26 17:55:20 -0400 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2019-05-26 17:55:20 -0400 |
| commit | df7aa9a4f0360945db999f6a6190290eb91d6351 (patch) | |
| tree | eef23c1ab9733469783fdcb2f1d45c37bf705d5f | |
| parent | 269a53b6afb052ec09f7b26db68219cfeaa0460e (diff) | |
| download | zig-df7aa9a4f0360945db999f6a6190290eb91d6351.tar.gz zig-df7aa9a4f0360945db999f6a6190290eb91d6351.zip | |
allow implicit optional pointer to optional c_void pointer
| -rw-r--r-- | src/ir.cpp | 25 | ||||
| -rw-r--r-- | test/stage1/behavior/ptrcast.zig | 8 |
2 files changed, 23 insertions, 10 deletions
diff --git a/src/ir.cpp b/src/ir.cpp index 3ab936d14c..42b1acc4df 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -11521,6 +11521,19 @@ static IrInstruction *ir_analyze_int_to_c_ptr(IrAnalyze *ira, IrInstruction *sou return ir_analyze_int_to_ptr(ira, source_instr, unsigned_integer, dest_type); } +static bool is_pointery_and_elem_is_not_pointery(ZigType *ty) { + if (ty->id == ZigTypeIdPointer) return ty->data.pointer.child_type->id != ZigTypeIdPointer; + if (ty->id == ZigTypeIdFn) return true; + if (ty->id == ZigTypeIdPromise) return true; + if (ty->id == ZigTypeIdOptional) { + ZigType *ptr_ty = ty->data.maybe.child_type; + if (ptr_ty->id == ZigTypeIdPointer) return ptr_ty->data.pointer.child_type->id != ZigTypeIdPointer; + if (ptr_ty->id == ZigTypeIdFn) return true; + if (ptr_ty->id == ZigTypeIdPromise) return true; + } + return false; +} + static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr, ZigType *wanted_type, IrInstruction *value) { @@ -11895,27 +11908,19 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst // cast from *T and [*]T to *c_void and ?*c_void // but don't do it if the actual type is a double pointer - if (actual_type->id == ZigTypeIdPointer && actual_type->data.pointer.child_type->id != ZigTypeIdPointer) { + if (is_pointery_and_elem_is_not_pointery(actual_type)) { ZigType *dest_ptr_type = nullptr; if (wanted_type->id == ZigTypeIdPointer && - wanted_type->data.pointer.ptr_len == PtrLenSingle && wanted_type->data.pointer.child_type == ira->codegen->builtin_types.entry_c_void) { dest_ptr_type = wanted_type; } else if (wanted_type->id == ZigTypeIdOptional && wanted_type->data.maybe.child_type->id == ZigTypeIdPointer && - wanted_type->data.maybe.child_type->data.pointer.ptr_len == PtrLenSingle && wanted_type->data.maybe.child_type->data.pointer.child_type == ira->codegen->builtin_types.entry_c_void) { dest_ptr_type = wanted_type->data.maybe.child_type; } - if (dest_ptr_type != nullptr && - (!actual_type->data.pointer.is_const || dest_ptr_type->data.pointer.is_const) && - (!actual_type->data.pointer.is_volatile || dest_ptr_type->data.pointer.is_volatile) && - actual_type->data.pointer.bit_offset_in_host == dest_ptr_type->data.pointer.bit_offset_in_host && - actual_type->data.pointer.host_int_bytes == dest_ptr_type->data.pointer.host_int_bytes && - get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, dest_ptr_type)) - { + if (dest_ptr_type != nullptr) { return ir_analyze_ptr_cast(ira, source_instr, value, wanted_type, source_instr, true); } } diff --git a/test/stage1/behavior/ptrcast.zig b/test/stage1/behavior/ptrcast.zig index c83b2f7327..87d559ac06 100644 --- a/test/stage1/behavior/ptrcast.zig +++ b/test/stage1/behavior/ptrcast.zig @@ -58,3 +58,11 @@ test "comptime ptrcast keeps larger alignment" { std.debug.assert(@typeOf(p) == [*]align(@alignOf(u32)) const u8); } } + +test "implicit optional pointer to optional c_void pointer" { + var buf: [4]u8 = "aoeu"; + var x: ?[*]u8 = &buf; + var y: ?*c_void = x; + var z = @ptrCast(*[4]u8, y); + expect(std.mem.eql(u8, z, "aoeu")); +} |
