Commit 1273bc277f
Changed files (6)
src
src/translate_c/ast.zig
@@ -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,
src/clang.zig
@@ -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;
};
src/translate_c.zig
@@ -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));
src/zig_clang.cpp
@@ -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));
src/zig_clang.h
@@ -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);
test/run_translated_c.zig
@@ -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;
+ \\}
+ , "");
}