Commit f83b02a581
Changed files (3)
src-self-hosted
src-self-hosted/translate_c.zig
@@ -2880,35 +2880,57 @@ fn transCPtrCast(
) !*ast.Node {
const ty = ZigClangQualType_getTypePtr(dst_type);
const child_type = ZigClangType_getPointeeType(ty);
+ const src_ty = ZigClangQualType_getTypePtr(src_type);
+ const src_child_type = ZigClangType_getPointeeType(src_ty);
- // Implicit downcasting from higher to lower alignment values is forbidden,
- // use @alignCast to side-step this problem
- const ptrcast_node = try transCreateNodeBuiltinFnCall(rp.c, "@ptrCast");
- const dst_type_node = try transType(rp, ty, loc);
- try ptrcast_node.params.push(dst_type_node);
- _ = try appendToken(rp.c, .Comma, ",");
+ if ((ZigClangQualType_isConstQualified(src_child_type) and
+ !ZigClangQualType_isConstQualified(child_type)) or
+ (ZigClangQualType_isVolatileQualified(src_child_type) and
+ !ZigClangQualType_isVolatileQualified(child_type)))
+ {
+ // Casting away const or volatile requires us to use @intToPtr
+ const inttoptr_node = try transCreateNodeBuiltinFnCall(rp.c, "@intToPtr");
+ const dst_type_node = try transType(rp, ty, loc);
+ try inttoptr_node.params.push(dst_type_node);
+ _ = try appendToken(rp.c, .Comma, ",");
- if (ZigClangType_isVoidType(qualTypeCanon(child_type))) {
- // void has 1-byte alignment, so @alignCast is not needed
- try ptrcast_node.params.push(expr);
- } else if (typeIsOpaque(rp.c, qualTypeCanon(child_type), loc)) {
- // For opaque types a ptrCast is enough
- try ptrcast_node.params.push(expr);
+ const ptrtoint_node = try transCreateNodeBuiltinFnCall(rp.c, "@ptrToInt");
+ try ptrtoint_node.params.push(expr);
+ ptrtoint_node.rparen_token = try appendToken(rp.c, .RParen, ")");
+
+ try inttoptr_node.params.push(&ptrtoint_node.base);
+ inttoptr_node.rparen_token = try appendToken(rp.c, .RParen, ")");
+ return &inttoptr_node.base;
} else {
- const aligncast_node = try transCreateNodeBuiltinFnCall(rp.c, "@alignCast");
- const alignof_node = try transCreateNodeBuiltinFnCall(rp.c, "@alignOf");
- const child_type_node = try transQualType(rp, child_type, loc);
- try alignof_node.params.push(child_type_node);
- alignof_node.rparen_token = try appendToken(rp.c, .RParen, ")");
- try aligncast_node.params.push(&alignof_node.base);
+ // Implicit downcasting from higher to lower alignment values is forbidden,
+ // use @alignCast to side-step this problem
+ const ptrcast_node = try transCreateNodeBuiltinFnCall(rp.c, "@ptrCast");
+ const dst_type_node = try transType(rp, ty, loc);
+ try ptrcast_node.params.push(dst_type_node);
_ = try appendToken(rp.c, .Comma, ",");
- try aligncast_node.params.push(expr);
- aligncast_node.rparen_token = try appendToken(rp.c, .RParen, ")");
- try ptrcast_node.params.push(&aligncast_node.base);
- }
- ptrcast_node.rparen_token = try appendToken(rp.c, .RParen, ")");
- return &ptrcast_node.base;
+ if (ZigClangType_isVoidType(qualTypeCanon(child_type))) {
+ // void has 1-byte alignment, so @alignCast is not needed
+ try ptrcast_node.params.push(expr);
+ } else if (typeIsOpaque(rp.c, qualTypeCanon(child_type), loc)) {
+ // For opaque types a ptrCast is enough
+ try ptrcast_node.params.push(expr);
+ } else {
+ const aligncast_node = try transCreateNodeBuiltinFnCall(rp.c, "@alignCast");
+ const alignof_node = try transCreateNodeBuiltinFnCall(rp.c, "@alignOf");
+ const child_type_node = try transQualType(rp, child_type, loc);
+ try alignof_node.params.push(child_type_node);
+ alignof_node.rparen_token = try appendToken(rp.c, .RParen, ")");
+ try aligncast_node.params.push(&alignof_node.base);
+ _ = try appendToken(rp.c, .Comma, ",");
+ try aligncast_node.params.push(expr);
+ aligncast_node.rparen_token = try appendToken(rp.c, .RParen, ")");
+ try ptrcast_node.params.push(&aligncast_node.base);
+ }
+ ptrcast_node.rparen_token = try appendToken(rp.c, .RParen, ")");
+
+ return &ptrcast_node.base;
+ }
}
fn transBreak(rp: RestorePoint, scope: *Scope) TransError!*ast.Node {
test/run_translated_c.zig
@@ -23,4 +23,20 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void {
\\ return 0;
\\}
, "");
+
+ cases.add("casting away const and volatile",
+ \\void foo(int *a) {}
+ \\void bar(const int *a) {
+ \\ foo((int *)a);
+ \\}
+ \\void baz(volatile int *a) {
+ \\ foo((int *)a);
+ \\}
+ \\int main(int argc, char **argv) {
+ \\ int a = 0;
+ \\ bar((const int *)&a);
+ \\ baz((volatile int *)&a);
+ \\ return 0;
+ \\}
+ , "");
}
test/translate_c.zig
@@ -2452,4 +2452,26 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\pub export fn c() void {}
\\pub fn foo() callconv(.C) void {}
});
+
+ cases.add("casting away const and volatile",
+ \\void foo(int *a) {}
+ \\void bar(const int *a) {
+ \\ foo((int *)a);
+ \\}
+ \\void baz(volatile int *a) {
+ \\ foo((int *)a);
+ \\}
+ , &[_][]const u8{
+ \\pub export fn foo(arg_a: [*c]c_int) void {
+ \\ var a = arg_a;
+ \\}
+ \\pub export fn bar(arg_a: [*c]const c_int) void {
+ \\ var a = arg_a;
+ \\ foo(@intToPtr([*c]c_int, @ptrToInt(a)));
+ \\}
+ \\pub export fn baz(arg_a: [*c]volatile c_int) void {
+ \\ var a = arg_a;
+ \\ foo(@intToPtr([*c]c_int, @ptrToInt(a)));
+ \\}
+ });
}