translate-c: handle int to ptr and ptr to int casting

See #2451
This commit is contained in:
Andrew Kelley 2019-05-09 12:17:23 -04:00
parent a7346ea49f
commit 62065a9aea
No known key found for this signature in database
GPG Key ID: 7C5F548F728501A9
2 changed files with 52 additions and 0 deletions

View File

@ -581,6 +581,33 @@ static bool qual_type_is_ptr(ZigClangQualType qt) {
return ZigClangType_getTypeClass(ty) == ZigClangType_Pointer;
}
static bool qual_type_is_int(ZigClangQualType qt) {
const ZigClangType *ty = qual_type_canon(qt);
if (ZigClangType_getTypeClass(ty) != ZigClangType_Builtin)
return false;
const clang::BuiltinType *builtin_ty = reinterpret_cast<const clang::BuiltinType*>(ty);
switch (builtin_ty->getKind()) {
case clang::BuiltinType::Char_U:
case clang::BuiltinType::UChar:
case clang::BuiltinType::Char_S:
case clang::BuiltinType::Char8:
case clang::BuiltinType::SChar:
case clang::BuiltinType::UShort:
case clang::BuiltinType::UInt:
case clang::BuiltinType::ULong:
case clang::BuiltinType::ULongLong:
case clang::BuiltinType::Short:
case clang::BuiltinType::Int:
case clang::BuiltinType::Long:
case clang::BuiltinType::LongLong:
case clang::BuiltinType::UInt128:
case clang::BuiltinType::Int128:
return true;
default:
return false;
}
}
static const clang::FunctionProtoType *qual_type_get_fn_proto(ZigClangQualType qt, bool *is_ptr) {
const ZigClangType *ty = qual_type_canon(qt);
*is_ptr = false;
@ -744,6 +771,17 @@ static AstNode* trans_c_cast(Context *c, ZigClangSourceLocation source_location,
if (qual_type_is_ptr(dest_type) && qual_type_is_ptr(src_type)) {
return trans_c_ptr_cast(c, source_location, dest_type, src_type, expr);
}
if (qual_type_is_int(dest_type) && qual_type_is_ptr(src_type)) {
AstNode *addr_node = trans_create_node_builtin_fn_call_str(c, "ptrToInt");
addr_node->data.fn_call_expr.params.append(expr);
return trans_create_node_fn_call_1(c, trans_qual_type(c, dest_type, source_location), addr_node);
}
if (qual_type_is_int(src_type) && qual_type_is_ptr(dest_type)) {
AstNode *ptr_node = trans_create_node_builtin_fn_call_str(c, "intToPtr");
ptr_node->data.fn_call_expr.params.append(trans_qual_type(c, dest_type, source_location));
ptr_node->data.fn_call_expr.params.append(expr);
return ptr_node;
}
// TODO: maybe widen to increase size
// TODO: maybe bitcast to change sign
// TODO: maybe truncate to reduce size

View File

@ -2,6 +2,20 @@ const tests = @import("tests.zig");
const builtin = @import("builtin");
pub fn addCases(cases: *tests.TranslateCContext) void {
cases.add("casting pointers to ints and ints to pointers",
\\void foo(void);
\\void bar(void) {
\\ void *func_ptr = foo;
\\ void (*typed_func_ptr)(void) = (void (*)(void)) (unsigned long) func_ptr;
\\}
,
\\pub extern fn foo() void;
\\pub fn bar() void {
\\ var func_ptr: ?*c_void = @ptrCast(?*c_void, foo);
\\ var typed_func_ptr: ?extern fn() void = @intToPtr(?extern fn() void, c_ulong(@ptrToInt(func_ptr)));
\\}
);
if (builtin.os != builtin.Os.windows) {
// Windows treats this as an enum with type c_int
cases.add("big negative enum init values when C ABI supports long long enums",