summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/codegen/codegen.c30
-rw-r--r--src/codegen/codegen.h3
-rw-r--r--src/codegen/codegen_stmt.c15
-rw-r--r--src/codegen/codegen_utils.c81
-rw-r--r--src/parser/parser_expr.c11
5 files changed, 122 insertions, 18 deletions
diff --git a/src/codegen/codegen.c b/src/codegen/codegen.c
index b5aecfa..8f2b6c1 100644
--- a/src/codegen/codegen.c
+++ b/src/codegen/codegen.c
@@ -289,9 +289,23 @@ void codegen_expression(ParserContext *ctx, ASTNode *node, FILE *out)
else
{
fprintf(out, "(");
- codegen_expression(ctx, node->binary.left, out);
+ // Left side: Only move if NOT an assignment target
+ int is_assignment =
+ (node->binary.op[strlen(node->binary.op) - 1] == '=' &&
+ strcmp(node->binary.op, "==") != 0 && strcmp(node->binary.op, "!=") != 0 &&
+ strcmp(node->binary.op, "<=") != 0 && strcmp(node->binary.op, ">=") != 0);
+
+ if (is_assignment)
+ {
+ codegen_expression(ctx, node->binary.left, out);
+ }
+ else
+ {
+ codegen_expression_with_move(ctx, node->binary.left, out);
+ }
+
fprintf(out, " %s ", node->binary.op);
- codegen_expression(ctx, node->binary.right, out);
+ codegen_expression_with_move(ctx, node->binary.right, out);
fprintf(out, ")");
}
break;
@@ -408,7 +422,7 @@ void codegen_expression(ParserContext *ctx, ASTNode *node, FILE *out)
while (arg)
{
fprintf(out, ", ");
- codegen_expression(ctx, arg, out);
+ codegen_expression_with_move(ctx, arg, out);
arg = arg->next;
}
fprintf(out, "); })");
@@ -491,7 +505,7 @@ void codegen_expression(ParserContext *ctx, ASTNode *node, FILE *out)
while (arg)
{
fprintf(out, ", ");
- codegen_expression(ctx, arg, out);
+ codegen_expression_with_move(ctx, arg, out);
arg = arg->next;
}
fprintf(out, ")");
@@ -541,7 +555,7 @@ void codegen_expression(ParserContext *ctx, ASTNode *node, FILE *out)
while (arg)
{
fprintf(out, ", ");
- codegen_expression(ctx, arg, out);
+ codegen_expression_with_move(ctx, arg, out);
arg = arg->next;
}
fprintf(out, "); })");
@@ -583,7 +597,7 @@ void codegen_expression(ParserContext *ctx, ASTNode *node, FILE *out)
fprintf(out, ", ");
}
first = 0;
- codegen_expression(ctx, arg, out);
+ codegen_expression_with_move(ctx, arg, out);
arg = arg->next;
}
}
@@ -634,7 +648,7 @@ void codegen_expression(ParserContext *ctx, ASTNode *node, FILE *out)
fprintf(out, ", ");
}
first_field = 0;
- codegen_expression(ctx, curr, out);
+ codegen_expression_with_move(ctx, curr, out);
curr = curr->next;
}
fprintf(out, "}");
@@ -654,7 +668,7 @@ void codegen_expression(ParserContext *ctx, ASTNode *node, FILE *out)
}
else
{
- codegen_expression(ctx, arg, out);
+ codegen_expression_with_move(ctx, arg, out);
}
if (arg && arg->next)
diff --git a/src/codegen/codegen.h b/src/codegen/codegen.h
index d27356a..942de41 100644
--- a/src/codegen/codegen.h
+++ b/src/codegen/codegen.h
@@ -26,6 +26,9 @@ void emit_auto_type(ParserContext *ctx, ASTNode *init_expr, Token t, FILE *out);
char *codegen_type_to_string(Type *t);
void emit_func_signature(FILE *out, ASTNode *func, const char *name_override);
char *strip_template_suffix(const char *name);
+char *strip_template_suffix(const char *name);
+int emit_move_invalidation(ParserContext *ctx, ASTNode *node, FILE *out);
+void codegen_expression_with_move(ParserContext *ctx, ASTNode *node, FILE *out);
// Declaration emission (codegen_decl.c).
void emit_preamble(ParserContext *ctx, FILE *out);
diff --git a/src/codegen/codegen_stmt.c b/src/codegen/codegen_stmt.c
index 1cbd3a2..542a3c0 100644
--- a/src/codegen/codegen_stmt.c
+++ b/src/codegen/codegen_stmt.c
@@ -901,6 +901,11 @@ void codegen_node_single(ParserContext *ctx, ASTNode *node, FILE *out)
codegen_expression(ctx, node->var_decl.init_expr, out);
}
fprintf(out, ";\n");
+ if (node->var_decl.init_expr &&
+ emit_move_invalidation(ctx, node->var_decl.init_expr, out))
+ {
+ fprintf(out, ";\n");
+ }
if (node->type_info)
{
@@ -935,6 +940,11 @@ void codegen_node_single(ParserContext *ctx, ASTNode *node, FILE *out)
fprintf(out, " = ");
codegen_expression(ctx, node->var_decl.init_expr, out);
fprintf(out, ";\n");
+ if (node->var_decl.init_expr &&
+ emit_move_invalidation(ctx, node->var_decl.init_expr, out))
+ {
+ fprintf(out, ";\n");
+ }
}
else
{
@@ -949,6 +959,11 @@ void codegen_node_single(ParserContext *ctx, ASTNode *node, FILE *out)
fprintf(out, " = ");
codegen_expression(ctx, node->var_decl.init_expr, out);
fprintf(out, ";\n");
+ if (node->var_decl.init_expr &&
+ emit_move_invalidation(ctx, node->var_decl.init_expr, out))
+ {
+ fprintf(out, ";\n");
+ }
}
}
}
diff --git a/src/codegen/codegen_utils.c b/src/codegen/codegen_utils.c
index 3169eba..38ae409 100644
--- a/src/codegen/codegen_utils.c
+++ b/src/codegen/codegen_utils.c
@@ -706,3 +706,84 @@ void emit_func_signature(FILE *out, ASTNode *func, const char *name_override)
}
fprintf(out, ")");
}
+
+// Invalidate a moved-from variable by zeroing it out to prevent double-free
+int emit_move_invalidation(ParserContext *ctx, ASTNode *node, FILE *out)
+{
+ if (!node)
+ {
+ return 0;
+ }
+
+ // Check if it's a valid l-value we can memset
+ if (node->type != NODE_EXPR_VAR && node->type != NODE_EXPR_MEMBER)
+ {
+ return 0;
+ }
+
+ // Common logic to find type and check Drop
+ char *type_name = infer_type(ctx, node);
+ ASTNode *def = NULL;
+ if (type_name)
+ {
+ char *clean_type = type_name;
+ if (strncmp(clean_type, "struct ", 7) == 0)
+ {
+ clean_type += 7;
+ }
+ def = find_struct_def(ctx, clean_type);
+ }
+
+ if (def && def->type_info && def->type_info->traits.has_drop)
+ {
+ if (node->type == NODE_EXPR_VAR)
+ {
+ fprintf(out, "memset(&%s, 0, sizeof(%s))", node->var_ref.name, node->var_ref.name);
+ return 1;
+ }
+ else if (node->type == NODE_EXPR_MEMBER)
+ {
+ // For members: memset(&foo.bar, 0, sizeof(foo.bar))
+ fprintf(out, "memset(&");
+ codegen_expression(ctx, node, out);
+ fprintf(out, ", 0, sizeof(");
+ codegen_expression(ctx, node, out);
+ fprintf(out, "))");
+ return 1;
+ }
+ }
+ return 0;
+}
+
+// Emits expression, wrapping it in a move-invalidation block if it's a consuming variable usage
+void codegen_expression_with_move(ParserContext *ctx, ASTNode *node, FILE *out)
+{
+ if (node && (node->type == NODE_EXPR_VAR || node->type == NODE_EXPR_MEMBER))
+ {
+ // Re-use infer logic to see if we need invalidation
+ char *type_name = infer_type(ctx, node);
+ ASTNode *def = NULL;
+ if (type_name)
+ {
+ char *clean_type = type_name;
+ if (strncmp(clean_type, "struct ", 7) == 0)
+ {
+ clean_type += 7;
+ }
+ def = find_struct_def(ctx, clean_type);
+ }
+
+ if (def && def->type_info && def->type_info->traits.has_drop)
+ {
+ fprintf(out, "({ __typeof__(");
+ codegen_expression(ctx, node, out);
+ fprintf(out, ") _mv = ");
+ codegen_expression(ctx, node, out);
+ fprintf(out, "; ");
+ emit_move_invalidation(ctx, node, out);
+ fprintf(out, "; _mv; })");
+ return;
+ }
+ }
+ codegen_expression(ctx, node, out);
+}
diff --git a/src/parser/parser_expr.c b/src/parser/parser_expr.c
index 455baa3..50d96f0 100644
--- a/src/parser/parser_expr.c
+++ b/src/parser/parser_expr.c
@@ -4884,8 +4884,6 @@ ASTNode *parse_expr_prec(ParserContext *ctx, Lexer *l, Precedence min_prec)
bin->binary.op = token_strdup(op);
}
- fprintf(stderr, "DEBUG: Binary Loop Op: %s\n", bin->binary.op);
-
if (strcmp(bin->binary.op, "/") == 0 || strcmp(bin->binary.op, "%") == 0)
{
if (rhs->type == NODE_EXPR_LITERAL && rhs->literal.type_kind == LITERAL_INT &&
@@ -5285,8 +5283,6 @@ ASTNode *parse_expr_prec(ParserContext *ctx, Lexer *l, Precedence min_prec)
}
}
- fprintf(stderr, "DEBUG: Past Method Check Op=%s\n", bin->binary.op);
-
// Standard Type Checking (if no overload found)
if (lhs->type_info && rhs->type_info)
{
@@ -5577,7 +5573,7 @@ ASTNode *parse_arrow_lambda_single(ParserContext *ctx, Lexer *l, char *param_nam
{
if (param_name[0] == 'x')
{
- fprintf(stderr, "DEBUG: Updating return type to %d\n", ret_val->type_info->kind);
+ // fprintf(stderr, "DEBUG: Updating return type to %d\n", ret_val->type_info->kind);
}
// Update return type
if (t->inner)
@@ -5606,11 +5602,6 @@ ASTNode *parse_arrow_lambda_single(ParserContext *ctx, Lexer *l, char *param_nam
}
else
{
- if (param_name[0] == 'x')
- {
- fprintf(stderr, "DEBUG: Fallback! sym=%p kind=%d\n", sym,
- sym && sym->type_info ? sym->type_info->kind : -1);
- }
// Fallback to int if still unknown
if (lambda->lambda.param_types[0])
{