mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Version bump. More generous wildcard length matching and conversions.
This commit is contained in:
committed by
Christoffer Lerno
parent
314369d069
commit
9424bba49f
@@ -2016,8 +2016,9 @@ AsmRegister *asm_reg_by_index(unsigned index);
|
||||
|
||||
bool cast_implicit(SemaContext *context, Expr *expr, Type *to_type);
|
||||
bool cast(Expr *expr, Type *to_type);
|
||||
bool cast_may_implicit(Type *from_type, Type *to_type, bool is_simple_expr, bool failable_allowed);
|
||||
bool cast_may_implicit(Type *from_type, Type *to_type, CastOption option);
|
||||
bool cast_may_explicit(Type *from_type, Type *to_type, bool ignore_failability, bool is_const);
|
||||
Type *cast_infer_len(Type *to_infer, Type *actual_type);
|
||||
bool cast_to_index(Expr *index);
|
||||
|
||||
bool cast_untyped_to_type(SemaContext *context, Expr *expr, Type *to_type);
|
||||
@@ -2304,6 +2305,8 @@ INLINE Type *type_new(TypeKind kind, const char *name);
|
||||
INLINE bool type_is_pointer_sized(Type *type);
|
||||
INLINE bool type_is_pointer_sized_or_more(Type *type);
|
||||
INLINE Type *type_add_optional(Type *type, bool make_optional);
|
||||
INLINE Type *type_from_inferred(Type *flattened, Type *element_type, unsigned count);
|
||||
INLINE bool type_len_is_inferred(Type *type);
|
||||
INLINE bool type_is_substruct(Type *type);
|
||||
INLINE Type *type_flatten_for_bitstruct(Type *type);
|
||||
INLINE bool type_is_float(Type *type);
|
||||
@@ -2316,9 +2319,11 @@ INLINE bool type_is_integer_unsigned(Type *type);
|
||||
INLINE bool type_is_integer_signed(Type *type);
|
||||
INLINE bool type_is_integer_or_bool_kind(Type *type);
|
||||
INLINE bool type_is_numeric(Type *type);
|
||||
INLINE bool type_is_len_inferred(Type *type);
|
||||
INLINE bool type_underlying_is_numeric(Type *type);
|
||||
INLINE bool type_is_pointer(Type *type);
|
||||
INLINE bool type_is_arraylike(Type *type);
|
||||
INLINE bool type_is_any_arraylike(Type *type);
|
||||
INLINE bool type_is_promotable_float(Type *type);
|
||||
INLINE bool type_is_promotable_integer(Type *type);
|
||||
INLINE bool type_is_signed(Type *type);
|
||||
@@ -2387,11 +2392,49 @@ INLINE Type *type_add_optional(Type *type, bool make_optional)
|
||||
return type_get_optional(type);
|
||||
}
|
||||
|
||||
INLINE Type *type_from_inferred(Type *flattened, Type *element_type, unsigned count)
|
||||
{
|
||||
switch (flattened->type_kind)
|
||||
{
|
||||
case TYPE_INFERRED_VECTOR:
|
||||
return type_get_vector(element_type, count);
|
||||
break;
|
||||
case TYPE_INFERRED_ARRAY:
|
||||
return type_get_array(element_type, count);
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE
|
||||
}
|
||||
}
|
||||
INLINE bool type_len_is_inferred(Type *type)
|
||||
{
|
||||
if (!type) return true;
|
||||
DECL_TYPE_KIND_REAL(kind, type);
|
||||
return kind == TYPE_INFERRED_VECTOR || kind == TYPE_INFERRED_ARRAY;
|
||||
while (1)
|
||||
{
|
||||
switch (type->type_kind)
|
||||
{
|
||||
case TYPE_TYPEDEF:
|
||||
type = type->canonical;
|
||||
continue;
|
||||
case TYPE_ARRAY:
|
||||
case TYPE_SUBARRAY:
|
||||
case TYPE_FLEXIBLE_ARRAY:
|
||||
case TYPE_VECTOR:
|
||||
case TYPE_SCALED_VECTOR:
|
||||
type = type->array.base;
|
||||
continue;
|
||||
case TYPE_INFERRED_ARRAY:
|
||||
case TYPE_INFERRED_VECTOR:
|
||||
return true;
|
||||
case TYPE_POINTER:
|
||||
type = type->pointer;
|
||||
continue;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
UNREACHABLE;
|
||||
}
|
||||
}
|
||||
|
||||
INLINE bool type_is_optional(Type *type)
|
||||
@@ -2452,6 +2495,14 @@ INLINE bool type_is_arraylike(Type *type)
|
||||
return kind == TYPE_ARRAY || kind == TYPE_VECTOR || kind == TYPE_FLEXIBLE_ARRAY || kind == TYPE_SCALED_VECTOR;
|
||||
}
|
||||
|
||||
INLINE bool type_is_any_arraylike(Type *type)
|
||||
{
|
||||
DECL_TYPE_KIND_REAL(kind, type);
|
||||
return kind == TYPE_ARRAY || kind == TYPE_VECTOR
|
||||
|| kind == TYPE_FLEXIBLE_ARRAY || kind == TYPE_SCALED_VECTOR
|
||||
|| kind == TYPE_INFERRED_VECTOR || kind == TYPE_INFERRED_ARRAY;
|
||||
}
|
||||
|
||||
INLINE CanonicalType *type_pointer_type(Type *type)
|
||||
{
|
||||
CanonicalType *res = type->canonical;
|
||||
@@ -2672,6 +2723,12 @@ bool type_is_scalar(Type *type);
|
||||
|
||||
INLINE bool type_is_signed(Type *type) { return type->type_kind >= TYPE_I8 && type->type_kind < TYPE_U8; }
|
||||
|
||||
INLINE bool type_is_len_inferred(Type *type)
|
||||
{
|
||||
TypeKind kind = type->type_kind;
|
||||
return kind == TYPE_INFERRED_VECTOR || kind == TYPE_INFERRED_ARRAY;
|
||||
}
|
||||
|
||||
INLINE bool type_is_numeric(Type *type)
|
||||
{
|
||||
DECL_TYPE_KIND_REAL(kind, type);
|
||||
|
||||
@@ -118,6 +118,13 @@ typedef enum
|
||||
CAST_VECARR,
|
||||
} CastKind;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CAST_OPTION_NONE = 0x00,
|
||||
CAST_OPTION_SIMPLE_EXPR = 0x01,
|
||||
CAST_OPTION_ALLOW_OPTIONAL = 0x02,
|
||||
} CastOption;
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
|
||||
@@ -12,6 +12,8 @@ static void sema_error_const_int_out_of_range(Expr *expr, Expr *problem, Type *t
|
||||
static Expr *recursive_may_narrow_float(Expr *expr, Type *type);
|
||||
static Expr *recursive_may_narrow_int(Expr *expr, Type *type);
|
||||
static void recursively_rewrite_untyped_list(Expr *expr, Expr **list);
|
||||
static inline bool cast_may_implicit_ptr(Type *from_pointee, Type *to_pointee);
|
||||
static inline bool cast_may_array(Type *from, Type *to, bool is_explicit);
|
||||
|
||||
static inline bool insert_cast(Expr *expr, CastKind kind, Type *type)
|
||||
{
|
||||
@@ -32,6 +34,38 @@ bool sema_error_failed_cast(Expr *expr, Type *from, Type *to)
|
||||
return false;
|
||||
}
|
||||
|
||||
Type *cast_infer_len(Type *to_infer, Type *actual_type)
|
||||
{
|
||||
Type *may_infer = to_infer->canonical;
|
||||
Type *actual = actual_type->canonical;
|
||||
if (may_infer == actual) return to_infer;
|
||||
bool canonical_same_kind = may_infer->type_kind == to_infer->type_kind;
|
||||
if (may_infer->type_kind == TYPE_INFERRED_ARRAY)
|
||||
{
|
||||
assert(actual_type->type_kind == TYPE_ARRAY);
|
||||
Type *base_type = cast_infer_len(canonical_same_kind ? to_infer->array.base :
|
||||
may_infer->array.base, actual->array.base);
|
||||
return type_get_array(base_type, actual->array.len);
|
||||
}
|
||||
if (may_infer->type_kind == TYPE_INFERRED_VECTOR)
|
||||
{
|
||||
assert(actual_type->type_kind == TYPE_VECTOR || actual->type_kind == TYPE_SCALED_VECTOR);
|
||||
Type *base_type = cast_infer_len(canonical_same_kind ? to_infer->array.base : may_infer->array.base, actual->array.base);
|
||||
if (actual_type->type_kind == TYPE_SCALED_VECTOR)
|
||||
{
|
||||
return type_get_scaled_vector(base_type);
|
||||
}
|
||||
return type_get_vector(base_type, actual->array.len);
|
||||
}
|
||||
if (may_infer->type_kind == TYPE_POINTER)
|
||||
{
|
||||
assert(actual->type_kind == TYPE_POINTER);
|
||||
Type *base_type = cast_infer_len(canonical_same_kind ? to_infer->array.base : may_infer->pointer, actual->pointer);
|
||||
return type_get_ptr(base_type);
|
||||
}
|
||||
UNREACHABLE
|
||||
}
|
||||
|
||||
static inline bool insert_runtime_cast_unless_const(Expr *expr, CastKind kind, Type *type)
|
||||
{
|
||||
if (expr->expr_kind == EXPR_CONST) return false;
|
||||
@@ -406,6 +440,7 @@ CastKind cast_to_bool_kind(Type *type)
|
||||
UNREACHABLE
|
||||
}
|
||||
|
||||
|
||||
bool cast_may_explicit(Type *from_type, Type *to_type, bool ignore_failability, bool is_const)
|
||||
{
|
||||
// 1. failable -> non-failable can't be cast unless we ignore failability.
|
||||
@@ -431,15 +466,9 @@ bool cast_may_explicit(Type *from_type, Type *to_type, bool ignore_failability,
|
||||
// 2. Same underlying type, always ok
|
||||
if (from_type == to_type) return true;
|
||||
|
||||
if (to_type->type_kind == TYPE_INFERRED_ARRAY)
|
||||
if (type_is_any_arraylike(to_type) && type_is_any_arraylike(from_type))
|
||||
{
|
||||
if (from_type->type_kind == TYPE_ARRAY && type_flatten_distinct(from_type->array.base) == type_flatten_distinct(to_type->array.base)) return true;
|
||||
return false;
|
||||
}
|
||||
if (to_type->type_kind == TYPE_INFERRED_VECTOR)
|
||||
{
|
||||
if (from_type->type_kind == TYPE_VECTOR && type_flatten_distinct(from_type->array.base) == type_flatten_distinct(to_type->array.base)) return true;
|
||||
return false;
|
||||
return cast_may_array(from_type, to_type, true);
|
||||
}
|
||||
|
||||
TypeKind to_kind = to_type->type_kind;
|
||||
@@ -534,30 +563,183 @@ bool type_may_convert_to_anyerr(Type *type)
|
||||
if (!type_is_optional_type(type)) return false;
|
||||
return type->failable->canonical == type_void;
|
||||
}
|
||||
|
||||
|
||||
static inline bool cast_may_array(Type *from, Type *to, bool is_explicit)
|
||||
{
|
||||
RETRY:;
|
||||
assert(!type_is_optional(from) && !type_is_optional(to) && "Optional should already been handled");
|
||||
|
||||
bool compare_len = true;
|
||||
if (from->type_kind != to->type_kind)
|
||||
{
|
||||
switch (to->type_kind)
|
||||
{
|
||||
case TYPE_INFERRED_ARRAY:
|
||||
switch (from->type_kind)
|
||||
{
|
||||
case TYPE_INFERRED_VECTOR:
|
||||
case TYPE_VECTOR:
|
||||
if (!is_explicit) return false;
|
||||
FALLTHROUGH;
|
||||
case TYPE_ARRAY:
|
||||
compare_len = false;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case TYPE_ARRAY:
|
||||
switch (from->type_kind)
|
||||
{
|
||||
case TYPE_INFERRED_VECTOR:
|
||||
compare_len = false;
|
||||
FALLTHROUGH;
|
||||
case TYPE_VECTOR:
|
||||
if (!is_explicit) return false;
|
||||
break;
|
||||
case TYPE_INFERRED_ARRAY:
|
||||
compare_len = false;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case TYPE_INFERRED_VECTOR:
|
||||
switch (from->type_kind)
|
||||
{
|
||||
case TYPE_INFERRED_ARRAY:
|
||||
case TYPE_ARRAY:
|
||||
if (!is_explicit) return false;
|
||||
FALLTHROUGH;
|
||||
case TYPE_VECTOR:
|
||||
case TYPE_SCALED_VECTOR:
|
||||
compare_len = false;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case TYPE_VECTOR:
|
||||
switch (from->type_kind)
|
||||
{
|
||||
case TYPE_INFERRED_ARRAY:
|
||||
compare_len = false;
|
||||
FALLTHROUGH;
|
||||
case TYPE_ARRAY:
|
||||
if (!is_explicit) return false;
|
||||
break;
|
||||
case TYPE_INFERRED_VECTOR:
|
||||
compare_len = false;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case TYPE_SCALED_VECTOR:
|
||||
if (from->type_kind != TYPE_INFERRED_VECTOR) return false;
|
||||
compare_len = false;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (compare_len && to->array.len != from->array.len) return false;
|
||||
|
||||
Type *from_base = from->array.base;
|
||||
Type *to_base = to->array.base;
|
||||
if (is_explicit)
|
||||
{
|
||||
from_base = type_flatten(from_base);
|
||||
to_base = type_flatten(to_base);
|
||||
}
|
||||
|
||||
if (from_base == to_base) return true;
|
||||
|
||||
switch (to_base->type_kind)
|
||||
{
|
||||
case TYPE_POINTER:
|
||||
if (from_base->type_kind == TYPE_POINTER)
|
||||
{
|
||||
if (is_explicit) return true;
|
||||
return cast_may_implicit_ptr(to_base->pointer, from_base->pointer);
|
||||
}
|
||||
return false;
|
||||
case TYPE_ARRAY:
|
||||
case TYPE_INFERRED_ARRAY:
|
||||
case TYPE_VECTOR:
|
||||
case TYPE_INFERRED_VECTOR:
|
||||
to = to_base;
|
||||
from = from_base;
|
||||
goto RETRY;
|
||||
default:
|
||||
return is_explicit && type_is_structurally_equivalent(to_base, from_base);
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool cast_may_implicit_ptr(Type *from_pointee, Type *to_pointee)
|
||||
{
|
||||
assert(!type_is_optional(from_pointee) && !type_is_optional(to_pointee) && "Optional should already been handled");
|
||||
if (from_pointee == to_pointee) return true;
|
||||
|
||||
// For void* on either side, no checks.
|
||||
if (to_pointee == type_voidptr || from_pointee == type_voidptr) return true;
|
||||
|
||||
// Step through all *:
|
||||
while (from_pointee->type_kind == TYPE_POINTER && to_pointee->type_kind == TYPE_POINTER)
|
||||
{
|
||||
if (from_pointee == type_voidptr || to_pointee == type_voidptr) return true;
|
||||
from_pointee = from_pointee->pointer;
|
||||
to_pointee = to_pointee->pointer;
|
||||
}
|
||||
|
||||
assert(to_pointee != from_pointee);
|
||||
|
||||
// Functions compare raw types.
|
||||
if (from_pointee->type_kind == TYPE_FUNC && to_pointee->type_kind == TYPE_FUNC)
|
||||
{
|
||||
return to_pointee->function.prototype->raw_type == from_pointee->function.prototype->raw_type;
|
||||
}
|
||||
|
||||
// Special handling of int* = int[4]* (so we have int[4] -> int)
|
||||
if (type_is_arraylike(from_pointee))
|
||||
{
|
||||
if (cast_may_implicit_ptr(to_pointee, from_pointee->array.base)) return true;
|
||||
}
|
||||
|
||||
if (type_is_any_arraylike(to_pointee) || type_is_any_arraylike(from_pointee))
|
||||
{
|
||||
return cast_may_array(from_pointee, to_pointee, false);
|
||||
}
|
||||
// Use subtype matching
|
||||
return type_is_subtype(to_pointee, from_pointee);
|
||||
}
|
||||
|
||||
/**
|
||||
* Can the conversion occur implicitly?
|
||||
*/
|
||||
bool cast_may_implicit(Type *from_type, Type *to_type, bool is_simple_expr, bool failable_allowed)
|
||||
bool cast_may_implicit(Type *from_type, Type *to_type, CastOption option)
|
||||
{
|
||||
Type *to = to_type->canonical;
|
||||
|
||||
// 1. First handle void! => any error
|
||||
// First handle void! => any error
|
||||
if (to == type_anyerr && type_may_convert_to_anyerr(from_type)) return true;
|
||||
|
||||
// 2. any! => may implicitly to convert to any.
|
||||
if (type_is_optional_any(from_type)) return failable_allowed;
|
||||
// any! => may implicitly to convert to any.
|
||||
if (type_is_optional_any(from_type)) return (CAST_OPTION_ALLOW_OPTIONAL & option) != 0;
|
||||
|
||||
// Check if optional was allowed
|
||||
Type *from = from_type->canonical;
|
||||
if (type_is_optional_type(from_type))
|
||||
{
|
||||
if (!failable_allowed) return false;
|
||||
if (!(CAST_OPTION_ALLOW_OPTIONAL & option)) return false;
|
||||
from = from_type->failable->canonical;
|
||||
}
|
||||
|
||||
// 4. Same canonical type - we're fine.
|
||||
// Same canonical type - we're fine.
|
||||
if (from == to) return true;
|
||||
|
||||
// 2. Handle floats
|
||||
// Handle floats
|
||||
if (type_is_float(to))
|
||||
{
|
||||
// 2a. Any integer may convert to a float.
|
||||
@@ -569,14 +751,12 @@ bool cast_may_implicit(Type *from_type, Type *to_type, bool is_simple_expr, bool
|
||||
ByteSize to_size = type_size(to);
|
||||
ByteSize from_size = type_size(from);
|
||||
if (to_size == from_size) return true;
|
||||
return to_size > from_size && is_simple_expr;
|
||||
return to_size > from_size && (option & CAST_OPTION_SIMPLE_EXPR);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (to == type_anyerr && from->type_kind == TYPE_FAULTTYPE) return true;
|
||||
|
||||
// 3. Handle ints
|
||||
// Handle ints
|
||||
if (type_is_integer(to))
|
||||
{
|
||||
// For an enum, lower to the underlying enum type.
|
||||
@@ -591,61 +771,41 @@ bool cast_may_implicit(Type *from_type, Type *to_type, bool is_simple_expr, bool
|
||||
ByteSize to_size = type_size(to);
|
||||
ByteSize from_size = type_size(from);
|
||||
if (to_size == from_size) return true;
|
||||
return to_size > from_size && is_simple_expr;
|
||||
return to_size > from_size && (option & CAST_OPTION_SIMPLE_EXPR);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// 4. Handle pointers
|
||||
// Convert any fault to anyerr
|
||||
if (to == type_anyerr && from->type_kind == TYPE_FAULTTYPE) return true;
|
||||
|
||||
// Handle pointers
|
||||
if (type_is_pointer(to))
|
||||
{
|
||||
// 4a. Assigning a subarray to a pointer of the same base type is fine
|
||||
// Assigning a subarray to a pointer
|
||||
if (from->type_kind == TYPE_SUBARRAY)
|
||||
{
|
||||
// void* conversion always work.
|
||||
// Casting to a void* always works.
|
||||
if (to == type_voidptr) return true;
|
||||
|
||||
// Use subtype matching
|
||||
return type_is_subtype(to->pointer->canonical, from->array.base->canonical);
|
||||
// Compare as if it was a pointer.
|
||||
return cast_may_implicit_ptr(from->array.base, to_type->pointer);
|
||||
}
|
||||
|
||||
// 4b. Assigning a pointer
|
||||
// Assigning a pointer to a pointer
|
||||
if (from->type_kind == TYPE_POINTER)
|
||||
{
|
||||
// For void* on either side, no checks.
|
||||
// Casting to or from a void* always works.
|
||||
if (to == type_voidptr || from == type_voidptr) return true;
|
||||
|
||||
Type *from_pointee = from->pointer;
|
||||
|
||||
if (from_pointee->type_kind == TYPE_FUNC && to->type_kind == TYPE_POINTER && to->pointer->type_kind == TYPE_FUNC)
|
||||
{
|
||||
return to->pointer->function.prototype->raw_type == from_pointee->function.prototype->raw_type;
|
||||
}
|
||||
// Special handling of int* = int[4]*
|
||||
if (from_pointee->type_kind == TYPE_ARRAY || from_pointee->type_kind == TYPE_FLEXIBLE_ARRAY)
|
||||
{
|
||||
if (type_is_subtype(to->pointer, from_pointee->array.base))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Use subtype matching
|
||||
return type_is_subtype(to->pointer, from_pointee);
|
||||
return cast_may_implicit_ptr(from->pointer, to->pointer);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (to_type->type_kind == TYPE_INFERRED_ARRAY)
|
||||
if (type_is_any_arraylike(to) && type_is_any_arraylike(from))
|
||||
{
|
||||
if (from->type_kind == TYPE_ARRAY && type_flatten_distinct(from->array.base) == type_flatten_distinct(to_type->array.base)) return true;
|
||||
return false;
|
||||
}
|
||||
if (to_type->type_kind == TYPE_INFERRED_VECTOR)
|
||||
{
|
||||
if (from->type_kind == TYPE_VECTOR && type_flatten_distinct(from->array.base) == type_flatten_distinct(to_type->array.base)) return true;
|
||||
return false;
|
||||
return cast_may_array(from, to, false);
|
||||
}
|
||||
|
||||
// 5. Handle sub arrays
|
||||
@@ -680,7 +840,7 @@ bool cast_may_implicit(Type *from_type, Type *to_type, bool is_simple_expr, bool
|
||||
// 11. Substruct cast, if the first member is inline, see if we can cast to this member.
|
||||
if (type_is_substruct(from))
|
||||
{
|
||||
return cast_may_implicit(from->decl->strukt.members[0]->type, to, is_simple_expr, failable_allowed);
|
||||
return cast_may_implicit(from->decl->strukt.members[0]->type, to, option);
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -1135,8 +1295,10 @@ bool cast_implicit(SemaContext *context, Expr *expr, Type *to_type)
|
||||
return cast_untyped_to_type(context, expr, to_type);
|
||||
}
|
||||
|
||||
bool is_simple = expr_is_simple(expr);
|
||||
if (!cast_may_implicit(expr_canonical, to_canonical, is_simple, true))
|
||||
CastOption option = CAST_OPTION_ALLOW_OPTIONAL;
|
||||
if (expr_is_simple(expr)) option |= CAST_OPTION_SIMPLE_EXPR;
|
||||
|
||||
if (!cast_may_implicit(expr_canonical, to_canonical, option))
|
||||
{
|
||||
if (!cast_may_explicit(expr_canonical, to_canonical, false, expr->expr_kind == EXPR_CONST))
|
||||
{
|
||||
@@ -1209,8 +1371,9 @@ bool cast_implicit(SemaContext *context, Expr *expr, Type *to_type)
|
||||
}
|
||||
goto OK;
|
||||
}
|
||||
SEMA_ERROR(expr, "Implicitly casting %s to %s is not permitted, but you can do an explicit cast using '(<type>)(value)'.", type_quoted_error_string(
|
||||
type_no_optional(expr->type)), type_quoted_error_string(type_no_optional(to_type)));
|
||||
SEMA_ERROR(expr, "Implicitly casting %s to %s is not permitted, but you can do an explicit cast by placing '(%s)' before the expression.", type_quoted_error_string(
|
||||
type_no_optional(expr->type)), type_quoted_error_string(type_no_optional(to_type)),
|
||||
type_to_error_string(to_type));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -2446,15 +2446,12 @@ bool sema_analyse_var_decl(SemaContext *context, Decl *decl, bool local)
|
||||
|
||||
if (infer_len)
|
||||
{
|
||||
Type *right_side_type = init->type->canonical;
|
||||
if (right_side_type->type_kind == TYPE_ARRAY)
|
||||
if (type_is_len_inferred(init->type))
|
||||
{
|
||||
decl->type = type_get_array(decl->type->array.base, right_side_type->array.len);
|
||||
}
|
||||
else
|
||||
{
|
||||
decl->type = type_get_vector(decl->type->array.base, right_side_type->array.len);
|
||||
SEMA_ERROR(decl->var.type_info, "You cannot use [*] and [<*>] underlying types with initializers.");
|
||||
return false;
|
||||
}
|
||||
decl->type = cast_infer_len(decl->type, init->type);
|
||||
}
|
||||
|
||||
Expr *init_expr = decl->var.init_expr;
|
||||
|
||||
@@ -1797,7 +1797,7 @@ bool sema_expr_analyse_macro_call(SemaContext *context, Expr *call_expr, Expr *s
|
||||
inferred_len = false;
|
||||
}
|
||||
}
|
||||
if (!cast_may_implicit(type, rtype, true, may_failable) || inferred_len)
|
||||
if (!cast_may_implicit(type, rtype, CAST_OPTION_SIMPLE_EXPR | (may_failable ? CAST_OPTION_ALLOW_OPTIONAL : 0)) || inferred_len)
|
||||
{
|
||||
SEMA_ERROR(ret_expr, "Expected %s, not %s.", type_quoted_error_string(rtype),
|
||||
type_quoted_error_string(type));
|
||||
@@ -3820,7 +3820,7 @@ static bool sema_expr_analyse_slice_assign(SemaContext *context, Expr *expr, Typ
|
||||
Range *left_range = &left->subscript_expr.range;
|
||||
Range *right_range = &right->subscript_expr.range;
|
||||
if (!sema_analyse_expr(context, right)) return false;
|
||||
if (cast_may_implicit(right->type, base, true, false)) goto ASSIGN;
|
||||
if (cast_may_implicit(right->type, base, CAST_OPTION_SIMPLE_EXPR)) goto ASSIGN;
|
||||
if (!cast_implicit(context, right, left_type)) return false;
|
||||
IndexDiff left_len = range_const_len(left_range);
|
||||
IndexDiff right_len = range_const_len(right_range);
|
||||
@@ -4248,7 +4248,7 @@ static Type *defer_iptr_cast(Expr *maybe_pointer, Expr *maybe_diff)
|
||||
if (maybe_pointer->expr_kind == EXPR_CAST
|
||||
&& maybe_pointer->cast_expr.kind == CAST_PTRXI
|
||||
&& type_flatten(maybe_pointer->type) == type_flatten(type_iptr)
|
||||
&& cast_may_implicit(maybe_diff->type, maybe_diff->type, true, true))
|
||||
&& cast_may_implicit(maybe_diff->type, maybe_diff->type, CAST_OPTION_SIMPLE_EXPR | CAST_OPTION_ALLOW_OPTIONAL))
|
||||
{
|
||||
Type *cast_to_iptr = maybe_pointer->type;
|
||||
maybe_pointer->cast_expr.kind = CAST_PTRPTR;
|
||||
@@ -5301,7 +5301,7 @@ static inline bool sema_expr_analyse_not(SemaContext *context, Expr *expr)
|
||||
}
|
||||
|
||||
// 4. Let's see if it's possible to cast it implicitly
|
||||
if (!cast_may_implicit(type, type_bool, true, true))
|
||||
if (!cast_may_implicit(type, type_bool, CAST_OPTION_SIMPLE_EXPR | CAST_OPTION_ALLOW_OPTIONAL))
|
||||
{
|
||||
SEMA_ERROR(expr, "The use of '!' on %s is not allowed as it can't be converted to a boolean value.", type_quoted_error_string(inner->type));
|
||||
return false;
|
||||
|
||||
@@ -5,11 +5,13 @@
|
||||
#include "sema_internal.h"
|
||||
|
||||
static inline bool sema_expr_analyse_struct_plain_initializer(SemaContext *context, Decl *assigned, Expr *initializer);
|
||||
static inline bool sema_expr_analyse_array_plain_initializer(SemaContext *context, Type *assigned, Expr *initializer);
|
||||
static inline bool sema_expr_analyse_array_plain_initializer(SemaContext *context, Type *assigned, Type *flattened,
|
||||
Expr *initializer);
|
||||
static inline bool sema_expr_analyse_untyped_initializer(SemaContext *context, Expr *initializer);
|
||||
static bool sema_expr_analyse_designated_initializer(SemaContext *context, Type *assigned, Expr *initializer);
|
||||
static bool sema_expr_analyse_designated_initializer(SemaContext *context, Type *assigned, Type *flattened,
|
||||
Expr *initializer);
|
||||
static inline void sema_not_enough_elements_error(Expr *initializer, int element);
|
||||
static inline bool sema_expr_analyse_initializer(SemaContext *context, Type *external_type, Type *assigned, Expr *expr);
|
||||
static inline bool sema_expr_analyse_initializer(SemaContext *context, Type *assigned_type, Type *flattened, Expr *expr);
|
||||
static void sema_create_const_initializer_value(ConstInitializer *const_init, Expr *value);
|
||||
static void sema_create_const_initializer_from_designated_init(ConstInitializer *const_init, Expr *initializer);
|
||||
static Decl *sema_resolve_element_for_name(Decl** decls, DesignatorElement **elements, unsigned *index);
|
||||
@@ -218,16 +220,27 @@ static inline bool sema_expr_analyse_struct_plain_initializer(SemaContext *conte
|
||||
* Perform analysis for a plain initializer, that is one initializing all fields.
|
||||
* @return true if analysis succeeds.
|
||||
*/
|
||||
static inline bool sema_expr_analyse_array_plain_initializer(SemaContext *context, Type *assigned, Expr *initializer)
|
||||
static inline bool sema_expr_analyse_array_plain_initializer(SemaContext *context, Type *assigned, Type *flattened,
|
||||
Expr *initializer)
|
||||
{
|
||||
Expr **elements = initializer->initializer_list;
|
||||
bool inferred_len = type_len_is_inferred(flattened);
|
||||
|
||||
// We have the case where "Foo = int[*]"
|
||||
if (inferred_len && !type_len_is_inferred(assigned))
|
||||
{
|
||||
assert(assigned->type_kind == TYPE_TYPEDEF);
|
||||
assert(assigned->decl->decl_kind == DECL_TYPEDEF);
|
||||
while (assigned->type_kind == TYPE_TYPEDEF) assigned = assigned->decl->type;
|
||||
assert(type_len_is_inferred(assigned));
|
||||
}
|
||||
// Prefer the typedef index: define Bar = int; Bar[1] => Bar and not int
|
||||
Type *inner_type = type_get_indexed_type(assigned);
|
||||
assert(inner_type);
|
||||
|
||||
unsigned size = vec_size(elements);
|
||||
unsigned expected_members = assigned->array.len;
|
||||
if (assigned->type_kind != TYPE_ARRAY && assigned->type_kind != TYPE_VECTOR) expected_members = size;
|
||||
unsigned expected_members = flattened->array.len;
|
||||
if (type_is_len_inferred(flattened)) expected_members = size;
|
||||
|
||||
assert(size > 0 && "We should already have handled the size == 0 case.");
|
||||
if (expected_members == 0)
|
||||
@@ -238,7 +251,8 @@ static inline bool sema_expr_analyse_array_plain_initializer(SemaContext *contex
|
||||
}
|
||||
|
||||
bool failable = false;
|
||||
VECEACH(elements, i)
|
||||
unsigned count = vec_size(elements);
|
||||
for (unsigned i = 0; i < count; i++)
|
||||
{
|
||||
Expr *element = elements[i];
|
||||
if (i >= expected_members)
|
||||
@@ -246,10 +260,19 @@ static inline bool sema_expr_analyse_array_plain_initializer(SemaContext *contex
|
||||
SEMA_ERROR(element, "Too many elements in initializer, expected only %d.", expected_members);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!sema_analyse_expr_rhs(context, inner_type, element, true)) return false;
|
||||
Type *element_type = type_no_optional(element->type);
|
||||
failable = failable || IS_OPTIONAL(element);
|
||||
}
|
||||
if (inferred_len)
|
||||
{
|
||||
initializer->type = type_from_inferred(flattened, inner_type, count);
|
||||
}
|
||||
else
|
||||
{
|
||||
initializer->type = assigned;
|
||||
}
|
||||
|
||||
assert(initializer->type);
|
||||
if (failable) initializer->type = type_get_optional(initializer->type);
|
||||
|
||||
@@ -303,14 +326,17 @@ static inline bool sema_expr_analyse_untyped_initializer(SemaContext *context, E
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool sema_expr_analyse_designated_initializer(SemaContext *context, Type *assigned, Expr *initializer)
|
||||
static bool sema_expr_analyse_designated_initializer(SemaContext *context, Type *assigned, Type *flattened,
|
||||
Expr *initializer)
|
||||
{
|
||||
Expr **init_expressions = initializer->designated_init_list;
|
||||
Type *original = assigned->canonical;
|
||||
Type *original = flattened->canonical;
|
||||
bool is_bitstruct = original->type_kind == TYPE_BITSTRUCT;
|
||||
bool is_structlike = type_is_union_or_strukt(original) || is_bitstruct;
|
||||
MemberIndex max_index = -1;
|
||||
bool failable = false;
|
||||
Type *inner_type = NULL;
|
||||
bool is_inferred = type_is_len_inferred(flattened);
|
||||
VECEACH(init_expressions, i)
|
||||
{
|
||||
Expr *expr = init_expressions[i];
|
||||
@@ -325,11 +351,19 @@ static bool sema_expr_analyse_designated_initializer(SemaContext *context, Type
|
||||
}
|
||||
failable = failable || IS_OPTIONAL(value);
|
||||
expr->resolve_status = RESOLVE_DONE;
|
||||
if (!inner_type)
|
||||
{
|
||||
inner_type = type_no_optional(value->type);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_structlike && initializer->type->type_kind == TYPE_INFERRED_ARRAY)
|
||||
if (!is_structlike && is_inferred)
|
||||
{
|
||||
initializer->type = sema_type_lower_by_size(initializer->type, (ArraySize)(max_index + 1));
|
||||
initializer->type = type_from_inferred(flattened, type_get_indexed_type(assigned), (ArraySize)(max_index + 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
initializer->type = assigned;
|
||||
}
|
||||
initializer->resolve_status = RESOLVE_DONE;
|
||||
if (expr_is_constant_eval(initializer, env_eval_type(context)))
|
||||
@@ -342,17 +376,21 @@ static bool sema_expr_analyse_designated_initializer(SemaContext *context, Type
|
||||
}
|
||||
|
||||
|
||||
static inline bool sema_expr_analyse_initializer(SemaContext *context, Type *external_type, Type *assigned, Expr *expr)
|
||||
static inline bool sema_expr_analyse_initializer(SemaContext *context, Type *assigned_type, Type *flattened, Expr *expr)
|
||||
{
|
||||
// Note at this point this we either have
|
||||
// EXPR_DESIGNATED_INITIALIZER_LIST
|
||||
// or EXPR_INITIALIZER_LIST
|
||||
|
||||
if (type_len_is_inferred(flattened) && type_len_is_inferred(type_get_indexed_type(flattened)))
|
||||
{
|
||||
SEMA_ERROR(expr, "Initializers cannot be used with inferred length element types (e.g. %s).", type_quoted_error_string(type_get_indexed_type(flattened)));
|
||||
return false;
|
||||
}
|
||||
// 1. Designated initializer is separately evaluated.
|
||||
if (expr->expr_kind == EXPR_DESIGNATED_INITIALIZER_LIST)
|
||||
{
|
||||
expr->type = external_type;
|
||||
return sema_expr_analyse_designated_initializer(context, assigned, expr);
|
||||
return sema_expr_analyse_designated_initializer(context, assigned_type, flattened, expr);
|
||||
}
|
||||
|
||||
assert(expr->expr_kind == EXPR_INITIALIZER_LIST);
|
||||
@@ -369,45 +407,37 @@ static inline bool sema_expr_analyse_initializer(SemaContext *context, Type *ext
|
||||
// 3. Zero size init will initialize to empty.
|
||||
if (init_expression_count == 0)
|
||||
{
|
||||
if (type_len_is_inferred(external_type))
|
||||
if (type_len_is_inferred(assigned_type))
|
||||
{
|
||||
SEMA_ERROR(expr, "Zero length arrays / vectors are not permitted.");
|
||||
return false;
|
||||
}
|
||||
external_type = sema_type_lower_by_size(external_type, 0);
|
||||
expr->type = external_type;
|
||||
ConstInitializer *initializer = CALLOCS(ConstInitializer);
|
||||
initializer->kind = CONST_INIT_ZERO;
|
||||
initializer->type = type_flatten(expr->type);
|
||||
expr_rewrite_const_initializer(expr, expr->type, initializer);
|
||||
initializer->type = flattened;
|
||||
expr_rewrite_const_initializer(expr, assigned_type, initializer);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// 4. If we have an inferred array, we need to set the size.
|
||||
external_type = sema_type_lower_by_size(external_type, init_expression_count);
|
||||
assigned = sema_type_lower_by_size(assigned, init_expression_count);
|
||||
|
||||
// 5. Set the type.
|
||||
expr->type = external_type;
|
||||
|
||||
// 6. We might have a complist, because were analyzing $foo = { ... } or similar.
|
||||
if (external_type == type_untypedlist)
|
||||
// 4. We might have a complist, because were analyzing $foo = { ... } or similar.
|
||||
if (assigned_type == type_untypedlist)
|
||||
{
|
||||
return sema_expr_analyse_untyped_initializer(context, expr);
|
||||
}
|
||||
// 7. If not, then we see if we have an array.
|
||||
if (assigned->type_kind == TYPE_UNTYPED_LIST ||
|
||||
assigned->type_kind == TYPE_ARRAY ||
|
||||
assigned->type_kind == TYPE_INFERRED_ARRAY ||
|
||||
assigned->type_kind == TYPE_INFERRED_VECTOR ||
|
||||
assigned->type_kind == TYPE_SUBARRAY ||
|
||||
assigned->type_kind == TYPE_VECTOR)
|
||||
|
||||
// 5. If not, then we see if we have an array.
|
||||
if (flattened->type_kind == TYPE_UNTYPED_LIST ||
|
||||
flattened->type_kind == TYPE_ARRAY ||
|
||||
flattened->type_kind == TYPE_INFERRED_ARRAY ||
|
||||
flattened->type_kind == TYPE_INFERRED_VECTOR ||
|
||||
flattened->type_kind == TYPE_SUBARRAY ||
|
||||
flattened->type_kind == TYPE_VECTOR)
|
||||
{
|
||||
return sema_expr_analyse_array_plain_initializer(context, assigned, expr);
|
||||
return sema_expr_analyse_array_plain_initializer(context, assigned_type, flattened, expr);
|
||||
}
|
||||
|
||||
return sema_expr_analyse_struct_plain_initializer(context, assigned->decl, expr);
|
||||
expr->type = assigned_type;
|
||||
return sema_expr_analyse_struct_plain_initializer(context, flattened->decl, expr);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -434,8 +464,8 @@ bool sema_expr_analyse_initializer_list(SemaContext *context, Type *to, Expr *ex
|
||||
{
|
||||
if (!to) to = type_untypedlist;
|
||||
assert(to);
|
||||
Type *assigned = type_flatten(to);
|
||||
switch (assigned->type_kind)
|
||||
Type *flattened = type_flatten(to);
|
||||
switch (flattened->type_kind)
|
||||
{
|
||||
case TYPE_UNTYPED_LIST:
|
||||
case TYPE_STRUCT:
|
||||
@@ -445,7 +475,7 @@ bool sema_expr_analyse_initializer_list(SemaContext *context, Type *to, Expr *ex
|
||||
case TYPE_INFERRED_ARRAY:
|
||||
case TYPE_INFERRED_VECTOR:
|
||||
case TYPE_VECTOR:
|
||||
return sema_expr_analyse_initializer(context, to, assigned, expr);
|
||||
return sema_expr_analyse_initializer(context, to, flattened, expr);
|
||||
case TYPE_SUBARRAY:
|
||||
{
|
||||
if (expr->expr_kind == EXPR_INITIALIZER_LIST && !vec_size(expr->initializer_list))
|
||||
@@ -453,11 +483,11 @@ bool sema_expr_analyse_initializer_list(SemaContext *context, Type *to, Expr *ex
|
||||
expr->expr_kind = EXPR_CONST;
|
||||
expr->const_expr.const_kind = CONST_POINTER;
|
||||
expr->const_expr.ptr = 0;
|
||||
expr->type = assigned;
|
||||
expr->type = flattened;
|
||||
return true;
|
||||
}
|
||||
// Resolve this as an inferred array.
|
||||
Type *type = type_get_inferred_array(assigned->array.base);
|
||||
Type *type = type_get_inferred_array(flattened->array.base);
|
||||
if (!sema_expr_analyse_initializer(context, type, type, expr)) return false;
|
||||
expr->resolve_status = RESOLVE_DONE;
|
||||
expr_insert_addr(expr);
|
||||
|
||||
@@ -901,7 +901,7 @@ static inline bool sema_analyse_cond(SemaContext *context, Expr *expr, CondType
|
||||
// 3a. Check for failables in case of an expression.
|
||||
if (IS_OPTIONAL(last))
|
||||
{
|
||||
if (!cast_to_bool || cast_may_implicit(type_no_optional(last->type), type_bool, false, false))
|
||||
if (!cast_to_bool || cast_may_implicit(type_no_optional(last->type), type_bool, CAST_OPTION_NONE))
|
||||
{
|
||||
SEMA_ERROR(last, "The expression may not be a failable, but was %s.", type_quoted_error_string(last->type));
|
||||
return false;
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
|
||||
#include "sema_internal.h"
|
||||
|
||||
static inline bool sema_resolve_ptr_type(SemaContext *context, TypeInfo *type_info)
|
||||
static inline bool sema_resolve_ptr_type(SemaContext *context, TypeInfo *type_info, bool allow_inferred)
|
||||
{
|
||||
if (!sema_resolve_type_shallow(context, type_info->pointer, false, true))
|
||||
if (!sema_resolve_type_shallow(context, type_info->pointer, allow_inferred, true))
|
||||
{
|
||||
return type_info_poison(type_info);
|
||||
}
|
||||
@@ -77,18 +77,18 @@ bool sema_resolve_array_like_len(SemaContext *context, TypeInfo *type_info, Arra
|
||||
}
|
||||
|
||||
// TODO cleanup.
|
||||
static inline bool sema_resolve_array_type(SemaContext *context, TypeInfo *type, bool shallow)
|
||||
static inline bool sema_resolve_array_type(SemaContext *context, TypeInfo *type, bool allow_inferred, bool shallow)
|
||||
{
|
||||
if (type->kind == TYPE_INFO_SUBARRAY || shallow)
|
||||
{
|
||||
if (!sema_resolve_type_shallow(context, type->array.base, false, true))
|
||||
if (!sema_resolve_type_shallow(context, type->array.base, allow_inferred, true))
|
||||
{
|
||||
return type_info_poison(type);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!sema_resolve_type_info(context, type->array.base))
|
||||
if (!sema_resolve_type_info_maybe_inferred(context, type->array.base, allow_inferred))
|
||||
{
|
||||
return type_info_poison(type);
|
||||
}
|
||||
@@ -271,7 +271,6 @@ bool sema_resolve_type_shallow(SemaContext *context, TypeInfo *type_info, bool a
|
||||
TypeInfoCompressedKind kind = type_info->subtype;
|
||||
if (kind != TYPE_COMPRESSED_NONE)
|
||||
{
|
||||
allow_inferred_type = false;
|
||||
in_shallow = true;
|
||||
}
|
||||
switch (type_info->kind)
|
||||
@@ -366,10 +365,10 @@ bool sema_resolve_type_shallow(SemaContext *context, TypeInfo *type_info, bool a
|
||||
case TYPE_INFO_SUBARRAY:
|
||||
case TYPE_INFO_ARRAY:
|
||||
case TYPE_INFO_VECTOR:
|
||||
if (!sema_resolve_array_type(context, type_info, in_shallow)) return false;
|
||||
if (!sema_resolve_array_type(context, type_info, allow_inferred_type, in_shallow)) return false;
|
||||
break;
|
||||
case TYPE_INFO_POINTER:
|
||||
if (!sema_resolve_ptr_type(context, type_info)) return false;
|
||||
if (!sema_resolve_ptr_type(context, type_info, allow_inferred_type)) return false;
|
||||
break;
|
||||
}
|
||||
APPEND_QUALIFIERS:
|
||||
|
||||
@@ -1 +1 @@
|
||||
#define COMPILER_VERSION "0.3.80"
|
||||
#define COMPILER_VERSION "0.3.81"
|
||||
Reference in New Issue
Block a user