aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2024-11-30 14:16:08 -0500
committerBruce Hill <bruce@bruce-hill.com>2024-11-30 14:16:08 -0500
commit18c1ce7fd18c02abda235781db780c9d5fe73ad4 (patch)
tree32aaf2bce95564fade698f07434fa92d6cb98938
parent566f97307dd5d960d4b9ce2f7308bc9f0ec016c1 (diff)
Fix for non-idempotent update assignments
-rw-r--r--compile.c20
1 files changed, 17 insertions, 3 deletions
diff --git a/compile.c b/compile.c
index 8c82c4bc..bc035343 100644
--- a/compile.c
+++ b/compile.c
@@ -608,10 +608,15 @@ CORD compile_statement(env_t *env, ast_t *ast)
}
} else if (test->expr->tag == UpdateAssign) {
type_t *lhs_t = get_type(env, Match(test->expr, UpdateAssign)->lhs);
+ auto update = Match(test->expr, UpdateAssign);
+ ast_t *update_var = WrapAST(ast, UpdateAssign,
+ .lhs=WrapAST(update->lhs, Index, .indexed=WrapAST(update->lhs, InlineCCode, .code="expr", .type=Type(PointerType, lhs_t))),
+ .op=update->op, .rhs=update->rhs);
return CORD_asprintf(
- "test(({%r %r;}), %r, %r, %ld, %ld);",
- compile_statement(env, test->expr),
- compile_lvalue(env, Match(test->expr, UpdateAssign)->lhs),
+ "test(({%r = &(%r); %r; *expr;}), %r, %r, %ld, %ld);",
+ compile_declaration(Type(PointerType, lhs_t), "expr"),
+ compile_lvalue(env, update->lhs),
+ compile_statement(env, update_var),
compile_type_info(env, lhs_t),
CORD_quoted(test->output),
(int64_t)(test->expr->start - test->expr->file->text),
@@ -676,6 +681,15 @@ CORD compile_statement(env_t *env, ast_t *ast)
}
case UpdateAssign: {
auto update = Match(ast, UpdateAssign);
+ if (!is_idempotent(update->lhs)) {
+ type_t *lhs_t = get_type(env, update->lhs);
+ return CORD_all("{ ", compile_declaration(Type(PointerType, lhs_t), "update_lhs"), " = &",
+ compile_lvalue(env, update->lhs), ";\n",
+ "*update_lhs = ", compile(env, WrapAST(ast, BinaryOp,
+ .lhs=WrapAST(update->lhs, InlineCCode, .code="(*update_lhs)", .type=lhs_t),
+ .op=update->op, .rhs=update->rhs)), "; }");
+ }
+
CORD lhs = compile_lvalue(env, update->lhs);
CORD method_call = compile_math_method(env, update->op, update->lhs, update->rhs, get_type(env, update->lhs));