Skip to content

Commit f83b02a

Browse files
tadeokondrakandrewrk
authored andcommitted
translate-c: use @intToPtr to cast away qualifiers
1 parent e3a63b4 commit f83b02a

File tree

3 files changed

+84
-24
lines changed

3 files changed

+84
-24
lines changed

src-self-hosted/translate_c.zig

Lines changed: 46 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -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

29142936
fn transBreak(rp: RestorePoint, scope: *Scope) TransError!*ast.Node {

test/run_translated_c.zig

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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
}

0 commit comments

Comments
 (0)