From be511b26cd6e1a78118f615e3028f8677ba6ba5f Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Fri, 6 Jun 2025 20:11:58 +0200 Subject: [PATCH] Additional fixes on $define --- releasenotes.md | 1 + src/compiler/compiler_internal.h | 1 + src/compiler/sema_stmts.c | 13 ++++++++--- src/compiler/semantic_analyser.c | 2 ++ .../errors/catch_err_single_error.c3 | 22 +++++++++++++++++++ 5 files changed, 36 insertions(+), 3 deletions(-) create mode 100644 test/test_suite/errors/catch_err_single_error.c3 diff --git a/releasenotes.md b/releasenotes.md index d9a7ce09f..39c05d295 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -14,6 +14,7 @@ - Added support for custom file extensions in project.json targets. - `$eval` now also works with `@foo`, `#foo`, `$Foo` and `$foo` parameters #2114. - `@sprintf` macro (based on the `$$sprintf` builtin) allows compile time format strings #1874. +- Improve error reports when encountering a broken "if-catch". ### Fixes - `-2147483648`, MIN literals work correctly. diff --git a/src/compiler/compiler_internal.h b/src/compiler/compiler_internal.h index 299a17c2a..5b61ac865 100644 --- a/src/compiler/compiler_internal.h +++ b/src/compiler/compiler_internal.h @@ -1542,6 +1542,7 @@ typedef struct DynamicScope_ bool allow_dead_code : 1; bool jump_end : 1; bool is_dead : 1; + bool is_invalid : 1; ScopeFlags flags; unsigned label_start; unsigned current_local; diff --git a/src/compiler/sema_stmts.c b/src/compiler/sema_stmts.c index d2a414846..a5a96aad5 100644 --- a/src/compiler/sema_stmts.c +++ b/src/compiler/sema_stmts.c @@ -1029,8 +1029,7 @@ static inline bool sema_analyse_last_cond(SemaContext *context, Expr *expr, Cond case EXPR_TRY_UNWRAP_CHAIN: if (cond_type != COND_TYPE_UNWRAP_BOOL) { - SEMA_ERROR(expr, "Try unwrapping is only allowed inside of a 'while' or 'if' conditional."); - return false; + RETURN_SEMA_ERROR(expr, "Try unwrapping is only allowed inside of a 'while' or 'if' conditional."); } return sema_analyse_try_unwrap_chain(context, expr, cond_type, result); case EXPR_CATCH_UNRESOLVED: @@ -1038,7 +1037,11 @@ static inline bool sema_analyse_last_cond(SemaContext *context, Expr *expr, Cond { RETURN_SEMA_ERROR(expr, "Catch unwrapping is only allowed inside of a 'while' or 'if' conditional, maybe '@catch()' will do what you need?"); } - return sema_analyse_catch_unwrap(context, expr); + if (!sema_analyse_catch_unwrap(context, expr)) + { + context->active_scope.is_invalid = true; + return false; + } default: break; } @@ -1876,6 +1879,7 @@ static inline bool sema_analyse_if_stmt(SemaContext *context, Ast *statement) AstId else_id = statement->if_stmt.else_body; Ast *else_body = else_id ? astptr(else_id) : NULL; CondResult result = COND_MISSING; + bool is_invalid = false; SCOPE_OUTER_START success = sema_analyse_cond(context, cond, COND_TYPE_UNWRAP_BOOL, &result); @@ -1933,7 +1937,9 @@ static inline bool sema_analyse_if_stmt(SemaContext *context, Ast *statement) END: context_pop_defers_and_replace_ast(context, statement); + is_invalid = context->active_scope.is_invalid; SCOPE_OUTER_END; + if (is_invalid) context->active_scope.is_invalid = is_invalid; if (!success) return false; if (then_jump) { @@ -3081,6 +3087,7 @@ static inline bool sema_analyse_statement_inner(SemaContext *context, Ast *state bool sema_analyse_statement(SemaContext *context, Ast *statement) { + if (context->active_scope.is_invalid) return false; if (statement->ast_kind == AST_POISONED) return false; bool dead_code = context->active_scope.jump_end; unsigned returns = vec_size(context->returns); diff --git a/src/compiler/semantic_analyser.c b/src/compiler/semantic_analyser.c index 3f529c52e..0cac2cdb0 100644 --- a/src/compiler/semantic_analyser.c +++ b/src/compiler/semantic_analyser.c @@ -17,6 +17,7 @@ void context_change_scope_with_flags(SemaContext *context, ScopeFlags flags) } bool scope_is_dead = context->active_scope.is_dead; + bool scope_is_invalid = context->active_scope.is_invalid; Ast *previous_defer = context->active_scope.in_defer; AstId parent_defer = context->active_scope.defer_last; unsigned last_local = context->active_scope.current_local; @@ -38,6 +39,7 @@ void context_change_scope_with_flags(SemaContext *context, ScopeFlags flags) .allow_dead_code = false, .jump_end = false, .is_dead = scope_is_dead, + .is_invalid = scope_is_invalid, .depth = depth, .current_local = last_local, .label_start = label_start, diff --git a/test/test_suite/errors/catch_err_single_error.c3 b/test/test_suite/errors/catch_err_single_error.c3 new file mode 100644 index 000000000..6cbf30699 --- /dev/null +++ b/test/test_suite/errors/catch_err_single_error.c3 @@ -0,0 +1,22 @@ +module foo; + +fn void foo() +{ + int? x; + if (catch err) + { + z = 1233; // #error: could not be found, did you spell it right + return; + } + int y = x; +} + +fn void main() +{ + int? x; + if (catch err = BAR) // #error: 'BAR' could not be found + { + return; + } + int y = x; +} \ No newline at end of file