- Using @noreturn in a trailing body macro would not work properly #2326.

- Bug when reporting error in a macro return would crash the compiler #2326.
- Short body return expression would not have the correct span.
This commit is contained in:
Christoffer Lerno
2025-07-26 02:03:02 +02:00
parent a673b4ad66
commit 0bc546595d
5 changed files with 23 additions and 2 deletions

View File

@@ -74,6 +74,9 @@
- Regression: Chaining an optional together with contracts could in some cases lose the optional.
- `char[*] b = *(char[*]*)&a;` would crash the compiler if `a` was a slice. #2320
- Implicitly cast const int expressions would sometimes not be detected as compile time const.
- Using @noreturn in a short body macro would not work properly #2326.
- Bug when reporting error in a macro return would crash the compiler #2326.
- Short body return expression would not have the correct span.
### Stdlib changes
- Improve contract for readline. #2280

View File

@@ -1077,6 +1077,7 @@ static inline Ast *parse_return_stmt(ParseContext *c)
if (!tok_is(c, TOKEN_EOS))
{
ASSIGN_EXPR_OR_RET(ast->return_stmt.expr, parse_expr(c), poisoned_ast);
RANGE_EXTEND_PREV(ast);
}
CONSUME_EOS_OR_RET(poisoned_ast);
return ast;
@@ -1532,6 +1533,7 @@ Ast *parse_short_body(ParseContext *c, TypeInfoId return_type, bool is_regular_f
TypeInfo *rtype = return_type ? type_infoptr(return_type) : NULL;
bool is_void_return = rtype && rtype->resolve_status == RESOLVE_DONE && rtype->type->type_kind == TYPE_VOID;
ASSIGN_EXPR_OR_RET(Expr *expr, parse_expr(c), poisoned_ast);
ret->span = expr->span;
if (expr->expr_kind == EXPR_CALL && expr->call_expr.macro_body)
{
ret->ast_kind = AST_EXPR_STMT;
@@ -1548,7 +1550,7 @@ Ast *parse_short_body(ParseContext *c, TypeInfoId return_type, bool is_regular_f
}
ret->return_stmt.expr = expr;
END:;
RANGE_EXTEND_PREV(ast);
if (is_regular_fn)
{
CONSUME_EOS_OR_RET(poisoned_ast);

View File

@@ -2809,7 +2809,7 @@ bool sema_expr_analyse_macro_call(SemaContext *context, Expr *call_expr, Expr *s
}
else if (is_no_return)
{
SEMA_ERROR(context->block_returns[0], "Return used despite macro being marked '@noreturn'.");
SEMA_ERROR(macro_context.block_returns[0], "Return used despite macro being marked '@noreturn'.");
goto EXIT_FAIL;
}

View File

@@ -575,6 +575,13 @@ static inline bool sema_analyse_block_exit_stmt(SemaContext *context, Ast *state
if (!sema_analyse_expr(context, ret_expr)) return false;
}
if (!sema_check_return_matches_opt_returns(context, ret_expr)) return false;
if (ret_expr->expr_kind == EXPR_CALL && ret_expr->call_expr.no_return)
{
statement->ast_kind = AST_EXPR_STMT;
statement->expr_stmt = ret_expr;
sema_inline_return_defers(context, statement, context->block_return_defer);
return true;
}
}
else
{

View File

@@ -0,0 +1,9 @@
import std;
macro @gogo_abort() @noreturn => os::exit(1);
fn void main()
{
File? f = file::open("/tmp/ooo", "w");
if (catch err = f) @gogo_abort();
File g = f;
}