aboutsummaryrefslogtreecommitdiff
path: root/src/check_expr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/check_expr.cpp')
-rw-r--r--src/check_expr.cpp133
1 files changed, 93 insertions, 40 deletions
diff --git a/src/check_expr.cpp b/src/check_expr.cpp
index b854a693b..1a01eef31 100644
--- a/src/check_expr.cpp
+++ b/src/check_expr.cpp
@@ -2260,6 +2260,8 @@ bool check_cast_internal(CheckerContext *c, Operand *x, Type *type) {
x->mode = Addressing_Value;
} else if (is_type_slice(type) && is_type_string(x->type)) {
x->mode = Addressing_Value;
+ } else if (is_type_union(type)) {
+ x->mode = Addressing_Value;
}
return true;
}
@@ -5278,6 +5280,10 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
break;
}
+ case BuiltinProc_cpu_relax:
+ operand->mode = Addressing_NoValue;
+ break;
+
case BuiltinProc_atomic_fence:
case BuiltinProc_atomic_fence_acq:
case BuiltinProc_atomic_fence_rel:
@@ -5942,7 +5948,9 @@ CALL_ARGUMENT_CHECKER(check_call_arguments_internal) {
Entity *e = sig_params[operand_index];
Type *t = e->type;
Operand o = operands[operand_index];
- call->viral_state_flags |= o.expr->viral_state_flags;
+ if (o.expr != nullptr) {
+ call->viral_state_flags |= o.expr->viral_state_flags;
+ }
if (e->kind == Entity_TypeName) {
// GB_ASSERT(!variadic);
@@ -5983,6 +5991,15 @@ CALL_ARGUMENT_CHECKER(check_call_arguments_internal) {
}
score += s;
+ if (e->flags & EntityFlag_ConstInput) {
+ if (o.mode != Addressing_Constant) {
+ if (show_error) {
+ error(o.expr, "Expected a constant value for the argument '%.*s'", LIT(e->token.string));
+ }
+ err = CallArgumentError_NoneConstantParameter;
+ }
+ }
+
if (o.mode == Addressing_Type && is_type_typeid(e->type)) {
add_type_info_type(c, o.type);
add_type_and_value(c->info, o.expr, Addressing_Value, e->type, exact_value_typeid(o.type));
@@ -6238,6 +6255,15 @@ CALL_ARGUMENT_CHECKER(check_named_call_arguments) {
}
err = CallArgumentError_WrongTypes;
}
+
+ if (e->flags & EntityFlag_ConstInput) {
+ if (o->mode != Addressing_Constant) {
+ if (show_error) {
+ error(o->expr, "Expected a constant value for the argument '%.*s'", LIT(e->token.string));
+ }
+ err = CallArgumentError_NoneConstantParameter;
+ }
+ }
}
score += s;
}
@@ -6296,7 +6322,7 @@ Entity **populate_proc_parameter_list(CheckerContext *c, Type *proc_type, isize
}
-bool evaluate_where_clauses(CheckerContext *ctx, Scope *scope, Array<Ast *> *clauses, bool print_err) {
+bool evaluate_where_clauses(CheckerContext *ctx, Ast *call_expr, Scope *scope, Array<Ast *> *clauses, bool print_err) {
if (clauses != nullptr) {
for_array(i, *clauses) {
Ast *clause = (*clauses)[i];
@@ -6304,9 +6330,11 @@ bool evaluate_where_clauses(CheckerContext *ctx, Scope *scope, Array<Ast *> *cla
check_expr(ctx, &o, clause);
if (o.mode != Addressing_Constant) {
if (print_err) error(clause, "'where' clauses expect a constant boolean evaluation");
+ if (print_err && call_expr) error(call_expr, "at caller location");
return false;
} else if (o.value.kind != ExactValue_Bool) {
if (print_err) error(clause, "'where' clauses expect a constant boolean evaluation");
+ if (print_err && call_expr) error(call_expr, "at caller location");
return false;
} else if (!o.value.value_bool) {
if (print_err) {
@@ -6348,6 +6376,7 @@ bool evaluate_where_clauses(CheckerContext *ctx, Scope *scope, Array<Ast *> *cla
}
}
+ if (call_expr) error(call_expr, "at caller location");
}
return false;
}
@@ -6613,7 +6642,7 @@ CallArgumentData check_call_arguments(CheckerContext *c, Operand *operand, Type
ctx.curr_proc_sig = e->type;
GB_ASSERT(decl->proc_lit->kind == Ast_ProcLit);
- if (!evaluate_where_clauses(&ctx, decl->scope, &decl->proc_lit->ProcLit.where_clauses, false)) {
+ if (!evaluate_where_clauses(&ctx, operand->expr, decl->scope, &decl->proc_lit->ProcLit.where_clauses, false)) {
continue;
}
}
@@ -8572,8 +8601,6 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
o->expr = node;
return kind;
}
- Type *t = check_type(c, ta->type);
-
if (o->mode == Addressing_Constant) {
gbString expr_str = expr_to_string(o->expr);
error(o->expr, "A type assertion cannot be applied to a constant expression: '%s'", expr_str);
@@ -8594,54 +8621,80 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
bool src_is_ptr = is_type_pointer(o->type);
Type *src = type_deref(o->type);
- Type *dst = t;
Type *bsrc = base_type(src);
- Type *bdst = base_type(dst);
- if (is_type_union(src)) {
- bool ok = false;
- for_array(i, bsrc->Union.variants) {
- Type *vt = bsrc->Union.variants[i];
- if (are_types_identical(vt, dst)) {
- ok = true;
- break;
- }
+ if (ta->type != nullptr && ta->type->kind == Ast_UnaryExpr && ta->type->UnaryExpr.op.kind == Token_Question) {
+ if (!is_type_union(src)) {
+ gbString str = type_to_string(o->type);
+ error(o->expr, "Type assertions with .? can only operate on unions with 1 variant, got %s", str);
+ gb_string_free(str);
+ o->mode = Addressing_Invalid;
+ o->expr = node;
+ return kind;
}
-
- if (!ok) {
- gbString expr_str = expr_to_string(o->expr);
- gbString dst_type_str = type_to_string(t);
- defer (gb_string_free(expr_str));
- defer (gb_string_free(dst_type_str));
- if (bsrc->Union.variants.count == 0) {
- error(o->expr, "Cannot type assert '%s' to '%s' as this is an empty union", expr_str, dst_type_str);
- } else {
- error(o->expr, "Cannot type assert '%s' to '%s' as it is not a variant of that union", expr_str, dst_type_str);
- }
+ if (bsrc->Union.variants.count != 1) {
+ error(o->expr, "Type assertions with .? can only operate on unions with 1 variant, got %lld", cast(long long)bsrc->Union.variants.count);
o->mode = Addressing_Invalid;
o->expr = node;
return kind;
}
add_type_info_type(c, o->type);
- add_type_info_type(c, t);
+ add_type_info_type(c, bsrc->Union.variants[0]);
- o->type = t;
+ o->type = bsrc->Union.variants[0];
o->mode = Addressing_OptionalOk;
- } else if (is_type_any(src)) {
- o->type = t;
- o->mode = Addressing_OptionalOk;
-
- add_type_info_type(c, o->type);
- add_type_info_type(c, t);
} else {
- gbString str = type_to_string(o->type);
- error(o->expr, "Type assertions can only operate on unions and 'any', got %s", str);
- gb_string_free(str);
- o->mode = Addressing_Invalid;
- o->expr = node;
- return kind;
+ Type *t = check_type(c, ta->type);
+ Type *dst = t;
+ Type *bdst = base_type(dst);
+
+
+ if (is_type_union(src)) {
+ bool ok = false;
+ for_array(i, bsrc->Union.variants) {
+ Type *vt = bsrc->Union.variants[i];
+ if (are_types_identical(vt, dst)) {
+ ok = true;
+ break;
+ }
+ }
+
+ if (!ok) {
+ gbString expr_str = expr_to_string(o->expr);
+ gbString dst_type_str = type_to_string(t);
+ defer (gb_string_free(expr_str));
+ defer (gb_string_free(dst_type_str));
+ if (bsrc->Union.variants.count == 0) {
+ error(o->expr, "Cannot type assert '%s' to '%s' as this is an empty union", expr_str, dst_type_str);
+ } else {
+ error(o->expr, "Cannot type assert '%s' to '%s' as it is not a variant of that union", expr_str, dst_type_str);
+ }
+ o->mode = Addressing_Invalid;
+ o->expr = node;
+ return kind;
+ }
+
+ add_type_info_type(c, o->type);
+ add_type_info_type(c, t);
+
+ o->type = t;
+ o->mode = Addressing_OptionalOk;
+ } else if (is_type_any(src)) {
+ o->type = t;
+ o->mode = Addressing_OptionalOk;
+
+ add_type_info_type(c, o->type);
+ add_type_info_type(c, t);
+ } else {
+ gbString str = type_to_string(o->type);
+ error(o->expr, "Type assertions can only operate on unions and 'any', got %s", str);
+ gb_string_free(str);
+ o->mode = Addressing_Invalid;
+ o->expr = node;
+ return kind;
+ }
}
add_package_dependency(c, "runtime", "type_assertion_check");