From f8e63c458478022813a67bfd5ee64bfad6eee82e Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 31 Mar 2017 06:18:20 -0400 Subject: [PATCH] change `@bitcast` to `@ptrcast` See #290 --- doc/langref.md | 7 ++-- src/all_types.hpp | 8 ++--- src/codegen.cpp | 14 ++++---- src/ir.cpp | 72 +++++++++++++++++++------------------ src/ir_print.cpp | 14 +++++--- std/debug.zig | 2 +- std/hash_map.zig | 2 +- std/mem.zig | 2 +- std/os/linux.zig | 2 +- std/special/compiler_rt.zig | 24 ++++++------- test/cases/cast.zig | 2 +- test/cases/generics.zig | 2 +- test/cases/misc.zig | 8 ++--- test/cases/struct.zig | 2 +- test/run_tests.cpp | 12 +++++-- 15 files changed, 91 insertions(+), 82 deletions(-) diff --git a/doc/langref.md b/doc/langref.md index 529191bf26..991471c015 100644 --- a/doc/langref.md +++ b/doc/langref.md @@ -634,9 +634,6 @@ calls the public `panic` function exposed in the root source file, or if there is not one specified, invokes the one provided in `std/special/panic.zig`. -### @bitcast(comptime DestType: type, value: var) -> DestType +### @ptrcast(comptime DestType: type, value: var) -> DestType -Transmutes memory from one type to another without changing any bits. -The source and destination types must have the same size. This function -can be used to, for example, reinterpret a pointer, or convert a `f32` to a -`u32`. +Converts a pointer of one type to a pointer of another type. diff --git a/src/all_types.hpp b/src/all_types.hpp index 347654351c..7cf410faa4 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -1196,7 +1196,7 @@ enum BuiltinFnId { BuiltinFnIdSetGlobalSection, BuiltinFnIdSetGlobalLinkage, BuiltinFnIdPanic, - BuiltinFnIdBitCast, + BuiltinFnIdPtrCast, }; struct BuiltinFnEntry { @@ -1720,7 +1720,7 @@ enum IrInstructionId { IrInstructionIdFnProto, IrInstructionIdTestComptime, IrInstructionIdInitEnum, - IrInstructionIdBitCast, + IrInstructionIdPtrCast, IrInstructionIdWidenOrShorten, IrInstructionIdIntToPtr, IrInstructionIdPtrToInt, @@ -2370,11 +2370,11 @@ struct IrInstructionInitEnum { LLVMValueRef tmp_ptr; }; -struct IrInstructionBitCast { +struct IrInstructionPtrCast { IrInstruction base; IrInstruction *dest_type; - IrInstruction *target; + IrInstruction *ptr; }; struct IrInstructionWidenOrShorten { diff --git a/src/codegen.cpp b/src/codegen.cpp index 25290bc279..cbc0d4c0b0 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -1345,12 +1345,12 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable, zig_unreachable(); } -static LLVMValueRef ir_render_bitcast(CodeGen *g, IrExecutable *executable, - IrInstructionBitCast *instruction) +static LLVMValueRef ir_render_ptr_cast(CodeGen *g, IrExecutable *executable, + IrInstructionPtrCast *instruction) { TypeTableEntry *wanted_type = instruction->base.value.type; - LLVMValueRef target = ir_llvm_value(g, instruction->target); - return LLVMBuildBitCast(g->builder, target, wanted_type->type_ref, ""); + LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr); + return LLVMBuildBitCast(g->builder, ptr, wanted_type->type_ref, ""); } static LLVMValueRef ir_render_widen_or_shorten(CodeGen *g, IrExecutable *executable, @@ -2776,8 +2776,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, return ir_render_init_enum(g, executable, (IrInstructionInitEnum *)instruction); case IrInstructionIdStructInit: return ir_render_struct_init(g, executable, (IrInstructionStructInit *)instruction); - case IrInstructionIdBitCast: - return ir_render_bitcast(g, executable, (IrInstructionBitCast *)instruction); + case IrInstructionIdPtrCast: + return ir_render_ptr_cast(g, executable, (IrInstructionPtrCast *)instruction); case IrInstructionIdWidenOrShorten: return ir_render_widen_or_shorten(g, executable, (IrInstructionWidenOrShorten *)instruction); case IrInstructionIdPtrToInt: @@ -4260,7 +4260,7 @@ static void define_builtin_fns(CodeGen *g) { create_builtin_fn(g, BuiltinFnIdSetGlobalSection, "setGlobalSection", 2); create_builtin_fn(g, BuiltinFnIdSetGlobalLinkage, "setGlobalLinkage", 2); create_builtin_fn(g, BuiltinFnIdPanic, "panic", 1); - create_builtin_fn(g, BuiltinFnIdBitCast, "bitcast", 2); + create_builtin_fn(g, BuiltinFnIdPtrCast, "ptrcast", 2); } static void add_compile_var(CodeGen *g, const char *name, ConstExprValue *value) { diff --git a/src/ir.cpp b/src/ir.cpp index 0a0756f27a..06f761c8b0 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -480,8 +480,8 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionInitEnum *) { return IrInstructionIdInitEnum; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionBitCast *) { - return IrInstructionIdBitCast; +static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrCast *) { + return IrInstructionIdPtrCast; } static constexpr IrInstructionId ir_instruction_id(IrInstructionWidenOrShorten *) { @@ -1940,16 +1940,16 @@ static IrInstruction *ir_build_init_enum_from(IrBuilder *irb, IrInstruction *old return new_instruction; } -static IrInstruction *ir_build_bit_cast(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *dest_type, IrInstruction *target) +static IrInstruction *ir_build_ptr_cast(IrBuilder *irb, Scope *scope, AstNode *source_node, + IrInstruction *dest_type, IrInstruction *ptr) { - IrInstructionBitCast *instruction = ir_build_instruction( + IrInstructionPtrCast *instruction = ir_build_instruction( irb, scope, source_node); instruction->dest_type = dest_type; - instruction->target = target; + instruction->ptr = ptr; if (dest_type) ir_ref_instruction(dest_type, irb->current_basic_block); - ir_ref_instruction(target, irb->current_basic_block); + ir_ref_instruction(ptr, irb->current_basic_block); return &instruction->base; } @@ -2666,12 +2666,12 @@ static IrInstruction *ir_instruction_initenum_get_dep(IrInstructionInitEnum *ins } } -static IrInstruction *ir_instruction_bitcast_get_dep(IrInstructionBitCast *instruction, +static IrInstruction *ir_instruction_ptrcast_get_dep(IrInstructionPtrCast *instruction, size_t index) { switch (index) { case 0: return instruction->dest_type; - case 1: return instruction->target; + case 1: return instruction->ptr; default: return nullptr; } } @@ -2928,8 +2928,8 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t return ir_instruction_testcomptime_get_dep((IrInstructionTestComptime *) instruction, index); case IrInstructionIdInitEnum: return ir_instruction_initenum_get_dep((IrInstructionInitEnum *) instruction, index); - case IrInstructionIdBitCast: - return ir_instruction_bitcast_get_dep((IrInstructionBitCast *) instruction, index); + case IrInstructionIdPtrCast: + return ir_instruction_ptrcast_get_dep((IrInstructionPtrCast *) instruction, index); case IrInstructionIdWidenOrShorten: return ir_instruction_widenorshorten_get_dep((IrInstructionWidenOrShorten *) instruction, index); case IrInstructionIdIntToPtr: @@ -4200,7 +4200,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo return ir_build_panic(irb, scope, node, arg0_value); } - case BuiltinFnIdBitCast: + case BuiltinFnIdPtrCast: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); @@ -4212,7 +4212,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo if (arg1_value == irb->codegen->invalid_instruction) return arg1_value; - return ir_build_bit_cast(irb, scope, node, arg0_value, arg1_value); + return ir_build_ptr_cast(irb, scope, node, arg0_value, arg1_value); } } zig_unreachable(); @@ -12182,34 +12182,36 @@ static TypeTableEntry *ir_analyze_instruction_panic(IrAnalyze *ira, IrInstructio return ir_finish_anal(ira, ira->codegen->builtin_types.entry_unreachable); } -static TypeTableEntry *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstructionBitCast *instruction) { +static bool is_ptr_type(TypeTableEntry *t) { + return (t->id == TypeTableEntryIdPointer || t->id == TypeTableEntryIdFn || + (t->id == TypeTableEntryIdMaybe && (t->data.maybe.child_type->id == TypeTableEntryIdPointer || + t->data.maybe.child_type->id == TypeTableEntryIdFn))); +} + +static TypeTableEntry *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstructionPtrCast *instruction) { IrInstruction *dest_type_value = instruction->dest_type->other; TypeTableEntry *dest_type = ir_resolve_type(ira, dest_type_value); if (type_is_invalid(dest_type)) return ira->codegen->builtin_types.entry_invalid; - IrInstruction *target = instruction->target->other; - TypeTableEntry *src_type = target->value.type; + IrInstruction *ptr = instruction->ptr->other; + TypeTableEntry *src_type = ptr->value.type; if (type_is_invalid(src_type)) return ira->codegen->builtin_types.entry_invalid; - ensure_complete_type(ira->codegen, dest_type); - ensure_complete_type(ira->codegen, src_type); - - uint64_t dest_size_bytes = type_size(ira->codegen, dest_type); - uint64_t src_size_bytes = type_size(ira->codegen, src_type); - if (dest_size_bytes != src_size_bytes) { - ir_add_error(ira, &instruction->base, - buf_sprintf("destination type '%s' has size %" PRIu64 " but source type '%s' has size %" PRIu64, - buf_ptr(&dest_type->name), dest_size_bytes, - buf_ptr(&src_type->name), src_size_bytes)); + if (!is_ptr_type(src_type)) { + ir_add_error(ira, ptr, buf_sprintf("expected pointer, found '%s'", buf_ptr(&src_type->name))); return ira->codegen->builtin_types.entry_invalid; } - if (instr_is_comptime(target) && src_type->id == dest_type->id && - (src_type->id == TypeTableEntryIdPointer || src_type->id == TypeTableEntryIdMaybe)) - { - ConstExprValue *val = ir_resolve_const(ira, target, UndefOk); + if (!is_ptr_type(dest_type)) { + ir_add_error(ira, dest_type_value, + buf_sprintf("expected pointer, found '%s'", buf_ptr(&dest_type->name))); + return ira->codegen->builtin_types.entry_invalid; + } + + if (instr_is_comptime(ptr)) { + ConstExprValue *val = ir_resolve_const(ira, ptr, UndefOk); if (!val) return ira->codegen->builtin_types.entry_invalid; @@ -12219,8 +12221,8 @@ static TypeTableEntry *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruc return dest_type; } - IrInstruction *result = ir_build_bit_cast(&ira->new_irb, instruction->base.scope, - instruction->base.source_node, nullptr, target); + IrInstruction *result = ir_build_ptr_cast(&ira->new_irb, instruction->base.scope, + instruction->base.source_node, nullptr, ptr); ir_link_new_instruction(result, &instruction->base); result->value.type = dest_type; return dest_type; @@ -12464,8 +12466,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi return ir_analyze_instruction_decl_ref(ira, (IrInstructionDeclRef *)instruction); case IrInstructionIdPanic: return ir_analyze_instruction_panic(ira, (IrInstructionPanic *)instruction); - case IrInstructionIdBitCast: - return ir_analyze_instruction_bit_cast(ira, (IrInstructionBitCast *)instruction); + case IrInstructionIdPtrCast: + return ir_analyze_instruction_ptr_cast(ira, (IrInstructionPtrCast *)instruction); case IrInstructionIdMaybeWrap: case IrInstructionIdErrWrapCode: case IrInstructionIdErrWrapPayload: @@ -12637,7 +12639,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { case IrInstructionIdFnProto: case IrInstructionIdTestComptime: case IrInstructionIdInitEnum: - case IrInstructionIdBitCast: + case IrInstructionIdPtrCast: case IrInstructionIdWidenOrShorten: case IrInstructionIdPtrToInt: case IrInstructionIdIntToPtr: diff --git a/src/ir_print.cpp b/src/ir_print.cpp index 9446be43bd..7814064f85 100644 --- a/src/ir_print.cpp +++ b/src/ir_print.cpp @@ -765,9 +765,13 @@ static void ir_print_init_enum(IrPrint *irp, IrInstructionInitEnum *instruction) fprintf(irp->f, "}"); } -static void ir_print_bit_cast(IrPrint *irp, IrInstructionBitCast *instruction) { - fprintf(irp->f, "@bitcast("); - ir_print_other_instruction(irp, instruction->target); +static void ir_print_ptr_cast(IrPrint *irp, IrInstructionPtrCast *instruction) { + fprintf(irp->f, "@ptrcast("); + if (instruction->dest_type) { + ir_print_other_instruction(irp, instruction->dest_type); + } + fprintf(irp->f, ","); + ir_print_other_instruction(irp, instruction->ptr); fprintf(irp->f, ")"); } @@ -1098,8 +1102,8 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { case IrInstructionIdInitEnum: ir_print_init_enum(irp, (IrInstructionInitEnum *)instruction); break; - case IrInstructionIdBitCast: - ir_print_bit_cast(irp, (IrInstructionBitCast *)instruction); + case IrInstructionIdPtrCast: + ir_print_ptr_cast(irp, (IrInstructionPtrCast *)instruction); break; case IrInstructionIdWidenOrShorten: ir_print_widen_or_shorten(irp, (IrInstructionWidenOrShorten *)instruction); diff --git a/std/debug.zig b/std/debug.zig index cc0583dd45..7112ad0da2 100644 --- a/std/debug.zig +++ b/std/debug.zig @@ -74,7 +74,7 @@ pub fn writeStackTrace(out_stream: &io.OutStream) -> %void { const name = %return compile_unit.die.getAttrString(st, DW.AT_name); %return out_stream.printf("{} -> {}\n", return_address, name); - maybe_fp = *@bitcast(&const ?&const u8, fp); + maybe_fp = *@ptrcast(&const ?&const u8, fp); } }, ObjectFormat.coff => { diff --git a/std/hash_map.zig b/std/hash_map.zig index 5c2edb33b9..f7245ba107 100644 --- a/std/hash_map.zig +++ b/std/hash_map.zig @@ -236,7 +236,7 @@ test "basicHashMapTest" { } fn hash_i32(x: i32) -> u32 { - *@bitcast(&u32, &x) + *@ptrcast(&u32, &x) } fn eql_i32(a: i32, b: i32) -> bool { a == b diff --git a/std/mem.zig b/std/mem.zig index f118a280e1..438fdb88d0 100644 --- a/std/mem.zig +++ b/std/mem.zig @@ -78,7 +78,7 @@ pub const IncrementingAllocator = struct { fn alloc(allocator: &Allocator, n: usize) -> %[]u8 { // TODO //const self = @fieldParentPtr(IncrementingAllocator, "allocator", allocator); - const self = @bitcast(&IncrementingAllocator, allocator); + const self = @ptrcast(&IncrementingAllocator, allocator); const new_end_index = self.end_index + n; if (new_end_index > self.bytes.len) { return error.NoMem; diff --git a/std/os/linux.zig b/std/os/linux.zig index 0e616cfc53..a42bebe4c8 100644 --- a/std/os/linux.zig +++ b/std/os/linux.zig @@ -239,7 +239,7 @@ pub const AF_MAX = PF_MAX; /// Get the errno from a syscall return value, or 0 for no error. pub fn getErrno(r: usize) -> usize { - const signed_r = *@bitcast(&isize, &r); + const signed_r = *@ptrcast(&isize, &r); if (signed_r > -4096 and signed_r < 0) usize(-signed_r) else 0 } diff --git a/std/special/compiler_rt.zig b/std/special/compiler_rt.zig index f5c83becc7..1ad408beb9 100644 --- a/std/special/compiler_rt.zig +++ b/std/special/compiler_rt.zig @@ -15,7 +15,7 @@ export fn __udivdi3(a: du_int, b: du_int) -> du_int { fn du_int_to_udwords(x: du_int) -> udwords { @setDebugSafety(this, false); - return *@bitcast(&udwords, &x); + return *@ptrcast(&udwords, &x); } export fn __udivmoddi4(a: du_int, b: du_int, maybe_rem: ?&du_int) -> du_int { @@ -66,7 +66,7 @@ export fn __udivmoddi4(a: du_int, b: du_int, maybe_rem: ?&du_int) -> du_int { if (var rem ?= maybe_rem) { r[high] = n[high] % d[high]; r[low] = 0; - *rem = *@bitcast(&du_int, &r[0]); + *rem = *@ptrcast(&du_int, &r[0]); } return n[high] / d[high]; } @@ -78,7 +78,7 @@ export fn __udivmoddi4(a: du_int, b: du_int, maybe_rem: ?&du_int) -> du_int { if (var rem ?= maybe_rem) { r[low] = n[low]; r[high] = n[high] & (d[high] - 1); - *rem = *@bitcast(&du_int, &r[0]); + *rem = *@ptrcast(&du_int, &r[0]); } return n[high] >> @ctz(d[high]); } @@ -89,7 +89,7 @@ export fn __udivmoddi4(a: du_int, b: du_int, maybe_rem: ?&du_int) -> du_int { // 0 <= sr <= n_uword_bits - 2 or sr large if (sr > n_uword_bits - 2) { if (var rem ?= maybe_rem) { - *rem = *@bitcast(&du_int, &n[0]); + *rem = *@ptrcast(&du_int, &n[0]); } return 0; } @@ -113,12 +113,12 @@ export fn __udivmoddi4(a: du_int, b: du_int, maybe_rem: ?&du_int) -> du_int { *rem = n[low] & (d[low] - 1); } if (d[low] == 1) { - return *@bitcast(&du_int, &n[0]); + return *@ptrcast(&du_int, &n[0]); } sr = @ctz(d[low]); q[high] = n[high] >> sr; q[low] = (n[high] << (n_uword_bits - sr)) | (n[low] >> sr); - return *@bitcast(&du_int, &q[0]); + return *@ptrcast(&du_int, &q[0]); } // K X // --- @@ -154,7 +154,7 @@ export fn __udivmoddi4(a: du_int, b: du_int, maybe_rem: ?&du_int) -> du_int { // 0 <= sr <= n_uword_bits - 1 or sr large if (sr > n_uword_bits - 1) { if (var rem ?= maybe_rem) { - *rem = *@bitcast(&du_int, &n[0]); + *rem = *@ptrcast(&du_int, &n[0]); } return 0; } @@ -191,17 +191,17 @@ export fn __udivmoddi4(a: du_int, b: du_int, maybe_rem: ?&du_int) -> du_int { // r.all -= d.all; // carry = 1; // } - const s: di_int = (di_int)(*@bitcast(&du_int, &d[0]) - *@bitcast(&du_int, &r[0]) - 1) >> (n_udword_bits - 1); + const s: di_int = (di_int)(*@ptrcast(&du_int, &d[0]) - *@ptrcast(&du_int, &r[0]) - 1) >> (n_udword_bits - 1); carry = su_int(s & 1); - *@bitcast(&du_int, &r[0]) -= *@bitcast(&du_int, &d[0]) & u64(s); + *@ptrcast(&du_int, &r[0]) -= *@ptrcast(&du_int, &d[0]) & u64(s); sr -= 1; } - *@bitcast(&du_int, &q[0]) = (*@bitcast(&du_int, &q[0]) << 1) | u64(carry); + *@ptrcast(&du_int, &q[0]) = (*@ptrcast(&du_int, &q[0]) << 1) | u64(carry); if (var rem ?= maybe_rem) { - *rem = *@bitcast(&du_int, &r[0]); + *rem = *@ptrcast(&du_int, &r[0]); } - return *@bitcast(&du_int, &q[0]); + return *@ptrcast(&du_int, &q[0]); } export fn __umoddi3(a: du_int, b: du_int) -> du_int { diff --git a/test/cases/cast.zig b/test/cases/cast.zig index 7f97e6660b..030dd68150 100644 --- a/test/cases/cast.zig +++ b/test/cases/cast.zig @@ -15,7 +15,7 @@ test "numLitIntToPtrCast" { test "pointerReinterpretConstFloatToInt" { const float: f64 = 5.99999999999994648725e-01; const float_ptr = &float; - const int_ptr = @bitcast(&i32, float_ptr); + const int_ptr = @ptrcast(&i32, float_ptr); const int_val = *int_ptr; assert(int_val == 858993411); } diff --git a/test/cases/generics.zig b/test/cases/generics.zig index 68637c614b..dfae572054 100644 --- a/test/cases/generics.zig +++ b/test/cases/generics.zig @@ -121,5 +121,5 @@ test "genericFnWithImplicitCast" { } fn getByte(ptr: ?&const u8) -> u8 {*??ptr} fn getFirstByte(comptime T: type, mem: []const T) -> u8 { - getByte(@bitcast(&const u8, &mem[0])) + getByte(@ptrcast(&const u8, &mem[0])) } diff --git a/test/cases/misc.zig b/test/cases/misc.zig index 81b9db3a24..b9dc2de536 100644 --- a/test/cases/misc.zig +++ b/test/cases/misc.zig @@ -246,15 +246,15 @@ test "typeEquality" { const global_a: i32 = 1234; const global_b: &const i32 = &global_a; -const global_c: &const f32 = @bitcast(&const f32, global_b); +const global_c: &const f32 = @ptrcast(&const f32, global_b); test "compileTimeGlobalReinterpret" { - const d = @bitcast(&const i32, global_c); + const d = @ptrcast(&const i32, global_c); assert(*d == 1234); } test "explicitCastMaybePointers" { const a: ?&i32 = undefined; - const b: ?&f32 = @bitcast(?&f32, a); + const b: ?&f32 = @ptrcast(?&f32, a); } test "genericMallocFree" { @@ -263,7 +263,7 @@ test "genericMallocFree" { } const some_mem : [100]u8 = undefined; fn memAlloc(comptime T: type, n: usize) -> %[]T { - return @bitcast(&T, &some_mem[0])[0...n]; + return @ptrcast(&T, &some_mem[0])[0...n]; } fn memFree(comptime T: type, memory: []T) { } diff --git a/test/cases/struct.zig b/test/cases/struct.zig index bd69177d4f..2cecef0078 100644 --- a/test/cases/struct.zig +++ b/test/cases/struct.zig @@ -41,7 +41,7 @@ const VoidStructFieldsFoo = struct { test "fn" { var foo: StructFoo = undefined; - @memset(@bitcast(&u8, &foo), 0, @sizeOf(StructFoo)); + @memset(@ptrcast(&u8, &foo), 0, @sizeOf(StructFoo)); foo.a += 1; foo.b = foo.a == 1; testFoo(foo); diff --git a/test/run_tests.cpp b/test/run_tests.cpp index b82431fae1..e56d6625c7 100644 --- a/test/run_tests.cpp +++ b/test/run_tests.cpp @@ -460,8 +460,8 @@ const foo : i32 = 0; const c = @cImport(@cInclude("stdlib.h")); export fn compare_fn(a: ?&const c_void, b: ?&const c_void) -> c_int { - const a_int = @bitcast(&i32, a ?? unreachable); - const b_int = @bitcast(&i32, b ?? unreachable); + const a_int = @ptrcast(&i32, a ?? unreachable); + const b_int = @ptrcast(&i32, b ?? unreachable); if (*a_int < *b_int) { -1 } else if (*a_int > *b_int) { @@ -474,7 +474,7 @@ export fn compare_fn(a: ?&const c_void, b: ?&const c_void) -> c_int { export fn main(args: c_int, argv: &&u8) -> c_int { var array = []u32 { 1, 7, 3, 2, 0, 9, 4, 8, 6, 5 }; - c.qsort(@bitcast(&c_void, &array[0]), c_ulong(array.len), @sizeOf(i32), compare_fn); + c.qsort(@ptrcast(&c_void, &array[0]), c_ulong(array.len), @sizeOf(i32), compare_fn); for (array) |item, i| { if (item != i) { @@ -1812,6 +1812,12 @@ export fn entry() { foo(global_array); } )SOURCE", 1, ".tmp_source.zig:5:9: error: expected type '[]i32', found '[10]i32'"); + + add_compile_fail_case("ptrcast to non-pointer", R"SOURCE( +export fn entry(a: &i32) -> usize { + return @ptrcast(usize, a); +} + )SOURCE", 1, ".tmp_source.zig:3:21: error: expected pointer, found 'usize'"); } //////////////////////////////////////////////////////////////////////////////