aboutsummaryrefslogtreecommitdiff
path: root/src/check_stmt.cpp
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2021-06-16 11:41:29 +0100
committergingerBill <bill@gingerbill.org>2021-06-16 11:41:29 +0100
commit8f57bb07991930f242ec4ab4d9fb3a851a4e9662 (patch)
tree8c5c6ed78a4b59663ab0ee89bebb5785f1be4ba6 /src/check_stmt.cpp
parent84a4188c7214fdf0270f9f835e626fa214a98df0 (diff)
Add unreachable detection for deferred statements in a scope which contains a diverging procedure call
```odin { defer foo(); // Unreachable defer statement due to diverging procedure call at the end of the current scope os.exit(0); } ```
Diffstat (limited to 'src/check_stmt.cpp')
-rw-r--r--src/check_stmt.cpp44
1 files changed, 44 insertions, 0 deletions
diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp
index c6a9a5d93..4fdece852 100644
--- a/src/check_stmt.cpp
+++ b/src/check_stmt.cpp
@@ -27,6 +27,37 @@ bool is_diverging_stmt(Ast *stmt) {
return t != nullptr && t->kind == Type_Proc && t->Proc.diverging;
}
+bool contains_deferred_call(Ast *node) {
+ if (node->viral_state_flags & ViralStateFlag_ContainsDeferredProcedure) {
+ return true;
+ }
+ switch (node->kind) {
+ case Ast_ExprStmt:
+ return contains_deferred_call(node->ExprStmt.expr);
+ case Ast_AssignStmt:
+ for_array(i, node->AssignStmt.rhs) {
+ if (contains_deferred_call(node->AssignStmt.rhs[i])) {
+ return true;
+ }
+ }
+ for_array(i, node->AssignStmt.lhs) {
+ if (contains_deferred_call(node->AssignStmt.lhs[i])) {
+ return true;
+ }
+ }
+ break;
+ case Ast_ValueDecl:
+ for_array(i, node->ValueDecl.values) {
+ if (contains_deferred_call(node->ValueDecl.values[i])) {
+ return true;
+ }
+ }
+ break;
+ }
+
+ return false;
+}
+
void check_stmt_list(CheckerContext *ctx, Slice<Ast *> const &stmts, u32 flags) {
if (stmts.count == 0) {
return;
@@ -86,6 +117,19 @@ void check_stmt_list(CheckerContext *ctx, Slice<Ast *> const &stmts, u32 flags)
}
break;
}
+ } else if (i+1 == max_non_constant_declaration) {
+ if (is_diverging_stmt(n)) {
+ for (isize j = 0; j < i; j++) {
+ Ast *stmt = stmts[j];
+ if (stmt->kind == Ast_ValueDecl && !stmt->ValueDecl.is_mutable) {
+
+ } else if (stmt->kind == Ast_DeferStmt) {
+ error(stmt, "Unreachable defer statement due to diverging procedure call at the end of the current scope");
+ } else if (contains_deferred_call(stmt)) {
+ error(stmt, "Unreachable deferred procedure call due to a diverging procedure call at the end of the current scope");
+ }
+ }
+ }
}
}
}