aboutsummaryrefslogtreecommitdiff
path: root/src/check_stmt.cpp
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2020-09-23 11:16:33 +0100
committergingerBill <bill@gingerbill.org>2020-09-23 11:16:33 +0100
commit4844dd4d96f0921f44e70c9960d3e4476aad7115 (patch)
treee10abe007fd353ba4304ab88b7f6961f2a21d28f /src/check_stmt.cpp
parent609af3a6513f0a35823089c090077171e87546c5 (diff)
Add check to block statements to see if they only contain one statement, a value declaration, and err.
Diffstat (limited to 'src/check_stmt.cpp')
-rw-r--r--src/check_stmt.cpp60
1 files changed, 60 insertions, 0 deletions
diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp
index 3e8c8802b..e6902f6a3 100644
--- a/src/check_stmt.cpp
+++ b/src/check_stmt.cpp
@@ -1295,6 +1295,65 @@ void check_type_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags) {
}
}
+void check_block_stmt_for_errors(CheckerContext *ctx, Ast *body) {
+ if (body->kind != Ast_BlockStmt) {
+ return;
+ }
+ ast_node(bs, BlockStmt, body);
+ // NOTE(bill, 2020-09-23): This logic is prevent common erros with block statements
+ // e.g. if cond { x := 123; } // this is an error
+ if (body->scope != nullptr && body->scope->elements.entries.count > 0) {
+ if (body->scope->parent->node != nullptr) {
+ switch (body->scope->parent->node->kind) {
+ case Ast_IfStmt:
+ case Ast_ForStmt:
+ case Ast_RangeStmt:
+ case Ast_InlineRangeStmt:
+ case Ast_SwitchStmt:
+ case Ast_TypeSwitchStmt:
+ // TODO(bill): Is this a correct checking system?
+ break;
+ default:
+ return;
+ }
+ }
+
+ isize stmt_count = 0;
+ Ast *the_stmt = nullptr;
+ for_array(i, bs->stmts) {
+ Ast *stmt = bs->stmts[i];
+ GB_ASSERT(stmt != nullptr);
+ switch (stmt->kind) {
+ case_ast_node(es, EmptyStmt, stmt);
+ case_end;
+ case_ast_node(bs, BadStmt, stmt);
+ case_end;
+ case_ast_node(bd, BadDecl, stmt);
+ case_end;
+ default:
+ the_stmt = stmt;
+ stmt_count += 1;
+ break;
+ }
+ }
+
+ if (stmt_count == 1) {
+ if (the_stmt->kind == Ast_ValueDecl) {
+ for_array(i, the_stmt->ValueDecl.names) {
+ Ast *name = the_stmt->ValueDecl.names[i];
+ if (name->kind != Ast_Ident) {
+ continue;
+ }
+ String n = name->Ident.token.string;
+ if (n != "_") {
+ error(name, "'%.*s' declared but not used", LIT(n));
+ }
+ }
+ }
+ }
+ }
+}
+
void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) {
u32 mod_flags = flags & (~Stmt_FallthroughAllowed);
switch (node->kind) {
@@ -1505,6 +1564,7 @@ void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) {
check_label(ctx, bs->label, node);
check_stmt_list(ctx, bs->stmts, flags);
+ check_block_stmt_for_errors(ctx, node);
check_close_scope(ctx);
case_end;