commit 6c6bcd46c2d73f2f4ebacbd38d8bdb1dc1e62490
parent 73be71e38e2f009914a8f1c2994377da02805581
Author: Steven Guikal <void@fluix.dev>
Date: Wed, 10 Mar 2021 14:08:45 -0500
Call deferred functions before noreturn functions
Diffstat:
2 files changed, 27 insertions(+), 0 deletions(-)
diff --git a/src/gen.c b/src/gen.c
@@ -1044,6 +1044,17 @@ gen_expr_call(struct gen_context *ctx,
ftype->func.result, true), "returns.%d");
call.out = qval_dup(&result);
}
+ if (ftype->func.flags & FN_NORETURN) {
+ struct gen_scope_context *scope = ctx->scope;
+ while (scope) {
+ gen_defers(ctx, scope);
+ if (scope->class == SCOPE_FUNC) {
+ break;
+ }
+ scope = scope->parent;
+ }
+ assert(scope);
+ }
while (carg) {
arg = *next = xcalloc(1, sizeof(struct qbe_arguments));
diff --git a/tests/16-defer.ha b/tests/16-defer.ha
@@ -1,3 +1,5 @@
+use rt;
+
let x: int = 10;
fn basics() void = {
@@ -47,10 +49,24 @@ fn control() void = {
assert(x == 1);
};
+fn noreturn() void = {
+ defer x = 30;
+ for (true) {
+ defer x = 20;
+ exit();
+ };
+};
+
+@noreturn fn exit() void = {
+ assert(x == 30);
+ rt::exit(0);
+};
+
export fn main() void = {
basics();
assert(x == 20);
scope();
loops();
control();
+ noreturn();
};