aboutsummaryrefslogtreecommitdiff
path: root/src/check_expr.cpp
diff options
context:
space:
mode:
authorDaniel Gavin <danielgavin5@hotmail.com>2021-04-23 10:24:05 +0200
committerDaniel Gavin <danielgavin5@hotmail.com>2021-04-23 10:24:05 +0200
commitf10f7ebbf1c9833c74d09db68c0a0f5a149bde8d (patch)
treed25d97bafc0f762e537428f99607680aa5e434b3 /src/check_expr.cpp
parent40ed7e48d0e4a1f000efbd03d19a4eebe9b8e2f6 (diff)
parent17bbb48d8a04aaf6cc53777fe4da6ba1b7fff61b (diff)
Merge remote-tracking branch 'upstream/master' into prototype-fmt
Diffstat (limited to 'src/check_expr.cpp')
-rw-r--r--src/check_expr.cpp490
1 files changed, 376 insertions, 114 deletions
diff --git a/src/check_expr.cpp b/src/check_expr.cpp
index 2114746a3..9818b5015 100644
--- a/src/check_expr.cpp
+++ b/src/check_expr.cpp
@@ -79,15 +79,12 @@ void check_expr_with_type_hint (CheckerContext *c, Operand *o, Ast *e,
Type * check_type (CheckerContext *c, Ast *expression);
Type * check_type_expr (CheckerContext *c, Ast *expression, Type *named_type);
Type * make_optional_ok_type (Type *value, bool typed=true);
-void check_type_decl (CheckerContext *c, Entity *e, Ast *type_expr, Type *def);
Entity * check_selector (CheckerContext *c, Operand *operand, Ast *node, Type *type_hint);
Entity * check_ident (CheckerContext *c, Operand *o, Ast *n, Type *named_type, Type *type_hint, bool allow_import_name);
Entity * find_polymorphic_record_entity (CheckerContext *c, Type *original_type, isize param_count, Array<Operand> const &ordered_operands, bool *failure);
void check_not_tuple (CheckerContext *c, Operand *operand);
void convert_to_typed (CheckerContext *c, Operand *operand, Type *target_type);
gbString expr_to_string (Ast *expression);
-void check_entity_decl (CheckerContext *c, Entity *e, DeclInfo *decl, Type *named_type);
-void check_const_decl (CheckerContext *c, Entity *e, Ast *type_expr, Ast *init_expr, Type *named_type);
void check_proc_body (CheckerContext *c, Token token, DeclInfo *decl, Type *type, Ast *body);
void update_expr_type (CheckerContext *c, Ast *e, Type *type, bool final);
bool check_is_terminating (Ast *node, String const &label);
@@ -654,13 +651,27 @@ i64 check_distance_between_types(CheckerContext *c, Operand *operand, Type *type
}
Ast *expr = unparen_expr(operand->expr);
- if (expr != nullptr && expr->kind == Ast_AutoCast) {
- Operand x = *operand;
- x.expr = expr->AutoCast.expr;
- bool ok = check_cast_internal(c, &x, type);
- if (ok) {
- return MAXIMUM_TYPE_DISTANCE;
- }
+ if (expr != nullptr) {
+ if (expr->kind == Ast_AutoCast) {
+ Operand x = *operand;
+ x.expr = expr->AutoCast.expr;
+ bool ok = check_cast_internal(c, &x, type);
+ if (ok) {
+ return MAXIMUM_TYPE_DISTANCE;
+ }
+ } /*else if (expr->kind == Ast_CallExpr) {
+ // NOTE(bill, 2021-04-19): Allow assignment of procedure calls with #optional_ok
+ ast_node(ce, CallExpr, expr);
+ Type *pt = base_type(type_of_expr(ce->proc));
+ if (pt->kind == Type_Proc && pt->Proc.optional_ok) {
+ Operand x = *operand;
+ x.type = pt->Proc.results->Tuple.variables[0]->type;
+ i64 res = check_distance_between_types(c, &x, type);
+ if (res >= 0) {
+ return res+1;
+ }
+ }
+ }*/
}
return -1;
@@ -774,6 +785,8 @@ void check_assignment(CheckerContext *c, Operand *operand, Type *type, String co
LIT(context_name));
operand->mode = Addressing_Invalid;
}
+
+
return;
}
@@ -1714,12 +1727,14 @@ void check_cast_error_suggestion(CheckerContext *c, Operand *o, Type *type) {
}
-void check_is_expressible(CheckerContext *c, Operand *o, Type *type) {
+void check_is_expressible(CheckerContext *ctx, Operand *o, Type *type) {
GB_ASSERT(o->mode == Addressing_Constant);
- if (!is_type_constant_type(type) || !check_representable_as_constant(c, o->value, type, &o->value)) {
+ if (!is_type_constant_type(type) || !check_representable_as_constant(ctx, o->value, type, &o->value)) {
gbString a = expr_to_string(o->expr);
gbString b = type_to_string(type);
+ gbString c = type_to_string(o->type);
defer(
+ gb_string_free(c);
gb_string_free(b);
gb_string_free(a);
o->mode = Addressing_Invalid;
@@ -1729,12 +1744,12 @@ void check_is_expressible(CheckerContext *c, Operand *o, Type *type) {
if (!is_type_integer(o->type) && is_type_integer(type)) {
error(o->expr, "'%s' truncated to '%s'", a, b);
} else {
- error(o->expr, "Cannot convert '%s' to '%s'", a, b);
- check_assignment_error_suggestion(c, o, type);
+ error(o->expr, "Cannot convert '%s' to '%s' from '%s", a, b, c);
+ check_assignment_error_suggestion(ctx, o, type);
}
} else {
- error(o->expr, "Cannot convert '%s' to '%s'", a, b);
- check_assignment_error_suggestion(c, o, type);
+ error(o->expr, "Cannot convert '%s' to '%s' from '%s", a, b, c);
+ check_assignment_error_suggestion(ctx, o, type);
}
}
}
@@ -2224,6 +2239,26 @@ bool check_is_castable_to(CheckerContext *c, Operand *operand, Type *y) {
return true;
}
+ // if (is_type_tuple(src)) {
+ // Ast *expr = unparen_expr(operand->expr);
+ // if (expr && expr->kind == Ast_CallExpr) {
+ // // NOTE(bill, 2021-04-19): Allow casting procedure calls with #optional_ok
+ // ast_node(ce, CallExpr, expr);
+ // Type *pt = base_type(type_of_expr(ce->proc));
+ // if (pt->kind == Type_Proc && pt->Proc.optional_ok) {
+ // if (pt->Proc.result_count > 0) {
+ // Operand op = *operand;
+ // op.type = pt->Proc.results->Tuple.variables[0]->type;
+ // bool ok = check_is_castable_to(c, &op, y);
+ // if (ok) {
+ // ce->optional_ok_one = true;
+ // }
+ // return ok;
+ // }
+ // }
+ // }
+ // }
+
if (is_constant && is_type_untyped(src) && is_type_string(src)) {
if (is_type_u8_array(dst)) {
String s = operand->value.value_string;
@@ -2339,6 +2374,7 @@ bool check_is_castable_to(CheckerContext *c, Operand *operand, Type *y) {
if (is_type_rawptr(src) && is_type_proc(dst)) {
return true;
}
+
return false;
}
@@ -2728,31 +2764,27 @@ void check_binary_expr(CheckerContext *c, Operand *x, Ast *node, Type *type_hint
ExactValue a = x->value;
ExactValue b = y->value;
- // Type *type = base_type(x->type);
- Type *type = x->type;
- if (is_type_pointer(type)) {
- GB_ASSERT(op.kind == Token_Sub);
- i64 bytes = a.value_pointer - b.value_pointer;
- i64 diff = bytes/type_size_of(type);
- x->value = exact_value_pointer(diff);
- return;
- }
-
- if (!is_type_constant_type(type)) {
+ if (!is_type_constant_type(x->type)) {
+ #if 0
gbString xt = type_to_string(x->type);
gbString err_str = expr_to_string(node);
error(op, "Invalid type, '%s', for constant binary expression '%s'", xt, err_str);
gb_string_free(err_str);
gb_string_free(xt);
x->mode = Addressing_Invalid;
+ #else
+ // NOTE(bill, 2021-04-21): The above is literally a useless error message.
+ // Why did I add it in the first place?!
+ x->mode = Addressing_Value;
+ #endif
return;
}
- if (op.kind == Token_Quo && is_type_integer(type)) {
+ if (op.kind == Token_Quo && is_type_integer(x->type)) {
op.kind = Token_QuoEq; // NOTE(bill): Hack to get division of integers
}
- if (is_type_bit_set(type)) {
+ if (is_type_bit_set(x->type)) {
switch (op.kind) {
case Token_Add: op.kind = Token_Or; break;
case Token_Sub: op.kind = Token_AndNot; break;
@@ -2761,11 +2793,11 @@ void check_binary_expr(CheckerContext *c, Operand *x, Ast *node, Type *type_hint
x->value = exact_binary_operator_value(op.kind, a, b);
- if (is_type_typed(type)) {
+ if (is_type_typed(x->type)) {
if (node != nullptr) {
x->expr = node;
}
- check_is_expressible(c, x, type);
+ check_is_expressible(c, x, x->type);
}
return;
} else if (is_type_string(x->type)) {
@@ -2797,8 +2829,14 @@ void check_binary_expr(CheckerContext *c, Operand *x, Ast *node, Type *type_hint
void update_expr_type(CheckerContext *c, Ast *e, Type *type, bool final) {
+ GB_ASSERT(e != nullptr);
ExprInfo *found = check_get_expr_info(&c->checker->info, e);
if (found == nullptr) {
+ if (type != nullptr && type != t_invalid) {
+ if (e->tav.type == nullptr || e->tav.type == t_invalid) {
+ add_type_and_value(&c->checker->info, e, e->tav.mode, type ? type : e->tav.type, e->tav.value);
+ }
+ }
return;
}
ExprInfo old = *found;
@@ -2865,6 +2903,7 @@ void update_expr_value(CheckerContext *c, Ast *e, ExactValue value) {
void convert_untyped_error(CheckerContext *c, Operand *operand, Type *target_type) {
gbString expr_str = expr_to_string(operand->expr);
gbString type_str = type_to_string(target_type);
+ gbString from_type_str = type_to_string(operand->type);
char const *extra_text = "";
if (operand->mode == Addressing_Constant) {
@@ -2875,8 +2914,9 @@ void convert_untyped_error(CheckerContext *c, Operand *operand, Type *target_typ
}
}
}
- error(operand->expr, "Cannot convert '%s' to '%s'%s", expr_str, type_str, extra_text);
+ error(operand->expr, "Cannot convert '%s' to '%s' from '%s'%s", expr_str, type_str, from_type_str, extra_text);
+ gb_string_free(from_type_str);
gb_string_free(type_str);
gb_string_free(expr_str);
operand->mode = Addressing_Invalid;
@@ -5717,8 +5757,131 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
operand->mode = Addressing_NoValue;
break;
+ case BuiltinProc_trap:
+ case BuiltinProc_debug_trap:
+ if (!build_context.use_llvm_api) {
+ error(ce->args[0], "'%.*s' is not supported on this backend", LIT(builtin_procs[id].name));
+ }
+ operand->mode = Addressing_NoValue;
+ break;
+
+ case BuiltinProc_read_cycle_counter:
+ if (!build_context.use_llvm_api) {
+ error(ce->args[0], "'%.*s' is not supported on this backend", LIT(builtin_procs[id].name));
+ }
+ operand->mode = Addressing_Value;
+ operand->type = t_i64;
+ break;
+
+ case BuiltinProc_count_ones:
+ case BuiltinProc_trailing_zeros:
+ case BuiltinProc_reverse_bits:
+ if (!build_context.use_llvm_api) {
+ error(ce->args[0], "'%.*s' is not supported on this backend", LIT(builtin_procs[id].name));
+ // continue anyway
+ }
+ {
+ Operand x = {};
+ check_expr(c, &x, ce->args[0]);
+ if (x.mode == Addressing_Invalid) {
+ return false;
+ }
+
+ if (!is_type_integer_like(x.type)) {
+ gbString xts = type_to_string(x.type);
+ error(x.expr, "Values passed to '%.*s' must be an integer-like type (integer, boolean, enum, bit_set), got %s", LIT(builtin_procs[id].name), xts);
+ gb_string_free(xts);
+ } else if (x.type == t_llvm_bool) {
+ gbString xts = type_to_string(x.type);
+ error(x.expr, "Invalid type passed to '%.*s', got %s", LIT(builtin_procs[id].name), xts);
+ gb_string_free(xts);
+ }
+
+ operand->mode = Addressing_Value;
+ operand->type = default_type(x.type);
+ }
+ break;
+
+ case BuiltinProc_byte_swap:
+ if (!build_context.use_llvm_api) {
+ error(ce->args[0], "'%.*s' is not supported on this backend", LIT(builtin_procs[id].name));
+ // continue anyway
+ }
+ {
+ Operand x = {};
+ check_expr(c, &x, ce->args[0]);
+ if (x.mode == Addressing_Invalid) {
+ return false;
+ }
+
+ if (!is_type_integer_like(x.type) && !is_type_float(x.type)) {
+ gbString xts = type_to_string(x.type);
+ error(x.expr, "Values passed to '%.*s' must be an integer-like type (integer, boolean, enum, bit_set) or float, got %s", LIT(builtin_procs[id].name), xts);
+ gb_string_free(xts);
+ } else if (x.type == t_llvm_bool) {
+ gbString xts = type_to_string(x.type);
+ error(x.expr, "Invalid type passed to '%.*s', got %s", LIT(builtin_procs[id].name), xts);
+ gb_string_free(xts);
+ }
+ i64 sz = type_size_of(x.type);
+ if (sz < 2) {
+ gbString xts = type_to_string(x.type);
+ error(x.expr, "Type passed to '%.*s' must be at least 2 bytes, got %s with size of %lld", LIT(builtin_procs[id].name), xts, sz);
+ gb_string_free(xts);
+ }
+ operand->mode = Addressing_Value;
+ operand->type = default_type(x.type);
+ }
+ break;
+
+ case BuiltinProc_overflow_add:
+ case BuiltinProc_overflow_sub:
+ case BuiltinProc_overflow_mul:
+ if (!build_context.use_llvm_api) {
+ error(ce->args[0], "'%.*s' is not supported on this backend", LIT(builtin_procs[id].name));
+ // continue anyway
+ }
+ {
+ Operand x = {};
+ Operand y = {};
+ check_expr(c, &x, ce->args[0]);
+ check_expr(c, &y, ce->args[1]);
+ if (x.mode == Addressing_Invalid) {
+ return false;
+ }
+ if (y.mode == Addressing_Invalid) {
+ return false;
+ }
+ convert_to_typed(c, &y, x.type);
+ convert_to_typed(c, &x, y.type);
+ if (is_type_untyped(x.type)) {
+ gbString xts = type_to_string(x.type);
+ error(x.expr, "Expected a typed integer for '%.*s', got %s", LIT(builtin_procs[id].name), xts);
+ gb_string_free(xts);
+ return false;
+ }
+ if (!is_type_integer(x.type)) {
+ gbString xts = type_to_string(x.type);
+ error(x.expr, "Expected an integer for '%.*s', got %s", LIT(builtin_procs[id].name), xts);
+ gb_string_free(xts);
+ return false;
+ }
+ Type *ct = core_type(x.type);
+ if (is_type_different_to_arch_endianness(ct)) {
+ GB_ASSERT(ct->kind == Type_Basic);
+ if (ct->Basic.flags & (BasicFlag_EndianLittle|BasicFlag_EndianBig)) {
+ gbString xts = type_to_string(x.type);
+ error(x.expr, "Expected an integer which does not specify the explicit endianness for '%.*s', got %s", LIT(builtin_procs[id].name), xts);
+ gb_string_free(xts);
+ return false;
+ }
+ }
+ operand->mode = Addressing_Value;
+ operand->type = make_optional_ok_type(default_type(x.type), false); // Just reusing this procedure, it's not optional
+ }
+ break;
case BuiltinProc_atomic_fence:
case BuiltinProc_atomic_fence_acq:
@@ -5859,8 +6022,8 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
case BuiltinProc_fixed_point_div_sat:
{
if (!build_context.use_llvm_api) {
- error(ce->args[0], "%.*s is not supported on this backend", LIT(builtin_procs[id].name));
- return false;
+ error(ce->args[0], "'%.*s' is not supported on this backend", LIT(builtin_procs[id].name));
+ // continue anyway
}
Operand x = {};
@@ -5885,7 +6048,7 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
if (!are_types_identical(x.type, y.type)) {
gbString xts = type_to_string(x.type);
gbString yts = type_to_string(y.type);
- error(x.expr, "Mismatched types for %.*s, %s vs %s", LIT(builtin_procs[id].name), xts, yts);
+ error(x.expr, "Mismatched types for '%.*s', %s vs %s", LIT(builtin_procs[id].name), xts, yts);
gb_string_free(yts);
gb_string_free(xts);
return false;
@@ -5893,7 +6056,7 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
if (!is_type_integer(x.type) || is_type_untyped(x.type)) {
gbString xts = type_to_string(x.type);
- error(x.expr, "Expected an integer type for %.*s, got %s", LIT(builtin_procs[id].name), xts);
+ error(x.expr, "Expected an integer type for '%.*s', got %s", LIT(builtin_procs[id].name), xts);
gb_string_free(xts);
return false;
}
@@ -5903,17 +6066,17 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
return false;
}
if (z.mode != Addressing_Constant || !is_type_integer(z.type)) {
- error(z.expr, "Expected a constant integer for the scale in %.*s", LIT(builtin_procs[id].name));
+ error(z.expr, "Expected a constant integer for the scale in '%.*s'", LIT(builtin_procs[id].name));
return false;
}
i64 n = exact_value_to_i64(z.value);
if (n <= 0) {
- error(z.expr, "Scale parameter in %.*s must be positive, got %lld", LIT(builtin_procs[id].name), n);
+ error(z.expr, "Scale parameter in '%.*s' must be positive, got %lld", LIT(builtin_procs[id].name), n);
return false;
}
i64 sz = 8*type_size_of(x.type);
if (n > sz) {
- error(z.expr, "Scale parameter in %.*s is larger than the base integer bit width, got %lld, expected a maximum of %lld", LIT(builtin_procs[id].name), n, sz);
+ error(z.expr, "Scale parameter in '%.*s' is larger than the base integer bit width, got %lld, expected a maximum of %lld", LIT(builtin_procs[id].name), n, sz);
return false;
}
@@ -5923,6 +6086,59 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
break;
+ case BuiltinProc_expect:
+ if (!build_context.use_llvm_api) {
+ error(ce->args[0], "'%.*s' is not supported on this backend", LIT(builtin_procs[id].name));
+ // continue anyway
+ }
+ {
+ Operand x = {};
+ Operand y = {};
+ check_expr(c, &x, ce->args[0]);
+ check_expr(c, &y, ce->args[1]);
+ if (x.mode == Addressing_Invalid) {
+ return false;
+ }
+ if (y.mode == Addressing_Invalid) {
+ return false;
+ }
+ convert_to_typed(c, &y, x.type);
+ convert_to_typed(c, &x, y.type);
+ if (!are_types_identical(x.type, y.type)) {
+ gbString xts = type_to_string(x.type);
+ gbString yts = type_to_string(y.type);
+ error(x.expr, "Mismatched types for '%.*s', %s vs %s", LIT(builtin_procs[id].name), xts, yts);
+ gb_string_free(yts);
+ gb_string_free(xts);
+ *operand = x; // minimize error propagation
+ return true;
+ }
+
+ if (!is_type_integer_like(x.type)) {
+ gbString xts = type_to_string(x.type);
+ error(x.expr, "Values passed to '%.*s' must be an integer-like type (integer, boolean, enum, bit_set), got %s", LIT(builtin_procs[id].name), xts);
+ gb_string_free(xts);
+ *operand = x;
+ return true;
+ }
+
+ if (y.mode != Addressing_Constant) {
+ error(y.expr, "Second argument to '%.*s' must be constant as it is the expected value", LIT(builtin_procs[id].name));
+ }
+
+ if (x.mode == Addressing_Constant) {
+ // NOTE(bill): just completely ignore this intrinsic entirely
+ *operand = x;
+ return true;
+ }
+
+ operand->mode = Addressing_Value;
+ operand->type = x.type;
+ }
+ break;
+
+
+
case BuiltinProc_type_base_type:
if (operand->mode != Addressing_Type) {
@@ -6462,17 +6678,38 @@ bool check_assignment_arguments(CheckerContext *ctx, Array<Operand> const &lhs,
if (o.type == nullptr || o.type->kind != Type_Tuple) {
if (lhs.count == 2 && rhs.count == 1 &&
(o.mode == Addressing_MapIndex || o.mode == Addressing_OptionalOk)) {
- Type *tuple = make_optional_ok_type(o.type);
- add_type_and_value(&c->checker->info, o.expr, o.mode, tuple, o.value);
+ bool do_normal = true;
+ Ast *expr = unparen_expr(o.expr);
- Operand val = o;
- Operand ok = o;
- val.mode = Addressing_Value;
- ok.mode = Addressing_Value;
- ok.type = t_untyped_bool;
- array_add(operands, val);
- array_add(operands, ok);
+ Operand val0 = o;
+ Operand val1 = o;
+ val0.mode = Addressing_Value;
+ val1.mode = Addressing_Value;
+ val1.type = t_untyped_bool;
+
+ if (expr->kind == Ast_CallExpr) {
+ Type *pt = base_type(type_of_expr(expr->CallExpr.proc));
+ if (is_type_proc(pt)) {
+ do_normal = false;
+ Type *tuple = pt->Proc.results;
+ add_type_and_value(&c->checker->info, o.expr, o.mode, tuple, o.value);
+
+ if (pt->Proc.result_count >= 2) {
+ Type *t1 = tuple->Tuple.variables[1]->type;
+ val1.type = t1;
+ }
+ expr->CallExpr.optional_ok_one = false;
+ }
+ }
+
+ if (do_normal) {
+ Type *tuple = make_optional_ok_type(o.type);
+ add_type_and_value(&c->checker->info, o.expr, o.mode, tuple, o.value);
+ }
+
+ array_add(operands, val0);
+ array_add(operands, val1);
optional_ok = true;
tuple_index += 2;
} else if (o.mode == Addressing_OptionalOk && is_type_tuple(o.type)) {
@@ -6493,27 +6730,12 @@ bool check_assignment_arguments(CheckerContext *ctx, Array<Operand> const &lhs,
}
} else {
TypeTuple *tuple = &o.type->Tuple;
- if (o.mode == Addressing_OptionalOk && is_type_tuple(o.type) && lhs.count == 1) {
- GB_ASSERT(tuple->variables.count == 2);
- Ast *expr = unparen_expr(o.expr);
- if (expr->kind == Ast_CallExpr) {
- expr->CallExpr.optional_ok_one = true;
- }
- Operand val = o;
- val.type = tuple->variables[0]->type;
- val.mode = Addressing_Value;
- array_add(operands, val);
- tuple_index += tuple->variables.count;
-
- add_type_and_value(c->info, val.expr, val.mode, val.type, val.value);
- } else {
- for_array(j, tuple->variables) {
- o.type = tuple->variables[j]->type;
- array_add(operands, o);
- }
-
- tuple_index += tuple->variables.count;
+ for_array(j, tuple->variables) {
+ o.type = tuple->variables[j]->type;
+ array_add(operands, o);
}
+
+ tuple_index += tuple->variables.count;
}
}
@@ -6570,18 +6792,38 @@ bool check_unpack_arguments(CheckerContext *ctx, Entity **lhs, isize lhs_count,
if (o.type == nullptr || o.type->kind != Type_Tuple) {
if (allow_ok && lhs_count == 2 && rhs.count == 1 &&
(o.mode == Addressing_MapIndex || o.mode == Addressing_OptionalOk)) {
- Type *tuple = make_optional_ok_type(o.type);
- add_type_and_value(&c->checker->info, o.expr, o.mode, tuple, o.value);
+ bool do_normal = true;
+ Ast *expr = unparen_expr(o.expr);
- Operand val = o;
- Operand ok = o;
- val.mode = Addressing_Value;
- ok.mode = Addressing_Value;
- // ok.type = t_bool;
- ok.type = t_untyped_bool;
- array_add(operands, val);
- array_add(operands, ok);
+ Operand val0 = o;
+ Operand val1 = o;
+ val0.mode = Addressing_Value;
+ val1.mode = Addressing_Value;
+ val1.type = t_untyped_bool;
+
+ if (expr->kind == Ast_CallExpr) {
+ Type *pt = base_type(type_of_expr(expr->CallExpr.proc));
+ if (is_type_proc(pt)) {
+ do_normal = false;
+ Type *tuple = pt->Proc.results;
+ add_type_and_value(&c->checker->info, o.expr, o.mode, tuple, o.value);
+
+ if (pt->Proc.result_count >= 2) {
+ Type *t1 = tuple->Tuple.variables[1]->type;
+ val1.type = t1;
+ }
+ expr->CallExpr.optional_ok_one = false;
+ }
+ }
+
+ if (do_normal) {
+ Type *tuple = make_optional_ok_type(o.type);
+ add_type_and_value(&c->checker->info, o.expr, o.mode, tuple, o.value);
+ }
+
+ array_add(operands, val0);
+ array_add(operands, val1);
optional_ok = true;
tuple_index += add_dependencies_from_unpacking(c, lhs, lhs_count, tuple_index, 2);
} else {
@@ -6590,30 +6832,13 @@ bool check_unpack_arguments(CheckerContext *ctx, Entity **lhs, isize lhs_count,
}
} else {
TypeTuple *tuple = &o.type->Tuple;
- if (o.mode == Addressing_OptionalOk && lhs_count == 1) {
- GB_ASSERT(tuple->variables.count == 2);
- Ast *expr = unparen_expr(o.expr);
- if (expr->kind == Ast_CallExpr) {
- expr->CallExpr.optional_ok_one = true;
- }
- Operand val = o;
- val.type = tuple->variables[0]->type;
- val.mode = Addressing_Value;
- array_add(operands, val);
-
- isize count = tuple->variables.count;
- tuple_index += add_dependencies_from_unpacking(c, lhs, lhs_count, tuple_index, count);
-
- add_type_and_value(c->info, val.expr, val.mode, val.type, val.value);
- } else {
- for_array(j, tuple->variables) {
- o.type = tuple->variables[j]->type;
- array_add(operands, o);
- }
-
- isize count = tuple->variables.count;
- tuple_index += add_dependencies_from_unpacking(c, lhs, lhs_count, tuple_index, count);
+ for_array(j, tuple->variables) {
+ o.type = tuple->variables[j]->type;
+ array_add(operands, o);
}
+
+ isize count = tuple->variables.count;
+ tuple_index += add_dependencies_from_unpacking(c, lhs, lhs_count, tuple_index, count);
}
}
@@ -6863,6 +7088,7 @@ CALL_ARGUMENT_CHECKER(check_call_arguments_internal) {
data->score = score;
data->result_type = final_proc_type->Proc.results;
data->gen_entity = gen_entity;
+ add_type_and_value(c->info, ce->proc, Addressing_Value, final_proc_type, {});
}
return err;
@@ -7080,6 +7306,7 @@ CALL_ARGUMENT_CHECKER(check_named_call_arguments) {
data->score = score;
data->result_type = pt->results;
data->gen_entity = gen_entity;
+ add_type_and_value(c->info, ce->proc, Addressing_Value, proc_type, {});
}
return err;
@@ -7333,7 +7560,6 @@ CallArgumentData check_call_arguments(CheckerContext *c, Operand *operand, Type
lhs = populate_proc_parameter_list(c, e->type, &lhs_count, &is_variadic);
check_unpack_arguments(c, lhs, lhs_count, &operands, args, false, is_variadic);
-
CallArgumentData data = {};
CallArgumentError err = call_checker(c, call, e->type, e, operands, CallArgumentMode_ShowErrors, &data);
if (err != CallArgumentError_None) {
@@ -7341,7 +7567,9 @@ CallArgumentData check_call_arguments(CheckerContext *c, Operand *operand, Type
}
Entity *entity_to_use = data.gen_entity != nullptr ? data.gen_entity : e;
add_entity_use(c, ident, entity_to_use);
-
+ if (entity_to_use != nullptr) {
+ update_expr_type(c, operand->expr, entity_to_use->type, true);
+ }
return data;
}
@@ -7613,6 +7841,9 @@ CallArgumentData check_call_arguments(CheckerContext *c, Operand *operand, Type
CallArgumentError err = call_checker(c, call, proc_type, e, operands, CallArgumentMode_ShowErrors, &data);
Entity *entity_to_use = data.gen_entity != nullptr ? data.gen_entity : e;
add_entity_use(c, ident, entity_to_use);
+ if (entity_to_use != nullptr) {
+ update_expr_type(c, operand->expr, entity_to_use->type, true);
+ }
if (data.gen_entity != nullptr) {
Entity *e = data.gen_entity;
@@ -7628,7 +7859,6 @@ CallArgumentData check_call_arguments(CheckerContext *c, Operand *operand, Type
evaluate_where_clauses(&ctx, call, decl->scope, &decl->proc_lit->ProcLit.where_clauses, true);
decl->where_clauses_evaluated = true;
}
-
return data;
}
} else {
@@ -7644,6 +7874,9 @@ CallArgumentData check_call_arguments(CheckerContext *c, Operand *operand, Type
CallArgumentError err = call_checker(c, call, proc_type, e, operands, CallArgumentMode_ShowErrors, &data);
Entity *entity_to_use = data.gen_entity != nullptr ? data.gen_entity : e;
add_entity_use(c, ident, entity_to_use);
+ if (entity_to_use != nullptr) {
+ update_expr_type(c, operand->expr, entity_to_use->type, true);
+ }
if (data.gen_entity != nullptr) {
Entity *e = data.gen_entity;
@@ -7659,10 +7892,10 @@ CallArgumentData check_call_arguments(CheckerContext *c, Operand *operand, Type
evaluate_where_clauses(&ctx, call, decl->scope, &decl->proc_lit->ProcLit.where_clauses, true);
decl->where_clauses_evaluated = true;
}
-
return data;
}
+
CallArgumentData data = {};
data.result_type = t_invalid;
return data;
@@ -8147,6 +8380,14 @@ ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *call, Ast *pr
}
Type *pt = base_type(proc_type);
+ if (pt == t_invalid) {
+ if (operand->expr != nullptr && operand->expr->kind == Ast_CallExpr) {
+ pt = type_of_expr(operand->expr->CallExpr.proc);
+ }
+ if (pt == t_invalid && data.gen_entity) {
+ pt = data.gen_entity->type;
+ }
+ }
if (pt->kind == Type_Proc && pt->Proc.calling_convention == ProcCC_Odin) {
if ((c->scope->flags & ScopeFlag_ContextDefined) == 0) {
@@ -8175,7 +8416,7 @@ ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *call, Ast *pr
}
switch (inlining) {
- case ProcInlining_inline: {
+ case ProcInlining_inline:
if (proc != nullptr) {
Entity *e = entity_from_expr(proc);
if (e != nullptr && e->kind == Entity_Procedure) {
@@ -8189,16 +8430,31 @@ ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *call, Ast *pr
}
}
break;
- }
-
case ProcInlining_no_inline:
break;
}
operand->expr = call;
- if (pt->kind == Type_Proc && pt->Proc.optional_ok) {
- operand->mode = Addressing_OptionalOk;
+ {
+ if (proc_type == t_invalid) {
+ // gb_printf_err("%s\n", expr_to_string(operand->expr));
+ }
+ Type *type = nullptr;
+ if (operand->expr != nullptr && operand->expr->kind == Ast_CallExpr) {
+ type = type_of_expr(operand->expr->CallExpr.proc);
+ }
+ if (type == nullptr) {
+ type = pt;
+ }
+ type = base_type(type);
+ if (type->kind == Type_Proc && type->Proc.optional_ok) {
+ operand->mode = Addressing_OptionalOk;
+ operand->type = type->Proc.results->Tuple.variables[0]->type;
+ if (operand->expr != nullptr && operand->expr->kind == Ast_CallExpr) {
+ operand->expr->CallExpr.optional_ok_one = true;
+ }
+ }
}
// add_type_and_value(c->info, operand->expr, operand->mode, operand->type, operand->value);
@@ -9179,9 +9435,6 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
if (!is_constant) {
error(node, "Expected all constant elements for a simd vector");
}
- if (t->SimdVector.is_x86_mmx) {
- error(node, "Compound literals are not allowed with intrinsics.x86_mmx");
- }
}
@@ -9822,7 +10075,16 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
return kind;
}
if (type_hint) {
+ Type *type = type_of_expr(ac->expr);
check_cast(c, o, type_hint);
+ if (is_type_typed(type) && are_types_identical(type, type_hint)) {
+ if (build_context.vet) {
+ error(node, "Redundant 'auto_cast' applied to expression");
+ } else {
+ warning(node, "Redundant 'auto_cast' applied to expression");
+ }
+ }
+
}
o->expr = node;
return Expr_Expr;
@@ -10563,7 +10825,7 @@ void check_not_tuple(CheckerContext *c, Operand *o) {
if (o->type->kind == Type_Tuple) {
isize count = o->type->Tuple.variables.count;
error(o->expr,
- "%td-valued tuple found where single value expected", count);
+ "%td-valued expression found where single value expected", count);
o->mode = Addressing_Invalid;
GB_ASSERT(count != 1);
}