From 576914aee1565618d8448a2bbc3cbef0c4acc4d1 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 5 Aug 2022 11:57:33 +0100 Subject: Make `unreachable()` a built-in compiler-level procedure --- src/check_stmt.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'src/check_stmt.cpp') diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index a6f6f1a7d..451325324 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -1,8 +1,5 @@ -bool is_diverging_stmt(Ast *stmt) { - if (stmt->kind != Ast_ExprStmt) { - return false; - } - Ast *expr = unparen_expr(stmt->ExprStmt.expr); +bool is_diverging_expr(Ast *expr) { + expr = unparen_expr(expr); if (expr->kind != Ast_CallExpr) { return false; } @@ -26,6 +23,12 @@ bool is_diverging_stmt(Ast *stmt) { t = base_type(t); return t != nullptr && t->kind == Type_Proc && t->Proc.diverging; } +bool is_diverging_stmt(Ast *stmt) { + if (stmt->kind != Ast_ExprStmt) { + return false; + } + return is_diverging_expr(stmt->ExprStmt.expr); +} bool contains_deferred_call(Ast *node) { if (node->viral_state_flags & ViralStateFlag_ContainsDeferredProcedure) { -- cgit v1.2.3 From d56789e5a77e597ec09d7ffed46ba65543d25750 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 24 Aug 2022 15:58:20 +0100 Subject: Add very basic escape analysis on `return` values --- src/check_stmt.cpp | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) (limited to 'src/check_stmt.cpp') diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index 451325324..5673206f3 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -1396,6 +1396,22 @@ bool check_stmt_internal_builtin_proc_id(Ast *expr, BuiltinProcId *id_) { return id != BuiltinProc_Invalid; } +bool check_expr_is_stack_variable(Ast *expr) { + Entity *e = entity_of_node(expr); + if (e && e->kind == Entity_Variable) { + if (e->flags & EntityFlag_Static) { + // okay + } else if (e->Variable.thread_local_model.len != 0) { + // okay + } else if (e->scope) { + if ((e->scope->flags & (ScopeFlag_Global|ScopeFlag_File)) == 0) { + return true; + } + } + } + return false; +} + void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) { u32 mod_flags = flags & (~Stmt_FallthroughAllowed); switch (node->kind) { @@ -1678,6 +1694,29 @@ void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) { if (is_type_untyped(o->type)) { update_untyped_expr_type(ctx, o->expr, e->type, true); } + + + // NOTE(bill): This is very basic escape analysis + // This needs to be improved tremendously, and a lot of it done during the + // middle-end (or LLVM side) to improve checks and error messages + Ast *expr = unparen_expr(o->expr); + if (expr->kind == Ast_UnaryExpr && expr->UnaryExpr.op.kind == Token_And) { + Ast *x = unparen_expr(expr->UnaryExpr.expr); + if (x->kind == Ast_CompoundLit) { + error(expr, "Cannot return the address to a stack value from a procedure"); + } else if (x->kind == Ast_IndexExpr) { + Ast *array = x->IndexExpr.expr; + if (is_type_array_like(type_of_expr(array)) && check_expr_is_stack_variable(array)) { + gbString t = type_to_string(type_of_expr(array)); + error(expr, "Cannot return the address to an element of stack variable from a procedure, of type %s", t); + gb_string_free(t); + } + } else { + if (check_expr_is_stack_variable(x)) { + error(expr, "Cannot return the address to a stack variable from a procedure"); + } + } + } } } case_end; -- cgit v1.2.3 From af1b3b6368ffe690ba7f395920fd658b575fa042 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 24 Aug 2022 16:03:04 +0100 Subject: Correct `check_expr_is_stack_variable` --- src/check_stmt.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/check_stmt.cpp') diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index 5673206f3..133ca581f 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -1397,6 +1397,7 @@ bool check_stmt_internal_builtin_proc_id(Ast *expr, BuiltinProcId *id_) { } bool check_expr_is_stack_variable(Ast *expr) { + expr = unparen_expr(expr); Entity *e = entity_of_node(expr); if (e && e->kind == Entity_Variable) { if (e->flags & EntityFlag_Static) { @@ -1404,7 +1405,7 @@ bool check_expr_is_stack_variable(Ast *expr) { } else if (e->Variable.thread_local_model.len != 0) { // okay } else if (e->scope) { - if ((e->scope->flags & (ScopeFlag_Global|ScopeFlag_File)) == 0) { + if ((e->scope->flags & (ScopeFlag_Global|ScopeFlag_File|ScopeFlag_Type)) == 0) { return true; } } -- cgit v1.2.3 From 776927709bbf274a8c7d63dcff250726a90cf3a3 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 26 Aug 2022 12:11:27 +0100 Subject: Check for `using` variables --- src/check_stmt.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/check_stmt.cpp') diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index 133ca581f..884c7b5ae 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -1400,7 +1400,7 @@ bool check_expr_is_stack_variable(Ast *expr) { expr = unparen_expr(expr); Entity *e = entity_of_node(expr); if (e && e->kind == Entity_Variable) { - if (e->flags & EntityFlag_Static) { + if (e->flags & (EntityFlag_Static|EntityFlag_Using)) { // okay } else if (e->Variable.thread_local_model.len != 0) { // okay -- cgit v1.2.3 From 8fd5bef0bd3dd149219acb866b717f80dd7b8061 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 26 Aug 2022 12:14:04 +0100 Subject: Fix #1977 --- src/check_stmt.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src/check_stmt.cpp') diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index 884c7b5ae..d741ceabf 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -1464,6 +1464,12 @@ void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) { AstSelectorCallExpr *se = &expr->SelectorCallExpr; ast_node(ce, CallExpr, se->call); Type *t = base_type(type_of_expr(ce->proc)); + if (t == nullptr) { + gbString expr_str = expr_to_string(ce->proc); + error(node, "'%s' is not a value field nor procedure", expr_str); + gb_string_free(expr_str); + return; + } if (t->kind == Type_Proc) { do_require = t->Proc.require_results; } else if (check_stmt_internal_builtin_proc_id(ce->proc, &builtin_id)) { -- cgit v1.2.3