From cdc1656f3ab41c094625560aa48fe44b6fd63794 Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Thu, 9 Jan 2025 01:28:30 +0100 Subject: [PATCH] `#foo` style arguments were not type checked when given a type. #1790 --- lib/std/core/mem.c3 | 12 +++++++----- releasenotes.md | 1 + src/compiler/llvm_codegen_internal_impl.h | 1 - src/compiler/sema_decls.c | 13 +++++-------- src/compiler/sema_expr.c | 11 +++++++++++ test/test_suite/functions/macro_expr_type.c3 | 7 +++++++ 6 files changed, 31 insertions(+), 14 deletions(-) create mode 100644 test/test_suite/functions/macro_expr_type.c3 diff --git a/lib/std/core/mem.c3 b/lib/std/core/mem.c3 index 44b765a69..c7ed62a00 100644 --- a/lib/std/core/mem.c3 +++ b/lib/std/core/mem.c3 @@ -550,19 +550,21 @@ fn void temp_pop(TempState old_state) allocator::thread_temp_allocator = old_state.old; } -macro void @pool(TempAllocator* #other_temp = null; @body) @builtin +<* + @require @is_empty_macro_slot(#other_temp) ||| $assignable(#other_temp, Allocator) "Must be an allocator" + *> +macro void @pool(#other_temp = EMPTY_MACRO_SLOT; @body) @builtin { TempAllocator* current = allocator::temp(); - var $has_arg = !$is_const(#other_temp); - $if $has_arg: + $if @is_valid_macro_slot(#other_temp): TempAllocator* original = current; - if (current == (void*)#other_temp) current = allocator::temp_allocator_next(); + if (current == #other_temp.ptr) current = allocator::temp_allocator_next(); $endif usz mark = current.used; defer { current.reset(mark); - $if $has_arg: + $if @is_valid_macro_slot(#other_temp): allocator::thread_temp_allocator = original; $endif; } diff --git a/releasenotes.md b/releasenotes.md index 3384c490b..9a01f6dd8 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -64,6 +64,7 @@ - Macros with trailing bodys aren't allowed as the single statement after a while loop with no body #1772. - Deref subscripts as needed for macro ref method arguments. #1789 - Change ordering to simplify adding methods to type in conditional modules. +- `#foo` style arguments were not type checked when given a type. #1790 ### Stdlib changes - Increase BitWriter.write_bits limit up to 32 bits. diff --git a/src/compiler/llvm_codegen_internal_impl.h b/src/compiler/llvm_codegen_internal_impl.h index c5c10e2e1..3f944a2fc 100644 --- a/src/compiler/llvm_codegen_internal_impl.h +++ b/src/compiler/llvm_codegen_internal_impl.h @@ -357,7 +357,6 @@ INLINE void llvm_emit_statement_chain(GenContext *c, AstId current) { while (current) { - llvm_emit_stmt(c, ast_next(¤t)); } } diff --git a/src/compiler/sema_decls.c b/src/compiler/sema_decls.c index 14accfdfa..fdd7a2502 100755 --- a/src/compiler/sema_decls.c +++ b/src/compiler/sema_decls.c @@ -4132,19 +4132,16 @@ bool sema_analyse_var_decl(SemaContext *context, Decl *decl, bool local) decl->type = type_add_optional(init->type, IS_OPTIONAL(decl)); } - Expr *init_expr = decl->var.init_expr; - // 2. Check const-ness - if (global_level_var && !expr_is_runtime_const(init_expr)) + if (global_level_var && !expr_is_runtime_const(init)) { - SEMA_ERROR(init_expr, "The expression must be a constant value."); - expr_is_runtime_const(init_expr); + SEMA_ERROR(init, "The expression must be a constant value."); return decl_poison(decl); } - if (global_level_var || !type_is_abi_aggregate(init_expr->type)) sema_cast_const(init_expr); - if (expr_is_const(init_expr)) + if (global_level_var || !type_is_abi_aggregate(init->type)) sema_cast_const(init); + if (expr_is_const(init)) { - init_expr->const_expr.is_hex = false; + init->const_expr.is_hex = false; } } EXIT_OK:; diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index bdd3ed5ec..0f6495ab6 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -1390,6 +1390,14 @@ static bool sema_analyse_parameter(SemaContext *context, Expr *arg, Decl *param, } break; case VARDECL_PARAM_EXPR: + if (param->type) + { + if (!sema_analyse_expr_rhs(context, param->type, arg, true, NULL, false)) + { + SEMA_NOTE(definition, "The definition is here."); + return false; + } + } // #foo if (context->is_temp) { @@ -2137,6 +2145,8 @@ bool sema_expr_analyse_macro_call(SemaContext *context, Expr *call_expr, Expr *s } } param->var.init_expr = args[i]; + // Ref arguments doesn't affect optional arg. + if (param->var.kind == VARDECL_PARAM_EXPR) continue; has_optional_arg = has_optional_arg || IS_OPTIONAL(args[i]); } @@ -5751,6 +5761,7 @@ static bool sema_binary_analyse_ct_common_assign(SemaContext *context, Expr *exp expr->binary_expr.operator = binaryop_assign_base_op(expr->binary_expr.operator); if (!sema_expr_analyse_binary(context, expr, NULL)) return false; + expr->resolve_status = RESOLVE_DONE; if (!sema_cast_const(expr)) { diff --git a/test/test_suite/functions/macro_expr_type.c3 b/test/test_suite/functions/macro_expr_type.c3 new file mode 100644 index 000000000..bc9d666ca --- /dev/null +++ b/test/test_suite/functions/macro_expr_type.c3 @@ -0,0 +1,7 @@ +macro void @foo(int #a) +{ +} +fn void main() +{ + @foo(1.0); // #error: cannot implicitly be converted +} \ No newline at end of file