mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Refactor casts and make untyped list conversions not dependent on context.
This commit is contained in:
@@ -2141,7 +2141,7 @@ bool cast_explicit(SemaContext *context, Expr *expr, Type *to_type);
|
||||
|
||||
bool may_cast(SemaContext *cc, Expr *expr, Type *to_type, bool is_explicit, bool is_silent);
|
||||
|
||||
void cast_no_check(SemaContext *context, Expr *expr, Type *to_type, bool add_optional);
|
||||
void cast_no_check(Expr *expr, Type *to_type, bool add_optional);
|
||||
|
||||
bool cast_to_index(SemaContext *context, Expr *index, Type *subscripted_type);
|
||||
|
||||
@@ -2337,7 +2337,7 @@ Expr **sema_expand_vasplat_exprs(SemaContext *context, Expr **exprs);
|
||||
bool sema_expr_analyse_general_call(SemaContext *context, Expr *expr, Decl *decl, Expr *struct_var, bool optional,
|
||||
bool *no_match_ref);
|
||||
|
||||
void sema_expr_convert_enum_to_int(SemaContext *context, Expr *expr);
|
||||
void sema_expr_convert_enum_to_int(Expr *expr);
|
||||
Decl *sema_decl_stack_resolve_symbol(const char *symbol);
|
||||
Decl *sema_find_decl_in_modules(Module **module_list, Path *path, const char *interned_name);
|
||||
bool unit_resolve_parameterized_symbol(SemaContext *context, NameResolve *name_resolve);
|
||||
|
||||
@@ -24,8 +24,8 @@ typedef struct
|
||||
|
||||
static bool sema_error_const_int_out_of_range(CastContext *cc, Expr *expr, Expr *problem, Type *to_type);
|
||||
static Expr *recursive_may_narrow(Expr *expr, Type *type);
|
||||
static void expr_recursively_rewrite_untyped_list(Expr *expr, Expr **list);
|
||||
static void vector_const_initializer_convert_to_type(SemaContext *context, ConstInitializer *initializer, Type *to_type);
|
||||
static void expr_recursively_rewrite_untyped_list(Expr *expr, Type *to_type);
|
||||
static void vector_const_initializer_convert_to_type(ConstInitializer *initializer, Type *to_type);
|
||||
static bool cast_is_allowed(CastContext *cc, bool is_explicit, bool is_silent);
|
||||
|
||||
static bool cast_if_valid(SemaContext *context, Expr *expr, Type *to_type, bool is_explicit, bool is_silent,
|
||||
@@ -35,7 +35,7 @@ INLINE void cast_context_set_from(CastContext *cc, Type *new_from);
|
||||
INLINE void cast_context_set_to(CastContext *cc, Type *new_to);
|
||||
|
||||
typedef bool(*CastRule)(CastContext *cc, bool is_explicit, bool is_silent);
|
||||
typedef void(*CastFunction)(SemaContext *context, Expr *expr, Type *to_type);
|
||||
typedef void(*CastFunction)(Expr *expr, Type *to_type);
|
||||
extern CastFunction cast_function[CONV_LAST + 1][CONV_LAST + 1];
|
||||
extern CastRule cast_rules[CONV_LAST + 1][CONV_LAST + 1];
|
||||
|
||||
@@ -122,7 +122,7 @@ static bool cast_is_allowed(CastContext *cc, bool is_explicit, bool is_silent)
|
||||
/**
|
||||
* Perform the cast with no additional checks. Casting from untyped not allowed.
|
||||
*/
|
||||
void cast_no_check(SemaContext *context, Expr *expr, Type *to_type, bool add_optional)
|
||||
void cast_no_check(Expr *expr, Type *to_type, bool add_optional)
|
||||
{
|
||||
Type *to = type_flatten(to_type);
|
||||
Type *from = type_flatten(expr->type);
|
||||
@@ -136,7 +136,7 @@ void cast_no_check(SemaContext *context, Expr *expr, Type *to_type, bool add_opt
|
||||
CastFunction func = cast_function[from_group][to_group];
|
||||
if (func)
|
||||
{
|
||||
func(context, expr, to_type);
|
||||
func(expr, to_type);
|
||||
expr->type = type_add_optional(expr->type, add_optional);
|
||||
return;
|
||||
}
|
||||
@@ -147,7 +147,7 @@ void cast_no_check(SemaContext *context, Expr *expr, Type *to_type, bool add_opt
|
||||
* Given lhs and rhs, promote to the maximum bit size, this will retain
|
||||
* signed/unsigned type of each side.
|
||||
*/
|
||||
void cast_to_int_to_max_bit_size(SemaContext *context, Expr *lhs, Expr *rhs, Type *left_type, Type *right_type)
|
||||
void cast_to_int_to_max_bit_size(Expr *lhs, Expr *rhs, Type *left_type, Type *right_type)
|
||||
{
|
||||
unsigned bit_size_left = left_type->builtin.bitsize;
|
||||
unsigned bit_size_right = right_type->builtin.bitsize;
|
||||
@@ -164,7 +164,7 @@ void cast_to_int_to_max_bit_size(SemaContext *context, Expr *lhs, Expr *rhs, Typ
|
||||
Type *to = lhs->type->type_kind < TYPE_U8
|
||||
? type_int_signed_by_bitsize(bit_size_right)
|
||||
: type_int_unsigned_by_bitsize(bit_size_right);
|
||||
cast_no_check(context, lhs, to, IS_OPTIONAL(lhs));
|
||||
cast_no_check(lhs, to, IS_OPTIONAL(lhs));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -172,7 +172,7 @@ void cast_to_int_to_max_bit_size(SemaContext *context, Expr *lhs, Expr *rhs, Typ
|
||||
Type *to = rhs->type->type_kind < TYPE_U8
|
||||
? type_int_signed_by_bitsize(bit_size_left)
|
||||
: type_int_unsigned_by_bitsize(bit_size_left);
|
||||
cast_no_check(context, rhs, to, IS_OPTIONAL(rhs));
|
||||
cast_no_check(rhs, to, IS_OPTIONAL(rhs));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -181,7 +181,7 @@ void cast_to_int_to_max_bit_size(SemaContext *context, Expr *lhs, Expr *rhs, Typ
|
||||
* 2. Widen float and smaller to double
|
||||
* 3. Turn slices into pointers
|
||||
*/
|
||||
void cast_promote_vararg(SemaContext *context, Expr *arg)
|
||||
void cast_promote_vararg(Expr *arg)
|
||||
{
|
||||
// Remove things like distinct, optional, enum etc.
|
||||
Type *arg_type = type_flatten(arg->type);
|
||||
@@ -189,21 +189,21 @@ void cast_promote_vararg(SemaContext *context, Expr *arg)
|
||||
// 1. Promote any integer or bool to at least CInt
|
||||
if (type_is_promotable_int_bool(arg_type))
|
||||
{
|
||||
cast_no_check(context, arg, type_cint, IS_OPTIONAL(arg));
|
||||
cast_no_check(arg, type_cint, IS_OPTIONAL(arg));
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. Promote any float to at least double
|
||||
if (type_is_promotable_float(arg_type))
|
||||
{
|
||||
cast_no_check(context, arg, type_double, IS_OPTIONAL(arg));
|
||||
cast_no_check(arg, type_double, IS_OPTIONAL(arg));
|
||||
return;
|
||||
}
|
||||
|
||||
// 3. Turn slices into pointers
|
||||
if (arg_type->type_kind == TYPE_SLICE)
|
||||
{
|
||||
cast_no_check(context, arg, type_get_ptr(arg_type->array.base), IS_OPTIONAL(arg));
|
||||
cast_no_check(arg, type_get_ptr(arg_type->array.base), IS_OPTIONAL(arg));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -316,7 +316,7 @@ static bool cast_if_valid(SemaContext *context, Expr *expr, Type *to_type, bool
|
||||
return false;
|
||||
}
|
||||
|
||||
cast_no_check(context, expr, to_type, add_optional);
|
||||
cast_no_check(expr, to_type, add_optional);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -524,16 +524,84 @@ static bool sema_error_const_int_out_of_range(CastContext *cc, Expr *expr, Expr
|
||||
/**
|
||||
* Recursively change a const list to an initializer list.
|
||||
*/
|
||||
static void expr_recursively_rewrite_untyped_list(Expr *expr, Expr **list)
|
||||
static void expr_recursively_rewrite_untyped_list(Expr *expr, Type *to_type)
|
||||
{
|
||||
if (!expr_is_const_untyped_list(expr)) return;
|
||||
expr->expr_kind = EXPR_INITIALIZER_LIST;
|
||||
expr->initializer_list = list;
|
||||
expr->resolve_status = RESOLVE_NOT_DONE;
|
||||
FOREACH(Expr *, inner, list)
|
||||
ASSERT_SPAN(expr, expr_is_const_untyped_list(expr));
|
||||
expr->expr_kind = EXPR_CONST;
|
||||
Expr **values = expr->const_expr.untyped_list;
|
||||
unsigned count = vec_size(values);
|
||||
ConstInitializer **elements = NULL;
|
||||
Type *flat = type_flatten(to_type);
|
||||
bool is_slice = flat->type_kind == TYPE_SLICE;
|
||||
if (type_is_inferred(flat))
|
||||
{
|
||||
expr_recursively_rewrite_untyped_list(inner, inner->const_expr.untyped_list);
|
||||
assert(vec_size(values) > 0);
|
||||
to_type = type_from_inferred(flat, type_get_indexed_type(to_type), vec_size(values));
|
||||
flat = type_flatten(to_type);
|
||||
}
|
||||
// Handle {}
|
||||
if (!count)
|
||||
{
|
||||
if (is_slice)
|
||||
{
|
||||
expr_rewrite_const_slice(expr, to_type, NULL);
|
||||
return;
|
||||
}
|
||||
expr_rewrite_const_initializer(expr, to_type, const_init_new_zero(flat));
|
||||
return;
|
||||
}
|
||||
switch (flat->type_kind)
|
||||
{
|
||||
case TYPE_VECTOR:
|
||||
{
|
||||
Type *indexed = type_get_indexed_type(to_type);
|
||||
FOREACH(Expr *, e, values)
|
||||
{
|
||||
vec_add(elements, const_init_new_value(e));
|
||||
cast_no_check(e, indexed, false);
|
||||
}
|
||||
expr_rewrite_const_initializer(expr, to_type, const_init_new_array_full(flat, elements));
|
||||
return;
|
||||
}
|
||||
case TYPE_SLICE:
|
||||
case TYPE_ARRAY:
|
||||
{
|
||||
Type *indexed = type_get_indexed_type(to_type);
|
||||
FOREACH(Expr *, e, values)
|
||||
{
|
||||
if (e->type == type_untypedlist)
|
||||
{
|
||||
expr_recursively_rewrite_untyped_list(e, indexed);
|
||||
}
|
||||
cast_no_check(e, indexed, false);
|
||||
vec_add(elements, const_init_new_value(e));
|
||||
}
|
||||
if (is_slice)
|
||||
{
|
||||
expr_rewrite_const_slice(expr, to_type, const_init_new_array_full(type_get_array(indexed, count), elements));
|
||||
return;
|
||||
}
|
||||
expr_rewrite_const_initializer(expr, to_type, const_init_new_array_full(to_type, elements));
|
||||
return;
|
||||
}
|
||||
case TYPE_STRUCT:
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE
|
||||
}
|
||||
Decl *decl = flat->decl;
|
||||
Decl **members = decl->strukt.members;
|
||||
|
||||
FOREACH_IDX(idx, Expr *, e, values)
|
||||
{
|
||||
Type *type = members[idx]->type;
|
||||
if (e->type == type_untypedlist)
|
||||
{
|
||||
expr_recursively_rewrite_untyped_list(e, type);
|
||||
}
|
||||
cast_no_check(e, type, false);
|
||||
}
|
||||
expr_rewrite_const_initializer(expr, to_type, const_init_new_struct(flat, values));
|
||||
}
|
||||
|
||||
|
||||
@@ -623,27 +691,24 @@ static bool report_cast_error(CastContext *cc, bool may_cast_explicit)
|
||||
type_quoted_error_string(to),
|
||||
type_to_error_string(type_no_optional(to)));
|
||||
}
|
||||
else
|
||||
if (to->type_kind == TYPE_INTERFACE)
|
||||
{
|
||||
if (to->type_kind == TYPE_INTERFACE)
|
||||
if (expr->type->canonical->type_kind != TYPE_POINTER)
|
||||
{
|
||||
if (expr->type->canonical->type_kind != TYPE_POINTER)
|
||||
{
|
||||
RETURN_CAST_ERROR(expr,
|
||||
"You can only convert pointers to an interface like %s. "
|
||||
"Try passing the address of the expression instead.",
|
||||
type_quoted_error_string(to));
|
||||
}
|
||||
RETURN_CAST_ERROR(expr,
|
||||
"You can only convert pointers to an interface like %s. "
|
||||
"Try passing the address of the expression instead.",
|
||||
type_quoted_error_string(to));
|
||||
}
|
||||
else if (to->type_kind == TYPE_ANY && expr->type->canonical->type_kind != TYPE_POINTER)
|
||||
{
|
||||
RETURN_CAST_ERROR(expr, "You can only convert pointers to 'any'. "
|
||||
"Try passing the address of the expression instead.");
|
||||
}
|
||||
RETURN_CAST_ERROR(expr,
|
||||
"It is not possible to cast %s to %s.",
|
||||
type_quoted_error_string(type_no_optional(expr->type)), type_quoted_error_string(to));
|
||||
}
|
||||
if (to->type_kind == TYPE_ANY && expr->type->canonical->type_kind != TYPE_POINTER)
|
||||
{
|
||||
RETURN_CAST_ERROR(expr, "You can only convert pointers to 'any'. "
|
||||
"Try passing the address of the expression instead.");
|
||||
}
|
||||
RETURN_CAST_ERROR(expr,
|
||||
"It is not possible to cast %s to %s.",
|
||||
type_quoted_error_string(type_no_optional(expr->type)), type_quoted_error_string(to));
|
||||
}
|
||||
|
||||
INLINE bool sema_cast_error(CastContext *cc, bool may_cast_explicit, bool is_silent)
|
||||
@@ -786,7 +851,7 @@ static bool rule_arrptr_to_slice(CastContext *cc, bool is_explicit, bool is_sile
|
||||
return sema_cast_error(cc, may_explicit, is_silent);
|
||||
}
|
||||
|
||||
static bool rule_ulist_to_struct(CastContext *cc, bool is_explicit, bool is_silent)
|
||||
static bool rule_ulist_to_struct(CastContext *cc, UNUSED bool is_explicit, bool is_silent)
|
||||
{
|
||||
ASSERT(expr_is_const_untyped_list(cc->expr));
|
||||
Expr **expressions = cc->expr->const_expr.untyped_list;
|
||||
@@ -1394,7 +1459,7 @@ static bool rule_bits_to_int(CastContext *cc, bool is_explicit, bool is_silent)
|
||||
// CASTS ----
|
||||
|
||||
|
||||
static void cast_vaptr_to_slice(SemaContext *context, Expr *expr, Type *type)
|
||||
static void cast_vaptr_to_slice(Expr *expr, Type *type)
|
||||
{
|
||||
Type *flat = type_flatten(expr->type);
|
||||
ASSERT(flat->type_kind == TYPE_POINTER);
|
||||
@@ -1407,7 +1472,7 @@ static void cast_vaptr_to_slice(SemaContext *context, Expr *expr, Type *type)
|
||||
expr->type = type;
|
||||
}
|
||||
|
||||
static void cast_ptr_to_any(SemaContext *context, Expr *expr, Type *type)
|
||||
static void cast_ptr_to_any(Expr *expr, Type *type)
|
||||
{
|
||||
Expr *inner = expr_copy(expr);
|
||||
Expr *typeid = expr_copy(expr);
|
||||
@@ -1416,21 +1481,23 @@ static void cast_ptr_to_any(SemaContext *context, Expr *expr, Type *type)
|
||||
expr->make_any_expr = (ExprMakeAny) { .inner = inner, .typeid = typeid };
|
||||
expr->type = type;
|
||||
}
|
||||
static void cast_struct_to_inline(SemaContext *context, Expr *expr, Type *type) { expr_rewrite_addr_conversion(expr, type); }
|
||||
static void cast_fault_to_anyfault(SemaContext *context, Expr *expr, Type *type) { expr->type = type; };
|
||||
static void cast_fault_to_ptr(SemaContext *context, Expr *expr, Type *type) { expr_rewrite_to_int_to_ptr(expr, type); }
|
||||
static void cast_typeid_to_int(SemaContext *context, Expr *expr, Type *type) { expr_rewrite_ext_trunc(expr, type, type_is_signed(type_flatten_to_int(type))); }
|
||||
static void cast_fault_to_int(SemaContext *context, Expr *expr, Type *type) { cast_typeid_to_int(context, expr, type); }
|
||||
static void cast_typeid_to_ptr(SemaContext *context, Expr *expr, Type *type) { expr_rewrite_to_int_to_ptr(expr, type); }
|
||||
static void cast_any_to_bool(SemaContext *context, Expr *expr, Type *type) {
|
||||
static void cast_struct_to_inline(Expr *expr, Type *type) { expr_rewrite_addr_conversion(expr, type); }
|
||||
static void cast_fault_to_anyfault(Expr *expr, Type *type) { expr->type = type; };
|
||||
static void cast_fault_to_ptr(Expr *expr, Type *type) { expr_rewrite_to_int_to_ptr(expr, type); }
|
||||
static void cast_typeid_to_int(Expr *expr, Type *type) { expr_rewrite_ext_trunc(expr, type, type_is_signed(type_flatten_to_int(type))); }
|
||||
static void cast_fault_to_int(Expr *expr, Type *type) { cast_typeid_to_int(expr, type); }
|
||||
static void cast_typeid_to_ptr(Expr *expr, Type *type) { expr_rewrite_to_int_to_ptr(expr, type); }
|
||||
static void cast_any_to_bool(Expr *expr, Type *type)
|
||||
{
|
||||
expr_rewrite_ptr_access(expr, expr_copy(expr), type_voidptr);
|
||||
expr_rewrite_int_to_bool(expr, false);
|
||||
expr->type = type;
|
||||
}
|
||||
static void cast_any_to_ptr(SemaContext *context, Expr *expr, Type *type) { expr_rewrite_ptr_access(expr, expr_copy(expr), type); }
|
||||
static void cast_all_to_void(SemaContext *context, Expr *expr, Type *to_type) { expr_rewrite_discard(expr); }
|
||||
static void cast_retype(SemaContext *context, Expr *expr, Type *to_type) { expr->type = to_type; }
|
||||
static void cast_any_to_ptr(Expr *expr, Type *type) { expr_rewrite_ptr_access(expr, expr_copy(expr), type); }
|
||||
static void cast_all_to_void(Expr *expr, UNUSED Type *to_type) { expr_rewrite_discard(expr); }
|
||||
static void cast_retype(Expr *expr, Type *to_type) { expr->type = to_type; }
|
||||
|
||||
static void vector_const_initializer_convert_to_type(SemaContext *context, ConstInitializer *initializer, Type *to_type)
|
||||
static void vector_const_initializer_convert_to_type(ConstInitializer *initializer, Type *to_type)
|
||||
{
|
||||
switch (initializer->kind)
|
||||
{
|
||||
@@ -1439,7 +1506,7 @@ static void vector_const_initializer_convert_to_type(SemaContext *context, Const
|
||||
Type *element_type = type_flatten(to_type)->array.base;
|
||||
FOREACH(ConstInitializer *, element, initializer->init_array.elements)
|
||||
{
|
||||
vector_const_initializer_convert_to_type(context, element, element_type);
|
||||
vector_const_initializer_convert_to_type(element, element_type);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -1448,7 +1515,7 @@ static void vector_const_initializer_convert_to_type(SemaContext *context, Const
|
||||
Type *element_type = type_flatten(to_type)->array.base;
|
||||
FOREACH(ConstInitializer *, element, initializer->init_array_full)
|
||||
{
|
||||
vector_const_initializer_convert_to_type(context, element, element_type);
|
||||
vector_const_initializer_convert_to_type(element, element_type);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -1468,7 +1535,7 @@ static void vector_const_initializer_convert_to_type(SemaContext *context, Const
|
||||
}
|
||||
else
|
||||
{
|
||||
cast_no_check(context, initializer->init_value, to_type, IS_OPTIONAL(initializer->init_value));
|
||||
cast_no_check(initializer->init_value, to_type, IS_OPTIONAL(initializer->init_value));
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -1478,7 +1545,7 @@ static void vector_const_initializer_convert_to_type(SemaContext *context, Const
|
||||
case CONST_INIT_STRUCT:
|
||||
UNREACHABLE
|
||||
case CONST_INIT_ARRAY_VALUE:
|
||||
vector_const_initializer_convert_to_type(context, initializer->init_array_value.element, to_type);
|
||||
vector_const_initializer_convert_to_type(initializer->init_array_value.element, to_type);
|
||||
break;
|
||||
}
|
||||
initializer->type = type_flatten(to_type);
|
||||
@@ -1487,7 +1554,7 @@ static void vector_const_initializer_convert_to_type(SemaContext *context, Const
|
||||
/**
|
||||
* Insert a PTRPTR cast or update the pointer type
|
||||
*/
|
||||
static void cast_ptr_to_ptr(SemaContext *context, Expr *expr, Type *type)
|
||||
static void cast_ptr_to_ptr(Expr *expr, Type *type)
|
||||
{
|
||||
if (!sema_cast_const(expr) || expr->const_expr.const_kind == CONST_STRING)
|
||||
{
|
||||
@@ -1504,7 +1571,7 @@ static void cast_ptr_to_ptr(SemaContext *context, Expr *expr, Type *type)
|
||||
/**
|
||||
* Convert any fp to another fp type using CAST_FPFP
|
||||
*/
|
||||
static void cast_float_to_float(SemaContext *context, Expr *expr, Type *type)
|
||||
static void cast_float_to_float(Expr *expr, Type *type)
|
||||
{
|
||||
// Change to same type should never enter here.
|
||||
ASSERT(type_flatten(type) != type_flatten(expr->type));
|
||||
@@ -1524,7 +1591,7 @@ static void cast_float_to_float(SemaContext *context, Expr *expr, Type *type)
|
||||
* Convert from any floating point to int using CAST_FPINT
|
||||
* Const conversion will disable narrowable and hex.
|
||||
*/
|
||||
static void cast_float_to_int(SemaContext *context, Expr *expr, Type *type)
|
||||
static void cast_float_to_int(Expr *expr, Type *type)
|
||||
{
|
||||
if (!sema_cast_const(expr))
|
||||
{
|
||||
@@ -1546,7 +1613,7 @@ static void cast_float_to_int(SemaContext *context, Expr *expr, Type *type)
|
||||
* Convert from integer to enum using CAST_INTENUM / or do a const conversion.
|
||||
* This will ensure that the conversion is valid (i.e. in the range 0 .. enumcount - 1)
|
||||
*/
|
||||
static void cast_int_to_enum(SemaContext *context, Expr *expr, Type *type)
|
||||
static void cast_int_to_enum(Expr *expr, Type *type)
|
||||
{
|
||||
static_assert(ALLOW_DEPRECATED_6, "Fix deprecation");
|
||||
SEMA_DEPRECATED(expr, "Using casts to convert integers to enums is deprecated in favour of using 'MyEnum.from_ordinal(i)`.");
|
||||
@@ -1574,7 +1641,7 @@ static void cast_int_to_enum(SemaContext *context, Expr *expr, Type *type)
|
||||
/**
|
||||
* Convert between integers: CAST_INTINT
|
||||
*/
|
||||
static void cast_int_to_int(SemaContext *context, Expr *expr, Type *type)
|
||||
static void cast_int_to_int(Expr *expr, Type *type)
|
||||
{
|
||||
// Fold pointer casts if narrowing
|
||||
// So (int)(uptr)&x => (int)&x in the backend.
|
||||
@@ -1603,11 +1670,11 @@ static void cast_int_to_int(SemaContext *context, Expr *expr, Type *type)
|
||||
/**
|
||||
* Convert 1 => { 1, 1, 1, 1 } using CAST_EXPVEC
|
||||
*/
|
||||
static void cast_expand_to_vec(SemaContext *context, Expr *expr, Type *type)
|
||||
static void cast_expand_to_vec(Expr *expr, Type *type)
|
||||
{
|
||||
// Fold pointer casts if narrowing
|
||||
Type *base = type_get_indexed_type(type);
|
||||
cast_no_check(context, expr, base, IS_OPTIONAL(expr));
|
||||
cast_no_check(expr, base, IS_OPTIONAL(expr));
|
||||
Expr *inner = expr_copy(expr);
|
||||
expr->expr_kind = EXPR_SCALAR_TO_VECTOR;
|
||||
expr->inner_expr = inner;
|
||||
@@ -1615,10 +1682,10 @@ static void cast_expand_to_vec(SemaContext *context, Expr *expr, Type *type)
|
||||
expr->resolve_status = RESOLVE_DONE;
|
||||
}
|
||||
|
||||
static void cast_bitstruct_to_int_arr(SemaContext *context, Expr *expr, Type *type) { expr_rewrite_recast(expr, type); }
|
||||
static void cast_int_arr_to_bitstruct(SemaContext *context, Expr *expr, Type *type) { expr_rewrite_recast(expr, type); }
|
||||
static void cast_bitstruct_to_int_arr(Expr *expr, Type *type) { expr_rewrite_recast(expr, type); }
|
||||
static void cast_int_arr_to_bitstruct(Expr *expr, Type *type) { expr_rewrite_recast(expr, type); }
|
||||
|
||||
static void cast_bitstruct_to_bool(SemaContext *context, Expr *expr, Type *type)
|
||||
static void cast_bitstruct_to_bool(Expr *expr, Type *type)
|
||||
{
|
||||
expr_rewrite_int_to_bool(expr, false);
|
||||
expr->type = type;
|
||||
@@ -1629,7 +1696,7 @@ static void cast_bitstruct_to_bool(SemaContext *context, Expr *expr, Type *type)
|
||||
* Cast a signed or unsigned integer -> floating point, using CAST_INTFP
|
||||
* for runtime, otherwise do const transformation.
|
||||
*/
|
||||
static void cast_int_to_float(SemaContext *context, Expr *expr, Type *type)
|
||||
static void cast_int_to_float(Expr *expr, Type *type)
|
||||
{
|
||||
if (!sema_cast_const(expr))
|
||||
{
|
||||
@@ -1641,19 +1708,19 @@ static void cast_int_to_float(SemaContext *context, Expr *expr, Type *type)
|
||||
expr_rewrite_const_float(expr, type, f);
|
||||
}
|
||||
|
||||
static void cast_enum_to_int(SemaContext *context, Expr* expr, Type *to_type)
|
||||
static void cast_enum_to_int(Expr* expr, Type *to_type)
|
||||
{
|
||||
static_assert(ALLOW_DEPRECATED_6, "Fix deprecation");
|
||||
SEMA_DEPRECATED(expr, "Using casts to convert enums to integers is deprecated in favour of using 'the_enum.ordinal`.");
|
||||
sema_expr_convert_enum_to_int(context, expr);
|
||||
cast_int_to_int(context, expr, to_type);
|
||||
sema_expr_convert_enum_to_int(expr);
|
||||
cast_int_to_int(expr, to_type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cast using CAST_VECARR, casting an array to a vector. For the constant, this
|
||||
* is a simple type change, see array_to_vec.
|
||||
*/
|
||||
static void cast_vec_to_arr(SemaContext *context, Expr *expr, Type *to_type)
|
||||
static void cast_vec_to_arr(Expr *expr, Type *to_type)
|
||||
{
|
||||
if (!sema_cast_const(expr))
|
||||
{
|
||||
@@ -1674,7 +1741,7 @@ static void cast_vec_to_arr(SemaContext *context, Expr *expr, Type *to_type)
|
||||
* Convert vector -> vector. This is somewhat complex as there are various functions
|
||||
* we need to invoke depending on the underlying type.
|
||||
*/
|
||||
static void cast_vec_to_vec(SemaContext *context, Expr *expr, Type *to_type)
|
||||
static void cast_vec_to_vec(Expr *expr, Type *to_type)
|
||||
{
|
||||
if (!sema_cast_const(expr))
|
||||
{
|
||||
@@ -1788,24 +1855,19 @@ static void cast_vec_to_vec(SemaContext *context, Expr *expr, Type *to_type)
|
||||
|
||||
// For the const initializer we need to change the internal type
|
||||
ConstInitializer *list = expr->const_expr.initializer;
|
||||
vector_const_initializer_convert_to_type(context, list, to_type);
|
||||
vector_const_initializer_convert_to_type(list, to_type);
|
||||
expr->type = to_type;
|
||||
}
|
||||
|
||||
|
||||
static void cast_untyped_list_to_other(SemaContext *context, Expr *expr, Type *to_type)
|
||||
static void cast_untyped_list_to_other(Expr *expr, Type *to_type)
|
||||
{
|
||||
ASSERT(expr_is_const_untyped_list(expr));
|
||||
// Recursively set the type of all ConstInitializer inside.
|
||||
expr_recursively_rewrite_untyped_list(expr, expr->const_expr.untyped_list);
|
||||
// We can now analyse the list (this is where the actual check happens)
|
||||
bool success = sema_expr_analyse_initializer_list(context, type_flatten(to_type), expr);
|
||||
ASSERT(success);
|
||||
// And set the type.
|
||||
expr->type = type_infer_len_from_actual_type(to_type, expr->type);
|
||||
expr_recursively_rewrite_untyped_list(expr, to_type);
|
||||
}
|
||||
|
||||
static void cast_anyfault_to_fault(SemaContext *context, Expr *expr, Type *type)
|
||||
static void cast_anyfault_to_fault(Expr *expr, Type *type)
|
||||
{
|
||||
if (!sema_cast_const(expr))
|
||||
{
|
||||
@@ -1821,7 +1883,7 @@ static void cast_anyfault_to_fault(SemaContext *context, Expr *expr, Type *type)
|
||||
expr->type = type;
|
||||
}
|
||||
|
||||
static void cast_slice_to_ptr(SemaContext *context, Expr *expr, Type *type)
|
||||
static void cast_slice_to_ptr(Expr *expr, Type *type)
|
||||
{
|
||||
if (expr_is_const_string(expr) || expr_is_const_bytes(expr))
|
||||
{
|
||||
@@ -1836,7 +1898,7 @@ static void cast_slice_to_ptr(SemaContext *context, Expr *expr, Type *type)
|
||||
* Cast any int to a pointer, will use CAST_INTPTR after a conversion to uptr for runtime.
|
||||
* Compile time it will check that the value fits the pointer size.
|
||||
*/
|
||||
static void cast_int_to_ptr(SemaContext *context, Expr *expr, Type *type)
|
||||
static void cast_int_to_ptr(Expr *expr, Type *type)
|
||||
{
|
||||
ASSERT(type_bit_size(type_uptr) <= 64 && "For > 64 bit pointers, this code needs updating.");
|
||||
|
||||
@@ -1849,7 +1911,7 @@ static void cast_int_to_ptr(SemaContext *context, Expr *expr, Type *type)
|
||||
return;
|
||||
}
|
||||
// This may be a narrowing
|
||||
cast_no_check(context, expr, type_uptr, IS_OPTIONAL(expr));
|
||||
cast_no_check(expr, type_uptr, IS_OPTIONAL(expr));
|
||||
expr_rewrite_to_int_to_ptr(expr, type);
|
||||
}
|
||||
|
||||
@@ -1857,14 +1919,13 @@ static void cast_int_to_ptr(SemaContext *context, Expr *expr, Type *type)
|
||||
* Bool into a signed or unsigned int using CAST_BOOLINT
|
||||
* or rewrite to 0 / 1 for false / true.
|
||||
*/
|
||||
static void cast_bool_to_int(SemaContext *context, Expr *expr, Type *type)
|
||||
static void cast_bool_to_int(Expr *expr, Type *type)
|
||||
{
|
||||
if (!sema_cast_const(expr))
|
||||
{
|
||||
expr_rewrite_ext_trunc(expr, type, false);
|
||||
return;
|
||||
}
|
||||
|
||||
expr_rewrite_const_int(expr, type, expr->const_expr.b ? 1 : 0);
|
||||
}
|
||||
|
||||
@@ -1873,7 +1934,7 @@ static void cast_bool_to_int(SemaContext *context, Expr *expr, Type *type)
|
||||
* Cast bool to float using CAST_BOOLFP
|
||||
* or rewrite to 0.0 / 1.0 for false / true
|
||||
*/
|
||||
static void cast_bool_to_float(SemaContext *context, Expr *expr, Type *type)
|
||||
static void cast_bool_to_float(Expr *expr, Type *type)
|
||||
{
|
||||
if (!sema_cast_const(expr))
|
||||
{
|
||||
@@ -1889,7 +1950,7 @@ static void cast_bool_to_float(SemaContext *context, Expr *expr, Type *type)
|
||||
* Cast int to bool using CAST_INTBOOL
|
||||
* or rewrite 0 => false, any other value => true
|
||||
*/
|
||||
static void cast_int_to_bool(SemaContext *context, Expr *expr, Type *type)
|
||||
static void cast_int_to_bool(Expr *expr, Type *type)
|
||||
{
|
||||
if (!expr_is_const(expr))
|
||||
{
|
||||
@@ -1905,7 +1966,7 @@ static void cast_int_to_bool(SemaContext *context, Expr *expr, Type *type)
|
||||
* Cast any float to bool using CAST_FPBOOL
|
||||
* or rewrite 0.0 => false, any other value => true
|
||||
*/
|
||||
static void cast_float_to_bool(SemaContext *context, Expr *expr, Type *type)
|
||||
static void cast_float_to_bool(Expr *expr, Type *type)
|
||||
{
|
||||
if (!expr_is_const(expr))
|
||||
{
|
||||
@@ -1926,7 +1987,7 @@ static void cast_float_to_bool(SemaContext *context, Expr *expr, Type *type)
|
||||
/**
|
||||
* Insert the PTRXI cast, or on const do a rewrite.
|
||||
*/
|
||||
static void cast_ptr_to_int(SemaContext *context, Expr *expr, Type *type)
|
||||
static void cast_ptr_to_int(Expr *expr, Type *type)
|
||||
{
|
||||
if (sema_cast_const(expr) && expr_is_const_pointer(expr))
|
||||
{
|
||||
@@ -1940,7 +2001,7 @@ static void cast_ptr_to_int(SemaContext *context, Expr *expr, Type *type)
|
||||
/**
|
||||
* Insert the PTRBOOL cast or on const do a rewrite.
|
||||
*/
|
||||
static void cast_ptr_to_bool(SemaContext *context, Expr *expr, Type *type)
|
||||
static void cast_ptr_to_bool(Expr *expr, Type *type)
|
||||
{
|
||||
if (!expr_is_const(expr))
|
||||
{
|
||||
@@ -1969,7 +2030,7 @@ static void cast_ptr_to_bool(SemaContext *context, Expr *expr, Type *type)
|
||||
}
|
||||
|
||||
|
||||
static void cast_slice_to_bool(SemaContext *context, Expr *expr, Type *type)
|
||||
static void cast_slice_to_bool(Expr *expr, Type *type)
|
||||
{
|
||||
if (expr_is_const_string(expr) || expr_is_const_bytes(expr))
|
||||
{
|
||||
@@ -1993,7 +2054,7 @@ static void cast_slice_to_bool(SemaContext *context, Expr *expr, Type *type)
|
||||
* 1. int[] -> Foo[] where Foo is a distinct or typedef or pointer. Then we can just redefine
|
||||
* 2. The second case is something like int[] -> float[] for this case we need to make a bitcast using CAST_SASA.
|
||||
*/
|
||||
static void cast_slice_to_slice(SemaContext *context, Expr *expr, Type *to_type)
|
||||
static void cast_slice_to_slice(Expr *expr, Type *to_type)
|
||||
{
|
||||
if (sema_cast_const(expr))
|
||||
{
|
||||
@@ -2003,7 +2064,7 @@ static void cast_slice_to_slice(SemaContext *context, Expr *expr, Type *to_type)
|
||||
expr_rewrite_recast(expr, to_type);
|
||||
}
|
||||
|
||||
static void cast_vecarr_to_slice(SemaContext *context, Expr *expr, Type *to_type)
|
||||
static void cast_vecarr_to_slice(Expr *expr, Type *to_type)
|
||||
{
|
||||
if (!sema_cast_const(expr))
|
||||
{
|
||||
@@ -2037,7 +2098,7 @@ static void cast_vecarr_to_slice(SemaContext *context, Expr *expr, Type *to_type
|
||||
}
|
||||
UNREACHABLE
|
||||
}
|
||||
static void cast_slice_to_vecarr(SemaContext *context, Expr *expr, Type *to_type)
|
||||
static void cast_slice_to_vecarr(Expr *expr, Type *to_type)
|
||||
{
|
||||
if (!sema_cast_const(expr))
|
||||
{
|
||||
@@ -2064,25 +2125,25 @@ static void cast_slice_to_vecarr(SemaContext *context, Expr *expr, Type *to_type
|
||||
return;
|
||||
}
|
||||
|
||||
static void cast_slice_to_infer(SemaContext *context, Expr *expr, Type *to_type)
|
||||
static void cast_slice_to_infer(Expr *expr, Type *to_type)
|
||||
{
|
||||
ArraySize len = sema_len_from_const(expr);
|
||||
ASSERT(len > 0);
|
||||
Type *indexed = type_get_indexed_type(expr->type);
|
||||
to_type = type_infer_len_from_actual_type(to_type, type_get_array(indexed, len));
|
||||
cast_no_check(context, expr, to_type, false);
|
||||
cast_no_check(expr, to_type, false);
|
||||
}
|
||||
|
||||
static void cast_vecarr_to_infer(SemaContext *context, Expr *expr, Type *to_type)
|
||||
static void cast_vecarr_to_infer(Expr *expr, Type *to_type)
|
||||
{
|
||||
to_type = type_infer_len_from_actual_type(to_type, type_flatten(expr->type));
|
||||
cast_no_check(context, expr, to_type, false);
|
||||
cast_no_check(expr, to_type, false);
|
||||
}
|
||||
|
||||
static void cast_ptr_to_infer(SemaContext *context, Expr *expr, Type *to_type)
|
||||
static void cast_ptr_to_infer(Expr *expr, Type *to_type)
|
||||
{
|
||||
to_type = type_infer_len_from_actual_type(to_type, type_flatten(expr->type));
|
||||
cast_no_check(context, expr, to_type, false);
|
||||
cast_no_check(expr, to_type, false);
|
||||
}
|
||||
|
||||
|
||||
@@ -2090,7 +2151,7 @@ static void cast_ptr_to_infer(SemaContext *context, Expr *expr, Type *to_type)
|
||||
* Cast using CAST_ARRVEC, casting an array to a vector. For the constant, this
|
||||
* is a simple type change.
|
||||
*/
|
||||
static void cast_arr_to_vec(SemaContext *context, Expr *expr, Type *to_type)
|
||||
static void cast_arr_to_vec(Expr *expr, Type *to_type)
|
||||
{
|
||||
Type *index_vec = type_flatten(type_get_indexed_type(to_type));
|
||||
Type *index_arr = type_flatten(type_get_indexed_type(expr->type));
|
||||
@@ -2112,22 +2173,22 @@ static void cast_arr_to_vec(SemaContext *context, Expr *expr, Type *to_type)
|
||||
}
|
||||
if (to_temp != to_type)
|
||||
{
|
||||
cast_vec_to_vec(context, expr, to_type);
|
||||
cast_vec_to_vec(expr, to_type);
|
||||
}
|
||||
}
|
||||
|
||||
static void cast_arr_to_arr(SemaContext *context, Expr *expr, Type *to_type)
|
||||
static void cast_arr_to_arr(Expr *expr, Type *to_type)
|
||||
{
|
||||
ASSERT(type_size(to_type) == type_size(expr->type));
|
||||
expr->type = to_type;
|
||||
}
|
||||
|
||||
static void cast_anyfault_to_bool(SemaContext *context, Expr *expr, Type *to_type)
|
||||
static void cast_anyfault_to_bool(Expr *expr, Type *to_type)
|
||||
{
|
||||
expr_rewrite_int_to_bool(expr, false);
|
||||
expr->type = to_type;
|
||||
}
|
||||
static void cast_typeid_to_bool(SemaContext *context, Expr *expr, Type *to_type) { expr_rewrite_int_to_bool(expr, false); expr->type = to_type; }
|
||||
static void cast_typeid_to_bool(Expr *expr, Type *to_type) { expr_rewrite_int_to_bool(expr, false); expr->type = to_type; }
|
||||
|
||||
#define XX2XX &cast_retype
|
||||
#define BS2IA &cast_bitstruct_to_int_arr
|
||||
|
||||
@@ -4190,7 +4190,7 @@ bool sema_analyse_var_decl(SemaContext *context, Decl *decl, bool local)
|
||||
if (type_is_user_defined(type) && type->decl)
|
||||
{
|
||||
if (!sema_analyse_decl(context, type->decl)) return false;
|
||||
sema_display_deprecated_warning_on_use(context, type->decl, type_info->span);
|
||||
sema_display_deprecated_warning_on_use(type->decl, type_info->span);
|
||||
}
|
||||
|
||||
if (is_static && context->call_env.pure)
|
||||
|
||||
@@ -91,7 +91,7 @@ static bool sema_expr_analyse_enum_add_sub(SemaContext *context, Expr *expr, Exp
|
||||
static bool sema_expr_analyse_shift(SemaContext *context, Expr *expr, Expr *left, Expr *right);
|
||||
static bool sema_expr_check_shift_rhs(SemaContext *context, Expr *expr, Type *left_type, Type *left_type_flat, Expr *right, Type *right_type_flat);
|
||||
static bool sema_expr_analyse_and_or(SemaContext *context, Expr *expr, Expr *left, Expr *right);
|
||||
static bool sema_expr_analyse_slice_assign(SemaContext *context, Expr *expr, Type *left_type, Expr *right, bool is_unwrapped);
|
||||
static bool sema_expr_analyse_slice_assign(SemaContext *context, Expr *expr, Type *left_type, Expr *right);
|
||||
static bool sema_expr_analyse_ct_identifier_assign(SemaContext *context, Expr *expr, Expr *left, Expr *right);
|
||||
static bool sema_expr_analyse_ct_type_identifier_assign(SemaContext *context, Expr *expr, Expr *left, Expr *right);
|
||||
static bool sema_expr_analyse_assign(SemaContext *context, Expr *expr, Expr *left, Expr *right, bool *failed_ref);
|
||||
@@ -175,7 +175,7 @@ static inline void sema_expr_rewrite_to_type_nameof(Expr *expr, Type *type, Toke
|
||||
static inline bool sema_create_const_kind(SemaContext *contect, Expr *expr, Type *type);
|
||||
static inline bool sema_create_const_len(SemaContext *context, Expr *expr, Type *type);
|
||||
static inline bool sema_create_const_inner(SemaContext *context, Expr *expr, Type *type);
|
||||
static inline bool sema_create_const_min(SemaContext *context, Expr *expr, Type *type, Type *flat);
|
||||
static inline bool sema_create_const_min(Expr *expr, Type *type, Type *flat);
|
||||
static inline bool sema_create_const_max(SemaContext *context, Expr *expr, Type *type, Type *flat);
|
||||
static inline bool sema_create_const_params(SemaContext *context, Expr *expr, Type *type);
|
||||
static inline void sema_create_const_membersof(SemaContext *context, Expr *expr, Type *type, AlignSize alignment, AlignSize offset);
|
||||
@@ -912,7 +912,7 @@ static inline bool sema_expr_analyse_ternary(SemaContext *context, Type *infer_t
|
||||
if (expr_is_const(cond))
|
||||
{
|
||||
Expr *copy = copy_expr_single(cond);
|
||||
cast_no_check(context, copy, type_bool, false);
|
||||
cast_no_check(copy, type_bool, false);
|
||||
ASSERT_SPAN(expr, expr_is_const_bool(copy));
|
||||
path = copy->const_expr.b ? COND_TRUE : COND_FALSE;
|
||||
expr->ternary_expr.then_expr = exprid(cond);
|
||||
@@ -1026,7 +1026,7 @@ static inline bool sema_expr_analyse_identifier(SemaContext *context, Type *to,
|
||||
|
||||
ASSERT_SPAN(expr, expr->resolve_status != RESOLVE_DONE);
|
||||
DeclId body_param;
|
||||
if (!expr->unresolved_ident_expr.path && context->current_macro && (body_param = context->current_macro->func_decl.body_param))
|
||||
if (!expr->unresolved_ident_expr.path && context->current_macro && (body_param = context->current_macro->func_decl.body_param)) // NOLINT
|
||||
{
|
||||
if (expr->unresolved_ident_expr.ident == declptr(body_param)->name)
|
||||
{
|
||||
@@ -1086,7 +1086,7 @@ static inline bool sema_expr_analyse_identifier(SemaContext *context, Type *to,
|
||||
{
|
||||
if (!sema_analyse_decl(context, decl)) return decl_poison(decl);
|
||||
}
|
||||
sema_display_deprecated_warning_on_use(context, decl, expr->span);
|
||||
sema_display_deprecated_warning_on_use(decl, expr->span);
|
||||
|
||||
unit_register_external_symbol(context, decl);
|
||||
if (decl->decl_kind == DECL_VAR)
|
||||
@@ -1780,7 +1780,7 @@ SPLAT_NORMAL:;
|
||||
RETURN_SEMA_ERROR(arg, "A value of type %s cannot be passed as a raw variadic argument.",
|
||||
type_quoted_error_string(arg->type));
|
||||
}
|
||||
cast_promote_vararg(context, arg);
|
||||
cast_promote_vararg(arg);
|
||||
}
|
||||
// Set the argument at the location.
|
||||
*optional |= IS_OPTIONAL(arg);
|
||||
@@ -1946,7 +1946,6 @@ static inline bool sema_call_analyse_func_invocation(SemaContext *context, Decl
|
||||
|
||||
static inline bool sema_expr_analyse_var_call(SemaContext *context, Expr *expr, Type *func_ptr_type, bool optional, bool *no_match_ref)
|
||||
{
|
||||
Decl *decl = NULL;
|
||||
func_ptr_type = type_flat_distinct_inline(func_ptr_type);
|
||||
if (func_ptr_type->type_kind != TYPE_FUNC_PTR)
|
||||
{
|
||||
@@ -2066,7 +2065,7 @@ static inline bool sema_expr_analyse_func_call(SemaContext *context, Expr *expr,
|
||||
return false;
|
||||
}
|
||||
|
||||
sema_display_deprecated_warning_on_use(context, decl, expr->span);
|
||||
sema_display_deprecated_warning_on_use(decl, expr->span);
|
||||
|
||||
// Tag dynamic dispatch.
|
||||
if (struct_var && decl->func_decl.attr_interface_method) expr->call_expr.is_dynamic_dispatch = true;
|
||||
@@ -2093,7 +2092,7 @@ bool sema_expr_analyse_macro_call(SemaContext *context, Expr *call_expr, Expr *s
|
||||
"possibly due non-terminating macro recursion.");
|
||||
}
|
||||
|
||||
sema_display_deprecated_warning_on_use(context, decl, call_expr->span);
|
||||
sema_display_deprecated_warning_on_use(decl, call_expr->span);
|
||||
|
||||
copy_begin();
|
||||
Decl **params = copy_decl_list_macro(decl->func_decl.signature.params);
|
||||
@@ -2414,7 +2413,6 @@ bool sema_expr_analyse_macro_call(SemaContext *context, Expr *call_expr, Expr *s
|
||||
Expr *result = ret ? ret->return_stmt.expr : NULL;
|
||||
if (!result) goto NOT_CT;
|
||||
if (!expr_is_runtime_const(result)) goto NOT_CT;
|
||||
bool only_ct_params = true;
|
||||
FOREACH(Decl *, param, params)
|
||||
{
|
||||
// Skip raw vararg
|
||||
@@ -2532,8 +2530,6 @@ static bool sema_call_analyse_body_expansion(SemaContext *macro_context, Expr *c
|
||||
call->body_expansion_expr.values = args;
|
||||
call->body_expansion_expr.declarations = macro_context->yield_params;
|
||||
AstId last_defer = context->active_scope.defer_last;
|
||||
bool success;
|
||||
bool ends_in_jump;
|
||||
SCOPE_START
|
||||
unsigned ct_context = sema_context_push_ct_stack(context);
|
||||
if (macro_defer)
|
||||
@@ -2579,7 +2575,7 @@ static bool sema_call_analyse_body_expansion(SemaContext *macro_context, Expr *c
|
||||
|
||||
}
|
||||
|
||||
void sema_expr_convert_enum_to_int(SemaContext *context, Expr *expr)
|
||||
void sema_expr_convert_enum_to_int(Expr *expr)
|
||||
{
|
||||
ASSERT(type_flatten(expr->type)->type_kind == TYPE_ENUM);
|
||||
Type *underlying_type = type_base(expr->type);
|
||||
@@ -3465,7 +3461,6 @@ INLINE bool sema_expr_analyse_range_internal(SemaContext *context, Range *range,
|
||||
RETURN_SEMA_ERROR(end, "Indexing from the end is not allowed for pointers or flexible array members.");
|
||||
}
|
||||
}
|
||||
bool end_is_const = !end || sema_cast_const(end);
|
||||
if (end && sema_cast_const(end))
|
||||
{
|
||||
// Only ArrayIndex sized
|
||||
@@ -3649,7 +3644,6 @@ static inline void sema_slice_initializer(SemaContext *context, Expr *expr, Expr
|
||||
vec_erase_at(initializer->init_array.elements, i);
|
||||
elements--;
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (vec_size(initializer->init_array.elements) == 0)
|
||||
@@ -3824,9 +3818,7 @@ RETRY:
|
||||
case EXPR_CT_EVAL:
|
||||
{
|
||||
ASSERT_SPAN(child, child->resolve_status != RESOLVE_DONE);
|
||||
TokenType type;
|
||||
// Only report missing if missing var is NULL
|
||||
Path *path = NULL;
|
||||
Expr *result = sema_ct_eval_expr(context, false, child->inner_expr, missing == NULL);
|
||||
if (!result)
|
||||
{
|
||||
@@ -4281,7 +4273,7 @@ static inline bool sema_create_const_parent(SemaContext *context, Expr *expr, Ty
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool sema_create_const_min(SemaContext *context, Expr *expr, Type *type, Type *flat)
|
||||
static inline bool sema_create_const_min(Expr *expr, Type *type, Type *flat)
|
||||
{
|
||||
if (type_is_float(flat))
|
||||
{
|
||||
@@ -4313,7 +4305,7 @@ static inline bool sema_create_const_min(SemaContext *context, Expr *expr, Type
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else if (type_is_integer(flat))
|
||||
if (type_is_integer(flat))
|
||||
{
|
||||
expr->expr_kind = EXPR_CONST;
|
||||
expr->const_expr.const_kind = CONST_INTEGER;
|
||||
@@ -4523,7 +4515,7 @@ static inline bool sema_create_const_max(SemaContext *context, Expr *expr, Type
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else if (type_is_float(flat))
|
||||
if (type_is_float(flat))
|
||||
{
|
||||
expr->expr_kind = EXPR_CONST;
|
||||
expr->const_expr.const_kind = CONST_FLOAT;
|
||||
@@ -4874,7 +4866,7 @@ static bool sema_expr_rewrite_to_type_property(SemaContext *context, Expr *expr,
|
||||
case TYPE_PROPERTY_LEN:
|
||||
return sema_create_const_len(context, expr, flat);
|
||||
case TYPE_PROPERTY_MIN:
|
||||
return sema_create_const_min(context, expr, type, flat);
|
||||
return sema_create_const_min(expr, type, flat);
|
||||
case TYPE_PROPERTY_MAX:
|
||||
return sema_create_const_max(context, expr, type, flat);
|
||||
case TYPE_PROPERTY_NAMES:
|
||||
@@ -5119,7 +5111,6 @@ static inline bool sema_expr_analyse_access(SemaContext *context, Expr *expr, bo
|
||||
}
|
||||
|
||||
// 3. Find the actual token.
|
||||
SourceSpan span;
|
||||
Expr *identifier = sema_expr_resolve_access_child(context, child, missing_ref);
|
||||
if (!identifier) return false;
|
||||
const char *kw = identifier->unresolved_ident_expr.ident;
|
||||
@@ -5249,7 +5240,7 @@ CHECK_DEEPER:
|
||||
{
|
||||
if (flat_type->type_kind == TYPE_ENUM)
|
||||
{
|
||||
sema_expr_convert_enum_to_int(context, current_parent);
|
||||
sema_expr_convert_enum_to_int(current_parent);
|
||||
expr_replace(expr, current_parent);
|
||||
return true;
|
||||
}
|
||||
@@ -5672,7 +5663,7 @@ static inline bool sema_expr_analyse_cast(SemaContext *context, Expr *expr, bool
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool sema_expr_analyse_slice_assign(SemaContext *context, Expr *expr, Type *left_type, Expr *right, bool is_unwrapped)
|
||||
static bool sema_expr_analyse_slice_assign(SemaContext *context, Expr *expr, Type *left_type, Expr *right)
|
||||
{
|
||||
Expr *left = exprptr(expr->binary_expr.left);
|
||||
if (!sema_analyse_expr(context, right)) return false;
|
||||
@@ -5786,7 +5777,7 @@ bool sema_expr_analyse_assign_right_side(SemaContext *context, Expr *expr, Type
|
||||
{
|
||||
if (expr && exprptr(expr->binary_expr.left)->expr_kind == EXPR_SLICE)
|
||||
{
|
||||
return sema_expr_analyse_slice_assign(context, expr, left_type, right, is_unwrapped);
|
||||
return sema_expr_analyse_slice_assign(context, expr, left_type, right);
|
||||
}
|
||||
|
||||
// 1. Evaluate right side to required type.
|
||||
@@ -6276,12 +6267,12 @@ static void sema_binary_unify_voidptr(SemaContext *context, Expr *left, Expr *ri
|
||||
if (*left_type_ref == *right_type_ref) return;
|
||||
if (*left_type_ref == type_voidptr)
|
||||
{
|
||||
cast_no_check(context, left, *right_type_ref, IS_OPTIONAL(left));
|
||||
cast_no_check(left, *right_type_ref, IS_OPTIONAL(left));
|
||||
*left_type_ref = *right_type_ref;
|
||||
}
|
||||
if (*right_type_ref == type_voidptr)
|
||||
{
|
||||
cast_no_check(context, right, *left_type_ref, IS_OPTIONAL(right));
|
||||
cast_no_check(right, *left_type_ref, IS_OPTIONAL(right));
|
||||
*right_type_ref = *left_type_ref;
|
||||
}
|
||||
}
|
||||
@@ -6305,7 +6296,6 @@ static bool sema_expr_analyse_enum_add_sub(SemaContext *context, Expr *expr, Exp
|
||||
{
|
||||
Type *left_type = type_no_optional(left->type)->canonical;
|
||||
bool is_sub = expr->binary_expr.operator == BINARYOP_SUB;
|
||||
bool swapped = false;
|
||||
if (left_type->type_kind != TYPE_ENUM)
|
||||
{
|
||||
if (is_sub)
|
||||
@@ -6332,8 +6322,8 @@ static bool sema_expr_analyse_enum_add_sub(SemaContext *context, Expr *expr, Exp
|
||||
type_quoted_error_string(right->type));
|
||||
}
|
||||
Type *underlying_type = left_type->decl->enums.type_info->type;
|
||||
sema_expr_convert_enum_to_int(context, left);
|
||||
sema_expr_convert_enum_to_int(context, right);
|
||||
sema_expr_convert_enum_to_int(left);
|
||||
sema_expr_convert_enum_to_int(right);
|
||||
expr->type = type_add_optional(underlying_type, IS_OPTIONAL(left) || IS_OPTIONAL(right));
|
||||
if (expr_both_const(left, right))
|
||||
{
|
||||
@@ -6354,7 +6344,7 @@ static bool sema_expr_analyse_enum_add_sub(SemaContext *context, Expr *expr, Exp
|
||||
}
|
||||
|
||||
// Enum - value / Enum + value
|
||||
sema_expr_convert_enum_to_int(context, left);
|
||||
sema_expr_convert_enum_to_int(left);
|
||||
if (!cast_implicit(context, right, left->type, true)) return false;
|
||||
expr->type = type_add_optional(left_type, IS_OPTIONAL(left) || IS_OPTIONAL(right));
|
||||
if (expr_both_const(left, right))
|
||||
@@ -7078,7 +7068,7 @@ static bool sema_expr_analyse_comp(SemaContext *context, Expr *expr, Expr *left,
|
||||
|| (type_is_signed(left_type) && type_is_unsigned(right_type)))
|
||||
{
|
||||
// 2a. Resize so that both sides have the same bit width. This will always work.
|
||||
cast_to_int_to_max_bit_size(context, left, right, left_type, right_type);
|
||||
cast_to_int_to_max_bit_size(left, right, left_type, right_type);
|
||||
goto DONE;
|
||||
}
|
||||
|
||||
@@ -7920,43 +7910,43 @@ INLINE bool expr_is_ungrouped_ternary(Expr *expr)
|
||||
return expr->expr_kind == EXPR_TERNARY && !expr->ternary_expr.grouped;
|
||||
}
|
||||
|
||||
static inline bool sema_expr_analyse_or_error(SemaContext *context, Expr *expr, Expr *lhs, Expr *rhs)
|
||||
static inline bool sema_expr_analyse_or_error(SemaContext *context, Expr *expr, Expr *left, Expr *right)
|
||||
{
|
||||
bool lhs_is_embed = lhs->expr_kind == EXPR_EMBED;
|
||||
if (expr_is_ungrouped_ternary(lhs) || expr_is_ungrouped_ternary(rhs))
|
||||
bool lhs_is_embed = left->expr_kind == EXPR_EMBED;
|
||||
if (expr_is_ungrouped_ternary(left) || expr_is_ungrouped_ternary(right))
|
||||
{
|
||||
SEMA_ERROR(expr, "Unclear precedence using ternary with ??, please use () to remove ambiguity.");
|
||||
return false;
|
||||
}
|
||||
if (lhs_is_embed)
|
||||
{
|
||||
if (!sema_expr_analyse_embed(context, lhs, true)) return false;
|
||||
if (!sema_expr_analyse_embed(context, left, true)) return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!sema_analyse_expr(context, lhs)) return false;
|
||||
if (!sema_analyse_expr(context, left)) return false;
|
||||
}
|
||||
|
||||
Type *type = lhs->type;
|
||||
Type *type = left->type;
|
||||
if (!type_is_optional(type))
|
||||
{
|
||||
if (lhs_is_embed)
|
||||
{
|
||||
expr_replace(expr, lhs);
|
||||
expr_replace(expr, left);
|
||||
return true;
|
||||
}
|
||||
RETURN_SEMA_ERROR(lhs, "No optional to use '\?\?' with, please remove the '\?\?'.");
|
||||
RETURN_SEMA_ERROR(left, "No optional to use '\?\?' with, please remove the '\?\?'.");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool active_scope_jump = context->active_scope.jump_end;
|
||||
|
||||
// First we analyse the "else" and try to implictly cast.
|
||||
if (!sema_analyse_expr(context, rhs)) return false;
|
||||
if (!sema_analyse_expr(context, right)) return false;
|
||||
|
||||
if (lhs->expr_kind == EXPR_OPTIONAL)
|
||||
if (left->expr_kind == EXPR_OPTIONAL)
|
||||
{
|
||||
expr_replace(expr, rhs);
|
||||
expr_replace(expr, right);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -7964,7 +7954,7 @@ static inline bool sema_expr_analyse_or_error(SemaContext *context, Expr *expr,
|
||||
context->active_scope.jump_end = active_scope_jump;
|
||||
|
||||
// Here we might need to insert casts.
|
||||
Type *else_type = rhs->type;
|
||||
Type *else_type = right->type;
|
||||
|
||||
|
||||
// Remove any possible optional of the else type.
|
||||
@@ -7974,12 +7964,12 @@ static inline bool sema_expr_analyse_or_error(SemaContext *context, Expr *expr,
|
||||
Type *common = type_find_max_type(type, else_type);
|
||||
if (!common)
|
||||
{
|
||||
SEMA_ERROR(rhs, "Cannot find a common type for %s and %s.", type_quoted_error_string(type),
|
||||
SEMA_ERROR(right, "Cannot find a common type for %s and %s.", type_quoted_error_string(type),
|
||||
type_quoted_error_string(else_type));
|
||||
return false;
|
||||
}
|
||||
if (!cast_implicit(context, lhs, common, false)) return false;
|
||||
if (!cast_implicit(context, rhs, common, false)) return false;
|
||||
if (!cast_implicit(context, left, common, false)) return false;
|
||||
if (!cast_implicit(context, right, common, false)) return false;
|
||||
expr->type = type_add_optional(common, add_optional);
|
||||
return true;
|
||||
}
|
||||
@@ -8998,7 +8988,6 @@ static inline Decl *sema_find_cached_lambda(SemaContext *context, Type *func_typ
|
||||
|
||||
static inline bool sema_expr_analyse_embed(SemaContext *context, Expr *expr, bool allow_fail)
|
||||
{
|
||||
static File no_file;
|
||||
Expr *filename = expr->embed_expr.filename;
|
||||
if (!sema_analyse_ct_expr(context, filename)) return false;
|
||||
Expr *len_expr = expr->embed_expr.len;
|
||||
@@ -9019,8 +9008,6 @@ static inline bool sema_expr_analyse_embed(SemaContext *context, Expr *expr, boo
|
||||
|
||||
CompilationUnit *unit = context->unit;
|
||||
const char *string = filename->const_expr.bytes.ptr;
|
||||
bool loaded;
|
||||
const char *error;
|
||||
char *path;
|
||||
char *name;
|
||||
if (file_namesplit(unit->file->full_path, &name, &path))
|
||||
@@ -10104,10 +10091,10 @@ bool sema_analyse_expr_rhs(SemaContext *context, Type *to, Expr *expr, bool allo
|
||||
RETURN_SEMA_ERROR(expr, "Slice length mismatch, expected %u but got %u.", to_canonical->array.len, len);
|
||||
}
|
||||
// Given x[3..7] -> (int[5]*)x[3..7]
|
||||
cast_no_check(context, expr, type_get_ptr(type_get_array(element, len)), IS_OPTIONAL(expr));
|
||||
cast_no_check(expr, type_get_ptr(type_get_array(element, len)), IS_OPTIONAL(expr));
|
||||
// Deref
|
||||
expr_rewrite_insert_deref(expr);
|
||||
cast_no_check(context, expr, to, IS_OPTIONAL(expr));
|
||||
cast_no_check(expr, to, IS_OPTIONAL(expr));
|
||||
return true;
|
||||
}
|
||||
NO_SLICE:;
|
||||
@@ -10159,8 +10146,7 @@ static inline bool sema_cast_rvalue(SemaContext *context, Expr *expr, bool mutat
|
||||
case EXPR_MACRO_BODY_EXPANSION:
|
||||
if (!expr->body_expansion_expr.first_stmt)
|
||||
{
|
||||
SEMA_ERROR(expr, "'@%s' must be followed by ().", declptr(context->current_macro->func_decl.body_param)->name);
|
||||
return false;
|
||||
RETURN_SEMA_ERROR(expr, "'@%s' must be followed by ().", declptr(context->current_macro->func_decl.body_param)->name); // NOLINT
|
||||
}
|
||||
break;
|
||||
case EXPR_TYPECALL:
|
||||
|
||||
@@ -203,8 +203,7 @@ static inline bool sema_expr_analyse_struct_plain_initializer(SemaContext *conte
|
||||
if (elements_needed == 0)
|
||||
{
|
||||
// Generate a nice error message for zero.
|
||||
SEMA_ERROR(elements[0], "Too many elements in initializer, it must be empty.");
|
||||
return false;
|
||||
RETURN_SEMA_ERROR(elements[0], "Too many elements in initializer, it must be empty.");
|
||||
}
|
||||
|
||||
bool optional = false;
|
||||
@@ -780,6 +779,7 @@ ConstInitializer *sema_merge_bitstruct_const_initializers(ConstInitializer *lhs,
|
||||
|
||||
bool sema_expr_analyse_initializer_list(SemaContext *context, Type *to, Expr *expr)
|
||||
{
|
||||
|
||||
if (!to) to = type_untypedlist;
|
||||
ASSERT(to);
|
||||
Type *flattened = type_flatten(to);
|
||||
|
||||
@@ -113,16 +113,16 @@ Expr *sema_create_struct_from_expressions(Decl *struct_decl, SourceSpan span, Ex
|
||||
ConstInitializer *sema_merge_bitstruct_const_initializers(ConstInitializer *lhs, ConstInitializer *rhs, BinaryOp op);
|
||||
void sema_invert_bitstruct_const_initializer(ConstInitializer *initializer);
|
||||
ArrayIndex sema_len_from_const(Expr *expr);
|
||||
void cast_promote_vararg(SemaContext *context, Expr *arg);
|
||||
void cast_promote_vararg(Expr *arg);
|
||||
Type *cast_numeric_arithmetic_promotion(Type *type);
|
||||
void cast_to_int_to_max_bit_size(SemaContext *context, Expr *lhs, Expr *rhs, Type *left_type, Type *right_type);
|
||||
void cast_to_int_to_max_bit_size(Expr *lhs, Expr *rhs, Type *left_type, Type *right_type);
|
||||
bool sema_decl_if_cond(SemaContext *context, Decl *decl);
|
||||
Decl *sema_analyse_parameterized_identifier(SemaContext *c, Path *decl_path, const char *name, SourceSpan span,
|
||||
Expr **params, bool *was_recursive_ref);
|
||||
Type *sema_resolve_type_get_func(Signature *signature, CallABI abi);
|
||||
INLINE bool sema_set_abi_alignment(SemaContext *context, Type *type, AlignSize *result);
|
||||
INLINE bool sema_set_alloca_alignment(SemaContext *context, Type *type, AlignSize *result);
|
||||
INLINE void sema_display_deprecated_warning_on_use(SemaContext *context, Decl *decl, SourceSpan use);
|
||||
INLINE void sema_display_deprecated_warning_on_use(Decl *decl, SourceSpan use);
|
||||
bool sema_expr_analyse_ct_concat(SemaContext *context, Expr *concat_expr, Expr *left, Expr *right);
|
||||
|
||||
|
||||
@@ -154,7 +154,7 @@ INLINE Attr* attr_find_kind(Attr **attrs, AttributeType attr_type)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
INLINE void sema_display_deprecated_warning_on_use(SemaContext *context, Decl *decl, SourceSpan span)
|
||||
INLINE void sema_display_deprecated_warning_on_use(Decl *decl, SourceSpan span)
|
||||
{
|
||||
ASSERT(decl->resolve_status == RESOLVE_DONE);
|
||||
if (!decl->resolved_attributes || !decl->attrs_resolved || !decl->attrs_resolved->deprecated) return;
|
||||
|
||||
@@ -1171,7 +1171,7 @@ static inline bool sema_analyse_cond(SemaContext *context, Expr *expr, CondType
|
||||
{
|
||||
RETURN_SEMA_ERROR(last->decl_expr->var.init_expr, "The expression needs to be convertible to a boolean.");
|
||||
}
|
||||
cast_no_check(context, last, type_bool, false);
|
||||
cast_no_check(last, type_bool, false);
|
||||
}
|
||||
if (cast_to_bool && expr_is_const_bool(init))
|
||||
{
|
||||
|
||||
47
test/test_suite/compile_time/more_untyped_conversions.c3t
Normal file
47
test/test_suite/compile_time/more_untyped_conversions.c3t
Normal file
@@ -0,0 +1,47 @@
|
||||
// #target: macos-x64
|
||||
module test;
|
||||
|
||||
struct Foo { int a; struct { int b; int c; }}
|
||||
fn int main()
|
||||
{
|
||||
var $z = { { 1, 2 }, { }};
|
||||
int[2][] z = $z;
|
||||
int[2][2] z_slice = $z;
|
||||
var $c = { 1, { 3, 4 }};
|
||||
var $d = { 1, 2 };
|
||||
Foo f = $c;
|
||||
int[?] y = $d;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* #expect: test.ll
|
||||
|
||||
@.__const = private unnamed_addr constant %Foo { i32 1, %.anon { i32 3, i32 4 } }, align 4
|
||||
@.__const.2 = private unnamed_addr constant [2 x i32] [i32 1, i32 2], align 4
|
||||
|
||||
entry:
|
||||
%z = alloca %"int[2][]", align 8
|
||||
%literal = alloca [2 x [2 x i32]], align 16
|
||||
%z_slice = alloca [2 x [2 x i32]], align 16
|
||||
%f = alloca %Foo, align 4
|
||||
%y = alloca [2 x i32], align 4
|
||||
store i32 1, ptr %literal, align 4
|
||||
%ptradd = getelementptr inbounds i8, ptr %literal, i64 4
|
||||
store i32 2, ptr %ptradd, align 4
|
||||
%ptradd1 = getelementptr inbounds i8, ptr %literal, i64 8
|
||||
store i32 0, ptr %ptradd1, align 4
|
||||
%ptradd2 = getelementptr inbounds i8, ptr %ptradd1, i64 4
|
||||
store i32 0, ptr %ptradd2, align 4
|
||||
%0 = insertvalue %"int[2][]" undef, ptr %literal, 0
|
||||
%1 = insertvalue %"int[2][]" %0, i64 2, 1
|
||||
store %"int[2][]" %1, ptr %z, align 8
|
||||
store i32 1, ptr %z_slice, align 4
|
||||
%ptradd3 = getelementptr inbounds i8, ptr %z_slice, i64 4
|
||||
store i32 2, ptr %ptradd3, align 4
|
||||
%ptradd4 = getelementptr inbounds i8, ptr %z_slice, i64 8
|
||||
store i32 0, ptr %ptradd4, align 4
|
||||
%ptradd5 = getelementptr inbounds i8, ptr %ptradd4, i64 4
|
||||
store i32 0, ptr %ptradd5, align 4
|
||||
call void @llvm.memcpy.p0.p0.i32(ptr align 4 %f, ptr align 4 @.__const, i32 12, i1 false)
|
||||
call void @llvm.memcpy.p0.p0.i32(ptr align 4 %y, ptr align 4 @.__const.2, i32 8, i1 false)
|
||||
ret i32 0
|
||||
Reference in New Issue
Block a user