aboutsummaryrefslogtreecommitdiff
path: root/src/check_expr.cpp
diff options
context:
space:
mode:
authorLucas Perlind <perlindluca@gmail.com>2025-04-27 22:47:03 +1000
committerLucas Perlind <perlindluca@gmail.com>2025-04-27 22:47:03 +1000
commit65b4c793f011ab67ad51773273ebc4333c12bff5 (patch)
tree3d53457878120d7f6431aef068590e3be050e743 /src/check_expr.cpp
parentc7f9d2b1b78b5bad6c677bf649abafcc5c5270c1 (diff)
Add -vet-explicit-allocators
This vet flag will make it so that allocators must be explicitly used in places where context.allocator and context.temp_allocator are a procedure parameter. The goal of this flag is to prevent using the context.allocator in cases where a different allocator was meant to be used. Some code bases default context.allocator to nil/panic allocator to catch this at runtime. This effectively makes it a compile time error instead.
Diffstat (limited to 'src/check_expr.cpp')
-rw-r--r--src/check_expr.cpp37
1 files changed, 30 insertions, 7 deletions
diff --git a/src/check_expr.cpp b/src/check_expr.cpp
index 91d9e669f..6daa3edf8 100644
--- a/src/check_expr.cpp
+++ b/src/check_expr.cpp
@@ -6253,20 +6253,43 @@ gb_internal CallArgumentError check_call_arguments_internal(CheckerContext *c, A
for (isize i = 0; i < pt->param_count; i++) {
if (!visited[i]) {
Entity *e = pt->params->Tuple.variables[i];
+ bool context_allocator_error = false;
if (e->kind == Entity_Variable) {
if (e->Variable.param_value.kind != ParameterValue_Invalid) {
- ordered_operands[i].mode = Addressing_Value;
- ordered_operands[i].type = e->type;
- ordered_operands[i].expr = e->Variable.param_value.original_ast_expr;
+ if (ast_file_vet_explicit_allocators(c->file)) {
+ // NOTE(lucas): check if we are trying to default to context.allocator or context.temp_allocator
+ if (e->Variable.param_value.original_ast_expr->kind == Ast_SelectorExpr) {
+ auto& expr = e->Variable.param_value.original_ast_expr->SelectorExpr.expr;
+ auto& selector = e->Variable.param_value.original_ast_expr->SelectorExpr.selector;
+ if (expr->kind == Ast_Implicit &&
+ expr->Implicit.string == STR_LIT("context") &&
+ selector->kind == Ast_Ident &&
+ (selector->Ident.token.string == STR_LIT("allocator") ||
+ selector->Ident.token.string == STR_LIT("temp_allocator"))) {
+ context_allocator_error = true;
+ }
+ }
+ }
- dummy_argument_count += 1;
- score += assign_score_function(1);
- continue;
+ if (!context_allocator_error) {
+ ordered_operands[i].mode = Addressing_Value;
+ ordered_operands[i].type = e->type;
+ ordered_operands[i].expr = e->Variable.param_value.original_ast_expr;
+
+ dummy_argument_count += 1;
+ score += assign_score_function(1);
+ continue;
+ }
}
}
if (show_error) {
- if (e->kind == Entity_TypeName) {
+ if (context_allocator_error) {
+ gbString str = type_to_string(e->type);
+ error(call, "Parameter '%.*s' of type '%s' must be explicitly provided in procedure call",
+ LIT(e->token.string), str);
+ gb_string_free(str);
+ } else if (e->kind == Entity_TypeName) {
error(call, "Type parameter '%.*s' is missing in procedure call",
LIT(e->token.string));
} else if (e->kind == Entity_Constant && e->Constant.value.kind != ExactValue_Invalid) {