mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 07:38:48 +00:00
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);
}
```
This commit is contained in:
@@ -27,6 +27,37 @@ bool is_diverging_stmt(Ast *stmt) {
|
|||||||
return t != nullptr && t->kind == Type_Proc && t->Proc.diverging;
|
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) {
|
void check_stmt_list(CheckerContext *ctx, Slice<Ast *> const &stmts, u32 flags) {
|
||||||
if (stmts.count == 0) {
|
if (stmts.count == 0) {
|
||||||
return;
|
return;
|
||||||
@@ -86,6 +117,19 @@ void check_stmt_list(CheckerContext *ctx, Slice<Ast *> const &stmts, u32 flags)
|
|||||||
}
|
}
|
||||||
break;
|
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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user