mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Flexible array member added, zero sized structs removed.
This commit is contained in:
@@ -26,7 +26,3 @@ struct VarArrayHeader
|
||||
|
||||
}
|
||||
|
||||
struct VarArrayContainer
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@@ -268,6 +268,8 @@ bool type_is_homogenous_aggregate(Type *type, Type **base, unsigned *elements)
|
||||
if (type_size(*base) * *elements != type_size(type)) return false;
|
||||
}
|
||||
goto TYPECHECK;
|
||||
case TYPE_FLEXIBLE_ARRAY:
|
||||
return false;
|
||||
case TYPE_ARRAY:
|
||||
// Empty arrays? Not homogenous.
|
||||
if (type->array.len == 0) return false;
|
||||
|
||||
@@ -100,7 +100,7 @@ typedef enum
|
||||
CONST_INIT_ARRAY,
|
||||
CONST_INIT_ARRAY_FULL,
|
||||
CONST_INIT_ARRAY_VALUE,
|
||||
} ConstInitType;
|
||||
} ConstInitType;
|
||||
|
||||
|
||||
typedef struct ConstInitializer_
|
||||
@@ -2054,6 +2054,7 @@ Type *type_get_ptr(Type *ptr_type);
|
||||
Type *type_get_ptr_recurse(Type *ptr_type);
|
||||
Type *type_get_subarray(Type *arr_type);
|
||||
Type *type_get_inferred_array(Type *arr_type);
|
||||
Type *type_get_flexible_array(Type *arr_type);
|
||||
Type *type_get_failable(Type *failable_type);
|
||||
Type *type_get_vector(Type *vector_type, unsigned len);
|
||||
Type *type_get_vector_bool(Type *original_type);
|
||||
|
||||
@@ -554,6 +554,7 @@ typedef enum
|
||||
TYPE_ARRAY,
|
||||
TYPE_SUBARRAY,
|
||||
TYPE_INFERRED_ARRAY,
|
||||
TYPE_FLEXIBLE_ARRAY,
|
||||
TYPE_UNTYPED_LIST,
|
||||
TYPE_FAILABLE,
|
||||
TYPE_FAILABLE_ANY,
|
||||
|
||||
@@ -97,6 +97,8 @@ static void header_print_type(FILE *file, Type *type)
|
||||
case TYPE_ERRTYPE:
|
||||
OUTPUT("enum %s__", type->decl->external_name);
|
||||
return;
|
||||
case TYPE_FLEXIBLE_ARRAY:
|
||||
TODO
|
||||
case TYPE_FUNC:
|
||||
TODO
|
||||
case TYPE_STRUCT:
|
||||
|
||||
@@ -328,6 +328,7 @@ void llvm_emit_ptr_from_array(GenContext *c, BEValue *value)
|
||||
return;
|
||||
case TYPE_ARRAY:
|
||||
case TYPE_VECTOR:
|
||||
case TYPE_FLEXIBLE_ARRAY:
|
||||
return;
|
||||
case TYPE_SUBARRAY:
|
||||
{
|
||||
|
||||
@@ -442,6 +442,7 @@ static void x64_classify(Type *type, ByteSize offset_base, X64Class *lo_class, X
|
||||
case TYPE_UNION:
|
||||
x64_classify_struct_union(type, offset_base, current, lo_class, hi_class, named);
|
||||
break;
|
||||
case TYPE_FLEXIBLE_ARRAY:
|
||||
case TYPE_ARRAY:
|
||||
x64_classify_array(type, offset_base, current, lo_class, hi_class, named);
|
||||
break;
|
||||
@@ -574,6 +575,8 @@ AbiType *x64_get_int_type_at_offset(Type *type, unsigned offset, Type *source_ty
|
||||
if (offset < 8) return abi_type_new_plain(type_voidptr);
|
||||
if (offset < 16) return abi_type_new_plain(type_ulong);
|
||||
break;
|
||||
case TYPE_FLEXIBLE_ARRAY:
|
||||
UNREACHABLE
|
||||
case TYPE_ARRAY:
|
||||
{
|
||||
Type *element = type->array.base;
|
||||
|
||||
@@ -120,6 +120,7 @@ static bool x86_should_return_type_in_reg(Type *type)
|
||||
case CT_TYPES:
|
||||
case TYPE_FAILABLE:
|
||||
case TYPE_FAILABLE_ANY:
|
||||
case TYPE_FLEXIBLE_ARRAY:
|
||||
UNREACHABLE
|
||||
case ALL_INTS:
|
||||
case ALL_FLOATS:
|
||||
@@ -597,6 +598,7 @@ static ABIArgInfo *x86_classify_argument(CallABI call, Regs *regs, Type *type)
|
||||
case TYPE_FAILABLE:
|
||||
case TYPE_FAILABLE_ANY:
|
||||
case CT_TYPES:
|
||||
case TYPE_FLEXIBLE_ARRAY:
|
||||
UNREACHABLE
|
||||
case ALL_FLOATS:
|
||||
case ALL_INTS:
|
||||
|
||||
@@ -543,6 +543,7 @@ static inline LLVMMetadataRef llvm_get_debug_type_internal(GenContext *c, Type *
|
||||
case TYPE_TYPEDEF:
|
||||
return type->backend_debug_type = llvm_debug_typedef_type(c, type);
|
||||
case TYPE_ARRAY:
|
||||
case TYPE_FLEXIBLE_ARRAY:
|
||||
return type->backend_debug_type = llvm_debug_array_type(c, type);
|
||||
case TYPE_SUBARRAY:
|
||||
return type->backend_debug_type = llvm_debug_subarray_type(c, type);
|
||||
|
||||
@@ -491,6 +491,13 @@ static inline void llvm_emit_subscript_addr_with_base(GenContext *c, BEValue *re
|
||||
case TYPE_POINTER:
|
||||
llvm_value_set_address(result, llvm_emit_pointer_inbounds_gep_raw(c, llvm_get_pointee_type(c, parent->type), parent->value, index->value), type->pointer);
|
||||
return;
|
||||
case TYPE_FLEXIBLE_ARRAY:
|
||||
{
|
||||
AlignSize alignment;
|
||||
LLVMValueRef ptr = llvm_emit_array_gep_raw_index(c, parent->value, llvm_get_type(c, type), index->value, parent->alignment, &alignment);
|
||||
llvm_value_set_address_align(result, ptr, type->array.base, alignment);
|
||||
return;
|
||||
}
|
||||
case TYPE_ARRAY:
|
||||
case TYPE_VECTOR:
|
||||
// TODO vector
|
||||
@@ -3861,6 +3868,7 @@ static void llvm_expand_type_to_args(GenContext *context, Type *param_type, LLVM
|
||||
case TYPE_FAILABLE:
|
||||
case CT_TYPES:
|
||||
case TYPE_FAILABLE_ANY:
|
||||
case TYPE_FLEXIBLE_ARRAY:
|
||||
UNREACHABLE
|
||||
break;
|
||||
case TYPE_BOOL:
|
||||
|
||||
@@ -352,6 +352,7 @@ LLVMTypeRef llvm_get_type(GenContext *c, Type *any_type)
|
||||
case TYPE_POINTER:
|
||||
return any_type->backend_type = llvm_type_from_ptr(c, any_type);
|
||||
case TYPE_ARRAY:
|
||||
case TYPE_FLEXIBLE_ARRAY:
|
||||
return any_type->backend_type = llvm_type_from_array(c, any_type);
|
||||
case TYPE_SUBARRAY:
|
||||
{
|
||||
|
||||
@@ -389,6 +389,7 @@ CastKind cast_to_bool_kind(Type *type)
|
||||
case TYPE_FAILABLE:
|
||||
case TYPE_ANY:
|
||||
case TYPE_FAILABLE_ANY:
|
||||
case TYPE_FLEXIBLE_ARRAY:
|
||||
return CAST_ERROR;
|
||||
}
|
||||
UNREACHABLE
|
||||
@@ -481,6 +482,8 @@ bool cast_may_explicit(Type *from_type, Type *to_type, bool ignore_failability,
|
||||
case TYPE_ERRTYPE:
|
||||
// Allow MyError.A -> error, to an integer or to bool
|
||||
return to_type->type_kind == TYPE_ANYERR || type_is_integer(to_type) || to_type == type_bool;
|
||||
case TYPE_FLEXIBLE_ARRAY:
|
||||
return false;
|
||||
case TYPE_ARRAY:
|
||||
if (to_kind == TYPE_VECTOR)
|
||||
{
|
||||
@@ -1260,6 +1263,8 @@ static bool cast_inner(Expr *expr, Type *from_type, Type *to, Type *to_type)
|
||||
if (to == type_bool) return err_to_bool(expr, to_type);
|
||||
if (type_is_integer(to)) return insert_cast(expr, CAST_ERINT, to_type);
|
||||
break;
|
||||
case TYPE_FLEXIBLE_ARRAY:
|
||||
return false;
|
||||
case TYPE_ARRAY:
|
||||
if (to->type_kind == TYPE_VECTOR) return insert_cast(expr, CAST_ARRVEC, to_type);
|
||||
FALLTHROUGH;
|
||||
|
||||
@@ -83,19 +83,30 @@ static inline bool sema_analyse_struct_member(Context *context, Decl *decl)
|
||||
}
|
||||
if (decl->name) sema_add_member(context, decl);
|
||||
}
|
||||
|
||||
switch (decl->decl_kind)
|
||||
{
|
||||
case DECL_VAR:
|
||||
assert(decl->var.kind == VARDECL_MEMBER);
|
||||
decl->resolve_status = RESOLVE_RUNNING;
|
||||
if (!sema_resolve_type_info(context, decl->var.type_info)) return decl_poison(decl);
|
||||
if (!sema_resolve_type_info_maybe_inferred(context, decl->var.type_info, true)) return decl_poison(decl);
|
||||
decl->type = decl->var.type_info->type;
|
||||
decl->resolve_status = RESOLVE_DONE;
|
||||
Type *member_type = type_flatten_distinct(decl->type);
|
||||
if (member_type->type_kind == TYPE_ARRAY)
|
||||
{
|
||||
if (member_type->array.len == 0)
|
||||
{
|
||||
SEMA_ERROR(decl, "Zero length arrays are not valid members.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
case DECL_STRUCT:
|
||||
case DECL_UNION:
|
||||
case DECL_BITSTRUCT:
|
||||
return sema_analyse_decl(context, decl);
|
||||
if (!sema_analyse_decl(context, decl)) return false;
|
||||
return true;
|
||||
default:
|
||||
UNREACHABLE
|
||||
}
|
||||
@@ -107,6 +118,7 @@ static bool sema_analyse_union_members(Context *context, Decl *decl, Decl **memb
|
||||
MemberIndex max_alignment_element = 0;
|
||||
AlignSize max_alignment = 0;
|
||||
|
||||
bool has_named_parameter = false;
|
||||
VECEACH(members, i)
|
||||
{
|
||||
Decl *member = members[i];
|
||||
@@ -124,7 +136,11 @@ static bool sema_analyse_union_members(Context *context, Decl *decl, Decl **memb
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (member->type->type_kind == TYPE_INFERRED_ARRAY)
|
||||
{
|
||||
SEMA_ERROR(member, "Flexible array members not allowed in unions.");
|
||||
return false;
|
||||
}
|
||||
AlignSize member_alignment = type_abi_alignment(member->type);
|
||||
ByteSize member_size = type_size(member->type);
|
||||
assert(member_size <= MAX_TYPE_SIZE);
|
||||
@@ -195,13 +211,14 @@ static bool sema_analyse_union_members(Context *context, Decl *decl, Decl **memb
|
||||
|
||||
static bool sema_analyse_struct_members(Context *context, Decl *decl, Decl **members)
|
||||
{
|
||||
// Default alignment is 1 even if the it is empty.
|
||||
// Default alignment is 1 even if it is empty.
|
||||
AlignSize natural_alignment = 1;
|
||||
bool is_unaligned = false;
|
||||
AlignSize size = 0;
|
||||
AlignSize offset = 0;
|
||||
bool is_packed = decl->is_packed;
|
||||
VECEACH(members, i)
|
||||
unsigned member_count = vec_size(members);
|
||||
for (unsigned i = 0; i < member_count; i++)
|
||||
{
|
||||
Decl *member = decl->strukt.members[i];
|
||||
if (!decl_ok(member))
|
||||
@@ -218,6 +235,31 @@ static bool sema_analyse_struct_members(Context *context, Decl *decl, Decl **mem
|
||||
}
|
||||
continue;
|
||||
}
|
||||
Type *member_type = type_flatten_distinct(member->type);
|
||||
if (member_type->type_kind == TYPE_STRUCT && member_type->decl->has_variable_array)
|
||||
{
|
||||
if (i != member_count - 1)
|
||||
{
|
||||
SEMA_ERROR(member, "A struct member with a flexible array must be the last element.");
|
||||
return false;
|
||||
}
|
||||
decl->has_variable_array = true;
|
||||
}
|
||||
if (member_type->type_kind == TYPE_INFERRED_ARRAY)
|
||||
{
|
||||
if (i != member_count - 1)
|
||||
{
|
||||
SEMA_ERROR(member, "The flexible array member must be the last element.");
|
||||
return false;
|
||||
}
|
||||
if (i == 0)
|
||||
{
|
||||
SEMA_ERROR(member, "The flexible array member cannot be the only element.");
|
||||
return false;
|
||||
}
|
||||
member->type = type_get_flexible_array(member->type->array.base);
|
||||
decl->has_variable_array = true;
|
||||
}
|
||||
|
||||
if (!decl_ok(decl)) return false;
|
||||
|
||||
@@ -366,6 +408,12 @@ static bool sema_analyse_struct_union(Context *context, Decl *decl)
|
||||
|
||||
DEBUG_LOG("Beginning analysis of %s.", decl->name ? decl->name : "anon");
|
||||
bool success;
|
||||
Decl **members = decl->strukt.members;
|
||||
if (!vec_size(members))
|
||||
{
|
||||
SEMA_ERROR(decl, decl->decl_kind == DECL_UNION ? "Zero sized unions are not permitted." : "Zero sized structs are not permitted.");
|
||||
return false;
|
||||
}
|
||||
if (decl->name)
|
||||
{
|
||||
SCOPE_START
|
||||
@@ -663,7 +711,13 @@ static inline bool sema_analyse_typedef(Context *context, Decl *decl)
|
||||
return true;
|
||||
}
|
||||
if (!sema_resolve_type_info(context, decl->typedef_decl.type_info)) return false;
|
||||
decl->type->canonical = decl->typedef_decl.type_info->type->canonical;
|
||||
Type *type = decl->typedef_decl.type_info->type->canonical;
|
||||
if (type == type_anyerr || type == type_any)
|
||||
{
|
||||
SEMA_ERROR(decl->typedef_decl.type_info, "%s may not be aliased.", type_quoted_error_string(type));
|
||||
return false;
|
||||
}
|
||||
decl->type->canonical = type;
|
||||
// Do we need anything else?
|
||||
return true;
|
||||
}
|
||||
@@ -687,6 +741,7 @@ static inline bool sema_analyse_distinct(Context *context, Decl *decl)
|
||||
case TYPE_TYPEDEF:
|
||||
case TYPE_DISTINCT:
|
||||
case CT_TYPES:
|
||||
case TYPE_FLEXIBLE_ARRAY:
|
||||
UNREACHABLE
|
||||
return false;
|
||||
case TYPE_FAILABLE_ANY:
|
||||
|
||||
@@ -2299,6 +2299,7 @@ static bool expr_check_index_in_range(Context *context, Type *type, Expr *index_
|
||||
switch (type->type_kind)
|
||||
{
|
||||
case TYPE_POINTER:
|
||||
case TYPE_FLEXIBLE_ARRAY:
|
||||
assert(!from_end);
|
||||
return true;
|
||||
case TYPE_ARRAY:
|
||||
|
||||
@@ -78,7 +78,15 @@ static inline bool sema_resolve_array_type(Context *context, TypeInfo *type, boo
|
||||
return type_info_poison(type);
|
||||
}
|
||||
}
|
||||
|
||||
Type *distinct_base = type_flatten_distinct(type->array.base->type);
|
||||
if (distinct_base->type_kind == TYPE_STRUCT)
|
||||
{
|
||||
if (distinct_base->decl->has_variable_array)
|
||||
{
|
||||
SEMA_ERROR(type, "Arrays of structs with flexible array members is not allowed.");
|
||||
return type_info_poison(type);
|
||||
}
|
||||
}
|
||||
switch (type->kind)
|
||||
{
|
||||
case TYPE_INFO_SUBARRAY:
|
||||
@@ -105,6 +113,7 @@ static inline bool sema_resolve_array_type(Context *context, TypeInfo *type, boo
|
||||
UNREACHABLE
|
||||
}
|
||||
assert(!type->array.len || type->array.len->expr_kind == EXPR_CONST);
|
||||
if (type->array.base)
|
||||
type->resolve_status = RESOLVE_DONE;
|
||||
return true;
|
||||
}
|
||||
@@ -211,6 +220,7 @@ bool sema_resolve_type(Context *context, Type *type)
|
||||
case TYPE_ARRAY:
|
||||
case TYPE_SUBARRAY:
|
||||
case TYPE_INFERRED_ARRAY:
|
||||
case TYPE_FLEXIBLE_ARRAY:
|
||||
return sema_resolve_type(context, type->array.base);
|
||||
case TYPE_FAILABLE:
|
||||
return sema_resolve_type(context, type->failable);
|
||||
|
||||
@@ -51,9 +51,10 @@ static AlignSize max_alignment_vector;
|
||||
|
||||
#define PTR_OFFSET 0
|
||||
#define INFERRED_ARRAY_OFFSET 1
|
||||
#define SUB_ARRAY_OFFSET 2
|
||||
#define FAILABLE_OFFSET 3
|
||||
#define ARRAY_OFFSET 4
|
||||
#define FLEXIBLE_ARRAY_OFFSET 2
|
||||
#define SUB_ARRAY_OFFSET 3
|
||||
#define FAILABLE_OFFSET 4
|
||||
#define ARRAY_OFFSET 5
|
||||
|
||||
Type *type_cint(void)
|
||||
{
|
||||
@@ -149,6 +150,7 @@ const char *type_to_error_string(Type *type)
|
||||
asprintf(&buffer, "%s[%llu]", type_to_error_string(type->array.base), (unsigned long long)type->array.len);
|
||||
return buffer;
|
||||
case TYPE_INFERRED_ARRAY:
|
||||
case TYPE_FLEXIBLE_ARRAY:
|
||||
asprintf(&buffer, "%s[*]", type_to_error_string(type->array.base));
|
||||
return buffer;
|
||||
case TYPE_SUBARRAY:
|
||||
@@ -207,6 +209,8 @@ RETRY:
|
||||
}
|
||||
case CT_TYPES:
|
||||
UNREACHABLE;
|
||||
case TYPE_FLEXIBLE_ARRAY:
|
||||
return 0;
|
||||
case TYPE_FAILABLE:
|
||||
type = type->failable;
|
||||
goto RETRY;
|
||||
@@ -315,6 +319,7 @@ bool type_is_abi_aggregate(Type *type)
|
||||
case TYPE_TYPEINFO:
|
||||
case TYPE_INFERRED_ARRAY:
|
||||
case TYPE_UNTYPED_LIST:
|
||||
case TYPE_FLEXIBLE_ARRAY:
|
||||
UNREACHABLE
|
||||
}
|
||||
UNREACHABLE
|
||||
@@ -446,6 +451,7 @@ AlignSize type_abi_alignment(Type *type)
|
||||
return t.iptr.canonical->builtin.abi_alignment;
|
||||
case TYPE_ARRAY:
|
||||
case TYPE_INFERRED_ARRAY:
|
||||
case TYPE_FLEXIBLE_ARRAY:
|
||||
type = type->array.base;
|
||||
goto RETRY;
|
||||
case TYPE_SUBARRAY:
|
||||
@@ -565,6 +571,33 @@ static Type *type_generate_inferred_array(Type *arr_type, bool canonical)
|
||||
return arr;
|
||||
}
|
||||
|
||||
static Type *type_generate_flexible_array(Type *arr_type, bool canonical)
|
||||
{
|
||||
if (canonical) arr_type = arr_type->canonical;
|
||||
if (!arr_type->type_cache)
|
||||
{
|
||||
create_type_cache(arr_type);
|
||||
}
|
||||
|
||||
Type *arr = arr_type->type_cache[FLEXIBLE_ARRAY_OFFSET];
|
||||
if (arr == NULL)
|
||||
{
|
||||
arr = type_new(TYPE_FLEXIBLE_ARRAY, strformat("%s[*]", arr_type->name));
|
||||
arr->array.base = arr_type;
|
||||
arr->array.len = 0;
|
||||
arr_type->type_cache[FLEXIBLE_ARRAY_OFFSET] = arr;
|
||||
if (arr_type == arr_type->canonical)
|
||||
{
|
||||
arr->canonical = arr;
|
||||
}
|
||||
else
|
||||
{
|
||||
arr->canonical = type_generate_flexible_array(arr_type->canonical, true);
|
||||
}
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
|
||||
Type *type_get_ptr_recurse(Type *ptr_type)
|
||||
{
|
||||
@@ -599,6 +632,11 @@ Type *type_get_inferred_array(Type *arr_type)
|
||||
return type_generate_inferred_array(arr_type, false);
|
||||
}
|
||||
|
||||
Type *type_get_flexible_array(Type *arr_type)
|
||||
{
|
||||
return type_generate_flexible_array(arr_type, false);
|
||||
}
|
||||
|
||||
static inline bool array_structurally_equivalent_to_struct(Type *array, Type *type)
|
||||
{
|
||||
assert(array->type_kind == TYPE_ARRAY);
|
||||
@@ -716,6 +754,7 @@ Type *type_get_indexed_type(Type *type)
|
||||
case TYPE_ARRAY:
|
||||
case TYPE_SUBARRAY:
|
||||
case TYPE_INFERRED_ARRAY:
|
||||
case TYPE_FLEXIBLE_ARRAY:
|
||||
case TYPE_VECTOR:
|
||||
return type->array.base;
|
||||
case TYPE_DISTINCT:
|
||||
@@ -895,6 +934,9 @@ static void type_append_name_to_scratch(Type *type)
|
||||
case TYPE_SUBARRAY:
|
||||
type_append_name_to_scratch(type->pointer);
|
||||
scratch_buffer_append("[]");
|
||||
case TYPE_FLEXIBLE_ARRAY:
|
||||
type_append_name_to_scratch(type->pointer);
|
||||
scratch_buffer_append("[*]");
|
||||
case TYPE_VOID:
|
||||
case TYPE_BOOL:
|
||||
case TYPE_I8:
|
||||
@@ -1078,6 +1120,7 @@ bool type_is_scalar(Type *type)
|
||||
case TYPE_VECTOR:
|
||||
case TYPE_FAILABLE_ANY:
|
||||
case TYPE_ANY:
|
||||
case TYPE_FLEXIBLE_ARRAY:
|
||||
return false;
|
||||
case TYPE_BOOL:
|
||||
case ALL_INTS:
|
||||
@@ -1355,6 +1398,7 @@ Type *type_find_max_type(Type *type, Type *other)
|
||||
case TYPE_TYPEINFO:
|
||||
case TYPE_ANY:
|
||||
case TYPE_BITSTRUCT:
|
||||
case TYPE_FLEXIBLE_ARRAY:
|
||||
return NULL;
|
||||
case ALL_INTS:
|
||||
if (other->type_kind == TYPE_DISTINCT && type_underlying_is_numeric(other)) return other;
|
||||
|
||||
@@ -11,12 +11,6 @@ struct Bar
|
||||
{
|
||||
int y;
|
||||
}
|
||||
struct
|
||||
{}
|
||||
union
|
||||
{
|
||||
struct { }
|
||||
}
|
||||
}
|
||||
bitstruct : uint
|
||||
{
|
||||
@@ -68,20 +62,20 @@ entry:
|
||||
%8 = ashr i32 %7, 23
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str, i32 0, i32 0), i32 %4, i32 %8)
|
||||
%9 = bitcast %Foo* %f to i8*
|
||||
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %9, i8* align 4 bitcast (%Foo* @.__const.8 to i8*), i32 16, i1 false)
|
||||
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %9, i8* align 4 bitcast (%Foo* @.__const.5 to i8*), i32 16, i1 false)
|
||||
%10 = getelementptr inbounds %Foo, %Foo* %f, i32 0, i32 0
|
||||
%11 = getelementptr inbounds %anon.4, %anon.4* %10, i32 0, i32 0
|
||||
%12 = getelementptr inbounds %anon.5, %anon.5* %11, i32 0, i32 0
|
||||
%11 = getelementptr inbounds %anon.1, %anon.1* %10, i32 0, i32 0
|
||||
%12 = getelementptr inbounds %anon.2, %anon.2* %11, i32 0, i32 0
|
||||
%13 = load i32, i32* %12, align 4
|
||||
%14 = getelementptr inbounds %Foo, %Foo* %f, i32 0, i32 0
|
||||
%15 = getelementptr inbounds %anon.4, %anon.4* %14, i32 0, i32 1
|
||||
%16 = getelementptr inbounds %anon.6, %anon.6* %15, i32 0, i32 0
|
||||
%15 = getelementptr inbounds %anon.1, %anon.1* %14, i32 0, i32 1
|
||||
%16 = getelementptr inbounds %anon.3, %anon.3* %15, i32 0, i32 0
|
||||
%17 = load i32, i32* %16, align 4
|
||||
%18 = getelementptr inbounds %Foo, %Foo* %f, i32 0, i32 0
|
||||
%19 = getelementptr inbounds %anon.4, %anon.4* %18, i32 0, i32 2
|
||||
%19 = getelementptr inbounds %anon.1, %anon.1* %18, i32 0, i32 2
|
||||
%20 = load i32, i32* %19, align 4
|
||||
%21 = getelementptr inbounds %Foo, %Foo* %f, i32 0, i32 1
|
||||
%22 = load i32, i32* %21, align 4
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([13 x i8], [13 x i8]* @.str.9, i32 0, i32 0), i32 %13, i32 %17, i32 %20, i32 %22)
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([13 x i8], [13 x i8]* @.str.6, i32 0, i32 0), i32 %13, i32 %17, i32 %20, i32 %22)
|
||||
ret void
|
||||
}
|
||||
|
||||
7
test/test_suite/bitstruct/invalid_empty_struct_union.c3
Normal file
7
test/test_suite/bitstruct/invalid_empty_struct_union.c3
Normal file
@@ -0,0 +1,7 @@
|
||||
struct Foo // #error: Zero sized structs are not permitted.
|
||||
{
|
||||
}
|
||||
|
||||
union Bar // #error: Zero sized unions are not permitted.
|
||||
{
|
||||
}
|
||||
@@ -4,7 +4,9 @@ fn void test1()
|
||||
}
|
||||
|
||||
struct Foo
|
||||
{}
|
||||
{
|
||||
int x;
|
||||
}
|
||||
|
||||
fn void test2()
|
||||
{
|
||||
|
||||
@@ -3,7 +3,7 @@ module mymodule;
|
||||
|
||||
extern fn void printf(char *, ...);
|
||||
|
||||
struct Foo { }
|
||||
struct Foo { int y; }
|
||||
|
||||
int b;
|
||||
|
||||
|
||||
3
test/test_suite/define/forbidden_defines.c3
Normal file
3
test/test_suite/define/forbidden_defines.c3
Normal file
@@ -0,0 +1,3 @@
|
||||
define Abc = int[*]; // #error: Inferred array types can only be used in declarations with initializers.
|
||||
define Bcd = anyerr; // #error: 'anyerr' may not be aliased.
|
||||
define Efd = variant; // #error: 'variant' may not be aliased.
|
||||
@@ -1,5 +1,5 @@
|
||||
struct Foo
|
||||
{}
|
||||
{ int j; }
|
||||
|
||||
fn int main()
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
define Callback = fn int(char c);
|
||||
struct Person {}
|
||||
struct Company {}
|
||||
struct Person { int i; }
|
||||
struct Company { int j; }
|
||||
enum Status : int
|
||||
{
|
||||
IDLE,
|
||||
|
||||
@@ -10,6 +10,7 @@ struct An3
|
||||
|
||||
struct An2
|
||||
{
|
||||
int z;
|
||||
}
|
||||
|
||||
extern fn void printf(char *string);
|
||||
|
||||
@@ -10,6 +10,7 @@ struct An3
|
||||
|
||||
struct An2
|
||||
{
|
||||
int y;
|
||||
}
|
||||
|
||||
extern fn void printf(char* string);
|
||||
|
||||
31
test/test_suite/struct/flex_array_struct_err.c3
Normal file
31
test/test_suite/struct/flex_array_struct_err.c3
Normal file
@@ -0,0 +1,31 @@
|
||||
struct Foo
|
||||
{
|
||||
int x;
|
||||
int[*] y; // #error: flexible array member must be the last element
|
||||
int z;
|
||||
}
|
||||
|
||||
struct Bar
|
||||
{
|
||||
int[*] y; // #error: flexible array member cannot be the only element
|
||||
}
|
||||
|
||||
struct Baz
|
||||
{
|
||||
int y;
|
||||
int[*] z;
|
||||
}
|
||||
|
||||
struct BazContainerOk
|
||||
{
|
||||
int z;
|
||||
Baz c;
|
||||
}
|
||||
|
||||
struct BazContainer
|
||||
{
|
||||
Baz c; // #error: A struct member with a flexible array must be the last element.
|
||||
int y;
|
||||
}
|
||||
|
||||
Baz[5] ab; // #error: Arrays of structs with flexible array members is not allowed.
|
||||
35
test/test_suite/struct/struct_codegen_fam.c3t
Normal file
35
test/test_suite/struct/struct_codegen_fam.c3t
Normal file
@@ -0,0 +1,35 @@
|
||||
// #target: x64-darwin
|
||||
module foo;
|
||||
|
||||
struct Bar
|
||||
{
|
||||
struct
|
||||
{
|
||||
int y;
|
||||
}
|
||||
int ufe;
|
||||
int[*] z;
|
||||
}
|
||||
|
||||
|
||||
fn void test(Bar b)
|
||||
{
|
||||
b.z[1];
|
||||
}
|
||||
|
||||
/* #expect: foo.ll
|
||||
|
||||
%Bar = type { %anon, i32, [0 x i32] }
|
||||
%anon = type { i32 }
|
||||
|
||||
define void @foo.test(%Bar* byval(%Bar) align 8 %0) #0 {
|
||||
entry:
|
||||
%b = alloca %Bar, align 4
|
||||
%1 = bitcast %Bar* %b to i8*
|
||||
%2 = bitcast %Bar* %0 to i8*
|
||||
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %1, i8* align 8 %2, i32 8, i1 false)
|
||||
%3 = getelementptr inbounds %Bar, %Bar* %b, i32 0, i32 2
|
||||
%4 = getelementptr inbounds [0 x i32], [0 x i32]* %3, i64 0, i64 1
|
||||
%5 = load i32, i32* %4, align 4
|
||||
ret void
|
||||
}
|
||||
7
test/test_suite/struct/zero_member.c3
Normal file
7
test/test_suite/struct/zero_member.c3
Normal file
@@ -0,0 +1,7 @@
|
||||
define Foo = int[0];
|
||||
|
||||
struct Bar
|
||||
{
|
||||
Foo x; // #error: Zero length arrays are not valid members.
|
||||
int b;
|
||||
}
|
||||
5
test/test_suite/union/flexible_array_union.c3
Normal file
5
test/test_suite/union/flexible_array_union.c3
Normal file
@@ -0,0 +1,5 @@
|
||||
union Zee
|
||||
{
|
||||
int z;
|
||||
int[*] y; // #error: Flexible array members not allowed in unions.
|
||||
}
|
||||
@@ -1,7 +1,5 @@
|
||||
module test;
|
||||
|
||||
struct Empty {}
|
||||
union Foo {}
|
||||
union Qu
|
||||
{
|
||||
Qu *x;
|
||||
Reference in New Issue
Block a user