aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2021-06-16 12:07:24 +0100
committergingerBill <bill@gingerbill.org>2021-06-16 12:07:24 +0100
commit41f2539484931cd73dfca36dcbdba01e954fc350 (patch)
treea76cd589c96065e2f2becb53004d564b0c6f5ff3
parent8f57bb07991930f242ec4ab4d9fb3a851a4e9662 (diff)
Improve logic for diverging procedures by checking if it terminates
-rw-r--r--core/runtime/core.odin8
-rw-r--r--src/check_decl.cpp11
-rw-r--r--src/check_stmt.cpp23
3 files changed, 31 insertions, 11 deletions
diff --git a/core/runtime/core.odin b/core/runtime/core.odin
index 8e71e1fa0..2dabbc90f 100644
--- a/core/runtime/core.odin
+++ b/core/runtime/core.odin
@@ -255,7 +255,7 @@ Source_Code_Location :: struct {
procedure: string,
}
-Assertion_Failure_Proc :: #type proc(prefix, message: string, loc: Source_Code_Location);
+Assertion_Failure_Proc :: #type proc(prefix, message: string, loc: Source_Code_Location) -> !;
// Allocation Stuff
Allocator_Mode :: enum byte {
@@ -483,7 +483,7 @@ __init_context :: proc "contextless" (c: ^Context) {
c.logger.data = nil;
}
-default_assertion_failure_proc :: proc(prefix, message: string, loc: Source_Code_Location) {
+default_assertion_failure_proc :: proc(prefix, message: string, loc: Source_Code_Location) -> ! {
print_caller_location(loc);
print_string(" ");
print_string(prefix);
@@ -492,6 +492,6 @@ default_assertion_failure_proc :: proc(prefix, message: string, loc: Source_Code
print_string(message);
}
print_byte('\n');
- debug_trap();
- // trap();
+ // debug_trap();
+ trap();
}
diff --git a/src/check_decl.cpp b/src/check_decl.cpp
index 1a87b57b8..583c4f133 100644
--- a/src/check_decl.cpp
+++ b/src/check_decl.cpp
@@ -1297,13 +1297,21 @@ void check_proc_body(CheckerContext *ctx_, Token token, DeclInfo *decl, Type *ty
error(bs->close, "Missing return statement at the end of the procedure");
}
}
+ } else if (type->Proc.diverging) {
+ if (!check_is_terminating(body, str_lit(""))) {
+ if (token.kind == Token_Ident) {
+ error(bs->close, "Missing diverging call at the end of the procedure '%.*s'", LIT(token.string));
+ } else {
+ // NOTE(bill): Anonymous procedure (lambda)
+ error(bs->close, "Missing diverging call at the end of the procedure");
+ }
+ }
}
}
check_close_scope(ctx);
check_scope_usage(ctx->checker, ctx->scope);
-#if 1
if (decl->parent != nullptr) {
Scope *ps = decl->parent->scope;
if (ps->flags & (ScopeFlag_File & ScopeFlag_Pkg & ScopeFlag_Global)) {
@@ -1321,7 +1329,6 @@ void check_proc_body(CheckerContext *ctx_, Token token, DeclInfo *decl, Type *ty
}
}
}
-#endif
}
diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp
index 4fdece852..24960b33c 100644
--- a/src/check_stmt.cpp
+++ b/src/check_stmt.cpp
@@ -247,11 +247,24 @@ bool check_is_terminating(Ast *node, String const &label) {
case_ast_node(ws, WhenStmt, node);
// TODO(bill): Is this logic correct for when statements?
- if (ws->else_stmt != nullptr) {
- if (check_is_terminating(ws->body, label) &&
- check_is_terminating(ws->else_stmt, label)) {
- return true;
- }
+ auto const &tv = ws->cond->tav;
+ if (tv.mode != Addressing_Constant) {
+ // NOTE(bill): Check the things regardless as a bug occurred earlier
+ if (ws->else_stmt != nullptr) {
+ if (check_is_terminating(ws->body, label) &&
+ check_is_terminating(ws->else_stmt, label)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ if (tv.value.kind == ExactValue_Bool) {
+ if (tv.value.value_bool) {
+ return check_is_terminating(ws->body, label);
+ } else {
+ return check_is_terminating(ws->else_stmt, label);
+ }
}
case_end;