mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Refactored structs.
This commit is contained in:
@@ -92,6 +92,7 @@ enum Inf2 : byte
|
||||
|
||||
typedef Inf as BooInf;
|
||||
|
||||
|
||||
struct TestStruct
|
||||
{
|
||||
int a;
|
||||
@@ -117,6 +118,36 @@ union SimpleUnion
|
||||
double f;
|
||||
}
|
||||
|
||||
struct ExtraSimple
|
||||
{
|
||||
int a;
|
||||
int b;
|
||||
struct c
|
||||
{
|
||||
double e;
|
||||
double f0;
|
||||
double f1;
|
||||
double f;
|
||||
double j;
|
||||
}
|
||||
struct
|
||||
{
|
||||
int r;
|
||||
int s;
|
||||
}
|
||||
union
|
||||
{
|
||||
double o0;
|
||||
int o1;
|
||||
}
|
||||
int g;
|
||||
}
|
||||
func void testSimple()
|
||||
{
|
||||
ExtraSimple a = { c.j = 3.3 };
|
||||
a.c.j = 3.4;
|
||||
printf("a = %d, c.e = %f, c.f = %f, c.j = %f, g = %d, o0 = %f, r = %d, s = %d\n", a.a, a.c.e, a.c.f, a.c.j, a.g, a.o0, a.r, a.s);
|
||||
}
|
||||
func void testPointer()
|
||||
{
|
||||
int i = 0;
|
||||
@@ -291,7 +322,12 @@ func void testSimpleStruct(int x)
|
||||
SimpleStruct sinit = { b = 1, d = 3.0, z1 = 1 };
|
||||
sinit.a = 1;
|
||||
sinit.b = 2;
|
||||
printf("a = %d, b = %d (1), c = %f, d = %f (3.0), z1 = %d (1), z2 = %d\n", sinit.a, sinit.b, sinit.c, sinit.d, cast(sinit.z1, int), cast(sinit.z2, int));
|
||||
printf("Testing:\n");
|
||||
printf("a = %d, b = %d (2), c = %f, d = %f (3.0), z1 = %d (1), z2 = %d\n", sinit.a, sinit.b, sinit.c, sinit.d, cast(sinit.z1, int), cast(sinit.z2, int));
|
||||
if (sinit.a != 1) printf("ERROR a\n");
|
||||
if (sinit.b != 2) printf("ERROR b\n");
|
||||
if (sinit.d != 3.0) printf("ERROR d\n");
|
||||
if (sinit.z1 != 1) printf("ERROR z1\n");
|
||||
snoinit.b = 1;
|
||||
snoinit.a = 100;
|
||||
snoinit.d = 3.0;
|
||||
@@ -299,6 +335,9 @@ func void testSimpleStruct(int x)
|
||||
snoinit.z1 = 1;
|
||||
snoinit.z2 = 2;
|
||||
printf("b = %d (1), d = %f (3.0), z1 = %d (1)\n", snoinit.b, snoinit.d, snoinit.z1);
|
||||
if (snoinit.b != 1) printf("ERROR b\n");
|
||||
if (snoinit.d != 3.0) printf("ERROR d\n");
|
||||
if (snoinit.z1 != 1) printf("ERROR z1\n");
|
||||
}
|
||||
|
||||
struct AnonStruct
|
||||
@@ -338,10 +377,18 @@ func void testAnonStruct2()
|
||||
|
||||
func void testAnonStruct()
|
||||
{
|
||||
|
||||
AnonStruct s = { b2 = 3, b1 = 7, xx.b = 1 };
|
||||
AnonStruct foo;
|
||||
|
||||
printf("a = %d, b = %d (1), c = %d, b1 = %d (7), c1 = %d, b2 = %d (3), c2 = %d (3), x = %d\n", s.a, s.xx.b, s.xx.c, s.b1, s.c1, s.b2, s.c2, s.x);
|
||||
if (s.a != 0) printf("Error s.a\n");
|
||||
if (s.x != 0) printf("Error s.x\n");
|
||||
if (s.xx.b != 1) printf("Error s.xx.b = %d\n", s.xx.b);
|
||||
if (s.xx.c != 0) printf("Error s.xx.c\n");
|
||||
if (s.b1 != 7) printf("Error s.b1\n");
|
||||
if (s.c1 != 0) printf("Error s.c1\n");
|
||||
if (s.b2 != 3) printf("Error s.b2\n");
|
||||
if (s.c2 != 3) printf("Error s.c2\n");
|
||||
|
||||
s.xx.b = 100;
|
||||
s.xx.c = 99;
|
||||
@@ -349,22 +396,50 @@ func void testAnonStruct()
|
||||
s.b2 = 5;
|
||||
s.c2 = 7;
|
||||
|
||||
printf("a = %d, b = %d (100), c = %d (99), b1 = %d (3), c1 = %d, b2 = %d (7), c2 = %d (7), x = %d\n", s.a, s.xx.b, s.xx.c, s.b1, s.c1, s.b2, s.c2, s.x);
|
||||
if (s.a != 0) printf("Error s.a\n");
|
||||
if (s.x != 0) printf("Error s.x\n");
|
||||
if (s.xx.b != 100) printf("Error s.xx.b = %d\n", s.xx.b);
|
||||
if (s.xx.c != 99) printf("Error s.xx.c\n");
|
||||
if (s.b1 != 3) printf("Error s.b1\n");
|
||||
if (s.c1 != 0) printf("Error s.c1\n");
|
||||
if (s.b2 != 7) printf("Error s.b2\n");
|
||||
if (s.c2 != 7) printf("Error s.c2\n");
|
||||
|
||||
s = { xx = { c = 2 }};
|
||||
|
||||
printf("a = %d, b = %d, c = %d (2), b1 = %d, c1 = %d, b2 = %d, c2 = %d, x = %d\n", s.a, s.xx.b, s.xx.c, s.b1, s.c1, s.b2, s.c2, s.x);
|
||||
if (s.a != 0) printf("Error s.a\n");
|
||||
if (s.x != 0) printf("Error s.x\n");
|
||||
if (s.xx.b != 0) printf("Error s.xx.b = %d\n", s.xx.b);
|
||||
if (s.xx.c != 2) printf("Error s.xx.c\n");
|
||||
if (s.b1 != 0) printf("Error s.b1\n");
|
||||
if (s.c1 != 0) printf("Error s.c1\n");
|
||||
if (s.b2 != 0) printf("Error s.b2\n");
|
||||
if (s.c2 != 0) printf("Error s.c2\n");
|
||||
|
||||
s.xx.c = 3;
|
||||
s.x = 1212;
|
||||
s.a = 29183;
|
||||
s = AnonStruct { xx = { c = 2 }};
|
||||
|
||||
printf("a = %d, b = %d, c = %d (2), b1 = %d, c1 = %d, b2 = %d, c2 = %d, x = %d\n", s.a, s.xx.b, s.xx.c, s.b1, s.c1, s.b2, s.c2, s.x);
|
||||
if (s.a != 0) printf("Error s.a\n");
|
||||
if (s.x != 0) printf("Error s.x\n");
|
||||
if (s.xx.b != 0) printf("Error s.xx.b = %d\n", s.xx.b);
|
||||
if (s.xx.c != 2) printf("Error s.xx.c\n");
|
||||
if (s.b1 != 0) printf("Error s.b1\n");
|
||||
if (s.c1 != 0) printf("Error s.c1\n");
|
||||
if (s.b2 != 0) printf("Error s.b2\n");
|
||||
if (s.c2 != 0) printf("Error s.c2\n");
|
||||
|
||||
s = sendAnonStruct();
|
||||
|
||||
printf("Got it sent: a = %d, b = %d (1), c = %d, b1 = %d (7), c1 = %d, b2 = %d (3), c2 = %d (3), x = %d\n", s.a, s.xx.b, s.xx.c, s.b1, s.c1, s.b2, s.c2, s.x);
|
||||
if (s.a != 1) printf("Error s.a\n");
|
||||
if (s.x != 0) printf("Error s.x\n");
|
||||
if (s.xx.b != 0) printf("Error s.xx.b = %d\n", s.xx.b);
|
||||
if (s.xx.c != 2) printf("Error s.xx.c\n");
|
||||
if (s.b1 != 0) printf("Error s.b1\n");
|
||||
if (s.c1 != 0) printf("Error s.c1\n");
|
||||
if (s.b2 != 123) printf("Error s.b2\n");
|
||||
if (s.c2 != 123) printf("Error s.c2\n");
|
||||
|
||||
}
|
||||
func int boba(int y, int j)
|
||||
@@ -1005,7 +1080,7 @@ union TestUnionSize
|
||||
}
|
||||
func void testTypeValues()
|
||||
{
|
||||
TestUnionSize.a.sizeof;
|
||||
// TestUnionSize.a.sizeof;
|
||||
printf("Enum size: %d = 2\n", TestEnumSize.sizeof);
|
||||
printf("Enum size: %d = 4\n", TestEnumSizeDefault.sizeof);
|
||||
printf("Struct size: %d = 12\n", TestStructInt.sizeof);
|
||||
@@ -1016,7 +1091,7 @@ func void testTypeValues()
|
||||
|
||||
func int main(int x)
|
||||
{
|
||||
printf("Helo!\n");
|
||||
testSimple();
|
||||
testErrorBug();
|
||||
testErrors();
|
||||
testDefault(y = 99);
|
||||
|
||||
@@ -47,7 +47,7 @@ void decl_set_external_name(Decl *decl)
|
||||
return;
|
||||
}
|
||||
char buffer[1024];
|
||||
uint32_t len = sprintf(buffer, "%s::%s", decl->module->name->module, decl->name);
|
||||
uint32_t len = sprintf(buffer, "%s.%s", decl->module->name->module, decl->name);
|
||||
assert(len);
|
||||
TokenType type = TOKEN_INVALID_TOKEN;
|
||||
decl->external_name = symtab_add(buffer, len, fnv1a(buffer, len), &type);
|
||||
@@ -89,6 +89,7 @@ Decl *decl_new_with_type(Token name, DeclKind decl_type, Visibility visibility)
|
||||
case DECL_CT_ELSE:
|
||||
case DECL_CT_ELIF:
|
||||
case DECL_ATTRIBUTE:
|
||||
case DECL_MEMBER:
|
||||
UNREACHABLE
|
||||
}
|
||||
Type *type = type_new(kind, name.string);
|
||||
@@ -110,8 +111,6 @@ const char *decl_var_to_string(VarDeclKind kind)
|
||||
return "local";
|
||||
case VARDECL_PARAM:
|
||||
return "param";
|
||||
case VARDECL_MEMBER:
|
||||
return "member";
|
||||
}
|
||||
UNREACHABLE
|
||||
}
|
||||
@@ -137,7 +136,7 @@ Decl *struct_find_name(Decl *decl, const char* name)
|
||||
VECEACH(compare_members, i)
|
||||
{
|
||||
Decl *member = compare_members[i];
|
||||
if (!member->name)
|
||||
if (member->member_decl.anonymous)
|
||||
{
|
||||
Decl *found = struct_find_name(member, name);
|
||||
if (found) return found;
|
||||
@@ -337,7 +336,7 @@ void fprint_type_recursive(FILE *file, Type *type, int indent)
|
||||
return;
|
||||
case TYPE_MEMBER:
|
||||
DUMPF("(member %s", type->name);
|
||||
DUMPTYPE(type->decl->parent_struct->type);
|
||||
DUMPTYPE(type->decl->member_decl.parent->type);
|
||||
DUMPEND();
|
||||
case TYPE_TYPEDEF:
|
||||
DUMPF("(typedef %s", type->name);
|
||||
@@ -716,7 +715,7 @@ void fprint_decl_recursive(FILE *file, Decl *decl, int indent)
|
||||
switch (decl->decl_kind)
|
||||
{
|
||||
case DECL_VAR:
|
||||
DUMPF("(var-%s %s", decl_var_to_string(decl->var.kind), decl->name ?: "");
|
||||
DUMPF("(var-%s %s", decl_var_to_string(decl->var.kind), decl->name);
|
||||
DUMPTI(decl->var.type_info);
|
||||
switch (decl->var.kind)
|
||||
{
|
||||
@@ -726,8 +725,6 @@ void fprint_decl_recursive(FILE *file, Decl *decl, int indent)
|
||||
case VARDECL_PARAM:
|
||||
DUMPEXPR(decl->var.init_expr);
|
||||
break;
|
||||
case VARDECL_MEMBER:
|
||||
break;
|
||||
}
|
||||
DUMPEND();
|
||||
case DECL_MACRO:
|
||||
@@ -837,6 +834,10 @@ void fprint_decl_recursive(FILE *file, Decl *decl, int indent)
|
||||
DUMPF("(import %s", decl->name);
|
||||
// TODO
|
||||
DUMPEND();
|
||||
case DECL_MEMBER:
|
||||
DUMPF("(member %s", decl->name);
|
||||
DUMPTI(decl->member_decl.type_info);
|
||||
DUMPEND();
|
||||
case DECL_ATTRIBUTE:
|
||||
DUMPF("(attribute %s)", decl->name);
|
||||
if (decl->attr.domains & ATTR_FUNC)
|
||||
|
||||
@@ -248,7 +248,6 @@ typedef struct
|
||||
typedef struct
|
||||
{
|
||||
uint32_t abi_alignment;
|
||||
uint32_t id;
|
||||
uint64_t size;
|
||||
Decl **members;
|
||||
} StructDecl;
|
||||
@@ -259,11 +258,7 @@ typedef struct _VarDecl
|
||||
unsigned id : 16;
|
||||
VarDeclKind kind : 3;
|
||||
TypeInfo *type_info;
|
||||
union
|
||||
{
|
||||
Expr *init_expr;
|
||||
Decl *parent;
|
||||
};
|
||||
Expr *init_expr;
|
||||
void *backend_debug_ref;
|
||||
} VarDecl;
|
||||
|
||||
@@ -379,6 +374,14 @@ typedef struct
|
||||
Path *path; // For redefinition
|
||||
} GenericDecl;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned index : 32;
|
||||
bool anonymous : 1;
|
||||
Decl *parent;
|
||||
TypeInfo *type_info;
|
||||
Type *reference_type;
|
||||
} MemberDecl;
|
||||
|
||||
typedef struct _Decl
|
||||
{
|
||||
@@ -414,7 +417,6 @@ typedef struct _Decl
|
||||
{
|
||||
union
|
||||
{
|
||||
Decl* parent_struct;
|
||||
Decl** methods;
|
||||
};
|
||||
union
|
||||
@@ -438,6 +440,7 @@ typedef struct _Decl
|
||||
Decl** ct_else_decl;
|
||||
Expr *incr_array_decl;
|
||||
TypeInfo *throws;
|
||||
MemberDecl member_decl;
|
||||
};
|
||||
} Decl;
|
||||
|
||||
|
||||
@@ -131,6 +131,7 @@ void context_register_global_decl(Context *context, Decl *decl)
|
||||
case DECL_CT_ELSE:
|
||||
case DECL_CT_ELIF:
|
||||
case DECL_ATTRIBUTE:
|
||||
case DECL_MEMBER:
|
||||
UNREACHABLE
|
||||
break;
|
||||
case DECL_CT_IF:
|
||||
|
||||
@@ -184,6 +184,7 @@ typedef enum
|
||||
DECL_ENUM_CONSTANT,
|
||||
DECL_TYPEDEF,
|
||||
DECL_STRUCT,
|
||||
DECL_MEMBER,
|
||||
DECL_UNION,
|
||||
DECL_ENUM,
|
||||
DECL_ERROR,
|
||||
@@ -545,7 +546,6 @@ typedef enum
|
||||
VARDECL_GLOBAL = 1,
|
||||
VARDECL_LOCAL = 2,
|
||||
VARDECL_PARAM = 3,
|
||||
VARDECL_MEMBER = 4,
|
||||
} VarDeclKind;
|
||||
|
||||
typedef enum
|
||||
|
||||
@@ -343,6 +343,7 @@ static void gencontext_emit_decl(GenContext *context, Decl *decl)
|
||||
case DECL_CT_ELSE:
|
||||
case DECL_CT_ELIF:
|
||||
case DECL_ATTRIBUTE:
|
||||
case DECL_MEMBER:
|
||||
UNREACHABLE
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ static inline LLVMMetadataRef gencontext_create_debug_type_from_decl(GenContext
|
||||
case DECL_ERROR_CONSTANT:
|
||||
case DECL_ARRAY_VALUE:
|
||||
case DECL_IMPORT:
|
||||
case DECL_MEMBER:
|
||||
UNREACHABLE;
|
||||
case DECL_FUNC:
|
||||
{
|
||||
|
||||
@@ -123,30 +123,18 @@ static inline LLVMValueRef gencontext_emit_subscript_addr(GenContext *context, E
|
||||
|
||||
static LLVMValueRef gencontext_emit_member_addr(GenContext *context, LLVMValueRef value, Decl *parent, Decl *member)
|
||||
{
|
||||
unsigned index;
|
||||
Decl *current_parent;
|
||||
assert(member->resolve_status == RESOLVE_DONE);
|
||||
if (decl_is_struct_type(member))
|
||||
{
|
||||
index = member->strukt.id;
|
||||
current_parent = member->parent_struct;
|
||||
}
|
||||
else
|
||||
{
|
||||
index = member->var.id;
|
||||
current_parent = member->var.parent;
|
||||
}
|
||||
assert(current_parent);
|
||||
if (parent != current_parent)
|
||||
Decl *current_parent = member->member_decl.parent;
|
||||
if (current_parent->decl_kind == DECL_MEMBER && current_parent->member_decl.anonymous)
|
||||
{
|
||||
value = gencontext_emit_member_addr(context, value, parent, current_parent);
|
||||
}
|
||||
|
||||
if (current_parent->decl_kind == DECL_UNION)
|
||||
if (current_parent->type->canonical->type_kind == TYPE_UNION)
|
||||
{
|
||||
return LLVMBuildBitCast(context->builder, value, LLVMPointerType(llvm_type(member->type), 0), member->name ?: "anon");
|
||||
return LLVMBuildBitCast(context->builder, value, LLVMPointerType(llvm_type(member->type), 0), member->name);
|
||||
}
|
||||
return LLVMBuildStructGEP2(context->builder, llvm_type(current_parent->type), value, index, member->name ?: "anon");
|
||||
return LLVMBuildStructGEP2(context->builder, llvm_type(current_parent->type), value, member->member_decl.index, member->name);
|
||||
}
|
||||
|
||||
|
||||
@@ -384,11 +372,11 @@ static inline LLVMValueRef gencontext_emit_initializer_list_expr_addr(GenContext
|
||||
case DESIGNATED_IDENT:
|
||||
if (parent_type->canonical->type_kind == TYPE_UNION)
|
||||
{
|
||||
sub_ref = LLVMBuildBitCast(context->builder, sub_ref, LLVMPointerType(llvm_type(path->type), 0), "unionref");
|
||||
sub_ref = LLVMBuildBitCast(context->builder, sub_ref, LLVMPointerType(llvm_type(path->type), 0), path->type->name);
|
||||
}
|
||||
else
|
||||
{
|
||||
sub_ref = LLVMBuildStructGEP2(context->builder, llvm_type(parent_type), sub_ref, path->index, "structref");
|
||||
sub_ref = LLVMBuildStructGEP2(context->builder, llvm_type(parent_type), sub_ref, path->index, path->type->name);
|
||||
}
|
||||
break;
|
||||
case DESIGNATED_SUBSCRIPT:
|
||||
|
||||
@@ -300,6 +300,7 @@ void gencontext_emit_extern_decl(GenContext *context, Decl *decl)
|
||||
TODO
|
||||
case DECL_ERROR_CONSTANT:
|
||||
TODO
|
||||
case DECL_MEMBER:
|
||||
case DECL_ARRAY_VALUE:
|
||||
case DECL_IMPORT:
|
||||
case DECL_MACRO:
|
||||
|
||||
@@ -23,6 +23,7 @@ static inline LLVMTypeRef llvm_type_from_decl(LLVMContextRef context, Decl *decl
|
||||
case DECL_ERROR_CONSTANT:
|
||||
case DECL_ARRAY_VALUE:
|
||||
case DECL_IMPORT:
|
||||
case DECL_MEMBER:
|
||||
UNREACHABLE;
|
||||
case DECL_FUNC:
|
||||
{
|
||||
@@ -46,7 +47,7 @@ static inline LLVMTypeRef llvm_type_from_decl(LLVMContextRef context, Decl *decl
|
||||
{
|
||||
vec_add(types, llvm_get_type(context, decl->strukt.members[i]->type));
|
||||
}
|
||||
LLVMTypeRef type = LLVMStructCreateNamed(context, decl->external_name);
|
||||
LLVMTypeRef type = LLVMStructCreateNamed(context, decl->name);
|
||||
LLVMStructSetBody(type, types, vec_size(types), decl->is_packed);
|
||||
return type;
|
||||
}
|
||||
|
||||
@@ -955,6 +955,17 @@ static inline bool parse_opt_parameter_type_list(Context *context, Visibility pa
|
||||
|
||||
#pragma mark --- Parse types
|
||||
|
||||
void add_struct_member(Decl *parent, Decl *parent_struct, Decl *member, TypeInfo *type)
|
||||
{
|
||||
unsigned index = vec_size(parent_struct->strukt.members);
|
||||
vec_add(parent_struct->strukt.members, member);
|
||||
member->member_decl.index = index;
|
||||
member->member_decl.reference_type = type_new(TYPE_MEMBER, member->name);
|
||||
member->member_decl.reference_type->decl = member;
|
||||
member->member_decl.type_info = type;
|
||||
member->member_decl.parent = parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Expect pointer to after '{'
|
||||
*
|
||||
@@ -973,14 +984,16 @@ static inline bool parse_opt_parameter_type_list(Context *context, Visibility pa
|
||||
* | struct_or_union opt_attributes struct_body
|
||||
* ;
|
||||
*
|
||||
* @param parent the direct parent.
|
||||
* @param visible_parent the visible parent when checking duplicate symbols.
|
||||
* @param parent the parent if this is the body of member
|
||||
* @param struct_parent the struct this is the body of
|
||||
* @param visible_parent the visible struct parent for checking duplicates.
|
||||
*/
|
||||
bool parse_struct_body(Context *context, Decl *parent, Decl *visible_parent)
|
||||
bool parse_struct_body(Context *context, Decl *parent, Decl *parent_struct, Decl *visible_parent)
|
||||
{
|
||||
|
||||
CONSUME_OR(TOKEN_LBRACE, false);
|
||||
|
||||
assert(decl_is_struct_type(parent_struct));
|
||||
while (context->tok.type != TOKEN_RBRACE)
|
||||
{
|
||||
TokenType token_type = context->tok.type;
|
||||
@@ -988,17 +1001,19 @@ bool parse_struct_body(Context *context, Decl *parent, Decl *visible_parent)
|
||||
{
|
||||
DeclKind decl_kind = decl_from_token(token_type);
|
||||
Decl *member;
|
||||
Token name_replacement = context->tok;
|
||||
name_replacement.string = "anon";
|
||||
Decl *strukt_type = decl_new_with_type(name_replacement, decl_kind, visible_parent->visibility);
|
||||
if (context->next_tok.type != TOKEN_IDENT)
|
||||
{
|
||||
Token name_replacement = context->tok;
|
||||
name_replacement.string = NULL;
|
||||
member = decl_new_with_type(name_replacement, decl_kind, parent->visibility);
|
||||
member = decl_new(DECL_MEMBER, name_replacement, visible_parent->visibility);
|
||||
member->member_decl.anonymous = true;
|
||||
advance(context);
|
||||
}
|
||||
else
|
||||
{
|
||||
advance(context);
|
||||
member = decl_new_with_type(context->tok, decl_kind, parent->visibility);
|
||||
member = decl_new(DECL_MEMBER, context->tok, visible_parent->visibility);
|
||||
Decl *other = struct_find_name(visible_parent, context->tok.string);
|
||||
if (other)
|
||||
{
|
||||
@@ -1007,26 +1022,25 @@ bool parse_struct_body(Context *context, Decl *parent, Decl *visible_parent)
|
||||
decl_poison(visible_parent);
|
||||
decl_poison(other);
|
||||
decl_poison(member);
|
||||
return false;
|
||||
}
|
||||
advance_and_verify(context, TOKEN_IDENT);
|
||||
}
|
||||
if (!parse_attributes(context, member)) return false;
|
||||
member->parent_struct = parent;
|
||||
member->strukt.id = vec_size(parent->strukt.members);
|
||||
parent->strukt.members = VECADD(parent->strukt.members, member);
|
||||
if (!parse_struct_body(context, member, context->tok.type == TOKEN_IDENT ? member : visible_parent))
|
||||
if (!parse_attributes(context, strukt_type)) return false;
|
||||
if (!parse_struct_body(context, member, strukt_type, context->tok.type == TOKEN_IDENT ? strukt_type : visible_parent))
|
||||
{
|
||||
decl_poison(visible_parent);
|
||||
return false;
|
||||
}
|
||||
VECADD(context->types, strukt_type);
|
||||
add_struct_member(parent, parent_struct, member, type_info_new_base(strukt_type->type, strukt_type->span));
|
||||
continue;
|
||||
}
|
||||
TypeInfo *type = TRY_TYPE_OR(parse_type(context), false);
|
||||
|
||||
while (1)
|
||||
{
|
||||
EXPECT_OR(TOKEN_IDENT, false);
|
||||
Decl *member = decl_new_var(context->tok, type, VARDECL_MEMBER, parent->visibility);
|
||||
Decl *member = decl_new(DECL_MEMBER, context->tok, visible_parent->visibility);
|
||||
Decl *other = struct_find_name(visible_parent, member->name);
|
||||
if (other)
|
||||
{
|
||||
@@ -1036,10 +1050,7 @@ bool parse_struct_body(Context *context, Decl *parent, Decl *visible_parent)
|
||||
decl_poison(other);
|
||||
decl_poison(member);
|
||||
}
|
||||
unsigned index = vec_size(parent->strukt.members);
|
||||
parent->strukt.members = VECADD(parent->strukt.members, member);
|
||||
member->var.id = index;
|
||||
member->var.parent = parent;
|
||||
add_struct_member(parent, parent_struct, member, type);
|
||||
advance(context);
|
||||
if (context->tok.type != TOKEN_COMMA) break;
|
||||
}
|
||||
@@ -1074,7 +1085,7 @@ static inline Decl *parse_struct_declaration(Context *context, Visibility visibi
|
||||
return poisoned_decl;
|
||||
}
|
||||
|
||||
if (!parse_struct_body(context, decl, decl))
|
||||
if (!parse_struct_body(context, decl, decl, decl))
|
||||
{
|
||||
return poisoned_decl;
|
||||
}
|
||||
|
||||
@@ -281,6 +281,7 @@ bool fpfp(Expr* left, Type *from, Type *canonical, Type *type, CastType cast_typ
|
||||
*/
|
||||
bool fpxi(Expr *left, Type *canonical, Type *type, CastType cast_type)
|
||||
{
|
||||
if (cast_type == CAST_TYPE_OPTIONAL_IMPLICIT) return true;
|
||||
if (cast_type != CAST_TYPE_EXPLICIT) EXIT_T_MISMATCH();
|
||||
RETURN_NON_CONST_CAST(CAST_FPUI);
|
||||
|
||||
|
||||
@@ -90,48 +90,9 @@ static inline bool sema_analyse_struct_member(Context *context, Decl *decl)
|
||||
{
|
||||
assert(decl->resolve_status == RESOLVE_NOT_DONE);
|
||||
decl->resolve_status = RESOLVE_RUNNING;
|
||||
if (decl->decl_kind == DECL_STRUCT || decl->decl_kind == DECL_UNION)
|
||||
{
|
||||
DEBUG_LOG("Beginning analysis of inner struct/union");
|
||||
VECEACH(decl->strukt.members, i)
|
||||
{
|
||||
Decl *member = decl->strukt.members[i];
|
||||
if (!decl_ok(member))
|
||||
{
|
||||
decl_poison(decl);
|
||||
continue;
|
||||
}
|
||||
if (!sema_analyse_struct_member(context, decl->strukt.members[i]))
|
||||
{
|
||||
if (decl_ok(decl))
|
||||
{
|
||||
decl_poison(decl);
|
||||
continue;
|
||||
}
|
||||
decl_poison(decl);
|
||||
}
|
||||
}
|
||||
if (decl->decl_kind == DECL_UNION)
|
||||
{
|
||||
sema_set_union_size(decl);
|
||||
}
|
||||
else
|
||||
{
|
||||
sema_set_struct_size(decl);
|
||||
}
|
||||
DEBUG_LOG("Analysis complete.");
|
||||
decl->resolve_status = RESOLVE_DONE;
|
||||
return decl_ok(decl);
|
||||
}
|
||||
assert(decl->decl_kind == DECL_VAR);
|
||||
assert(decl->var.kind == VARDECL_MEMBER);
|
||||
if (!sema_resolve_type_info(context, decl->var.type_info))
|
||||
{
|
||||
decl_poison(decl);
|
||||
return false;
|
||||
}
|
||||
decl->type = decl->var.type_info->type;
|
||||
assert(decl->var.type_info->type);
|
||||
assert(decl->decl_kind == DECL_MEMBER);
|
||||
if (!sema_resolve_type_info(context, decl->member_decl.type_info)) return decl_poison(decl);
|
||||
decl->type = decl->member_decl.type_info->type;
|
||||
decl->resolve_status = RESOLVE_DONE;
|
||||
return true;
|
||||
}
|
||||
@@ -767,12 +728,12 @@ bool sema_analyse_decl(Context *context, Decl *decl)
|
||||
case DECL_ARRAY_VALUE:
|
||||
case DECL_CT_ELSE:
|
||||
case DECL_CT_ELIF:
|
||||
case DECL_MEMBER:
|
||||
UNREACHABLE
|
||||
case DECL_CT_IF:
|
||||
// Handled elsewhere
|
||||
UNREACHABLE
|
||||
}
|
||||
decl->resolve_status = RESOLVE_DONE;
|
||||
DEBUG_LOG("<<< Analysis of %s successful.", decl->name);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -672,8 +672,7 @@ static Decl *strukt_recursive_search_member(Decl *strukt, const char *name)
|
||||
VECEACH(strukt->strukt.members, i)
|
||||
{
|
||||
Decl *member = strukt->strukt.members[i];
|
||||
if (member->name == name) return member;
|
||||
if (!member->name && type_is_structlike(member->type->canonical))
|
||||
if (member->member_decl.anonymous)
|
||||
{
|
||||
Decl *result = strukt_recursive_search_member(member->type->canonical->decl, name);
|
||||
if (result)
|
||||
@@ -681,6 +680,10 @@ static Decl *strukt_recursive_search_member(Decl *strukt, const char *name)
|
||||
return result;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (member->name == name) return member;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -852,17 +855,7 @@ static DesignatedPath *sema_analyse_init_identifier_string(Context *context, Des
|
||||
VECEACH(members, i)
|
||||
{
|
||||
Decl *member = members[i];
|
||||
if (member->name == string)
|
||||
{
|
||||
DesignatedPath *sub_path = CALLOCS(DesignatedPath);
|
||||
sub_path->type = member->type;
|
||||
sub_path->kind = DESIGNATED_IDENT;
|
||||
sub_path->index = i;
|
||||
parent_path->sub_path = sub_path;
|
||||
*has_found_match = true;
|
||||
return sub_path;
|
||||
}
|
||||
if (!member->name)
|
||||
if (member->member_decl.anonymous)
|
||||
{
|
||||
DesignatedPath temp_path;
|
||||
temp_path.type = member->type;
|
||||
@@ -876,6 +869,16 @@ static DesignatedPath *sema_analyse_init_identifier_string(Context *context, Des
|
||||
*has_found_match = true;
|
||||
return found;
|
||||
}
|
||||
if (member->name == string)
|
||||
{
|
||||
DesignatedPath *sub_path = CALLOCS(DesignatedPath);
|
||||
sub_path->type = member->type;
|
||||
sub_path->kind = DESIGNATED_IDENT;
|
||||
sub_path->index = i;
|
||||
parent_path->sub_path = sub_path;
|
||||
*has_found_match = true;
|
||||
return sub_path;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -136,6 +136,7 @@ static bool sema_resolve_type_identifier(Context *context, TypeInfo *type_info)
|
||||
case DECL_CT_IF:
|
||||
case DECL_CT_ELIF:
|
||||
case DECL_ATTRIBUTE:
|
||||
case DECL_MEMBER:
|
||||
UNREACHABLE
|
||||
}
|
||||
UNREACHABLE
|
||||
|
||||
@@ -176,6 +176,7 @@ static void type_append_signature_name_user_defined(Decl *decl, char *dst, size_
|
||||
case DECL_CT_ELSE:
|
||||
case DECL_CT_ELIF:
|
||||
case DECL_ATTRIBUTE:
|
||||
case DECL_MEMBER:
|
||||
UNREACHABLE
|
||||
case DECL_STRUCT:
|
||||
case DECL_UNION:
|
||||
@@ -230,6 +231,7 @@ size_t type_size(Type *canonical)
|
||||
return alignment_error_code;
|
||||
case TYPE_STRUCT:
|
||||
case TYPE_UNION:
|
||||
assert(canonical->decl->resolve_status == RESOLVE_DONE);
|
||||
return canonical->decl->strukt.size;
|
||||
case TYPE_VOID:
|
||||
return 1;
|
||||
|
||||
Reference in New Issue
Block a user