authorgravatar for me@tadeo.caTadeo Kondrak <me@tadeo.ca> 2020-01-02 19:36:36-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-01-06 19:09:49-05:00
logf83b02a581b2491e0a52f7c650ebd65ba8297263
treec6cd551f18517ad1bd96ad75e9a7f3bdfebf036a
parente3a63b4e5abd501d58a2fc574b827f3250c14461

translate-c: use @intToPtr to cast away qualifiers


3 files changed, 84 insertions(+), 24 deletions(-)

src-self-hosted/translate_c.zig+46-24
......@@ -2880,35 +2880,57 @@ fn transCPtrCast(
28802880) !*ast.Node {
28812881 const ty = ZigClangQualType_getTypePtr(dst_type);
28822882 const child_type = ZigClangType_getPointeeType(ty);
2883 const src_ty = ZigClangQualType_getTypePtr(src_type);
2884 const src_child_type = ZigClangType_getPointeeType(src_ty);
28832885
2884 // Implicit downcasting from higher to lower alignment values is forbidden,
2885 // use @alignCast to side-step this problem
2886 const ptrcast_node = try transCreateNodeBuiltinFnCall(rp.c, "@ptrCast");
2887 const dst_type_node = try transType(rp, ty, loc);
2888 try ptrcast_node.params.push(dst_type_node);
2889 _ = try appendToken(rp.c, .Comma, ",");
2886 if ((ZigClangQualType_isConstQualified(src_child_type) and
2887 !ZigClangQualType_isConstQualified(child_type)) or
2888 (ZigClangQualType_isVolatileQualified(src_child_type) and
2889 !ZigClangQualType_isVolatileQualified(child_type)))
2890 {
2891 // Casting away const or volatile requires us to use @intToPtr
2892 const inttoptr_node = try transCreateNodeBuiltinFnCall(rp.c, "@intToPtr");
2893 const dst_type_node = try transType(rp, ty, loc);
2894 try inttoptr_node.params.push(dst_type_node);
2895 _ = try appendToken(rp.c, .Comma, ",");
28902896
2891 if (ZigClangType_isVoidType(qualTypeCanon(child_type))) {
2892 // void has 1-byte alignment, so @alignCast is not needed
2893 try ptrcast_node.params.push(expr);
2894 } else if (typeIsOpaque(rp.c, qualTypeCanon(child_type), loc)) {
2895 // For opaque types a ptrCast is enough
2896 try ptrcast_node.params.push(expr);
2897 const ptrtoint_node = try transCreateNodeBuiltinFnCall(rp.c, "@ptrToInt");
2898 try ptrtoint_node.params.push(expr);
2899 ptrtoint_node.rparen_token = try appendToken(rp.c, .RParen, ")");
2900
2901 try inttoptr_node.params.push(&ptrtoint_node.base);
2902 inttoptr_node.rparen_token = try appendToken(rp.c, .RParen, ")");
2903 return &inttoptr_node.base;
28972904 } else {
2898 const aligncast_node = try transCreateNodeBuiltinFnCall(rp.c, "@alignCast");
2899 const alignof_node = try transCreateNodeBuiltinFnCall(rp.c, "@alignOf");
2900 const child_type_node = try transQualType(rp, child_type, loc);
2901 try alignof_node.params.push(child_type_node);
2902 alignof_node.rparen_token = try appendToken(rp.c, .RParen, ")");
2903 try aligncast_node.params.push(&alignof_node.base);
2905 // Implicit downcasting from higher to lower alignment values is forbidden,
2906 // use @alignCast to side-step this problem
2907 const ptrcast_node = try transCreateNodeBuiltinFnCall(rp.c, "@ptrCast");
2908 const dst_type_node = try transType(rp, ty, loc);
2909 try ptrcast_node.params.push(dst_type_node);
29042910 _ = try appendToken(rp.c, .Comma, ",");
2905 try aligncast_node.params.push(expr);
2906 aligncast_node.rparen_token = try appendToken(rp.c, .RParen, ")");
2907 try ptrcast_node.params.push(&aligncast_node.base);
2908 }
2909 ptrcast_node.rparen_token = try appendToken(rp.c, .RParen, ")");
29102911
2911 return &ptrcast_node.base;
2912 if (ZigClangType_isVoidType(qualTypeCanon(child_type))) {
2913 // void has 1-byte alignment, so @alignCast is not needed
2914 try ptrcast_node.params.push(expr);
2915 } else if (typeIsOpaque(rp.c, qualTypeCanon(child_type), loc)) {
2916 // For opaque types a ptrCast is enough
2917 try ptrcast_node.params.push(expr);
2918 } else {
2919 const aligncast_node = try transCreateNodeBuiltinFnCall(rp.c, "@alignCast");
2920 const alignof_node = try transCreateNodeBuiltinFnCall(rp.c, "@alignOf");
2921 const child_type_node = try transQualType(rp, child_type, loc);
2922 try alignof_node.params.push(child_type_node);
2923 alignof_node.rparen_token = try appendToken(rp.c, .RParen, ")");
2924 try aligncast_node.params.push(&alignof_node.base);
2925 _ = try appendToken(rp.c, .Comma, ",");
2926 try aligncast_node.params.push(expr);
2927 aligncast_node.rparen_token = try appendToken(rp.c, .RParen, ")");
2928 try ptrcast_node.params.push(&aligncast_node.base);
2929 }
2930 ptrcast_node.rparen_token = try appendToken(rp.c, .RParen, ")");
2931
2932 return &ptrcast_node.base;
2933 }
29122934}
29132935
29142936fn transBreak(rp: RestorePoint, scope: *Scope) TransError!*ast.Node {
test/run_translated_c.zig+16
......@@ -23,4 +23,20 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void {
2323 \\ return 0;
2424 \\}
2525 , "");
26
27 cases.add("casting away const and volatile",
28 \\void foo(int *a) {}
29 \\void bar(const int *a) {
30 \\ foo((int *)a);
31 \\}
32 \\void baz(volatile int *a) {
33 \\ foo((int *)a);
34 \\}
35 \\int main(int argc, char **argv) {
36 \\ int a = 0;
37 \\ bar((const int *)&a);
38 \\ baz((volatile int *)&a);
39 \\ return 0;
40 \\}
41 , "");
2642}
test/translate_c.zig+22
......@@ -2452,4 +2452,26 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
24522452 \\pub export fn c() void {}
24532453 \\pub fn foo() callconv(.C) void {}
24542454 });
2455
2456 cases.add("casting away const and volatile",
2457 \\void foo(int *a) {}
2458 \\void bar(const int *a) {
2459 \\ foo((int *)a);
2460 \\}
2461 \\void baz(volatile int *a) {
2462 \\ foo((int *)a);
2463 \\}
2464 , &[_][]const u8{
2465 \\pub export fn foo(arg_a: [*c]c_int) void {
2466 \\ var a = arg_a;
2467 \\}
2468 \\pub export fn bar(arg_a: [*c]const c_int) void {
2469 \\ var a = arg_a;
2470 \\ foo(@intToPtr([*c]c_int, @ptrToInt(a)));
2471 \\}
2472 \\pub export fn baz(arg_a: [*c]volatile c_int) void {
2473 \\ var a = arg_a;
2474 \\ foo(@intToPtr([*c]c_int, @ptrToInt(a)));
2475 \\}
2476 });
24552477}