mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Disallow $offsetof / $alignof on types. Version bump.
This commit is contained in:
committed by
Christoffer Lerno
parent
c84f82559c
commit
fa064276bc
@@ -60,7 +60,7 @@ private fn void*! arena_allocator_function(Allocator* data, usize size, usize al
|
||||
* @require alignment <= MAX_MEMORY_ALIGNMENT `alignment too big`
|
||||
* @require offset <= MAX_MEMORY_ALIGNMENT `offset too big`
|
||||
* @require offset <= size && offset >= 0
|
||||
* @require mem::aligned_offset(offset, $alignof(ArenaAllocatorHeader)) == offset
|
||||
* @require mem::aligned_offset(offset, ArenaAllocatorHeader.alignof) == offset
|
||||
* @require this != null
|
||||
**/
|
||||
private fn void*! ArenaAllocator._alloc(ArenaAllocator* this, usize size, usize alignment, usize offset)
|
||||
@@ -86,7 +86,7 @@ private fn void*! ArenaAllocator._alloc(ArenaAllocator* this, usize size, usize
|
||||
* @require alignment <= MAX_MEMORY_ALIGNMENT `alignment too big`
|
||||
* @require offset <= MAX_MEMORY_ALIGNMENT `offset too big`
|
||||
* @require offset <= size && offset >= 0
|
||||
* @require mem::aligned_offset(offset, $alignof(ArenaAllocatorHeader)) == offset
|
||||
* @require mem::aligned_offset(offset, ArenaAllocatorHeader.alignof) == offset
|
||||
* @require this != null
|
||||
**/
|
||||
private fn void*! ArenaAllocator._realloc(ArenaAllocator* this, void *old_pointer, usize size, usize alignment, usize offset)
|
||||
|
||||
@@ -176,9 +176,9 @@ private fn void*! TempAllocator._alloc(TempAllocator* this, usize size, usize al
|
||||
{
|
||||
void* start_mem = &this.data;
|
||||
void* starting_ptr = start_mem + this.used;
|
||||
void* aligned_header_start = mem::aligned_pointer(starting_ptr, $alignof(TempAllocatorChunk));
|
||||
void* aligned_header_start = mem::aligned_pointer(starting_ptr, TempAllocatorChunk.alignof);
|
||||
void* mem = aligned_header_start + TempAllocatorChunk.sizeof;
|
||||
if (alignment > $alignof(TempAllocatorChunk))
|
||||
if (alignment > TempAllocatorChunk.alignof)
|
||||
{
|
||||
mem = mem::aligned_pointer(mem + offset, alignment) - offset;
|
||||
}
|
||||
@@ -222,7 +222,7 @@ private fn void*! TempAllocator._alloc(TempAllocator* this, usize size, usize al
|
||||
|
||||
// Find the page.
|
||||
page = alloc + padded_header_size - TempAllocatorPage.sizeof;
|
||||
assert(mem::ptr_is_aligned(page, $alignof(TempAllocator)));
|
||||
assert(mem::ptr_is_aligned(page, TempAllocator.alignof));
|
||||
assert(mem::ptr_is_aligned(&page.data[0], DEFAULT_MEM_ALIGNMENT));
|
||||
page.start = alloc;
|
||||
page.size = size;
|
||||
|
||||
@@ -6,11 +6,11 @@ macro tconcat(arr1, arr2)
|
||||
$Type[] result = array::talloc($Type, arr1.len + arr2.len);
|
||||
if (arr1.len > 0)
|
||||
{
|
||||
mem::copy(result.ptr, &arr1[0], arr1.len * $Type.sizeof, $alignof($Type), $alignof($Type));
|
||||
mem::copy(result.ptr, &arr1[0], arr1.len * $Type.sizeof, $Type.alignof, $Type.alignof);
|
||||
}
|
||||
if (arr2.len > 0)
|
||||
{
|
||||
mem::copy(&result[arr1.len], &arr2[0], arr2.len * $Type.sizeof, $alignof($Type), $alignof($Type));
|
||||
mem::copy(&result[arr1.len], &arr2[0], arr2.len * $Type.sizeof, $Type.alignof, $Type.alignof);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -21,11 +21,11 @@ macro concat(arr1, arr2)
|
||||
$Type[] result = array::alloc($Type, arr1.len + arr2.len);
|
||||
if (arr1.len > 0)
|
||||
{
|
||||
mem::copy(result.ptr, &arr1[0], arr1.len * $Type.sizeof, $alignof($Type), $alignof($Type));
|
||||
mem::copy(result.ptr, &arr1[0], arr1.len * $Type.sizeof, $Type.alignof, $Type.alignof);
|
||||
}
|
||||
if (arr2.len > 0)
|
||||
{
|
||||
mem::copy(&result[arr1.len], &arr2[0], arr2.len * $Type.sizeof, $alignof($Type), $alignof($Type));
|
||||
mem::copy(&result[arr1.len], &arr2[0], arr2.len * $Type.sizeof, $Type.alignof, $Type.alignof);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -98,7 +98,7 @@ macro bitcast(expr, $Type) @builtin
|
||||
var $size = (usize)($sizeof(expr));
|
||||
$assert($size == $Type.sizeof, "Cannot bitcast between types of different size.");
|
||||
$Type x = void;
|
||||
mem::copy(&x, &expr, $size, $alignof($Type), $alignof(expr));
|
||||
mem::copy(&x, &expr, $size, $Type.alignof, $alignof(expr));
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ macro void clear(void* dst, usize len, usize $dst_align = 0, bool $is_volatile =
|
||||
macro bool equals(a, b, isize len = -1, usize $align = 0)
|
||||
{
|
||||
$if (!$align):
|
||||
$align = $alignof($typeof(a[0]));
|
||||
$align = $typeof(a[0]).alignof;
|
||||
$endif;
|
||||
void* x = void;
|
||||
void* y = void;
|
||||
@@ -214,7 +214,7 @@ macro void @tscoped(;@body())
|
||||
|
||||
macro talloc($Type) @builtin
|
||||
{
|
||||
return temp_allocator().alloc_aligned($Type.sizeof, $alignof($Type))!!;
|
||||
return temp_allocator().alloc_aligned($Type.sizeof, $Type.alignof)!!;
|
||||
}
|
||||
|
||||
fn void* tmalloc(usize size, usize alignment = allocator::DEFAULT_MEM_ALIGNMENT) @builtin @inline
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
module std::core::mem::allocator;
|
||||
|
||||
const MAX_MEMORY_ALIGNMENT = 0x1000_0000;
|
||||
const DEFAULT_MEM_ALIGNMENT = $alignof(void*) * 2;
|
||||
const DEFAULT_MEM_ALIGNMENT = (void*.alignof) * 2;
|
||||
const DEFAULT_SIZE_PREFIX = usize.sizeof;
|
||||
const DEFAULT_SIZE_PREFIX_ALIGNMENT = $alignof(usize);
|
||||
const DEFAULT_SIZE_PREFIX_ALIGNMENT = usize.alignof;
|
||||
|
||||
const Allocator* NULL_ALLOCATOR = &_NULL_ALLOCATOR;
|
||||
const Allocator* LIBC_ALLOCATOR = &_SYSTEM_ALLOCATOR;
|
||||
|
||||
@@ -17,7 +17,7 @@ macro alloc($Type, usize elements)
|
||||
**/
|
||||
macro talloc($Type, usize elements)
|
||||
{
|
||||
$Type* ptr = tmalloc($Type.sizeof * elements, $alignof($Type[1]));
|
||||
$Type* ptr = tmalloc($Type.sizeof * elements, $Type[1].alignof);
|
||||
return ptr[:elements];
|
||||
}
|
||||
|
||||
@@ -35,6 +35,6 @@ macro make($Type, usize elements, Allocator* allocator = mem::current_allocator(
|
||||
**/
|
||||
macro tmake($Type, usize elements)
|
||||
{
|
||||
$Type* ptr = tcalloc($Type.sizeof * elements, $alignof($Type[1]));
|
||||
$Type* ptr = tcalloc($Type.sizeof * elements, $Type[1].alignof);
|
||||
return ptr[:elements];
|
||||
}
|
||||
|
||||
@@ -2506,12 +2506,14 @@ INLINE bool type_is_float(Type *type)
|
||||
return kind >= TYPE_FLOAT_FIRST && kind <= TYPE_FLOAT_LAST;
|
||||
}
|
||||
|
||||
INLINE bool type_is_invalid_for_typeof(Type *type)
|
||||
INLINE bool type_is_invalid_storage_type(Type *type)
|
||||
{
|
||||
if (!type) return false;
|
||||
switch (type->type_kind)
|
||||
{
|
||||
case TYPE_MEMBER:
|
||||
case TYPE_UNTYPED_LIST:
|
||||
case TYPE_TYPEINFO:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
|
||||
@@ -2387,6 +2387,11 @@ bool sema_analyse_var_decl(SemaContext *context, Decl *decl, bool local)
|
||||
return false;
|
||||
}
|
||||
decl->type = init_expr->type;
|
||||
if (type_is_invalid_storage_type(init_expr->type))
|
||||
{
|
||||
SEMA_ERROR(init_expr, "A value of type '%s' cannot be used as a constant.", type_quoted_error_string(init_expr->type));
|
||||
return false;
|
||||
}
|
||||
if (!decl->alignment) decl->alignment = type_alloca_alignment(decl->type);
|
||||
if (!sema_analyse_decl_type(context, decl->type, init_expr->span)) return false;
|
||||
// Skip further evaluation.
|
||||
|
||||
@@ -92,7 +92,7 @@ static inline bool sema_expr_analyse_taddr(SemaContext *context, Expr *expr);
|
||||
|
||||
// -- ct_call
|
||||
static inline bool sema_expr_analyse_ct_alignof(SemaContext *context, Expr *expr);
|
||||
static inline bool sema_expr_analyse_ct_sizeof(SemaContext *context, Expr *expr);
|
||||
|
||||
static inline bool sema_expr_analyse_ct_nameof(SemaContext *context, Expr *expr);
|
||||
static inline bool sema_expr_analyse_ct_defined(SemaContext *context, Expr *expr);
|
||||
|
||||
@@ -150,8 +150,7 @@ static inline IndexDiff range_const_len(Range *range);
|
||||
static inline bool sema_expr_begin_analyse(Expr *expr);
|
||||
static inline bool sema_analyse_expr_dispatch(SemaContext *context, Expr *expr);
|
||||
|
||||
static bool sema_expr_analyse_type_var_path(SemaContext *context, Expr *expr, ExprFlatElement **elements, Type **type_ref,
|
||||
Decl **decl_ref);
|
||||
static Decl *sema_expr_analyse_var_path(SemaContext *context, Expr *expr, ExprFlatElement **elements);
|
||||
static inline bool sema_expr_analyse_flat_element(SemaContext *context, ExprFlatElement *element, Type *type, Decl **member_ref, ArraySize *index_ref, Type **return_type, unsigned i, SourceSpan loc,
|
||||
bool *is_missing);
|
||||
static Expr *sema_expr_resolve_access_child(SemaContext *context, Expr *child, bool *missing);
|
||||
@@ -176,9 +175,9 @@ static inline bool sema_create_const_max(SemaContext *context, Expr *expr, Type
|
||||
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);
|
||||
|
||||
void expr_insert_widening_type(Expr *expr, Type *infer_type);
|
||||
static Expr *expr_access_inline_member(Expr *parent, Decl *parent_decl);
|
||||
static inline int64_t expr_get_index_max(Expr *expr);
|
||||
static inline bool expr_both_any_integer_or_integer_vector(Expr *left, Expr *right);
|
||||
static inline bool expr_both_const(Expr *left, Expr *right);
|
||||
static inline bool sema_identifier_find_possible_inferred(Type *to, Expr *expr);
|
||||
@@ -1350,9 +1349,9 @@ static inline bool sema_call_analyse_invocation(SemaContext *context, Expr *call
|
||||
if (!sema_expr_check_assign(context, arg)) return false;
|
||||
*failable |= IS_OPTIONAL(arg);
|
||||
if (!sema_call_check_inout_param_match(context, param, arg)) return false;
|
||||
if (arg->type == type_untypedlist)
|
||||
if (type_is_invalid_storage_type(type))
|
||||
{
|
||||
SEMA_ERROR(arg, "An untyped list cannot be passed by reference.");
|
||||
SEMA_ERROR(arg, "A value of type %s cannot be passed by reference.", type_quoted_error_string(type));
|
||||
return false;
|
||||
}
|
||||
if (type && type->canonical != arg->type->canonical)
|
||||
@@ -1376,9 +1375,9 @@ static inline bool sema_call_analyse_invocation(SemaContext *context, Expr *call
|
||||
// foo
|
||||
if (!sema_analyse_expr_rhs(context, type, arg, true)) return false;
|
||||
if (IS_OPTIONAL(arg)) *failable = true;
|
||||
if (arg->type == type_untypedlist)
|
||||
if (type_is_invalid_storage_type(arg->type))
|
||||
{
|
||||
SEMA_ERROR(arg, "An untyped list can only be passed as a compile time parameter.");
|
||||
SEMA_ERROR(arg, "A value of type %s can only be passed as a compile time parameter.", type_quoted_error_string(arg->type));
|
||||
return false;
|
||||
}
|
||||
if (!param->alignment)
|
||||
@@ -2148,11 +2147,11 @@ static bool sema_slice_index_is_in_range(SemaContext *context, Type *type, Expr
|
||||
case TYPE_FLEXIBLE_ARRAY:
|
||||
assert(!from_end);
|
||||
return true;
|
||||
case TYPE_UNTYPED_LIST:
|
||||
case TYPE_ARRAY:
|
||||
case TYPE_VECTOR:
|
||||
{
|
||||
MemberIndex len = (MemberIndex)type->array.len;
|
||||
bool is_vector = type->type_kind == TYPE_VECTOR;
|
||||
if (from_end)
|
||||
{
|
||||
idx = len - idx;
|
||||
@@ -2162,22 +2161,17 @@ static bool sema_slice_index_is_in_range(SemaContext *context, Type *type, Expr
|
||||
// Checking end can only be done for arrays.
|
||||
if (end_index && idx >= len)
|
||||
{
|
||||
SEMA_ERROR(index_expr,
|
||||
is_vector ? "End index out of bounds, was %lld, exceeding vector width %lld."
|
||||
: "Array end index out of bounds, was %lld, exceeding array length %lld.",
|
||||
(long long)idx, (long long)len);
|
||||
SEMA_ERROR(index_expr, "End index out of bounds, was %lld, exceeding %lld.", (long long)idx, (long long)len);
|
||||
return false;
|
||||
}
|
||||
if (!end_index && idx >= len)
|
||||
{
|
||||
if (len == 0)
|
||||
{
|
||||
SEMA_ERROR(index_expr, "Cannot index into a zero size array.");
|
||||
SEMA_ERROR(index_expr, "Cannot index into a zero size list.");
|
||||
return false;
|
||||
}
|
||||
SEMA_ERROR(index_expr,
|
||||
is_vector ? "Index out of bounds, was %lld, exceeding max vector width %lld."
|
||||
: "Array index out of bounds, was %lld, exceeding max array index %lld.", (long long)idx, (long long)len - 1);
|
||||
SEMA_ERROR(index_expr, "Index out of bounds, was %lld, exceeding maximum (%lld).", (long long)idx, (long long)len - 1);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
@@ -2199,7 +2193,7 @@ static bool sema_slice_index_is_in_range(SemaContext *context, Type *type, Expr
|
||||
}
|
||||
if (idx < 0)
|
||||
{
|
||||
SEMA_ERROR(index_expr, "Array index out of bounds, using a negative array index is only allowed with pointers.");
|
||||
SEMA_ERROR(index_expr, "Index out of bounds, using a negative index is only allowed for pointers.");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -2303,7 +2297,8 @@ static inline bool sema_expr_analyse_subscript(SemaContext *context, Expr *expr,
|
||||
|
||||
int64_t index_value = -1;
|
||||
bool start_from_end = expr->subscript_expr.range.start_from_end;
|
||||
if (expr_is_const_int(index) && (current_type->type_kind == TYPE_ARRAY || current_type == type_untypedlist))
|
||||
int64_t size;
|
||||
if (expr_is_const_int(index) && (size = expr_get_index_max(subscripted)) >= 0)
|
||||
{
|
||||
// 4c. And that it's in range.
|
||||
if (int_is_neg(index->const_expr.ixx))
|
||||
@@ -2311,8 +2306,6 @@ static inline bool sema_expr_analyse_subscript(SemaContext *context, Expr *expr,
|
||||
SEMA_ERROR(index, "The index may not be negative.");
|
||||
return false;
|
||||
}
|
||||
int64_t size = current_type == type_untypedlist ? vec_size(subscripted->const_expr.untyped_list) : current_type->array.len;
|
||||
assert(size >= 0 && "Unexpected overflow");
|
||||
if (!int_fits(index->const_expr.ixx, TYPE_I64) || size == 0)
|
||||
{
|
||||
SEMA_ERROR(index, "The index is out of range.", size);
|
||||
@@ -2368,7 +2361,6 @@ static inline bool sema_expr_analyse_subscript(SemaContext *context, Expr *expr,
|
||||
expr_replace(expr, current_expr->const_expr.untyped_list[index_value]);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!sema_cast_rvalue(context, subscripted)) return false;
|
||||
|
||||
Decl *overload = NULL;
|
||||
@@ -3309,11 +3301,7 @@ static bool sema_expr_rewrite_to_type_property(SemaContext *context, Expr *expr,
|
||||
expr_rewrite_const_int(expr, type_usize, type_abi_alignment(type), true);
|
||||
return true;
|
||||
case TYPE_PROPERTY_EXTNAMEOF:
|
||||
if (type_is_builtin(type->type_kind))
|
||||
{
|
||||
SEMA_ERROR(expr, "'extnameof' cannot be used on builtin types.");
|
||||
return false;
|
||||
}
|
||||
if (type_is_builtin(type->type_kind)) return false;
|
||||
sema_expr_rewrite_to_type_nameof(expr, type, TOKEN_CT_EXTNAMEOF);
|
||||
return true;
|
||||
case TYPE_PROPERTY_NONE:
|
||||
@@ -5936,13 +5924,11 @@ static inline bool sema_expr_analyse_compiler_const(SemaContext *context, Expr *
|
||||
|
||||
|
||||
|
||||
static bool sema_expr_analyse_type_var_path(SemaContext *context, Expr *expr, ExprFlatElement **elements, Type **type_ref,
|
||||
Decl **decl_ref)
|
||||
static Decl *sema_expr_analyse_var_path(SemaContext *context, Expr *expr, ExprFlatElement **elements)
|
||||
{
|
||||
if (!sema_analyse_expr_lvalue_fold_const(context, expr)) return false;
|
||||
if (!sema_analyse_expr_lvalue_fold_const(context, expr)) return NULL;
|
||||
Expr *current = expr;
|
||||
Decl *decl = NULL;
|
||||
Type *type = NULL;
|
||||
RETRY:
|
||||
switch (current->expr_kind)
|
||||
{
|
||||
@@ -5952,21 +5938,12 @@ RETRY:
|
||||
case EXPR_IDENTIFIER:
|
||||
decl = current->identifier_expr.decl;
|
||||
break;
|
||||
case EXPR_TYPEINFO:
|
||||
type = current->type_expr->type;
|
||||
break;
|
||||
default:
|
||||
SEMA_ERROR(expr, "A type or a variable was expected here.");
|
||||
return false;
|
||||
SEMA_ERROR(expr, "A variable was expected here.");
|
||||
return NULL;
|
||||
}
|
||||
if (decl)
|
||||
{
|
||||
if (!sema_analyse_decl(context, decl)) return false;
|
||||
type = decl->type;
|
||||
}
|
||||
*decl_ref = decl;
|
||||
*type_ref = type;
|
||||
return true;
|
||||
if (!sema_analyse_decl(context, decl)) return NULL;
|
||||
return decl;
|
||||
}
|
||||
|
||||
static inline bool sema_expr_analyse_flat_element(SemaContext *context, ExprFlatElement *element, Type *type, Decl **member_ref, ArraySize *index_ref, Type **return_type, unsigned i, SourceSpan loc,
|
||||
@@ -6096,12 +6073,15 @@ static inline bool sema_expr_analyse_flat_element(SemaContext *context, ExprFlat
|
||||
static inline bool sema_expr_analyse_ct_alignof(SemaContext *context, Expr *expr)
|
||||
{
|
||||
Expr *main_var = expr->ct_call_expr.main_var;
|
||||
Type *type = NULL;
|
||||
Decl *decl = NULL;
|
||||
ExprFlatElement *path = expr->ct_call_expr.flat_path;
|
||||
|
||||
if (!sema_expr_analyse_type_var_path(context, main_var, &path, &type, &decl)) return false;
|
||||
|
||||
Decl *decl = sema_expr_analyse_var_path(context, main_var, &path);
|
||||
if (!decl) return false;
|
||||
Type *type = decl->type;
|
||||
if (type_is_invalid_storage_type(type))
|
||||
{
|
||||
SEMA_ERROR(main_var, "Cannot use '$alignof' on type %s.", type_quoted_error_string(type));
|
||||
return false;
|
||||
}
|
||||
AlignSize align = decl && !decl_is_user_defined_type(decl) ? decl->alignment : type_abi_alignment(type);
|
||||
VECEACH(path, i)
|
||||
{
|
||||
@@ -6123,31 +6103,6 @@ static inline bool sema_expr_analyse_ct_alignof(SemaContext *context, Expr *expr
|
||||
}
|
||||
|
||||
expr_rewrite_const_int(expr, type_isize, align, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool sema_expr_analyse_ct_sizeof(SemaContext *context, Expr *expr)
|
||||
{
|
||||
Expr *main_var = expr->ct_call_expr.main_var;
|
||||
Type *type = NULL;
|
||||
Decl *decl = NULL;
|
||||
ExprFlatElement *path = expr->ct_call_expr.flat_path;
|
||||
if (!sema_expr_analyse_type_var_path(context, main_var, &path, &type, &decl)) return false;
|
||||
|
||||
if (!type) return false;
|
||||
|
||||
VECEACH(path, i)
|
||||
{
|
||||
ExprFlatElement *element = &path[i];
|
||||
Decl *member;
|
||||
ArraySize index;
|
||||
Type *result_type;
|
||||
if (!sema_expr_analyse_flat_element(context, element, type, &member, &index, &result_type, i, i == 0 ? main_var->span : expr->span, NULL)) return false;
|
||||
type = result_type;
|
||||
}
|
||||
|
||||
expr_rewrite_const_int(expr, type_isize, type_size(type), true);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -6179,10 +6134,10 @@ static inline void sema_expr_rewrite_to_type_nameof(Expr *expr, Type *type, Toke
|
||||
static inline bool sema_expr_analyse_ct_nameof(SemaContext *context, Expr *expr)
|
||||
{
|
||||
Expr *main_var = expr->ct_call_expr.main_var;
|
||||
Type *type = NULL;
|
||||
Decl *decl = NULL;
|
||||
ExprFlatElement *path = expr->ct_call_expr.flat_path;
|
||||
if (!sema_expr_analyse_type_var_path(context, main_var, &path, &type, &decl)) return false;
|
||||
Decl *decl = sema_expr_analyse_var_path(context, main_var, &path);
|
||||
if (!decl) return false;
|
||||
Type *type = decl->type;
|
||||
|
||||
TokenType name_type = expr->ct_call_expr.token_type;
|
||||
|
||||
@@ -6192,39 +6147,26 @@ static inline bool sema_expr_analyse_ct_nameof(SemaContext *context, Expr *expr)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (decl)
|
||||
if (name_type == TOKEN_CT_EXTNAMEOF)
|
||||
{
|
||||
if (name_type == TOKEN_CT_EXTNAMEOF)
|
||||
if (!decl->extname)
|
||||
{
|
||||
if (!decl->extname)
|
||||
{
|
||||
SEMA_ERROR(main_var, "'%s' does not have an external name.", decl->name);
|
||||
return false;
|
||||
}
|
||||
expr_rewrite_to_string(expr, decl->extname);
|
||||
return true;
|
||||
SEMA_ERROR(main_var, "'%s' does not have an external name.", decl->name);
|
||||
return false;
|
||||
}
|
||||
if (!decl->unit || name_type == TOKEN_CT_NAMEOF || decl_is_local(decl))
|
||||
{
|
||||
expr_rewrite_to_string(expr, decl->name);
|
||||
return true;
|
||||
}
|
||||
scratch_buffer_clear();
|
||||
scratch_buffer_append(decl->unit->module->name->module);
|
||||
scratch_buffer_append("::");
|
||||
scratch_buffer_append(decl->name);
|
||||
expr_rewrite_to_string(expr, scratch_buffer_copy());
|
||||
expr_rewrite_to_string(expr, decl->extname);
|
||||
return true;
|
||||
}
|
||||
|
||||
assert(type);
|
||||
if (name_type == TOKEN_CT_EXTNAMEOF && !type_is_user_defined(type))
|
||||
if (!decl->unit || name_type == TOKEN_CT_NAMEOF || decl_is_local(decl))
|
||||
{
|
||||
SEMA_ERROR(main_var, "Only user defined types have an external name.");
|
||||
return false;
|
||||
expr_rewrite_to_string(expr, decl->name);
|
||||
return true;
|
||||
}
|
||||
|
||||
sema_expr_rewrite_to_type_nameof(expr, type, name_type);
|
||||
scratch_buffer_clear();
|
||||
scratch_buffer_append(decl->unit->module->name->module);
|
||||
scratch_buffer_append("::");
|
||||
scratch_buffer_append(decl->name);
|
||||
expr_rewrite_to_string(expr, scratch_buffer_copy());
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -6587,10 +6529,9 @@ static inline bool sema_expr_analyse_ct_eval(SemaContext *context, Expr *expr)
|
||||
static inline bool sema_expr_analyse_ct_offsetof(SemaContext *context, Expr *expr)
|
||||
{
|
||||
Expr *main_var = expr->ct_call_expr.main_var;
|
||||
Type *type = NULL;
|
||||
Decl *decl = NULL;
|
||||
ExprFlatElement *path = expr->ct_call_expr.flat_path;
|
||||
if (!sema_expr_analyse_type_var_path(context, main_var, &path, &type, &decl)) return false;
|
||||
Decl *decl = sema_expr_analyse_var_path(context, main_var, &path);
|
||||
if (!decl) return false;
|
||||
if (!vec_size(path))
|
||||
{
|
||||
SEMA_ERROR(expr, "Expected a path to get the offset of.");
|
||||
@@ -6598,6 +6539,7 @@ static inline bool sema_expr_analyse_ct_offsetof(SemaContext *context, Expr *exp
|
||||
}
|
||||
|
||||
ByteSize offset = 0;
|
||||
Type *type = decl->type;
|
||||
VECEACH(path, i)
|
||||
{
|
||||
ExprFlatElement *element = &path[i];
|
||||
@@ -6627,8 +6569,6 @@ static inline bool sema_expr_analyse_ct_call(SemaContext *context, Expr *expr)
|
||||
{
|
||||
case TOKEN_CT_DEFINED:
|
||||
return sema_expr_analyse_ct_defined(context, expr);
|
||||
case TOKEN_CT_SIZEOF:
|
||||
return sema_expr_analyse_ct_sizeof(context, expr);
|
||||
case TOKEN_CT_ALIGNOF:
|
||||
return sema_expr_analyse_ct_alignof(context, expr);
|
||||
case TOKEN_CT_OFFSETOF:
|
||||
@@ -7005,6 +6945,36 @@ bool sema_analyse_expr_require_const(SemaContext *context, Expr *expr)
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline int64_t expr_get_index_max(Expr *expr)
|
||||
{
|
||||
if (expr_is_const_untyped_list(expr))
|
||||
{
|
||||
return vec_size(expr->const_expr.untyped_list);
|
||||
}
|
||||
Type *type = expr->type;
|
||||
RETRY:
|
||||
switch (type->type_kind)
|
||||
{
|
||||
case TYPE_TYPEDEF:
|
||||
type = type->canonical;
|
||||
goto RETRY;
|
||||
case TYPE_DISTINCT:
|
||||
type = type->decl->distinct_decl.base_type;
|
||||
goto RETRY;
|
||||
case TYPE_UNTYPED_LIST:
|
||||
UNREACHABLE
|
||||
case TYPE_ARRAY:
|
||||
case TYPE_VECTOR:
|
||||
return type->array.len;
|
||||
case TYPE_OPTIONAL:
|
||||
type = type->failable;
|
||||
goto RETRY;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
UNREACHABLE
|
||||
}
|
||||
|
||||
void expr_insert_widening_type(Expr *expr, Type *infer_type)
|
||||
{
|
||||
if (!infer_type) return;
|
||||
|
||||
@@ -308,9 +308,9 @@ bool sema_resolve_type_shallow(SemaContext *context, TypeInfo *type_info, bool a
|
||||
SEMA_ERROR(expr, "Only type names may be resolved with $evaltype.");
|
||||
return type_info_poison(type_info);
|
||||
}
|
||||
if (type_is_invalid_for_typeof(expr->type))
|
||||
if (type_is_invalid_storage_type(expr->type))
|
||||
{
|
||||
SEMA_ERROR(expr, "Compile-time expressions may not be used with $evaltype.");
|
||||
SEMA_ERROR(expr, "Compile-time types may not be used with $evaltype.");
|
||||
return type_info_poison(type_info);
|
||||
}
|
||||
TypeInfo *inner_type = inner->type_expr;
|
||||
@@ -326,9 +326,9 @@ bool sema_resolve_type_shallow(SemaContext *context, TypeInfo *type_info, bool a
|
||||
{
|
||||
return type_info_poison(type_info);
|
||||
}
|
||||
if (type_is_invalid_for_typeof(expr->type))
|
||||
if (type_is_invalid_storage_type(expr->type))
|
||||
{
|
||||
SEMA_ERROR(expr, "Compile-time expressions are not allowed here.");
|
||||
SEMA_ERROR(expr, "Expected a regular runtime expression here.");
|
||||
return false;
|
||||
}
|
||||
type_info->type = expr->type;
|
||||
|
||||
@@ -1 +1 @@
|
||||
#define COMPILER_VERSION "0.3.74"
|
||||
#define COMPILER_VERSION "0.3.75"
|
||||
@@ -46,8 +46,8 @@ fn void test(int x)
|
||||
print_args($typeof(&test));
|
||||
print_args($typeof(&hell));
|
||||
print_args($typeof(&hello));
|
||||
io::println($nameof($typefrom($typeof(&test).returns)));
|
||||
io::println($nameof($typefrom($typeof(&hell).returns)));
|
||||
io::println($typeof(&test).returns.nameof);
|
||||
io::println($typeof(&hell).returns.nameof);
|
||||
print_fields(Foo);
|
||||
print_fields(Bar);
|
||||
print_fields(Bark);
|
||||
|
||||
@@ -36,55 +36,30 @@ union Foob
|
||||
}
|
||||
Ar izzy;
|
||||
|
||||
|
||||
long x = $alignof(zfe);
|
||||
short y = $alignof(Bob.y);
|
||||
int z = $alignof(Bob.y);
|
||||
int w = $alignof(Bob.y);
|
||||
short y = Bob.y.alignof;
|
||||
int z = Bob.w.z.alignof;
|
||||
int v = $alignof(v);
|
||||
int x1 = $alignof(Ex.c);
|
||||
int x2 = $alignof(Ex.y);
|
||||
int x3 = $alignof(char[8]);
|
||||
int x4 = $alignof(Ar.br[1]);
|
||||
int x5 = $alignof(Ar.br[1]);
|
||||
int x6 = $alignof(Ar.br[1]);
|
||||
int x7 = $alignof(Ar.br[1]);
|
||||
int x8 = $alignof(Ar.br[2]);
|
||||
int x1 = Ex.c.alignof;
|
||||
int x2 = Ex.y.alignof;
|
||||
int x3 = char[8].alignof;
|
||||
int x9 = $alignof(izzy.br[1]);
|
||||
int x10 = $alignof(izzy.br[1]);
|
||||
int x11 = $alignof(izzy.br[1]);
|
||||
int z0 = $alignof(Foob.c);
|
||||
int z00 = $alignof(Foob.c[0]);
|
||||
int z01 = $alignof(Foob.c[1]);
|
||||
int z02 = $alignof(Foob.c[2]);
|
||||
int z03 = $alignof(Foob.c[3]);
|
||||
int z04 = $alignof(Foob.c[4]);
|
||||
int z05 = $alignof(Foob.c[5]);
|
||||
int z0 = Foob.c.alignof;
|
||||
|
||||
|
||||
|
||||
// #expect: foo.ll
|
||||
/* #expect: foo.ll
|
||||
|
||||
@foo_x = local_unnamed_addr global i64 16, align 8
|
||||
@foo_y = local_unnamed_addr global i16 8, align 2
|
||||
@foo_z = local_unnamed_addr global i32 8, align 4
|
||||
@foo_w = local_unnamed_addr global i32 8, align 4
|
||||
@foo_z = local_unnamed_addr global i32 4, align 4
|
||||
@foo_v = local_unnamed_addr global i32 4, align 4
|
||||
@foo_x1 = local_unnamed_addr global i32 8, align 4
|
||||
@foo_x2 = local_unnamed_addr global i32 8, align 4
|
||||
@foo_x3 = local_unnamed_addr global i32 1, align 4
|
||||
@foo_x4 = local_unnamed_addr global i32 4, align 4
|
||||
@foo_x5 = local_unnamed_addr global i32 4, align 4
|
||||
@foo_x6 = local_unnamed_addr global i32 4, align 4
|
||||
@foo_x7 = local_unnamed_addr global i32 4, align 4
|
||||
@foo_x8 = local_unnamed_addr global i32 8, align 4
|
||||
@foo_x9 = local_unnamed_addr global i32 4, align 4
|
||||
@foo_x10 = local_unnamed_addr global i32 4, align 4
|
||||
@foo_x11 = local_unnamed_addr global i32 4, align 4
|
||||
@foo_z0 = local_unnamed_addr global i32 8, align 4
|
||||
@foo_z00 = local_unnamed_addr global i32 8, align 4
|
||||
@foo_z01 = local_unnamed_addr global i32 1, align 4
|
||||
@foo_z02 = local_unnamed_addr global i32 2, align 4
|
||||
@foo_z03 = local_unnamed_addr global i32 1, align 4
|
||||
@foo_z04 = local_unnamed_addr global i32 4, align 4
|
||||
@foo_z05 = local_unnamed_addr global i32 1, align 4
|
||||
@@ -11,10 +11,10 @@ fn void main2()
|
||||
|
||||
fn void main3()
|
||||
{
|
||||
$extnameof($evaltype("int")); // #error: Only user defined types have an external name.
|
||||
$evaltype("int").extnameof; // #error: 'int' does not have a property 'extnameof'
|
||||
}
|
||||
|
||||
fn void main4()
|
||||
{
|
||||
$extnameof($evaltype("foo::int")); // #error: Only valid types may be resolved with $evaltype.
|
||||
$evaltype("foo::int").extnameof; // #error: Only valid types may be resolved with $evaltype.
|
||||
}
|
||||
|
||||
@@ -36,35 +36,15 @@ union Foob
|
||||
}
|
||||
|
||||
|
||||
short y = $offsetof(Bob.y);
|
||||
int z = $offsetof(Bob.y);
|
||||
int w = $offsetof(Bob.y);
|
||||
int x1 = $offsetof(Ex.c[3]);
|
||||
int x2 = $offsetof(Ex.y[1]);
|
||||
int x4 = $offsetof(Ar.br[1]);
|
||||
int x6 = $offsetof(Ar.br[1].x);
|
||||
int x5 = $offsetof(Ar.br[1]);
|
||||
int x7 = $offsetof(Ar.br[2].x);
|
||||
int x8 = $offsetof(Ar.br[2]);
|
||||
int z0 = $offsetof(Foob.c);
|
||||
int z00 = $offsetof(Foob.c[0]);
|
||||
int z01 = $offsetof(Foob.c[1]);
|
||||
int z02 = $offsetof(Foob.c[5]);
|
||||
int z03 = $offsetof(Foob.a);
|
||||
short y = Bob.y.offsetof;
|
||||
int z = Bob.w.z.offsetof;
|
||||
int w = Bob.w.offsetof;
|
||||
int z0 = Foob.c.offsetof;
|
||||
int z03 = Foob.a.offsetof;
|
||||
|
||||
// #expect: foo.ll
|
||||
@foo_y = local_unnamed_addr global i16 16, align 2
|
||||
@foo_z = local_unnamed_addr global i32 16, align 4
|
||||
@foo_w = local_unnamed_addr global i32 16, align 4
|
||||
@foo_x1 = local_unnamed_addr global i32 3, align 4
|
||||
@foo_x2 = local_unnamed_addr global i32 4, align 4
|
||||
@foo_x4 = local_unnamed_addr global i32 16, align 4
|
||||
@foo_x6 = local_unnamed_addr global i32 20, align 4
|
||||
@foo_x5 = local_unnamed_addr global i32 16, align 4
|
||||
@foo_x7 = local_unnamed_addr global i32 28, align 4
|
||||
@foo_x8 = local_unnamed_addr global i32 24, align 4
|
||||
@foo_z = local_unnamed_addr global i32 116, align 4
|
||||
@foo_w = local_unnamed_addr global i32 116, align 4
|
||||
@foo_z0 = local_unnamed_addr global i32 0, align 4
|
||||
@foo_z00 = local_unnamed_addr global i32 0, align 4
|
||||
@foo_z01 = local_unnamed_addr global i32 1, align 4
|
||||
@foo_z02 = local_unnamed_addr global i32 5, align 4
|
||||
@foo_z03 = local_unnamed_addr global i32 0, align 4
|
||||
|
||||
@@ -6,7 +6,7 @@ enum MyEnum : short
|
||||
}
|
||||
|
||||
int myenum_elements = MyEnum.elements;
|
||||
int myenum_alignof = $alignof(MyEnum);
|
||||
int myenum_alignof = MyEnum.alignof;
|
||||
int myenum_sizeof = MyEnum.sizeof;
|
||||
|
||||
// #expect: compile_time.ll
|
||||
|
||||
@@ -7,5 +7,5 @@ macro test(foo)
|
||||
fn void main()
|
||||
{
|
||||
test(int[] { 1, 2 });
|
||||
test({ 1, 2 }); // #error: An untyped list can only be passed as a compile time parameter.
|
||||
test({ 1, 2 }); // #error: A value of type 'untyped_list' can only be passed as a compile time parameter.
|
||||
}
|
||||
@@ -6,21 +6,21 @@ macro testbitcast(expr, $Type)
|
||||
$Type x = void;
|
||||
var $size = (usize)($sizeof(expr));
|
||||
|
||||
$if ($alignof(expr) >= 8 && $alignof($Type) >= 8):
|
||||
$if ($alignof(expr) >= 8 && $Type.alignof >= 8):
|
||||
ulong *b = (ulong*)(&expr);
|
||||
ulong *to = (ulong*)(&x);
|
||||
for (usize i = 0; i < $size; i += 8)
|
||||
{
|
||||
to[i] = b[i];
|
||||
}
|
||||
$elif ($alignof(expr) >= 4 && $alignof($Type) >= 4):
|
||||
$elif ($alignof(expr) >= 4 && $Type.alignof >= 4):
|
||||
uint* b = (uint*)(&expr);
|
||||
uint* to = (uint*)(&x);
|
||||
for (usize i = 0; i < $size; i += 4)
|
||||
{
|
||||
to[i] = b[i];
|
||||
}
|
||||
$elif ($alignof(expr) >= 2 && $alignof($Type) >= 2):
|
||||
$elif ($alignof(expr) >= 2 && $Type.alignof >= 2):
|
||||
ushort* b = (ushort*)(&expr);
|
||||
ushort* to = (ushort*)(&x);
|
||||
for (usize i = 0; i < $size; i += 2)
|
||||
|
||||
@@ -16,7 +16,7 @@ fn void test2()
|
||||
fn void test3()
|
||||
{
|
||||
int[3] x = { 1, 2, 3 };
|
||||
int[] z = x[..4]; // #error: Array end index out of bounds, was 4, exceeding array length 3.
|
||||
int[] z = x[..4]; // #error: End index out of bounds, was 4, exceeding 3.
|
||||
}
|
||||
|
||||
fn void test4()
|
||||
@@ -29,31 +29,31 @@ fn void test4()
|
||||
fn void test5()
|
||||
{
|
||||
int[3] x = { 1, 2, 3 };
|
||||
int[] z = x[..^4]; // #error: Array index out of bounds, using a negative array index is only allowed with pointers.
|
||||
int[] z = x[..^4]; // #error: Index out of bounds, using a negative index is only allowed for pointers.
|
||||
}
|
||||
|
||||
fn void test6()
|
||||
{
|
||||
int[3] x = { 1, 2, 3 };
|
||||
int[] z = x[3..]; // #error: Array index out of bounds, was 3, exceeding max array index 2.
|
||||
int[] z = x[3..]; // #error: Index out of bounds, was 3, exceeding maximum (2).
|
||||
}
|
||||
|
||||
fn void test7()
|
||||
{
|
||||
int[3] x = { 1, 2, 3 };
|
||||
int[] z = x[-1..]; // #error: Array index out of bounds, using a negative array index is only allowed with pointers.
|
||||
int[] z = x[-1..]; // #error: Index out of bounds, using a negative index is only allowed for pointers.
|
||||
}
|
||||
|
||||
fn void test8()
|
||||
{
|
||||
int[3] x = { 1, 2, 3 };
|
||||
int[] z = x[^4..]; // #error: Array index out of bounds, using a negative array index is only allowed with pointers.
|
||||
int[] z = x[^4..]; // #error: Index out of bounds, using a negative index is only allowed for pointers.
|
||||
}
|
||||
|
||||
fn void test9()
|
||||
{
|
||||
int[3] x = { 1, 2, 3 };
|
||||
int[] z = x[^0..]; // #error: Array index out of bounds, was 3, exceeding max array index 2.
|
||||
int[] z = x[^0..]; // #error: Index out of bounds, was 3, exceeding maximum (2)
|
||||
}
|
||||
|
||||
fn void test10()
|
||||
@@ -68,5 +68,5 @@ fn void test10()
|
||||
fn void test11()
|
||||
{
|
||||
int[3] x = { 1, 2, 3 };
|
||||
int[] z = x[..^0]; // #error: Array end index out of bounds, was 3, exceeding array length 3
|
||||
int[] z = x[..^0]; // #error: End index out of bounds, was 3, exceeding 3.
|
||||
}
|
||||
|
||||
@@ -46,8 +46,8 @@ fn void test(int x)
|
||||
print_args($typeof(&test));
|
||||
print_args($typeof(&hell));
|
||||
print_args($typeof(&hello));
|
||||
io::println($nameof($typefrom($typeof(&test).returns)));
|
||||
io::println($nameof($typefrom($typeof(&hell).returns)));
|
||||
io::println($typeof(&test).returns.nameof);
|
||||
io::println($typeof(&hell).returns.nameof);
|
||||
print_fields(Foo);
|
||||
print_fields(Bar);
|
||||
print_fields(Bark);
|
||||
|
||||
@@ -36,55 +36,30 @@ union Foob
|
||||
}
|
||||
Ar izzy;
|
||||
|
||||
|
||||
long x = $alignof(zfe);
|
||||
short y = $alignof(Bob.y);
|
||||
int z = $alignof(Bob.y);
|
||||
int w = $alignof(Bob.y);
|
||||
short y = Bob.y.alignof;
|
||||
int z = Bob.w.z.alignof;
|
||||
int v = $alignof(v);
|
||||
int x1 = $alignof(Ex.c);
|
||||
int x2 = $alignof(Ex.y);
|
||||
int x3 = $alignof(char[8]);
|
||||
int x4 = $alignof(Ar.br[1]);
|
||||
int x5 = $alignof(Ar.br[1]);
|
||||
int x6 = $alignof(Ar.br[1]);
|
||||
int x7 = $alignof(Ar.br[1]);
|
||||
int x8 = $alignof(Ar.br[2]);
|
||||
int x1 = Ex.c.alignof;
|
||||
int x2 = Ex.y.alignof;
|
||||
int x3 = char[8].alignof;
|
||||
int x9 = $alignof(izzy.br[1]);
|
||||
int x10 = $alignof(izzy.br[1]);
|
||||
int x11 = $alignof(izzy.br[1]);
|
||||
int z0 = $alignof(Foob.c);
|
||||
int z00 = $alignof(Foob.c[0]);
|
||||
int z01 = $alignof(Foob.c[1]);
|
||||
int z02 = $alignof(Foob.c[2]);
|
||||
int z03 = $alignof(Foob.c[3]);
|
||||
int z04 = $alignof(Foob.c[4]);
|
||||
int z05 = $alignof(Foob.c[5]);
|
||||
int z0 = Foob.c.alignof;
|
||||
|
||||
|
||||
|
||||
// #expect: foo.ll
|
||||
/* #expect: foo.ll
|
||||
|
||||
@foo_x = local_unnamed_addr global i64 16, align 8
|
||||
@foo_y = local_unnamed_addr global i16 8, align 2
|
||||
@foo_z = local_unnamed_addr global i32 8, align 4
|
||||
@foo_w = local_unnamed_addr global i32 8, align 4
|
||||
@foo_z = local_unnamed_addr global i32 4, align 4
|
||||
@foo_v = local_unnamed_addr global i32 4, align 4
|
||||
@foo_x1 = local_unnamed_addr global i32 8, align 4
|
||||
@foo_x2 = local_unnamed_addr global i32 8, align 4
|
||||
@foo_x3 = local_unnamed_addr global i32 1, align 4
|
||||
@foo_x4 = local_unnamed_addr global i32 4, align 4
|
||||
@foo_x5 = local_unnamed_addr global i32 4, align 4
|
||||
@foo_x6 = local_unnamed_addr global i32 4, align 4
|
||||
@foo_x7 = local_unnamed_addr global i32 4, align 4
|
||||
@foo_x8 = local_unnamed_addr global i32 8, align 4
|
||||
@foo_x9 = local_unnamed_addr global i32 4, align 4
|
||||
@foo_x10 = local_unnamed_addr global i32 4, align 4
|
||||
@foo_x11 = local_unnamed_addr global i32 4, align 4
|
||||
@foo_z0 = local_unnamed_addr global i32 8, align 4
|
||||
@foo_z00 = local_unnamed_addr global i32 8, align 4
|
||||
@foo_z01 = local_unnamed_addr global i32 1, align 4
|
||||
@foo_z02 = local_unnamed_addr global i32 2, align 4
|
||||
@foo_z03 = local_unnamed_addr global i32 1, align 4
|
||||
@foo_z04 = local_unnamed_addr global i32 4, align 4
|
||||
@foo_z05 = local_unnamed_addr global i32 1, align 4
|
||||
@@ -11,10 +11,10 @@ fn void main2()
|
||||
|
||||
fn void main3()
|
||||
{
|
||||
$extnameof($evaltype("int")); // #error: Only user defined types have an external name.
|
||||
$evaltype("int").extnameof; // #error: 'int' does not have a property 'extnameof'
|
||||
}
|
||||
|
||||
fn void main4()
|
||||
{
|
||||
$extnameof($evaltype("foo::int")); // #error: Only valid types may be resolved with $evaltype.
|
||||
$evaltype("foo::int").extnameof; // #error: Only valid types may be resolved with $evaltype.
|
||||
}
|
||||
|
||||
@@ -36,35 +36,15 @@ union Foob
|
||||
}
|
||||
|
||||
|
||||
short y = $offsetof(Bob.y);
|
||||
int z = $offsetof(Bob.y);
|
||||
int w = $offsetof(Bob.y);
|
||||
int x1 = $offsetof(Ex.c[3]);
|
||||
int x2 = $offsetof(Ex.y[1]);
|
||||
int x4 = $offsetof(Ar.br[1]);
|
||||
int x6 = $offsetof(Ar.br[1].x);
|
||||
int x5 = $offsetof(Ar.br[1]);
|
||||
int x7 = $offsetof(Ar.br[2].x);
|
||||
int x8 = $offsetof(Ar.br[2]);
|
||||
int z0 = $offsetof(Foob.c);
|
||||
int z00 = $offsetof(Foob.c[0]);
|
||||
int z01 = $offsetof(Foob.c[1]);
|
||||
int z02 = $offsetof(Foob.c[5]);
|
||||
int z03 = $offsetof(Foob.a);
|
||||
short y = Bob.y.offsetof;
|
||||
int z = Bob.w.z.offsetof;
|
||||
int w = Bob.w.offsetof;
|
||||
int z0 = Foob.c.offsetof;
|
||||
int z03 = Foob.a.offsetof;
|
||||
|
||||
// #expect: foo.ll
|
||||
@foo_y = local_unnamed_addr global i16 16, align 2
|
||||
@foo_z = local_unnamed_addr global i32 16, align 4
|
||||
@foo_w = local_unnamed_addr global i32 16, align 4
|
||||
@foo_x1 = local_unnamed_addr global i32 3, align 4
|
||||
@foo_x2 = local_unnamed_addr global i32 4, align 4
|
||||
@foo_x4 = local_unnamed_addr global i32 16, align 4
|
||||
@foo_x6 = local_unnamed_addr global i32 20, align 4
|
||||
@foo_x5 = local_unnamed_addr global i32 16, align 4
|
||||
@foo_x7 = local_unnamed_addr global i32 28, align 4
|
||||
@foo_x8 = local_unnamed_addr global i32 24, align 4
|
||||
@foo_z = local_unnamed_addr global i32 116, align 4
|
||||
@foo_w = local_unnamed_addr global i32 116, align 4
|
||||
@foo_z0 = local_unnamed_addr global i32 0, align 4
|
||||
@foo_z00 = local_unnamed_addr global i32 0, align 4
|
||||
@foo_z01 = local_unnamed_addr global i32 1, align 4
|
||||
@foo_z02 = local_unnamed_addr global i32 5, align 4
|
||||
@foo_z03 = local_unnamed_addr global i32 0, align 4
|
||||
|
||||
@@ -6,7 +6,7 @@ enum MyEnum : short
|
||||
}
|
||||
|
||||
int myenum_elements = MyEnum.elements;
|
||||
int myenum_alignof = $alignof(MyEnum);
|
||||
int myenum_alignof = MyEnum.alignof;
|
||||
int myenum_sizeof = MyEnum.sizeof;
|
||||
|
||||
/* #expect: compile_time.ll
|
||||
|
||||
@@ -7,5 +7,5 @@ macro test(foo)
|
||||
fn void main()
|
||||
{
|
||||
test(int[] { 1, 2 });
|
||||
test({ 1, 2 }); // #error: An untyped list can only be passed as a compile time parameter.
|
||||
test({ 1, 2 }); // #error: A value of type 'untyped_list' can only be passed as a compile time parameter.
|
||||
}
|
||||
@@ -6,21 +6,21 @@ macro testbitcast(expr, $Type)
|
||||
$Type x = void;
|
||||
var $size = (usize)($sizeof(expr));
|
||||
|
||||
$if ($alignof(expr) >= 8 && $alignof($Type) >= 8):
|
||||
$if ($alignof(expr) >= 8 && $Type.alignof >= 8):
|
||||
ulong *b = (ulong*)(&expr);
|
||||
ulong *to = (ulong*)(&x);
|
||||
for (usize i = 0; i < $size; i += 8)
|
||||
{
|
||||
to[i] = b[i];
|
||||
}
|
||||
$elif ($alignof(expr) >= 4 && $alignof($Type) >= 4):
|
||||
$elif ($alignof(expr) >= 4 && $Type.alignof >= 4):
|
||||
uint* b = (uint*)(&expr);
|
||||
uint* to = (uint*)(&x);
|
||||
for (usize i = 0; i < $size; i += 4)
|
||||
{
|
||||
to[i] = b[i];
|
||||
}
|
||||
$elif ($alignof(expr) >= 2 && $alignof($Type) >= 2):
|
||||
$elif ($alignof(expr) >= 2 && $Type.alignof >= 2):
|
||||
ushort* b = (ushort*)(&expr);
|
||||
ushort* to = (ushort*)(&x);
|
||||
for (usize i = 0; i < $size; i += 2)
|
||||
|
||||
@@ -16,7 +16,7 @@ fn void test2()
|
||||
fn void test3()
|
||||
{
|
||||
int[3] x = { 1, 2, 3 };
|
||||
int[] z = x[..4]; // #error: Array end index out of bounds, was 4, exceeding array length 3.
|
||||
int[] z = x[..4]; // #error: End index out of bounds, was 4, exceeding 3.
|
||||
}
|
||||
|
||||
fn void test4()
|
||||
@@ -29,31 +29,31 @@ fn void test4()
|
||||
fn void test5()
|
||||
{
|
||||
int[3] x = { 1, 2, 3 };
|
||||
int[] z = x[..^4]; // #error: Array index out of bounds, using a negative array index is only allowed with pointers.
|
||||
int[] z = x[..^4]; // #error: Index out of bounds, using a negative index is only allowed for pointers.
|
||||
}
|
||||
|
||||
fn void test6()
|
||||
{
|
||||
int[3] x = { 1, 2, 3 };
|
||||
int[] z = x[3..]; // #error: Array index out of bounds, was 3, exceeding max array index 2.
|
||||
int[] z = x[3..]; // #error: Index out of bounds, was 3, exceeding maximum (2).
|
||||
}
|
||||
|
||||
fn void test7()
|
||||
{
|
||||
int[3] x = { 1, 2, 3 };
|
||||
int[] z = x[-1..]; // #error: Array index out of bounds, using a negative array index is only allowed with pointers.
|
||||
int[] z = x[-1..]; // #error: Index out of bounds, using a negative index is only allowed for pointers.
|
||||
}
|
||||
|
||||
fn void test8()
|
||||
{
|
||||
int[3] x = { 1, 2, 3 };
|
||||
int[] z = x[^4..]; // #error: Array index out of bounds, using a negative array index is only allowed with pointers.
|
||||
int[] z = x[^4..]; // #error: Index out of bounds, using a negative index is only allowed for pointers.
|
||||
}
|
||||
|
||||
fn void test9()
|
||||
{
|
||||
int[3] x = { 1, 2, 3 };
|
||||
int[] z = x[^0..]; // #error: Array index out of bounds, was 3, exceeding max array index 2.
|
||||
int[] z = x[^0..]; // #error: Index out of bounds, was 3, exceeding maximum (2)
|
||||
}
|
||||
|
||||
fn void test10()
|
||||
@@ -68,5 +68,5 @@ fn void test10()
|
||||
fn void test11()
|
||||
{
|
||||
int[3] x = { 1, 2, 3 };
|
||||
int[] z = x[..^0]; // #error: Array end index out of bounds, was 3, exceeding array length 3
|
||||
int[] z = x[..^0]; // #error: End index out of bounds, was 3, exceeding 3.
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user