mirror of
https://github.com/ziglang/zig.git
synced 2026-02-14 13:30:45 +00:00
translate-c: use @intToPtr to cast away qualifiers
This commit is contained in:
parent
e3a63b4e5a
commit
f83b02a581
@ -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 (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);
|
||||
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, ",");
|
||||
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;
|
||||
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 {
|
||||
// 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 (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 {
|
||||
|
||||
@ -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;
|
||||
\\}
|
||||
, "");
|
||||
}
|
||||
|
||||
@ -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)));
|
||||
\\}
|
||||
});
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user