Skip to content

Commit 62065a9

Browse files
committed
translate-c: handle int to ptr and ptr to int casting
See #2451
1 parent a7346ea commit 62065a9

File tree

2 files changed

+52
-0
lines changed

2 files changed

+52
-0
lines changed

src/translate_c.cpp

+38
Original file line numberDiff line numberDiff line change
@@ -581,6 +581,33 @@ static bool qual_type_is_ptr(ZigClangQualType qt) {
581581
return ZigClangType_getTypeClass(ty) == ZigClangType_Pointer;
582582
}
583583

584+
static bool qual_type_is_int(ZigClangQualType qt) {
585+
const ZigClangType *ty = qual_type_canon(qt);
586+
if (ZigClangType_getTypeClass(ty) != ZigClangType_Builtin)
587+
return false;
588+
const clang::BuiltinType *builtin_ty = reinterpret_cast<const clang::BuiltinType*>(ty);
589+
switch (builtin_ty->getKind()) {
590+
case clang::BuiltinType::Char_U:
591+
case clang::BuiltinType::UChar:
592+
case clang::BuiltinType::Char_S:
593+
case clang::BuiltinType::Char8:
594+
case clang::BuiltinType::SChar:
595+
case clang::BuiltinType::UShort:
596+
case clang::BuiltinType::UInt:
597+
case clang::BuiltinType::ULong:
598+
case clang::BuiltinType::ULongLong:
599+
case clang::BuiltinType::Short:
600+
case clang::BuiltinType::Int:
601+
case clang::BuiltinType::Long:
602+
case clang::BuiltinType::LongLong:
603+
case clang::BuiltinType::UInt128:
604+
case clang::BuiltinType::Int128:
605+
return true;
606+
default:
607+
return false;
608+
}
609+
}
610+
584611
static const clang::FunctionProtoType *qual_type_get_fn_proto(ZigClangQualType qt, bool *is_ptr) {
585612
const ZigClangType *ty = qual_type_canon(qt);
586613
*is_ptr = false;
@@ -744,6 +771,17 @@ static AstNode* trans_c_cast(Context *c, ZigClangSourceLocation source_location,
744771
if (qual_type_is_ptr(dest_type) && qual_type_is_ptr(src_type)) {
745772
return trans_c_ptr_cast(c, source_location, dest_type, src_type, expr);
746773
}
774+
if (qual_type_is_int(dest_type) && qual_type_is_ptr(src_type)) {
775+
AstNode *addr_node = trans_create_node_builtin_fn_call_str(c, "ptrToInt");
776+
addr_node->data.fn_call_expr.params.append(expr);
777+
return trans_create_node_fn_call_1(c, trans_qual_type(c, dest_type, source_location), addr_node);
778+
}
779+
if (qual_type_is_int(src_type) && qual_type_is_ptr(dest_type)) {
780+
AstNode *ptr_node = trans_create_node_builtin_fn_call_str(c, "intToPtr");
781+
ptr_node->data.fn_call_expr.params.append(trans_qual_type(c, dest_type, source_location));
782+
ptr_node->data.fn_call_expr.params.append(expr);
783+
return ptr_node;
784+
}
747785
// TODO: maybe widen to increase size
748786
// TODO: maybe bitcast to change sign
749787
// TODO: maybe truncate to reduce size

test/translate_c.zig

+14
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,20 @@ const tests = @import("tests.zig");
22
const builtin = @import("builtin");
33

44
pub fn addCases(cases: *tests.TranslateCContext) void {
5+
cases.add("casting pointers to ints and ints to pointers",
6+
\\void foo(void);
7+
\\void bar(void) {
8+
\\ void *func_ptr = foo;
9+
\\ void (*typed_func_ptr)(void) = (void (*)(void)) (unsigned long) func_ptr;
10+
\\}
11+
,
12+
\\pub extern fn foo() void;
13+
\\pub fn bar() void {
14+
\\ var func_ptr: ?*c_void = @ptrCast(?*c_void, foo);
15+
\\ var typed_func_ptr: ?extern fn() void = @intToPtr(?extern fn() void, c_ulong(@ptrToInt(func_ptr)));
16+
\\}
17+
);
18+
519
if (builtin.os != builtin.Os.windows) {
620
// Windows treats this as an enum with type c_int
721
cases.add("big negative enum init values when C ABI supports long long enums",

0 commit comments

Comments
 (0)