summaryrefslogtreecommitdiff
path: root/src/codegen
diff options
context:
space:
mode:
authorZuhaitz Méndez Fernández de Aránguiz <zuhaitz@debian>2026-01-21 00:38:14 +0000
committerZuhaitz Méndez Fernández de Aránguiz <zuhaitz@debian>2026-01-21 00:38:14 +0000
commitfd84225099175d54ea20f0d39ddf10ccd2daa381 (patch)
treeae42004d20ae3a6f3d4c3c48f999748a1e3e9b0a /src/codegen
parentabea7bb0b29f1f1672faff94d1bf26768f214dc1 (diff)
Modify codegen, tests should pass now
Diffstat (limited to 'src/codegen')
-rw-r--r--src/codegen/codegen.c50
1 files changed, 47 insertions, 3 deletions
diff --git a/src/codegen/codegen.c b/src/codegen/codegen.c
index b2f1ad1..776ed80 100644
--- a/src/codegen/codegen.c
+++ b/src/codegen/codegen.c
@@ -2228,10 +2228,54 @@ void codegen_node_single(ParserContext *ctx, ASTNode *node, FILE *out)
break;
}
case NODE_RETURN:
- fprintf(out, " return ");
- codegen_expression(ctx, node->ret.value, out);
- fprintf(out, ";\n");
+ {
+ int handled = 0;
+ // If returning a variable that implements Drop, we must zero it out
+ // to prevent the cleanup attribute from destroying the resource we just returned.
+ if (node->ret.value && node->ret.value->type == NODE_EXPR_VAR)
+ {
+ char *tname = infer_type(ctx, node->ret.value);
+ if (tname)
+ {
+ char *clean = tname;
+ if (strncmp(clean, "struct ", 7) == 0)
+ {
+ clean += 7;
+ }
+
+ ASTNode *def = find_struct_def(ctx, clean);
+ if (def && def->type_info && def->type_info->traits.has_drop)
+ {
+ fprintf(out, " return ({ ");
+ if (strstr(g_config.cc, "tcc"))
+ {
+ fprintf(out, "__typeof__(");
+ codegen_expression(ctx, node->ret.value, out);
+ fprintf(out, ")");
+ }
+ else
+ {
+ fprintf(out, "__auto_type");
+ }
+ fprintf(out, " _z_ret_mv = ");
+ codegen_expression(ctx, node->ret.value, out);
+ fprintf(out, "; memset(&");
+ codegen_expression(ctx, node->ret.value, out);
+ fprintf(out, ", 0, sizeof(_z_ret_mv)); _z_ret_mv; });\n");
+ handled = 1;
+ }
+ free(tname);
+ }
+ }
+
+ if (!handled)
+ {
+ fprintf(out, " return ");
+ codegen_expression(ctx, node->ret.value, out);
+ fprintf(out, ";\n");
+ }
break;
+ }
case NODE_EXPR_MEMBER:
{
codegen_expression(ctx, node->member.target, out);