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(...@@ -2880,35 +2880,57 @@ fn transCPtrCast(
2880) !*ast.Node {2880) !*ast.Node {
2881 const ty = ZigClangQualType_getTypePtr(dst_type);2881 const ty = ZigClangQualType_getTypePtr(dst_type);
2882 const child_type = ZigClangType_getPointeeType(ty);2882 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,2886 if ((ZigClangQualType_isConstQualified(src_child_type) and
2885 // use @alignCast to side-step this problem2887 !ZigClangQualType_isConstQualified(child_type)) or
2886 const ptrcast_node = try transCreateNodeBuiltinFnCall(rp.c, "@ptrCast");2888 (ZigClangQualType_isVolatileQualified(src_child_type) and
2887 const dst_type_node = try transType(rp, ty, loc);2889 !ZigClangQualType_isVolatileQualified(child_type)))
2888 try ptrcast_node.params.push(dst_type_node);2890 {
2889 _ = try appendToken(rp.c, .Comma, ",");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))) {2897 const ptrtoint_node = try transCreateNodeBuiltinFnCall(rp.c, "@ptrToInt");
2892 // void has 1-byte alignment, so @alignCast is not needed2898 try ptrtoint_node.params.push(expr);
2893 try ptrcast_node.params.push(expr);2899 ptrtoint_node.rparen_token = try appendToken(rp.c, .RParen, ")");
2894 } else if (typeIsOpaque(rp.c, qualTypeCanon(child_type), loc)) {2900
2895 // For opaque types a ptrCast is enough2901 try inttoptr_node.params.push(&ptrtoint_node.base);
2896 try ptrcast_node.params.push(expr);2902 inttoptr_node.rparen_token = try appendToken(rp.c, .RParen, ")");
2903 return &inttoptr_node.base;
2897 } else {2904 } else {
2898 const aligncast_node = try transCreateNodeBuiltinFnCall(rp.c, "@alignCast");2905 // Implicit downcasting from higher to lower alignment values is forbidden,
2899 const alignof_node = try transCreateNodeBuiltinFnCall(rp.c, "@alignOf");2906 // use @alignCast to side-step this problem
2900 const child_type_node = try transQualType(rp, child_type, loc);2907 const ptrcast_node = try transCreateNodeBuiltinFnCall(rp.c, "@ptrCast");
2901 try alignof_node.params.push(child_type_node);2908 const dst_type_node = try transType(rp, ty, loc);
2902 alignof_node.rparen_token = try appendToken(rp.c, .RParen, ")");2909 try ptrcast_node.params.push(dst_type_node);
2903 try aligncast_node.params.push(&alignof_node.base);
2904 _ = try appendToken(rp.c, .Comma, ",");2910 _ = 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 }
2912}2934}
29132935
2914fn transBreak(rp: RestorePoint, scope: *Scope) TransError!*ast.Node {2936fn 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 {...@@ -23,4 +23,20 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void {
23 \\ return 0;23 \\ return 0;
24 \\}24 \\}
25 , "");25 , "");
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 , "");
26}42}
test/translate_c.zig+22
...@@ -2452,4 +2452,26 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -2452,4 +2452,26 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
2452 \\pub export fn c() void {}2452 \\pub export fn c() void {}
2453 \\pub fn foo() callconv(.C) void {}2453 \\pub fn foo() callconv(.C) void {}
2454 });2454 });
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 });
2455}2477}