| author | |
| committer | |
| log | 7ba1f9bfb52a1f6fa776eeafb45790331be4388f |
| tree | e893b174fc9b7e88ea15190f75e05753b315e940 |
| parent | c8c798685f3a7d6454bc06d5f47531ad6f615eb5 |
Fixes #121947 files changed, 66 insertions(+), 5 deletions(-)
lib/std/zig/c_translation.zig+4| ... | ... | @@ -36,6 +36,9 @@ pub fn cast(comptime DestType: type, target: anytype) DestType { |
| 36 | 36 | .Int => { |
| 37 | 37 | return castInt(DestType, target); |
| 38 | 38 | }, |
| 39 | .Fn => { | |
| 40 | return castInt(DestType, @ptrToInt(&target)); | |
| 41 | }, | |
| 39 | 42 | else => {}, |
| 40 | 43 | } |
| 41 | 44 | }, |
| ... | ... | @@ -45,6 +48,7 @@ pub fn cast(comptime DestType: type, target: anytype) DestType { |
| 45 | 48 | } |
| 46 | 49 | @compileError("cast to union type '" ++ @typeName(DestType) ++ "' from type '" ++ @typeName(SourceType) ++ "' which is not present in union"); |
| 47 | 50 | }, |
| 51 | .Bool => return cast(usize, target) != 0, | |
| 48 | 52 | else => {}, |
| 49 | 53 | } |
| 50 | 54 | return @as(DestType, target); |
src/translate_c.zig+14-4| ... | ... | @@ -1950,7 +1950,10 @@ fn transDeclRefExpr( |
| 1950 | 1950 | const value_decl = expr.getDecl(); |
| 1951 | 1951 | const name = try c.str(@ptrCast(*const clang.NamedDecl, value_decl).getName_bytes_begin()); |
| 1952 | 1952 | const mangled_name = scope.getAlias(name); |
| 1953 | var ref_expr = try Tag.identifier.create(c.arena, mangled_name); | |
| 1953 | var ref_expr = if (cIsFunctionDeclRef(@ptrCast(*const clang.Expr, expr))) | |
| 1954 | try Tag.fn_identifier.create(c.arena, mangled_name) | |
| 1955 | else | |
| 1956 | try Tag.identifier.create(c.arena, mangled_name); | |
| 1954 | 1957 | |
| 1955 | 1958 | if (@ptrCast(*const clang.Decl, value_decl).getKind() == .Var) { |
| 1956 | 1959 | const var_decl = @ptrCast(*const clang.VarDecl, value_decl); |
| ... | ... | @@ -1999,7 +2002,11 @@ fn transImplicitCastExpr( |
| 1999 | 2002 | }, |
| 2000 | 2003 | .PointerToBoolean => { |
| 2001 | 2004 | // @ptrToInt(val) != 0 |
| 2002 | const ptr_to_int = try Tag.ptr_to_int.create(c.arena, try transExpr(c, scope, sub_expr, .used)); | |
| 2005 | var ptr_node = try transExpr(c, scope, sub_expr, .used); | |
| 2006 | if (ptr_node.tag() == .fn_identifier) { | |
| 2007 | ptr_node = try Tag.address_of.create(c.arena, ptr_node); | |
| 2008 | } | |
| 2009 | const ptr_to_int = try Tag.ptr_to_int.create(c.arena, ptr_node); | |
| 2003 | 2010 | |
| 2004 | 2011 | const ne = try Tag.not_equal.create(c.arena, .{ .lhs = ptr_to_int, .rhs = Tag.zero_literal.init() }); |
| 2005 | 2012 | return maybeSuppressResult(c, scope, result_used, ne); |
| ... | ... | @@ -2042,7 +2049,7 @@ fn isBuiltinDefined(name: []const u8) bool { |
| 2042 | 2049 | |
| 2043 | 2050 | fn transBuiltinFnExpr(c: *Context, scope: *Scope, expr: *const clang.Expr, used: ResultUsed) TransError!Node { |
| 2044 | 2051 | const node = try transExpr(c, scope, expr, used); |
| 2045 | if (node.castTag(.identifier)) |ident| { | |
| 2052 | if (node.castTag(.fn_identifier)) |ident| { | |
| 2046 | 2053 | const name = ident.data; |
| 2047 | 2054 | if (!isBuiltinDefined(name)) return fail(c, error.UnsupportedTranslation, expr.getBeginLoc(), "TODO implement function '{s}' in std.zig.c_builtins", .{name}); |
| 2048 | 2055 | } |
| ... | ... | @@ -2447,7 +2454,10 @@ fn transCCast( |
| 2447 | 2454 | } |
| 2448 | 2455 | if (cIsInteger(dst_type) and qualTypeIsPtr(src_type)) { |
| 2449 | 2456 | // @intCast(dest_type, @ptrToInt(val)) |
| 2450 | const ptr_to_int = try Tag.ptr_to_int.create(c.arena, expr); | |
| 2457 | const ptr_to_int = if (expr.tag() == .fn_identifier) | |
| 2458 | try Tag.ptr_to_int.create(c.arena, try Tag.address_of.create(c.arena, expr)) | |
| 2459 | else | |
| 2460 | try Tag.ptr_to_int.create(c.arena, expr); | |
| 2451 | 2461 | return Tag.int_cast.create(c.arena, .{ .lhs = dst_node, .rhs = ptr_to_int }); |
| 2452 | 2462 | } |
| 2453 | 2463 | if (cIsInteger(src_type) and qualTypeIsPtr(dst_type)) { |
src/translate_c/ast.zig+11| ... | ... | @@ -36,6 +36,7 @@ pub const Node = extern union { |
| 36 | 36 | /// "string"[0..end] |
| 37 | 37 | string_slice, |
| 38 | 38 | identifier, |
| 39 | fn_identifier, | |
| 39 | 40 | @"if", |
| 40 | 41 | /// if (!operand) break; |
| 41 | 42 | if_not_break, |
| ... | ... | @@ -335,6 +336,7 @@ pub const Node = extern union { |
| 335 | 336 | .char_literal, |
| 336 | 337 | .enum_literal, |
| 337 | 338 | .identifier, |
| 339 | .fn_identifier, | |
| 338 | 340 | .warning, |
| 339 | 341 | .type, |
| 340 | 342 | .helpers_macro, |
| ... | ... | @@ -1058,6 +1060,14 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { |
| 1058 | 1060 | .data = undefined, |
| 1059 | 1061 | }); |
| 1060 | 1062 | }, |
| 1063 | .fn_identifier => { | |
| 1064 | const payload = node.castTag(.fn_identifier).?.data; | |
| 1065 | return c.addNode(.{ | |
| 1066 | .tag = .identifier, | |
| 1067 | .main_token = try c.addIdentifier(payload), | |
| 1068 | .data = undefined, | |
| 1069 | }); | |
| 1070 | }, | |
| 1061 | 1071 | .float_literal => { |
| 1062 | 1072 | const payload = node.castTag(.float_literal).?.data; |
| 1063 | 1073 | return c.addNode(.{ |
| ... | ... | @@ -2234,6 +2244,7 @@ fn renderNodeGrouped(c: *Context, node: Node) !NodeIndex { |
| 2234 | 2244 | .char_literal, |
| 2235 | 2245 | .enum_literal, |
| 2236 | 2246 | .identifier, |
| 2247 | .fn_identifier, | |
| 2237 | 2248 | .field_access, |
| 2238 | 2249 | .ptr_cast, |
| 2239 | 2250 | .type, |
test/behavior/translate_c_macros.h+8| ... | ... | @@ -40,3 +40,11 @@ union U { |
| 40 | 40 | #define CAST_OR_CALL_WITH_PARENS(type_or_fn, val) ((type_or_fn)(val)) |
| 41 | 41 | |
| 42 | 42 | #define NESTED_COMMA_OPERATOR (1, (2, 3)) |
| 43 | ||
| 44 | #include <stdint.h> | |
| 45 | #if !defined(__UINTPTR_MAX__) | |
| 46 | typedef _Bool uintptr_t; | |
| 47 | #endif | |
| 48 | ||
| 49 | #define CAST_TO_BOOL(X) (_Bool)(X) | |
| 50 | #define CAST_TO_UINTPTR(X) (uintptr_t)(X) |
test/behavior/translate_c_macros.zig+14| ... | ... | @@ -99,3 +99,17 @@ test "nested comma operator" { |
| 99 | 99 | |
| 100 | 100 | try expectEqual(@as(c_int, 3), h.NESTED_COMMA_OPERATOR); |
| 101 | 101 | } |
| 102 | ||
| 103 | test "cast functions" { | |
| 104 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | |
| 105 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | |
| 106 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | |
| 107 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | |
| 108 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | |
| 109 | ||
| 110 | const S = struct { | |
| 111 | fn foo() void {} | |
| 112 | }; | |
| 113 | try expectEqual(true, h.CAST_TO_BOOL(S.foo)); | |
| 114 | try expect(h.CAST_TO_UINTPTR(S.foo) != 0); | |
| 115 | } |
test/run_translated_c.zig+14| ... | ... | @@ -1861,4 +1861,18 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void { |
| 1861 | 1861 | \\ return 0; |
| 1862 | 1862 | \\} |
| 1863 | 1863 | , ""); |
| 1864 | ||
| 1865 | // The C standard does not require function pointers to be convertible to any integer type. | |
| 1866 | // However, POSIX requires that function pointers have the same representation as `void *` | |
| 1867 | // so that dlsym() can work | |
| 1868 | cases.add("Function to integral", | |
| 1869 | \\#include <stdint.h> | |
| 1870 | \\int main(void) { | |
| 1871 | \\#if defined(__UINTPTR_MAX__) && __has_include(<unistd.h>) | |
| 1872 | \\ uintptr_t x = main; | |
| 1873 | \\ x = (uintptr_t)main; | |
| 1874 | \\#endif | |
| 1875 | \\ return 0; | |
| 1876 | \\} | |
| 1877 | , ""); | |
| 1864 | 1878 | } |
test/translate_c.zig+1-1| ... | ... | @@ -3435,7 +3435,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 3435 | 3435 | \\ var x = arg_x; |
| 3436 | 3436 | \\ var a: bool = @as(c_int, @boolToInt(x)) != @as(c_int, 1); |
| 3437 | 3437 | \\ var b: bool = @as(c_int, @boolToInt(a)) != @as(c_int, 0); |
| 3438 | \\ var c: bool = @ptrToInt(foo) != 0; | |
| 3438 | \\ var c: bool = @ptrToInt(&foo) != 0; | |
| 3439 | 3439 | \\ return foo(@as(c_int, @boolToInt(c)) != @as(c_int, @boolToInt(b))); |
| 3440 | 3440 | \\} |
| 3441 | 3441 | }); |