mirror of
https://github.com/ziglang/zig.git
synced 2026-02-12 20:37:54 +00:00
translate-c: add support for __cleanup__ attribute
Use a `defer` statement to implement the C __cleanup__ attribute. See https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html
This commit is contained in:
parent
28a89b9ebc
commit
1273bc277f
@ -976,6 +976,9 @@ pub const VarDecl = opaque {
|
||||
pub const getAlignedAttribute = ZigClangVarDecl_getAlignedAttribute;
|
||||
extern fn ZigClangVarDecl_getAlignedAttribute(*const VarDecl, *const ASTContext) c_uint;
|
||||
|
||||
pub const getCleanupAttribute = ZigClangVarDecl_getCleanupAttribute;
|
||||
extern fn ZigClangVarDecl_getCleanupAttribute(*const VarDecl) ?*const FunctionDecl;
|
||||
|
||||
pub const getTypeSourceInfo_getType = ZigClangVarDecl_getTypeSourceInfo_getType;
|
||||
extern fn ZigClangVarDecl_getTypeSourceInfo_getType(*const VarDecl) QualType;
|
||||
};
|
||||
|
||||
@ -1656,6 +1656,22 @@ fn transDeclStmtOne(
|
||||
.init = init_node,
|
||||
});
|
||||
try block_scope.statements.append(node);
|
||||
|
||||
const cleanup_attr = var_decl.getCleanupAttribute();
|
||||
if (cleanup_attr) |fn_decl| {
|
||||
const cleanup_fn_name = try c.str(@ptrCast(*const clang.NamedDecl, fn_decl).getName_bytes_begin());
|
||||
const fn_id = try Tag.identifier.create(c.arena, cleanup_fn_name);
|
||||
|
||||
const varname = try Tag.identifier.create(c.arena, mangled_name);
|
||||
const args = try c.arena.alloc(Node, 1);
|
||||
args[0] = try Tag.address_of.create(c.arena, varname);
|
||||
|
||||
const cleanup_call = try Tag.call.create(c.arena, .{ .lhs = fn_id, .args = args });
|
||||
const discard = try Tag.discard.create(c.arena, cleanup_call);
|
||||
const deferred_cleanup = try Tag.@"defer".create(c.arena, discard);
|
||||
|
||||
try block_scope.statements.append(deferred_cleanup);
|
||||
}
|
||||
},
|
||||
.Typedef => {
|
||||
try transTypeDef(c, scope, @ptrCast(*const clang.TypedefNameDecl, decl));
|
||||
|
||||
@ -67,6 +67,7 @@ pub const Node = extern union {
|
||||
@"struct",
|
||||
@"union",
|
||||
@"comptime",
|
||||
@"defer",
|
||||
array_init,
|
||||
tuple,
|
||||
container_init,
|
||||
@ -247,6 +248,7 @@ pub const Node = extern union {
|
||||
.std_mem_zeroes,
|
||||
.@"return",
|
||||
.@"comptime",
|
||||
.@"defer",
|
||||
.asm_simple,
|
||||
.discard,
|
||||
.std_math_Log2Int,
|
||||
@ -1020,6 +1022,17 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
|
||||
},
|
||||
});
|
||||
},
|
||||
.@"defer" => {
|
||||
const payload = node.castTag(.@"defer").?.data;
|
||||
return c.addNode(.{
|
||||
.tag = .@"defer",
|
||||
.main_token = try c.addToken(.keyword_defer, "defer"),
|
||||
.data = .{
|
||||
.lhs = undefined,
|
||||
.rhs = try renderNode(c, payload),
|
||||
},
|
||||
});
|
||||
},
|
||||
.asm_simple => {
|
||||
const payload = node.castTag(.asm_simple).?.data;
|
||||
const asm_token = try c.addToken(.keyword_asm, "asm");
|
||||
@ -2273,6 +2286,7 @@ fn renderNodeGrouped(c: *Context, node: Node) !NodeIndex {
|
||||
.@"continue",
|
||||
.@"return",
|
||||
.@"comptime",
|
||||
.@"defer",
|
||||
.asm_simple,
|
||||
.usingnamespace_builtins,
|
||||
.while_true,
|
||||
|
||||
@ -1784,6 +1784,14 @@ unsigned ZigClangVarDecl_getAlignedAttribute(const struct ZigClangVarDecl *self,
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct ZigClangFunctionDecl *ZigClangVarDecl_getCleanupAttribute(const struct ZigClangVarDecl *self) {
|
||||
auto casted_self = reinterpret_cast<const clang::VarDecl *>(self);
|
||||
if (const clang::CleanupAttr *CA = casted_self->getAttr<clang::CleanupAttr>()) {
|
||||
return reinterpret_cast<const ZigClangFunctionDecl *>(CA->getFunctionDecl());
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
unsigned ZigClangFieldDecl_getAlignedAttribute(const struct ZigClangFieldDecl *self, const ZigClangASTContext* ctx) {
|
||||
auto casted_self = reinterpret_cast<const clang::FieldDecl *>(self);
|
||||
auto casted_ctx = const_cast<clang::ASTContext *>(reinterpret_cast<const clang::ASTContext *>(ctx));
|
||||
|
||||
@ -997,6 +997,7 @@ ZIG_EXTERN_C const struct ZigClangTypedefNameDecl *ZigClangTypedefNameDecl_getCa
|
||||
ZIG_EXTERN_C const struct ZigClangFunctionDecl *ZigClangFunctionDecl_getCanonicalDecl(const ZigClangFunctionDecl *self);
|
||||
ZIG_EXTERN_C const struct ZigClangVarDecl *ZigClangVarDecl_getCanonicalDecl(const ZigClangVarDecl *self);
|
||||
ZIG_EXTERN_C const char* ZigClangVarDecl_getSectionAttribute(const struct ZigClangVarDecl *self, size_t *len);
|
||||
ZIG_EXTERN_C const struct ZigClangFunctionDecl *ZigClangVarDecl_getCleanupAttribute(const struct ZigClangVarDecl *self);
|
||||
ZIG_EXTERN_C unsigned ZigClangVarDecl_getAlignedAttribute(const struct ZigClangVarDecl *self, const ZigClangASTContext* ctx);
|
||||
ZIG_EXTERN_C unsigned ZigClangFunctionDecl_getAlignedAttribute(const struct ZigClangFunctionDecl *self, const ZigClangASTContext* ctx);
|
||||
ZIG_EXTERN_C unsigned ZigClangFieldDecl_getAlignedAttribute(const struct ZigClangFieldDecl *self, const ZigClangASTContext* ctx);
|
||||
|
||||
@ -1490,4 +1490,22 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void {
|
||||
\\ return 0;
|
||||
\\}
|
||||
, "");
|
||||
|
||||
cases.add("__cleanup__ attribute",
|
||||
\\#include <stdlib.h>
|
||||
\\static int cleanup_count = 0;
|
||||
\\void clean_up(int *final_value) {
|
||||
\\ if (*final_value != cleanup_count++) abort();
|
||||
\\}
|
||||
\\void doit(void) {
|
||||
\\ int a __attribute__ ((__cleanup__(clean_up))) __attribute__ ((unused)) = 2;
|
||||
\\ int b __attribute__ ((__cleanup__(clean_up))) __attribute__ ((unused)) = 1;
|
||||
\\ int c __attribute__ ((__cleanup__(clean_up))) __attribute__ ((unused)) = 0;
|
||||
\\}
|
||||
\\int main(void) {
|
||||
\\ doit();
|
||||
\\ if (cleanup_count != 3) abort();
|
||||
\\ return 0;
|
||||
\\}
|
||||
, "");
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user