mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Changed how structs/unions are parsed so that recovery becomes more robust. Allow for more complex error data. Fixed recursive structs/unions. Corrected prefix precedence rules. Begin work on checking initializer constant-ness. Fixed error on failed arithmetic promotion. Added checks on constant overflow of sub/add/mult. Allow "current_module_name::x" to refer to globals. Added many tests.
This commit is contained in:
@@ -28,8 +28,14 @@ Decl *decl_new(DeclKind decl_kind, TokenId name, Visibility visibility)
|
||||
decl->decl_kind = decl_kind;
|
||||
decl->name_token = name;
|
||||
decl->span = source_span_from_token_id(name);
|
||||
decl->name = name.index ? TOKSTR(name) : "anon";
|
||||
decl->member_decl.anonymous = name.index == 0;
|
||||
if (name.index)
|
||||
{
|
||||
decl->name = TOKSTR(name);
|
||||
}
|
||||
else
|
||||
{
|
||||
decl->name = NULL;
|
||||
}
|
||||
decl->visibility = visibility;
|
||||
return decl;
|
||||
}
|
||||
@@ -44,11 +50,12 @@ void decl_set_external_name(Decl *decl)
|
||||
{
|
||||
if (decl->visibility == VISIBLE_EXTERN)
|
||||
{
|
||||
assert(decl->name);
|
||||
decl->external_name = decl->name;
|
||||
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 ? decl->name : "anon");
|
||||
assert(len);
|
||||
TokenType type = TOKEN_INVALID_TOKEN;
|
||||
decl->external_name = symtab_add(buffer, len, fnv1a(buffer, len), &type);
|
||||
@@ -89,11 +96,10 @@ Decl *decl_new_with_type(TokenId name, DeclKind decl_type, Visibility visibility
|
||||
case DECL_CT_ELSE:
|
||||
case DECL_CT_ELIF:
|
||||
case DECL_ATTRIBUTE:
|
||||
case DECL_MEMBER:
|
||||
case DECL_LABEL:
|
||||
UNREACHABLE
|
||||
}
|
||||
Type *type = type_new(kind, TOKSTR(name));
|
||||
Type *type = type_new(kind, !name.index ? "anon" : TOKSTR(name));
|
||||
type->canonical = type;
|
||||
type->decl = decl;
|
||||
decl->type = type;
|
||||
@@ -110,6 +116,8 @@ const char *decl_var_to_string(VarDeclKind kind)
|
||||
return "global";
|
||||
case VARDECL_LOCAL:
|
||||
return "local";
|
||||
case VARDECL_MEMBER:
|
||||
return "member";
|
||||
case VARDECL_PARAM:
|
||||
return "param";
|
||||
case VARDECL_ALIAS:
|
||||
@@ -133,26 +141,6 @@ Decl *decl_new_var(TokenId name, TypeInfo *type, VarDeclKind kind, Visibility vi
|
||||
return decl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively find a node in a declaration.
|
||||
* @return NULL if it wasn't found, otherwise the member.
|
||||
*/
|
||||
Decl *struct_find_name(Decl *decl, const char* name)
|
||||
{
|
||||
Decl** compare_members = decl->strukt.members;
|
||||
VECEACH(compare_members, i)
|
||||
{
|
||||
Decl *member = compare_members[i];
|
||||
if (member->member_decl.anonymous)
|
||||
{
|
||||
assert(member->decl_kind == DECL_MEMBER);
|
||||
Decl *found = struct_find_name(member->member_decl.type_info->type->decl, name);
|
||||
if (found) return found;
|
||||
}
|
||||
else if (member->name == name) return member;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Expr *expr_new(ExprKind kind, SourceSpan start)
|
||||
{
|
||||
@@ -342,10 +330,6 @@ void fprint_type_recursive(Context *context, FILE *file, Type *type, int indent)
|
||||
case TYPE_ERRTYPE:
|
||||
DUMPF("(errtype %s)", type->name);
|
||||
return;
|
||||
case TYPE_MEMBER:
|
||||
DUMPF("(member %s", type->name);
|
||||
DUMPTYPE(type->decl->member_decl.parent->type);
|
||||
DUMPEND();
|
||||
case TYPE_TYPEDEF:
|
||||
DUMPF("(typedef %s", type->name);
|
||||
DUMPTYPE(type->canonical);
|
||||
@@ -737,7 +721,7 @@ void fprint_decl_recursive(Context *context, 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 ? decl->name : "anon");
|
||||
DUMPTI(decl->var.type_info);
|
||||
switch (decl->var.kind)
|
||||
{
|
||||
@@ -745,6 +729,7 @@ void fprint_decl_recursive(Context *context, FILE *file, Decl *decl, int indent)
|
||||
case VARDECL_GLOBAL:
|
||||
case VARDECL_LOCAL:
|
||||
case VARDECL_PARAM:
|
||||
case VARDECL_MEMBER:
|
||||
case VARDECL_LOCAL_CT:
|
||||
DUMPEXPR(decl->var.init_expr);
|
||||
break;
|
||||
@@ -783,11 +768,11 @@ void fprint_decl_recursive(Context *context, FILE *file, Decl *decl, int indent)
|
||||
if (decl->func.body) DUMPAST(decl->func.body);
|
||||
DUMPEND();
|
||||
case DECL_STRUCT:
|
||||
DUMPF("(struct %s", decl->name);
|
||||
DUMPF("(struct %s", decl->name ? decl->name : "anon");
|
||||
DUMPDECLS(decl->strukt.members);
|
||||
DUMPEND();
|
||||
case DECL_UNION:
|
||||
DUMPF("(union %s", decl->name);
|
||||
DUMPF("(union %s", decl->name ? decl->name : "anon");
|
||||
DUMPDECLS(decl->strukt.members);
|
||||
DUMPEND();
|
||||
case DECL_ENUM:
|
||||
@@ -863,10 +848,6 @@ void fprint_decl_recursive(Context *context, 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)
|
||||
|
||||
@@ -26,6 +26,7 @@ void bigint_read_twos_complement(BigInt *dest, const uint8_t *buf, size_t bit_co
|
||||
void bigint_add(BigInt *dest, const BigInt *op1, const BigInt *op2);
|
||||
void bigint_add_wrap(BigInt *dest, const BigInt *op1, const BigInt *op2, size_t bit_count, bool is_signed);
|
||||
void bigint_sub(BigInt *dest, const BigInt *op1, const BigInt *op2);
|
||||
void bigint_sub_wrap(BigInt *dest, const BigInt *op1, const BigInt *op2, size_t bit_count, bool is_signed);
|
||||
void bigint_mul(BigInt *dest, const BigInt *op1, const BigInt *op2);
|
||||
void bigint_mul_wrap(BigInt *dest, const BigInt *op1, const BigInt *op2, size_t bit_count, bool is_signed);
|
||||
void bigint_rem(BigInt *dest, const BigInt *op1, const BigInt *op2);
|
||||
|
||||
@@ -201,7 +201,6 @@ void compile_files(BuildTarget *target)
|
||||
compiler_compile(target);
|
||||
break;
|
||||
}
|
||||
TODO
|
||||
}
|
||||
|
||||
|
||||
@@ -250,6 +249,7 @@ Module *compiler_find_or_create_module(Path *module_name)
|
||||
|
||||
void compiler_register_public_symbol(Decl *decl)
|
||||
{
|
||||
assert(decl->name);
|
||||
Decl *prev = stable_get(&compiler.global_symbols, decl->name);
|
||||
// If the previous symbol was already declared globally, remove it.
|
||||
stable_set(&compiler.global_symbols, decl->name, prev ? poisoned_decl : decl);
|
||||
|
||||
@@ -302,11 +302,6 @@ typedef struct
|
||||
uint64_t ordinal;
|
||||
} EnumConstantDecl;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Decl *parent;
|
||||
uint32_t value;
|
||||
} ErrorConstantDecl;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@@ -399,14 +394,6 @@ typedef struct
|
||||
AstId parent;
|
||||
} LabelDecl;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned index : 32;
|
||||
bool anonymous : 1;
|
||||
Decl *parent;
|
||||
TypeInfo *type_info;
|
||||
Type *reference_type;
|
||||
} MemberDecl;
|
||||
|
||||
typedef struct _Decl
|
||||
{
|
||||
@@ -450,7 +437,6 @@ typedef struct _Decl
|
||||
EnumDecl enums;
|
||||
};
|
||||
};
|
||||
ErrorConstantDecl error_constant;
|
||||
ImportDecl import;
|
||||
VarDecl var;
|
||||
LabelDecl label;
|
||||
@@ -464,7 +450,6 @@ typedef struct _Decl
|
||||
CtIfDecl ct_elif_decl;
|
||||
Decl** ct_else_decl;
|
||||
Expr *incr_array_decl;
|
||||
MemberDecl member_decl;
|
||||
};
|
||||
} Decl;
|
||||
|
||||
@@ -1062,6 +1047,7 @@ typedef struct _Context
|
||||
STable scratch_table;
|
||||
Lexer lexer;
|
||||
Token tok;
|
||||
TokenId prev_tok;
|
||||
Token next_tok;
|
||||
struct
|
||||
{
|
||||
@@ -1142,7 +1128,7 @@ static inline Ast *new_ast(AstKind kind, SourceSpan range)
|
||||
|
||||
static inline Ast *extend_ast_with_prev_token(Context *context, Ast *ast)
|
||||
{
|
||||
ast->span.end_loc.index = context->tok.id.index - 1;
|
||||
ast->span.end_loc = context->prev_tok;
|
||||
return ast;
|
||||
}
|
||||
|
||||
@@ -1332,19 +1318,20 @@ void sema_analysis_pass_conditional_compilation(Context *context);
|
||||
void sema_analysis_pass_decls(Context *context);
|
||||
void sema_analysis_pass_functions(Context *context);
|
||||
|
||||
bool sema_add_member(Context *context, Decl *decl);
|
||||
bool sema_add_local(Context *context, Decl *decl);
|
||||
bool sema_unwrap_var(Context *context, Decl *decl);
|
||||
bool sema_rewrap_var(Context *context, Decl *decl);
|
||||
|
||||
bool sema_analyse_statement(Context *context, Ast *statement);
|
||||
Decl *sema_resolve_symbol_in_current_dynamic_scope(Context *context, const char *symbol);
|
||||
Decl *sema_resolve_symbol(Context *context, const char *symbol, Path *path, Decl **ambiguous_other_decl, Decl **private_decl);
|
||||
bool sema_resolve_type_info(Context *context, TypeInfo *type_info);
|
||||
bool sema_resolve_type_shallow(Context *context, TypeInfo *type_info);
|
||||
|
||||
void sema_error_at_prev_end(Token token, const char *message, ...);
|
||||
|
||||
void sema_error_range2(SourceLocation *location, const char *message, ...);
|
||||
void sema_error_range3(SourceSpan location, const char *message, ...);
|
||||
void sema_error_range3(SourceSpan span, const char *message, ...);
|
||||
|
||||
void sema_verror_range(SourceLocation *location, const char *message, va_list args);
|
||||
void sema_error(Context *context, const char *message, ...);
|
||||
@@ -1361,7 +1348,7 @@ static inline SourceSpan source_span_from_token_id(TokenId id)
|
||||
}
|
||||
|
||||
|
||||
#define RANGE_EXTEND_PREV(x) ((x)->span.end_loc.index = context->tok.id.index - 1)
|
||||
#define RANGE_EXTEND_PREV(x) ((x)->span.end_loc = context->prev_tok)
|
||||
|
||||
void stable_init(STable *table, uint32_t initial_size);
|
||||
void *stable_set(STable *table, const char *key, void *value);
|
||||
@@ -1390,6 +1377,7 @@ Type *type_get_vararray(Type *arr_type);
|
||||
Type *type_get_meta(Type *meta_type);
|
||||
Type *type_get_indexed_type(Type *type);
|
||||
Type *type_get_array(Type *arr_type, uint64_t len);
|
||||
bool type_is_user_defined(Type *type);
|
||||
Type *type_signed_int_by_bitsize(unsigned bytesize);
|
||||
Type *type_unsigned_int_by_bitsize(unsigned bytesize);
|
||||
bool type_is_subtype(Type *type, Type *possible_subtype);
|
||||
@@ -1423,6 +1411,7 @@ static inline bool type_is_structlike(Type *type)
|
||||
{
|
||||
case TYPE_UNION:
|
||||
case TYPE_STRUCT:
|
||||
case TYPE_ERRTYPE:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
@@ -1515,6 +1504,7 @@ static inline Type *type_new(TypeKind kind, const char *name)
|
||||
Type *type = malloc_arena(sizeof(Type));
|
||||
memset(type, 0, sizeof(Type));
|
||||
type->type_kind = kind;
|
||||
assert(name);
|
||||
type->name = name;
|
||||
compiler_add_type(type);
|
||||
return type;
|
||||
@@ -1548,9 +1538,6 @@ BinaryOp binaryop_assign_base_op(BinaryOp assign_binary_op);
|
||||
TokenType binaryop_to_token(BinaryOp type);
|
||||
|
||||
|
||||
Decl *struct_find_name(Decl *decl, const char* name);
|
||||
|
||||
|
||||
static inline const char* struct_union_name_from_token(TokenType type)
|
||||
{
|
||||
return type == TOKEN_STRUCT ? "struct" : "union";
|
||||
|
||||
@@ -85,6 +85,7 @@ void context_register_external_symbol(Context *context, Decl *decl)
|
||||
|
||||
void context_register_global_decl(Context *context, Decl *decl)
|
||||
{
|
||||
assert(decl->name);
|
||||
decl->module = context->module;
|
||||
switch (decl->decl_kind)
|
||||
{
|
||||
@@ -126,7 +127,6 @@ void context_register_global_decl(Context *context, Decl *decl)
|
||||
case DECL_CT_ELSE:
|
||||
case DECL_CT_ELIF:
|
||||
case DECL_ATTRIBUTE:
|
||||
case DECL_MEMBER:
|
||||
case DECL_LABEL:
|
||||
UNREACHABLE
|
||||
break;
|
||||
|
||||
@@ -131,18 +131,25 @@ void sema_verror_range(SourceLocation *location, const char *message, va_list ar
|
||||
diagnostics.errors++;
|
||||
}
|
||||
|
||||
void sema_error_range2(SourceLocation *location, const char *message, ...)
|
||||
|
||||
void sema_prev_at_range3(SourceSpan span, const char *message, ...)
|
||||
{
|
||||
va_list list;
|
||||
va_start(list, message);
|
||||
sema_verror_range(location, message, list);
|
||||
va_end(list);
|
||||
SourceLocation *start = TOKLOC(span.loc);
|
||||
SourceLocation *end = TOKLOC(span.end_loc);
|
||||
va_list args;
|
||||
va_start(args, message);
|
||||
char buffer[256];
|
||||
vsnprintf(buffer, 256, message, args);
|
||||
SourceLocation loc = *start;
|
||||
loc.length = end->start - start->start + end->length;
|
||||
print_error2(&loc, buffer, PRINT_TYPE_PREV);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void sema_error_range3(SourceSpan location, const char *message, ...)
|
||||
void sema_error_range3(SourceSpan span, const char *message, ...)
|
||||
{
|
||||
SourceLocation *start = TOKLOC(location.loc);
|
||||
SourceLocation *end = TOKLOC(location.end_loc);
|
||||
SourceLocation *start = TOKLOC(span.loc);
|
||||
SourceLocation *end = TOKLOC(span.end_loc);
|
||||
|
||||
SourceLocation loc = *start;
|
||||
loc.length = end->start - start->start + end->length;
|
||||
@@ -191,19 +198,6 @@ void sema_error(Context *context, const char *message, ...)
|
||||
va_end(list);
|
||||
}
|
||||
|
||||
void sema_prev_at_range3(SourceSpan span, const char *message, ...)
|
||||
{
|
||||
SourceLocation *start = TOKLOC(span.loc);
|
||||
SourceLocation *end = TOKLOC(span.end_loc);
|
||||
va_list args;
|
||||
va_start(args, message);
|
||||
char buffer[256];
|
||||
vsnprintf(buffer, 256, message, args);
|
||||
SourceLocation loc = *start;
|
||||
loc.length = end->start - start->start + end->length;
|
||||
print_error2(&loc, buffer, PRINT_TYPE_PREV);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
||||
@@ -136,7 +136,6 @@ typedef enum
|
||||
DECL_ENUM_CONSTANT,
|
||||
DECL_TYPEDEF,
|
||||
DECL_STRUCT,
|
||||
DECL_MEMBER,
|
||||
DECL_UNION,
|
||||
DECL_ENUM,
|
||||
DECL_ERR,
|
||||
@@ -468,7 +467,6 @@ typedef enum
|
||||
TYPE_VARARRAY,
|
||||
TYPE_SUBARRAY,
|
||||
TYPE_TYPEID,
|
||||
TYPE_MEMBER,
|
||||
TYPE_LAST = TYPE_TYPEID
|
||||
} TypeKind;
|
||||
|
||||
@@ -506,9 +504,10 @@ typedef enum
|
||||
VARDECL_GLOBAL = 1,
|
||||
VARDECL_LOCAL = 2,
|
||||
VARDECL_PARAM = 3,
|
||||
VARDECL_LOCAL_CT = 4,
|
||||
VARDECL_LOCAL_CT_TYPE = 5,
|
||||
VARDECL_ALIAS = 6,
|
||||
VARDECL_MEMBER = 4,
|
||||
VARDECL_LOCAL_CT = 5,
|
||||
VARDECL_LOCAL_CT_TYPE = 6,
|
||||
VARDECL_ALIAS = 7,
|
||||
} VarDeclKind;
|
||||
|
||||
typedef enum
|
||||
|
||||
@@ -240,7 +240,7 @@ void llvm_codegen_setup()
|
||||
void gencontext_emit_introspection_type(GenContext *context, Decl *decl)
|
||||
{
|
||||
llvm_type(decl->type);
|
||||
LLVMValueRef global_name = LLVMAddGlobal(context->module, llvm_type(type_byte), decl->name);
|
||||
LLVMValueRef global_name = LLVMAddGlobal(context->module, llvm_type(type_byte), decl->name ? decl->name : "anon");
|
||||
LLVMSetGlobalConstant(global_name, 1);
|
||||
LLVMSetInitializer(global_name, LLVMConstInt(llvm_type(type_byte), 1, false));
|
||||
decl->type->backend_typeid = LLVMBuildPtrToInt(context->builder, global_name, llvm_type(type_typeid), "");
|
||||
@@ -306,7 +306,6 @@ static void gencontext_emit_decl(GenContext *context, Decl *decl)
|
||||
case DECL_CT_ELSE:
|
||||
case DECL_CT_ELIF:
|
||||
case DECL_ATTRIBUTE:
|
||||
case DECL_MEMBER:
|
||||
case DECL_LABEL:
|
||||
UNREACHABLE
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@ static inline LLVMMetadataRef gencontext_create_debug_type_from_decl(GenContext
|
||||
case DECL_VAR:
|
||||
case DECL_ARRAY_VALUE:
|
||||
case DECL_IMPORT:
|
||||
case DECL_MEMBER:
|
||||
case DECL_LABEL:
|
||||
UNREACHABLE;
|
||||
case DECL_FUNC:
|
||||
@@ -95,7 +94,6 @@ LLVMMetadataRef gencontext_get_debug_type(GenContext *context, Type *type)
|
||||
case TYPE_IXX:
|
||||
case TYPE_FXX:
|
||||
case TYPE_TYPEID:
|
||||
case TYPE_MEMBER:
|
||||
UNREACHABLE
|
||||
case TYPE_BOOL:
|
||||
return gencontext_simple_debug_type(context, type, DW_ATE_boolean);
|
||||
|
||||
@@ -121,26 +121,51 @@ static inline LLVMValueRef gencontext_emit_subscript_addr(GenContext *context, E
|
||||
}
|
||||
}
|
||||
|
||||
static int find_member_index(Decl *parent, Decl *member)
|
||||
{
|
||||
VECEACH(parent->strukt.members, i)
|
||||
{
|
||||
Decl *maybe_member = parent->strukt.members[i];
|
||||
if (member == maybe_member)
|
||||
{
|
||||
return (int)i;
|
||||
}
|
||||
if (!maybe_member->name)
|
||||
{
|
||||
if (find_member_index(maybe_member, member) != -1) return (int)i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static LLVMValueRef gencontext_emit_member_addr(GenContext *context, LLVMValueRef value, Decl *parent, Decl *member)
|
||||
{
|
||||
assert(member->resolve_status == RESOLVE_DONE);
|
||||
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);
|
||||
}
|
||||
|
||||
switch (current_parent->type->canonical->type_kind)
|
||||
Decl *found = NULL;
|
||||
do
|
||||
{
|
||||
case TYPE_UNION:
|
||||
return LLVMBuildBitCast(context->builder, value, LLVMPointerType(llvm_type(member->type), 0), member->name);
|
||||
case TYPE_ERRTYPE:
|
||||
return LLVMBuildStructGEP2(context->builder, llvm_type(current_parent->type), value, member->member_decl.index + 1, member->name);
|
||||
case TYPE_STRUCT:
|
||||
return LLVMBuildStructGEP2(context->builder, llvm_type(current_parent->type), value, member->member_decl.index, member->name);
|
||||
default:
|
||||
UNREACHABLE
|
||||
}
|
||||
int index = find_member_index(parent, member);
|
||||
assert(index > -1);
|
||||
found = parent->strukt.members[index];
|
||||
const char *name = found->name ? found->name : "anon";
|
||||
switch (parent->type->canonical->type_kind)
|
||||
{
|
||||
case TYPE_UNION:
|
||||
value = LLVMBuildBitCast(context->builder, value, LLVMPointerType(llvm_type(found->type), 0), name);
|
||||
break;
|
||||
case TYPE_ERRTYPE:
|
||||
value = LLVMBuildStructGEP2(context->builder, llvm_type(parent->type), value, index + 1, name);
|
||||
break;
|
||||
case TYPE_STRUCT:
|
||||
value = LLVMBuildStructGEP2(context->builder, llvm_type(parent->type), value, index, name);
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE
|
||||
}
|
||||
parent = found;
|
||||
} while (found != member);
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@ static inline void gencontext_emit_parameter(GenContext *context, Decl *decl, un
|
||||
assert(decl->decl_kind == DECL_VAR && decl->var.kind == VARDECL_PARAM);
|
||||
|
||||
// Allocate room on stack and copy.
|
||||
decl->ref = gencontext_emit_alloca(context, llvm_type(decl->type), decl->name);
|
||||
decl->ref = gencontext_emit_alloca(context, llvm_type(decl->type), decl->name ? decl->name : "anon");
|
||||
gencontext_emit_store(context, decl, LLVMGetParam(context->function, index));
|
||||
}
|
||||
|
||||
@@ -291,7 +291,6 @@ void gencontext_emit_extern_decl(GenContext *context, Decl *decl)
|
||||
break;
|
||||
case DECL_ENUM:
|
||||
TODO
|
||||
case DECL_MEMBER:
|
||||
case DECL_ARRAY_VALUE:
|
||||
case DECL_IMPORT:
|
||||
case DECL_MACRO:
|
||||
|
||||
@@ -22,7 +22,6 @@ static inline LLVMTypeRef llvm_type_from_decl(LLVMContextRef context, Decl *decl
|
||||
case DECL_VAR:
|
||||
case DECL_ARRAY_VALUE:
|
||||
case DECL_IMPORT:
|
||||
case DECL_MEMBER:
|
||||
case DECL_LABEL:
|
||||
UNREACHABLE;
|
||||
case DECL_FUNC:
|
||||
@@ -43,11 +42,13 @@ static inline LLVMTypeRef llvm_type_from_decl(LLVMContextRef context, Decl *decl
|
||||
case DECL_STRUCT:
|
||||
{
|
||||
LLVMTypeRef *types = NULL;
|
||||
LLVMTypeRef type = LLVMStructCreateNamed(context, decl->external_name);
|
||||
// Avoid recursive issues.
|
||||
decl->type->backend_type = type;
|
||||
VECEACH(decl->strukt.members, i)
|
||||
{
|
||||
vec_add(types, llvm_get_type(context, decl->strukt.members[i]->type));
|
||||
}
|
||||
LLVMTypeRef type = LLVMStructCreateNamed(context, decl->name);
|
||||
LLVMStructSetBody(type, types, vec_size(types), decl->is_packed);
|
||||
return type;
|
||||
}
|
||||
@@ -55,6 +56,9 @@ static inline LLVMTypeRef llvm_type_from_decl(LLVMContextRef context, Decl *decl
|
||||
{
|
||||
Decl *max_type = NULL;
|
||||
unsigned long long max_size = 0;
|
||||
LLVMTypeRef type = LLVMStructCreateNamed(context, decl->external_name);
|
||||
// Avoid recursive issues.
|
||||
decl->type->backend_type = type;
|
||||
VECEACH(decl->strukt.members, i)
|
||||
{
|
||||
Decl *member = decl->strukt.members[i];
|
||||
@@ -65,7 +69,6 @@ static inline LLVMTypeRef llvm_type_from_decl(LLVMContextRef context, Decl *decl
|
||||
max_type = member;
|
||||
}
|
||||
}
|
||||
LLVMTypeRef type = LLVMStructCreateNamed(context, decl->external_name);
|
||||
if (max_type)
|
||||
{
|
||||
LLVMTypeRef type_ref = llvm_get_type(context, max_type->type);
|
||||
@@ -81,6 +84,9 @@ static inline LLVMTypeRef llvm_type_from_decl(LLVMContextRef context, Decl *decl
|
||||
return llvm_get_type(context, decl->type);
|
||||
case DECL_ERR:
|
||||
{
|
||||
LLVMTypeRef err_type = LLVMStructCreateNamed(context, decl->external_name);
|
||||
// Avoid recursive issues.
|
||||
decl->type->backend_type = err_type;
|
||||
LLVMTypeRef *types = NULL;
|
||||
vec_add(types, llvm_get_type(context, type_typeid));
|
||||
unsigned size = type_size(type_typeid);
|
||||
@@ -100,9 +106,8 @@ static inline LLVMTypeRef llvm_type_from_decl(LLVMContextRef context, Decl *decl
|
||||
{
|
||||
vec_add(types, LLVMIntTypeInContext(context, padding * 8));
|
||||
}
|
||||
LLVMTypeRef type = LLVMStructCreateNamed(context, decl->name);
|
||||
LLVMStructSetBody(type, types, vec_size(types), false);
|
||||
return type;
|
||||
LLVMStructSetBody(err_type, types, vec_size(types), false);
|
||||
return err_type;
|
||||
}
|
||||
}
|
||||
UNREACHABLE
|
||||
@@ -173,7 +178,6 @@ LLVMTypeRef llvm_get_type(LLVMContextRef context, Type *any_type)
|
||||
DEBUG_LOG("Generating type %s", any_type->name);
|
||||
switch (any_type->type_kind)
|
||||
{
|
||||
case TYPE_MEMBER:
|
||||
case TYPE_POISONED:
|
||||
UNREACHABLE
|
||||
case TYPE_TYPEID:
|
||||
|
||||
@@ -177,9 +177,8 @@ static Expr *parse_unary_expr(Context *context, Expr *left)
|
||||
|
||||
Expr *unary = EXPR_NEW_TOKEN(EXPR_UNARY, context->tok);
|
||||
unary->unary_expr.operator = unaryop_from_token(operator_type);
|
||||
Precedence rule_precedence = rules[operator_type].precedence;
|
||||
advance(context);
|
||||
Expr *right_side = parse_precedence(context, rule_precedence);
|
||||
Expr *right_side = parse_precedence(context, PREC_UNARY);
|
||||
|
||||
CHECK_EXPR(right_side);
|
||||
|
||||
|
||||
@@ -50,6 +50,7 @@ inline void advance(Context *context)
|
||||
context->lead_comment = context->next_lead_comment;
|
||||
context->trailing_comment = NULL;
|
||||
context->next_lead_comment = NULL;
|
||||
context->prev_tok = context->tok.id;
|
||||
context->tok = context->next_tok;
|
||||
while(1)
|
||||
{
|
||||
@@ -948,17 +949,6 @@ 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->canonical = member->member_decl.reference_type;
|
||||
member->member_decl.reference_type->decl = member;
|
||||
member->member_decl.type_info = type;
|
||||
member->member_decl.parent = parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Expect pointer to after '{'
|
||||
@@ -978,16 +968,14 @@ void add_struct_member(Decl *parent, Decl *parent_struct, Decl *member, TypeInfo
|
||||
* | struct_or_union opt_attributes struct_body
|
||||
* ;
|
||||
*
|
||||
* @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.
|
||||
* @param parent the parent of the struct
|
||||
*/
|
||||
bool parse_struct_body(Context *context, Decl *parent, Decl *parent_struct, Decl *visible_parent)
|
||||
bool parse_struct_body(Context *context, Decl *parent)
|
||||
{
|
||||
|
||||
CONSUME_OR(TOKEN_LBRACE, false);
|
||||
|
||||
assert(decl_is_struct_type(parent_struct));
|
||||
assert(decl_is_struct_type(parent));
|
||||
while (!TOKEN_IS(TOKEN_RBRACE))
|
||||
{
|
||||
TokenType token_type = context->tok.type;
|
||||
@@ -995,56 +983,36 @@ bool parse_struct_body(Context *context, Decl *parent, Decl *parent_struct, Decl
|
||||
{
|
||||
DeclKind decl_kind = decl_from_token(token_type);
|
||||
Decl *member;
|
||||
const char *name = TOKSTR(context->tok);
|
||||
Decl *strukt_type = decl_new_with_type(context->tok.id, decl_kind, visible_parent->visibility);
|
||||
if (context->next_tok.type != TOKEN_IDENT)
|
||||
{
|
||||
member = decl_new(DECL_MEMBER, NO_TOKEN_ID, visible_parent->visibility);
|
||||
member = decl_new_with_type(NO_TOKEN_ID, decl_kind, parent->visibility);
|
||||
member->span = source_span_from_token_id(context->tok.id);
|
||||
advance(context);
|
||||
}
|
||||
else
|
||||
{
|
||||
advance(context);
|
||||
member = decl_new(DECL_MEMBER, context->tok.id, visible_parent->visibility);
|
||||
Decl *other = struct_find_name(visible_parent, TOKSTR(context->tok));
|
||||
if (other)
|
||||
{
|
||||
SEMA_TOKEN_ERROR(context->tok, "Duplicate member '%s' found.", TOKSTR(context->tok.id));
|
||||
SEMA_PREV(other, "Previous declaration with the same name was here.");
|
||||
decl_poison(visible_parent);
|
||||
decl_poison(other);
|
||||
decl_poison(member);
|
||||
return false;
|
||||
}
|
||||
advance_and_verify(context, TOKEN_IDENT);
|
||||
member = decl_new_with_type(context->tok.id, decl_kind, parent->visibility);
|
||||
member->span.loc = context->prev_tok;
|
||||
advance_and_verify(context, TOKEN_IDENT);
|
||||
}
|
||||
if (!parse_attributes(context, strukt_type)) return false;
|
||||
if (!parse_struct_body(context, member, strukt_type, TOKEN_IS(TOKEN_IDENT) ? strukt_type : visible_parent))
|
||||
if (!parse_attributes(context, member)) return false;
|
||||
if (!parse_struct_body(context, member))
|
||||
{
|
||||
decl_poison(visible_parent);
|
||||
decl_poison(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));
|
||||
vec_add(parent->strukt.members, member);
|
||||
continue;
|
||||
}
|
||||
TypeInfo *type = TRY_TYPE_OR(parse_type(context), false);
|
||||
while (1)
|
||||
{
|
||||
EXPECT_OR(TOKEN_IDENT, false);
|
||||
Decl *member = decl_new(DECL_MEMBER, context->tok.id, visible_parent->visibility);
|
||||
Decl *other = struct_find_name(visible_parent, member->name);
|
||||
if (other)
|
||||
{
|
||||
SEMA_ERROR(member, "Duplicate member '%s' found.", member->name);
|
||||
SEMA_PREV(other, "Previous declaration with the same name was here.");
|
||||
decl_poison(visible_parent);
|
||||
decl_poison(other);
|
||||
decl_poison(member);
|
||||
}
|
||||
add_struct_member(parent, parent_struct, member, type);
|
||||
Decl *member = decl_new_var(context->tok.id, type, VARDECL_MEMBER, parent->visibility);
|
||||
vec_add(parent->strukt.members, member);
|
||||
advance(context);
|
||||
if (!TOKEN_IS(TOKEN_COMMA)) break;
|
||||
if (!try_consume(context, TOKEN_COMMA)) break;
|
||||
}
|
||||
CONSUME_OR(TOKEN_EOS, false);
|
||||
}
|
||||
@@ -1077,7 +1045,7 @@ static inline Decl *parse_struct_declaration(Context *context, Visibility visibi
|
||||
return poisoned_decl;
|
||||
}
|
||||
|
||||
if (!parse_struct_body(context, decl, decl, decl))
|
||||
if (!parse_struct_body(context, decl))
|
||||
{
|
||||
return poisoned_decl;
|
||||
}
|
||||
@@ -1373,9 +1341,9 @@ static inline Decl *parse_error_declaration(Context *context, Visibility visibil
|
||||
SEMA_TOKEN_ERROR(context->tok, "Expected an identifier here.");
|
||||
return poisoned_decl;
|
||||
}
|
||||
Decl *member = decl_new(DECL_MEMBER, context->tok.id, visibility);
|
||||
Decl *member = decl_new_var(context->tok.id, type, VARDECL_MEMBER, visibility);
|
||||
advance(context);
|
||||
add_struct_member(err_decl, err_decl, member, type);
|
||||
vec_add(err_decl->strukt.members, member);
|
||||
TRY_CONSUME_EOS_OR(poisoned_decl);
|
||||
}
|
||||
return err_decl;
|
||||
@@ -1392,7 +1360,7 @@ static inline Decl *parse_error_declaration(Context *context, Visibility visibil
|
||||
*/
|
||||
static inline bool parse_enum_spec(Context *context, TypeInfo **type_ref, Decl*** parameters_ref, Visibility parent_visibility)
|
||||
{
|
||||
*type_ref = TRY_TYPE_OR(parse_base_type(context), false);
|
||||
*type_ref = TRY_TYPE_OR(parse_type(context), false);
|
||||
if (!try_consume(context, TOKEN_LPAREN)) return true;
|
||||
while (!try_consume(context, TOKEN_RPAREN))
|
||||
{
|
||||
|
||||
@@ -306,7 +306,7 @@ bool ixxxi(Context *context, Expr *left, Type *canonical, Type *type, CastType c
|
||||
if (cast_type != CAST_TYPE_EXPLICIT && !bigint_fits_in_bits(&left->const_expr.i, bitsize, is_signed))
|
||||
{
|
||||
if (cast_type == CAST_TYPE_OPTIONAL_IMPLICIT) return true;
|
||||
SEMA_ERROR(left, "'%s' does not fit into '%s'", expr_const_to_error_string(&left->const_expr), canonical->name);
|
||||
SEMA_ERROR(left, "'%s' does not fit in type '%s'", expr_const_to_error_string(&left->const_expr), canonical->name);
|
||||
return false;
|
||||
}
|
||||
BigInt temp;
|
||||
@@ -571,7 +571,7 @@ bool enxi(Context *context, Expr* left, Type *from, Type *canonical, Type *type,
|
||||
if (cast_type != CAST_TYPE_EXPLICIT && type_find_max_type(enum_type_canonical, canonical) != canonical)
|
||||
{
|
||||
if (cast_type == CAST_TYPE_OPTIONAL_IMPLICIT) return true;
|
||||
SEMA_ERROR(left, "Cannot implictly convert '%s' with underlying type of '%s' to '%s',"
|
||||
SEMA_ERROR(left, "Cannot implicitly convert '%s' with underlying type of '%s' to '%s',"
|
||||
" use an explicit cast if this is what you want.", type_to_error_string(from),
|
||||
type_to_error_string(enum_type_canonical), type_to_error_string(canonical));
|
||||
return false;
|
||||
@@ -711,7 +711,6 @@ CastKind cast_to_bool_kind(Type *type)
|
||||
case TYPE_ERRTYPE:
|
||||
case TYPE_ENUM:
|
||||
case TYPE_FUNC:
|
||||
case TYPE_MEMBER:
|
||||
case TYPE_ARRAY:
|
||||
case TYPE_VARARRAY:
|
||||
case TYPE_SUBARRAY:
|
||||
@@ -751,7 +750,6 @@ bool cast(Context *context, Expr *expr, Type *to_type, CastType cast_type)
|
||||
case TYPE_POISONED:
|
||||
case TYPE_VOID:
|
||||
case TYPE_TYPEID:
|
||||
case TYPE_MEMBER:
|
||||
break;
|
||||
case TYPE_BOOL:
|
||||
// Bool may convert into integers and floats but only explicitly.
|
||||
|
||||
@@ -54,22 +54,43 @@ static inline void sema_set_union_size(Decl *decl)
|
||||
decl->strukt.size = size;
|
||||
}
|
||||
|
||||
static bool sema_analyse_struct_union(Context *context, Decl *decl);
|
||||
|
||||
static inline bool sema_analyse_struct_member(Context *context, Decl *decl)
|
||||
{
|
||||
assert(decl->resolve_status == RESOLVE_NOT_DONE);
|
||||
decl->resolve_status = RESOLVE_RUNNING;
|
||||
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;
|
||||
if (decl->name)
|
||||
{
|
||||
Decl *other = sema_resolve_symbol_in_current_dynamic_scope(context, decl->name);
|
||||
if (other)
|
||||
{
|
||||
SEMA_ERROR(decl, "Duplicate member name '%s'.", other->name);
|
||||
SEMA_PREV(other, "Previous declaration was here.");
|
||||
return false;
|
||||
}
|
||||
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);
|
||||
decl->type = decl->var.type_info->type;
|
||||
decl->resolve_status = RESOLVE_DONE;
|
||||
return true;
|
||||
case DECL_STRUCT:
|
||||
case DECL_UNION:
|
||||
return sema_analyse_decl(context, decl);
|
||||
default:
|
||||
UNREACHABLE
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool sema_analyse_struct_union(Context *context, Decl *decl)
|
||||
static bool sema_analyse_struct_union(Context *context, Decl *decl)
|
||||
{
|
||||
DEBUG_LOG("Beginning analysis of %s.", decl->name);
|
||||
DEBUG_LOG("Beginning analysis of %s.", decl->name ? decl->name : "anon");
|
||||
assert(decl->decl_kind == DECL_STRUCT || decl->decl_kind == DECL_UNION);
|
||||
if (decl->name) context_push_scope(context);
|
||||
VECEACH(decl->strukt.members, i)
|
||||
{
|
||||
Decl *member = decl->strukt.members[i];
|
||||
@@ -88,6 +109,7 @@ static inline bool sema_analyse_struct_union(Context *context, Decl *decl)
|
||||
decl_poison(decl);
|
||||
}
|
||||
}
|
||||
if (decl->name) context_pop_scope(context);
|
||||
DEBUG_LOG("Analysis complete.");
|
||||
return decl_ok(decl);
|
||||
}
|
||||
@@ -537,6 +559,35 @@ static inline bool sema_analyse_macro(Context *context, Decl *decl)
|
||||
|
||||
|
||||
|
||||
static inline bool expr_is_constant_eval(Expr *expr)
|
||||
{
|
||||
switch (expr->expr_kind)
|
||||
{
|
||||
case EXPR_CONST:
|
||||
return true;
|
||||
case EXPR_COMPOUND_LITERAL:
|
||||
return expr_is_constant_eval(expr->expr_compound_literal.initializer);
|
||||
case EXPR_INITIALIZER_LIST:
|
||||
{
|
||||
Expr** init_exprs = expr->expr_initializer.initializer_expr;
|
||||
switch (expr->expr_initializer.init_type)
|
||||
{
|
||||
case INITIALIZER_NORMAL:
|
||||
{
|
||||
VECEACH(init_exprs, i)
|
||||
{
|
||||
if (!expr_is_constant_eval(init_exprs[i])) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool sema_analyse_global(Context *context, Decl *decl)
|
||||
{
|
||||
@@ -545,8 +596,9 @@ static inline bool sema_analyse_global(Context *context, Decl *decl)
|
||||
if (decl->var.init_expr)
|
||||
{
|
||||
if (!sema_analyse_expr_of_required_type(context, decl->type, decl->var.init_expr, false)) return false;
|
||||
if (decl->var.init_expr->expr_kind != EXPR_CONST)
|
||||
if (!expr_is_constant_eval(decl->var.init_expr))
|
||||
{
|
||||
|
||||
SEMA_ERROR(decl->var.init_expr, "The expression must be a constant value.");
|
||||
return false;
|
||||
}
|
||||
@@ -595,6 +647,7 @@ static inline bool sema_analyse_global(Context *context, Decl *decl)
|
||||
case VARDECL_GLOBAL:
|
||||
return true;
|
||||
default:
|
||||
eprintf("Decl %s %d\n", decl->name, decl->var.kind);
|
||||
UNREACHABLE
|
||||
break;
|
||||
}
|
||||
@@ -614,22 +667,12 @@ static inline bool sema_analyse_error(Context *context __unused, Decl *decl)
|
||||
unsigned member_count = vec_size(members);
|
||||
bool success = true;
|
||||
unsigned error_size = 0;
|
||||
context_push_scope(context);
|
||||
for (unsigned i = 0; i < member_count; i++)
|
||||
{
|
||||
Decl *member = members[i];
|
||||
for (unsigned j = 0; j < i; j++)
|
||||
{
|
||||
if (member->name == members[j]->name)
|
||||
{
|
||||
SEMA_ERROR(member, "Duplicate error names, please remove one of them.");
|
||||
SEMA_PREV(members[j], "The previous declaration was here.");
|
||||
decl_poison(member);
|
||||
decl_poison(members[j]);
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
sema_analyse_struct_member(context, member);
|
||||
success = sema_analyse_struct_member(context, member);
|
||||
if (!success) continue;
|
||||
unsigned alignment = type_abi_alignment(member->type);
|
||||
unsigned size = type_size(member->type);
|
||||
if (error_size % alignment != 0)
|
||||
@@ -638,6 +681,8 @@ static inline bool sema_analyse_error(Context *context __unused, Decl *decl)
|
||||
}
|
||||
error_size += size;
|
||||
}
|
||||
context_pop_scope(context);
|
||||
if (!success) return false;
|
||||
sema_set_struct_size(decl);
|
||||
if (decl->strukt.size > type_size(type_usize))
|
||||
{
|
||||
@@ -654,10 +699,10 @@ bool sema_analyse_decl(Context *context, Decl *decl)
|
||||
{
|
||||
if (decl->resolve_status == RESOLVE_DONE) return decl_ok(decl);
|
||||
|
||||
DEBUG_LOG(">>> Analysing %s.", decl->name);
|
||||
DEBUG_LOG(">>> Analysing %s.", decl->name ? decl->name : "anon");
|
||||
if (decl->resolve_status == RESOLVE_RUNNING)
|
||||
{
|
||||
SEMA_ERROR(decl, "Recursive dependency on %s.", decl->name);
|
||||
SEMA_ERROR(decl, "Recursive definition of '%s'.", decl->name ? decl->name : "anon");
|
||||
decl_poison(decl);
|
||||
return false;
|
||||
}
|
||||
@@ -709,7 +754,6 @@ bool sema_analyse_decl(Context *context, Decl *decl)
|
||||
case DECL_ARRAY_VALUE:
|
||||
case DECL_CT_ELSE:
|
||||
case DECL_CT_ELIF:
|
||||
case DECL_MEMBER:
|
||||
case DECL_LABEL:
|
||||
UNREACHABLE
|
||||
case DECL_CT_IF:
|
||||
|
||||
@@ -311,6 +311,10 @@ static inline bool sema_expr_analyse_identifier(Context *context, Type *to, Expr
|
||||
{
|
||||
SEMA_ERROR(expr, "Only macro expansions can be prefixed with '@', please try to remove it.", decl->name);
|
||||
}
|
||||
if (decl->resolve_status != RESOLVE_DONE)
|
||||
{
|
||||
if (!sema_analyse_decl(context, decl)) return poisoned_decl;
|
||||
}
|
||||
if (decl->decl_kind == DECL_VAR && decl->var.failable)
|
||||
{
|
||||
expr->failable = true;
|
||||
@@ -787,13 +791,25 @@ static inline bool sema_expr_analyse_subscript_after_parent_resolution(Context *
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool sema_expr_analyse_subscript(Context *context, Type *to, Expr *expr)
|
||||
static inline bool sema_expr_analyse_subscript(Context *context, Expr *expr)
|
||||
{
|
||||
if (!sema_analyse_expr(context, NULL, expr->subscript_expr.expr)) return false;
|
||||
expr->failable = expr->subscript_expr.expr->failable;
|
||||
return sema_expr_analyse_subscript_after_parent_resolution(context, NULL, expr);
|
||||
}
|
||||
|
||||
static inline void insert_access_deref(Expr *expr)
|
||||
{
|
||||
Expr *deref = expr_new(EXPR_UNARY, expr->span);
|
||||
deref->unary_expr.operator = UNARYOP_DEREF;
|
||||
deref->unary_expr.expr = expr->access_expr.parent;
|
||||
deref->resolve_status = RESOLVE_DONE;
|
||||
assert(expr->access_expr.parent->type->canonical->type_kind == TYPE_POINTER);
|
||||
deref->type = expr->access_expr.parent->type->canonical->pointer;
|
||||
deref->failable = expr->access_expr.parent->failable;
|
||||
expr->access_expr.parent = deref;
|
||||
}
|
||||
|
||||
static inline bool sema_expr_analyse_method(Context *context, Expr *expr, Decl *decl, bool is_pointer)
|
||||
{
|
||||
const char *name = TOKSTR(expr->access_expr.sub_element);
|
||||
@@ -802,6 +818,10 @@ static inline bool sema_expr_analyse_method(Context *context, Expr *expr, Decl *
|
||||
Decl *function = decl->methods[i];
|
||||
if (function->name == name)
|
||||
{
|
||||
if (is_pointer)
|
||||
{
|
||||
insert_access_deref(expr);
|
||||
}
|
||||
expr->access_expr.ref = function;
|
||||
expr->type = function->type;
|
||||
return true;
|
||||
@@ -810,7 +830,7 @@ static inline bool sema_expr_analyse_method(Context *context, Expr *expr, Decl *
|
||||
|
||||
if (decl_is_struct_type(decl))
|
||||
{
|
||||
SEMA_ERROR(expr, "There is no element nor method '%s.%s'.", decl->name, name);
|
||||
SEMA_ERROR(expr, "There is no element or method '%s.%s'.", decl->name, name);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -825,25 +845,22 @@ static Decl *strukt_recursive_search_member(Decl *strukt, const char *name)
|
||||
VECEACH(strukt->strukt.members, i)
|
||||
{
|
||||
Decl *member = strukt->strukt.members[i];
|
||||
if (member->member_decl.anonymous)
|
||||
if (member->name == name) return member;
|
||||
if (decl_is_struct_type(member) && !member->name)
|
||||
{
|
||||
Decl *result = strukt_recursive_search_member(member->type->canonical->decl, name);
|
||||
Decl *result = strukt_recursive_search_member(member, name);
|
||||
if (result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (member->name == name) return member;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline bool sema_expr_analyse_group(Context *context, Type *to, Expr *expr)
|
||||
{
|
||||
if (!sema_analyse_expr(context, to, expr->group_expr)) return false;
|
||||
if (!sema_analyse_expr(context, NULL, expr->group_expr)) return false;
|
||||
*expr = *expr->group_expr;
|
||||
return true;
|
||||
}
|
||||
@@ -928,14 +945,14 @@ static bool sema_expr_analyse_type_access(Context *context, Type *to, Expr *expr
|
||||
if (name == member->name)
|
||||
{
|
||||
expr->type_access.decl = member;
|
||||
expr->type = member->member_decl.reference_type;
|
||||
expr->type = member->type;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
SEMA_ERROR(expr, "No function or member '%s.%s' found.", type_to_error_string(type_info->type), name);
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
static inline bool sema_expr_analyse_member_access(Context *context, Expr *expr)
|
||||
{
|
||||
Type *type = expr->access_expr.parent->type->decl->member_decl.type_info->type;
|
||||
@@ -1012,6 +1029,7 @@ static inline bool sema_expr_analyse_member_access(Context *context, Expr *expr)
|
||||
sub_element);
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
static inline bool sema_expr_analyse_access(Context *context, Expr *expr)
|
||||
@@ -1026,15 +1044,12 @@ static inline bool sema_expr_analyse_access(Context *context, Expr *expr)
|
||||
Type *parent_type = expr->access_expr.parent->type;
|
||||
Type *type = parent_type->canonical;
|
||||
|
||||
if (type->type_kind == TYPE_MEMBER)
|
||||
{
|
||||
return sema_expr_analyse_member_access(context, expr);
|
||||
}
|
||||
bool is_pointer = type->type_kind == TYPE_POINTER;
|
||||
if (is_pointer)
|
||||
{
|
||||
type = type->pointer;
|
||||
}
|
||||
|
||||
if (!type_may_have_sub_elements(type))
|
||||
{
|
||||
SEMA_ERROR(expr, "Cannot access '%s' on '%s'", TOKSTR(expr->access_expr.sub_element), type_to_error_string(parent_type));
|
||||
@@ -1060,13 +1075,7 @@ static inline bool sema_expr_analyse_access(Context *context, Expr *expr)
|
||||
}
|
||||
if (is_pointer)
|
||||
{
|
||||
Expr *deref = expr_new(EXPR_UNARY, expr->span);
|
||||
deref->unary_expr.operator = UNARYOP_DEREF;
|
||||
deref->unary_expr.expr = expr->access_expr.parent;
|
||||
deref->resolve_status = RESOLVE_DONE;
|
||||
deref->type = type;
|
||||
deref->failable = expr->access_expr.parent->failable;
|
||||
expr->access_expr.parent = deref;
|
||||
insert_access_deref(expr);
|
||||
}
|
||||
expr->type = member->type;
|
||||
expr->access_expr.ref = member;
|
||||
@@ -1082,7 +1091,7 @@ static DesignatedPath *sema_analyse_init_identifier_string(Context *context, Des
|
||||
VECEACH(members, i)
|
||||
{
|
||||
Decl *member = members[i];
|
||||
if (member->member_decl.anonymous)
|
||||
if (!member->name)
|
||||
{
|
||||
DesignatedPath temp_path;
|
||||
temp_path.type = member->type;
|
||||
@@ -1643,10 +1652,19 @@ static bool sema_expr_analyse_add_sub_assign(Context *context, Expr *expr, Expr
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool binary_arithmetic_promotion(Context *context, Expr *left, Expr *right, Type *left_type, Type *right_type)
|
||||
static bool binary_arithmetic_promotion(Context *context, Expr *left, Expr *right, Type *left_type, Type *right_type, Expr *parent, const char *error_message)
|
||||
{
|
||||
Type *max = type_find_max_type(left_type, right_type);
|
||||
return max && type_is_numeric(max) && cast_implicit(context, left, max) && cast_implicit(context, right, max);
|
||||
if (!max || !type_is_numeric(max))
|
||||
{
|
||||
if (!error_message)
|
||||
{
|
||||
return sema_type_error_on_binop(context, parent);
|
||||
}
|
||||
SEMA_ERROR(parent, error_message, type_to_error_string(left_type), type_to_error_string(right_type));
|
||||
return false;
|
||||
}
|
||||
return cast_implicit(context, left, max) && cast_implicit(context, right, max);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1709,19 +1727,38 @@ static bool sema_expr_analyse_sub(Context *context, Type *to, Expr *expr, Expr *
|
||||
}
|
||||
|
||||
// 7. Attempt arithmetic promotion, to promote both to a common type.
|
||||
if (!binary_arithmetic_promotion(context, left, right, left_type, right_type))
|
||||
if (!binary_arithmetic_promotion(context, left, right, left_type, right_type, expr, "Cannot subtract '%s' from '%s'"))
|
||||
{
|
||||
SEMA_ERROR(expr, "Cannot subtract '%s' from '%s'", type_to_error_string(left_type), type_to_error_string(right_type));
|
||||
return false;
|
||||
}
|
||||
|
||||
left_type = left->type->canonical;
|
||||
|
||||
// 8. Handle constant folding.
|
||||
if (both_const(left, right))
|
||||
{
|
||||
switch (left->const_expr.kind)
|
||||
expr->expr_kind = EXPR_CONST;
|
||||
expr->const_expr.kind = left_type->type_kind;
|
||||
switch (left_type->type_kind)
|
||||
{
|
||||
case ALL_INTS:
|
||||
bigint_sub(&expr->const_expr.i, &left->const_expr.i, &right->const_expr.i);
|
||||
if (is_mod && left_type != type_compint)
|
||||
{
|
||||
bigint_sub_wrap(&expr->const_expr.i,
|
||||
&left->const_expr.i,
|
||||
&right->const_expr.i,
|
||||
left_type->builtin.bitsize,
|
||||
type_is_signed(left_type));
|
||||
}
|
||||
else
|
||||
{
|
||||
bigint_sub(&expr->const_expr.i, &left->const_expr.i, &right->const_expr.i);
|
||||
}
|
||||
if (expr_const_int_overflowed(&expr->const_expr))
|
||||
{
|
||||
SEMA_ERROR(expr, "Cannot fit '%s' into type '%s'.", expr_const_to_error_string(&expr->const_expr), type_to_error_string(left_type));
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case ALL_FLOATS:
|
||||
// IMPROVE precision.
|
||||
@@ -1730,8 +1767,6 @@ static bool sema_expr_analyse_sub(Context *context, Type *to, Expr *expr, Expr *
|
||||
default:
|
||||
UNREACHABLE
|
||||
}
|
||||
expr->expr_kind = EXPR_CONST;
|
||||
expr->const_expr.kind = left->const_expr.kind;
|
||||
}
|
||||
|
||||
// 9. Is this -%? That's not ok unless we are adding integers.
|
||||
@@ -1807,19 +1842,34 @@ static bool sema_expr_analyse_add(Context *context, Type *to, Expr *expr, Expr *
|
||||
|
||||
// 5. Do the binary arithmetic promotion (finding a common super type)
|
||||
// If none can be find, send an error.
|
||||
if (!binary_arithmetic_promotion(context, left, right, left_type, right_type))
|
||||
if (!binary_arithmetic_promotion(context, left, right, left_type, right_type, expr, "Cannot add '%s' to '%s'"))
|
||||
{
|
||||
SEMA_ERROR(expr, "Cannot add '%s' to '%s'", type_to_error_string(left_type), type_to_error_string(right_type));
|
||||
return false;
|
||||
}
|
||||
|
||||
left_type = left->type->canonical;
|
||||
|
||||
// 6. Handle the "both const" case. We should only see ints and floats at this point.
|
||||
if (both_const(left, right))
|
||||
{
|
||||
expr->expr_kind = EXPR_CONST;
|
||||
expr->const_expr.kind = left_type->type_kind;
|
||||
switch (left->const_expr.kind)
|
||||
{
|
||||
case ALL_INTS:
|
||||
bigint_add(&expr->const_expr.i, &left->const_expr.i, &right->const_expr.i);
|
||||
if (is_mod && left_type != type_compint)
|
||||
{
|
||||
bigint_add_wrap(&expr->const_expr.i, &left->const_expr.i, &right->const_expr.i, left_type->builtin.bitsize, type_is_signed(left_type));
|
||||
}
|
||||
else
|
||||
{
|
||||
bigint_add(&expr->const_expr.i, &left->const_expr.i, &right->const_expr.i);
|
||||
}
|
||||
if (expr_const_int_overflowed(&expr->const_expr))
|
||||
{
|
||||
SEMA_ERROR(expr, "Cannot fit '%s' into type '%s'.", expr_const_to_error_string(&expr->const_expr), type_to_error_string(left_type));
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case ALL_FLOATS:
|
||||
expr->const_expr.f = left->const_expr.f + right->const_expr.f;
|
||||
@@ -1827,8 +1877,6 @@ static bool sema_expr_analyse_add(Context *context, Type *to, Expr *expr, Expr *
|
||||
default:
|
||||
UNREACHABLE
|
||||
}
|
||||
expr->expr_kind = EXPR_CONST;
|
||||
expr->const_expr.kind = left->const_expr.kind;
|
||||
}
|
||||
|
||||
// 7. Is this +%? That's not ok unless we are adding integers.
|
||||
@@ -1865,9 +1913,8 @@ static bool sema_expr_analyse_mult(Context *context, Type *to, Expr *expr, Expr
|
||||
Type *right_type = right->type->canonical;
|
||||
|
||||
// 2. Perform promotion to a common type.
|
||||
if (!binary_arithmetic_promotion(context, left, right, left_type, right_type))
|
||||
if (!binary_arithmetic_promotion(context, left, right, left_type, right_type, expr, "Cannot multiply '%s' by '%s'"))
|
||||
{
|
||||
SEMA_ERROR(expr, "Cannot multiply '%s' with '%s'", type_to_error_string(left->type), type_to_error_string(right->type));
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1880,7 +1927,7 @@ static bool sema_expr_analyse_mult(Context *context, Type *to, Expr *expr, Expr
|
||||
// 4. Prevent *% use on non-integers.
|
||||
if (is_mod && !type_is_any_integer(left_type))
|
||||
{
|
||||
SEMA_ERROR(expr, "*% can only be used with integer types, try * instead.");
|
||||
SEMA_ERROR(expr, "*%% can only be used with integer types, try * instead.");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1888,7 +1935,7 @@ static bool sema_expr_analyse_mult(Context *context, Type *to, Expr *expr, Expr
|
||||
if (both_const(left, right))
|
||||
{
|
||||
expr->expr_kind = EXPR_CONST;
|
||||
expr->const_expr.kind = left->const_expr.kind;
|
||||
expr->const_expr.kind = left_type->type_kind;
|
||||
|
||||
switch (left->const_expr.kind)
|
||||
{
|
||||
@@ -1899,11 +1946,18 @@ static bool sema_expr_analyse_mult(Context *context, Type *to, Expr *expr, Expr
|
||||
bigint_mul_wrap(&expr->const_expr.i,
|
||||
&left->const_expr.i,
|
||||
&right->const_expr.i,
|
||||
is_mod,
|
||||
left_type->builtin.bitsize);
|
||||
return true;
|
||||
left_type->builtin.bitsize,
|
||||
type_is_signed(left_type));
|
||||
}
|
||||
else
|
||||
{
|
||||
bigint_mul(&expr->const_expr.i, &left->const_expr.i, &right->const_expr.i);
|
||||
}
|
||||
if (expr_const_int_overflowed(&expr->const_expr))
|
||||
{
|
||||
SEMA_ERROR(expr, "Cannot fit '%s' into type '%s'.", expr_const_to_error_string(&expr->const_expr), type_to_error_string(left_type));
|
||||
return false;
|
||||
}
|
||||
bigint_mul(&expr->const_expr.i, &left->const_expr.i, &right->const_expr.i);
|
||||
break;
|
||||
case ALL_FLOATS:
|
||||
expr->const_expr.f = left->const_expr.f * right->const_expr.f;
|
||||
@@ -1930,9 +1984,8 @@ static bool sema_expr_analyse_div(Context *context, Type *to, Expr *expr, Expr *
|
||||
Type *right_type = right->type->canonical;
|
||||
|
||||
// 2. Perform promotion to a common type.
|
||||
if (!binary_arithmetic_promotion(context, left, right, left_type, right_type))
|
||||
if (!binary_arithmetic_promotion(context, left, right, left_type, right_type, expr, "Cannot divide '%s' by '%s'."))
|
||||
{
|
||||
SEMA_ERROR(expr, "Cannot divide '%s' by '%s'.", type_to_error_string(left_type), type_to_error_string(right_type));
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -2038,9 +2091,9 @@ static bool sema_expr_analyse_bit(Context *context, Type *to, Expr *expr, Expr *
|
||||
Type *left_type = left->type->canonical;
|
||||
Type *right_type = right->type->canonical;
|
||||
|
||||
if (!binary_arithmetic_promotion(context, left, right, left_type, right_type))
|
||||
if (!binary_arithmetic_promotion(context, left, right, left_type, right_type, expr, NULL))
|
||||
{
|
||||
return sema_type_error_on_binop(context, expr);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 4. Do constant folding if both sides are constant.
|
||||
@@ -2309,7 +2362,6 @@ static bool sema_expr_analyse_comp(Context *context, Expr *expr, Expr *left, Exp
|
||||
case TYPE_VARARRAY:
|
||||
case TYPE_SUBARRAY:
|
||||
case TYPE_TYPEID:
|
||||
case TYPE_MEMBER:
|
||||
// Only != and == allowed.
|
||||
goto ERR;
|
||||
case ALL_INTS:
|
||||
@@ -2551,7 +2603,6 @@ static bool sema_expr_analyse_not(Context *context, Type *to, Expr *expr, Expr *
|
||||
case TYPE_ENUM:
|
||||
case TYPE_ERRTYPE:
|
||||
case TYPE_TYPEID:
|
||||
case TYPE_MEMBER:
|
||||
SEMA_ERROR(expr, "Cannot use 'not' on %s", type_to_error_string(inner->type));
|
||||
return false;
|
||||
}
|
||||
@@ -3283,7 +3334,7 @@ static inline bool sema_analyse_expr_dispatch(Context *context, Type *to, Expr *
|
||||
case EXPR_CALL:
|
||||
return sema_expr_analyse_call(context, to, expr);
|
||||
case EXPR_SUBSCRIPT:
|
||||
return sema_expr_analyse_subscript(context, to, expr);
|
||||
return sema_expr_analyse_subscript(context, expr);
|
||||
case EXPR_GROUP:
|
||||
return sema_expr_analyse_group(context, to, expr);
|
||||
case EXPR_ACCESS:
|
||||
@@ -3317,15 +3368,16 @@ bool sema_analyse_expr(Context *context, Type *to, Expr *expr)
|
||||
{
|
||||
case RESOLVE_NOT_DONE:
|
||||
expr->resolve_status = RESOLVE_RUNNING;
|
||||
if (!sema_analyse_expr_dispatch(context, to, expr)) return expr_poison(expr);
|
||||
expr->resolve_status = RESOLVE_DONE;
|
||||
break;
|
||||
case RESOLVE_RUNNING:
|
||||
SEMA_ERROR(expr, "Recursive resolution of expression");
|
||||
return expr_poison(expr);
|
||||
case RESOLVE_DONE:
|
||||
return expr_ok(expr);
|
||||
if (!expr_ok(expr)) return false;
|
||||
break;
|
||||
}
|
||||
if (!sema_analyse_expr_dispatch(context, to, expr)) return expr_poison(expr);
|
||||
expr->resolve_status = RESOLVE_DONE;
|
||||
if (expr->expr_kind == EXPR_IDENTIFIER)
|
||||
{
|
||||
if (expr->identifier_expr.decl->decl_kind == DECL_FUNC)
|
||||
|
||||
@@ -11,6 +11,10 @@ int sema_check_comp_time_bool(Context *context, Expr *expr);
|
||||
bool sema_analyse_function_body(Context *context, Decl *func);
|
||||
void context_pop_scope(Context *context);
|
||||
void context_push_scope_with_flags(Context *context, ScopeFlags flags);
|
||||
static inline void context_push_scope(Context *context)
|
||||
{
|
||||
context_push_scope_with_flags(context, SCOPE_NONE);
|
||||
}
|
||||
#define PUSH_X(ast, X) AstId _old_##X##_defer = context->X##_defer; AstId _old_##X = context->X##_target; context->X##_target = astid(ast); context->X##_defer = context->current_scope->defers.start
|
||||
#define POP_X(X) context->X##_target = _old_##X; context->X##_defer = _old_##X##_defer
|
||||
#define PUSH_CONTINUE(ast) PUSH_X(ast, continue)
|
||||
|
||||
@@ -33,6 +33,10 @@ static Decl *sema_resolve_path_symbol(Context *context, const char *symbol, Path
|
||||
*ambiguous_other_decl = NULL;
|
||||
Decl *decl = NULL;
|
||||
bool path_found = false;
|
||||
if (matches_subpath(context->module->name, path))
|
||||
{
|
||||
return stable_get(&context->module->symbols, symbol);
|
||||
}
|
||||
VECEACH(context->imports, i)
|
||||
{
|
||||
Decl *import = context->imports[i];
|
||||
@@ -64,6 +68,21 @@ static Decl *sema_resolve_path_symbol(Context *context, const char *symbol, Path
|
||||
return decl;
|
||||
}
|
||||
|
||||
Decl *sema_resolve_symbol_in_current_dynamic_scope(Context *context, const char *symbol)
|
||||
{
|
||||
if (context->current_scope)
|
||||
{
|
||||
Decl **first = context->current_scope->local_decl_start;
|
||||
Decl **current = context->last_local - 1;
|
||||
while (current >= first)
|
||||
{
|
||||
if (current[0]->name == symbol) return current[0];
|
||||
current--;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Decl *sema_resolve_symbol(Context *context, const char *symbol, Path *path, Decl **ambiguous_other_decl,
|
||||
Decl **private_decl)
|
||||
{
|
||||
@@ -121,19 +140,20 @@ Decl *sema_resolve_symbol(Context *context, const char *symbol, Path *path, Decl
|
||||
|
||||
static inline bool sema_append_local(Context *context, Decl *decl)
|
||||
{
|
||||
Decl *** vars = &context->active_function_for_analysis->func.annotations->vars;
|
||||
unsigned num_vars = vec_size(*vars);
|
||||
if (num_vars == MAX_LOCALS - 1 || context->last_local == &context->locals[MAX_LOCALS - 1])
|
||||
if (context->last_local == &context->locals[MAX_LOCALS - 1])
|
||||
{
|
||||
SEMA_ERROR(decl, "Reached the maximum number of locals.");
|
||||
return false;
|
||||
}
|
||||
*vars = VECADD(*vars, decl);
|
||||
context->last_local[0] = decl;
|
||||
context->last_local++;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool sema_add_member(Context *context, Decl *decl)
|
||||
{
|
||||
return sema_append_local(context, decl);
|
||||
}
|
||||
bool sema_add_local(Context *context, Decl *decl)
|
||||
{
|
||||
Decl *dummy;
|
||||
@@ -146,6 +166,15 @@ bool sema_add_local(Context *context, Decl *decl)
|
||||
decl_poison(other);
|
||||
return false;
|
||||
}
|
||||
Decl ***vars = &context->active_function_for_analysis->func.annotations->vars;
|
||||
unsigned num_vars = vec_size(*vars);
|
||||
if (num_vars == MAX_LOCALS - 1)
|
||||
{
|
||||
SEMA_ERROR(decl, "Reached the maximum number of locals.");
|
||||
return false;
|
||||
}
|
||||
vec_add(*vars, decl);
|
||||
decl->resolve_status = RESOLVE_DONE;
|
||||
return sema_append_local(context, decl);
|
||||
}
|
||||
|
||||
@@ -155,6 +184,7 @@ bool sema_unwrap_var(Context *context, Decl *decl)
|
||||
alias->var.kind = VARDECL_ALIAS;
|
||||
alias->var.alias = decl;
|
||||
alias->var.failable = false;
|
||||
decl->resolve_status = RESOLVE_DONE;
|
||||
return sema_append_local(context, decl);
|
||||
}
|
||||
|
||||
|
||||
@@ -102,6 +102,9 @@ static inline bool analyse_func_body(Context *context, Decl *decl)
|
||||
void sema_analysis_pass_decls(Context *context)
|
||||
{
|
||||
DEBUG_LOG("Pass: Decl analysis %s", context->file->name);
|
||||
context->current_scope = &context->scopes[0];
|
||||
context->current_scope->scope_id = 0;
|
||||
context->last_local = &context->locals[0];
|
||||
VECEACH(context->enums, i)
|
||||
{
|
||||
sema_analyse_decl(context, context->enums[i]);
|
||||
|
||||
@@ -55,10 +55,6 @@ void context_push_scope_with_label(Context *context, Decl *label)
|
||||
}
|
||||
}
|
||||
|
||||
static inline void context_push_scope(Context *context)
|
||||
{
|
||||
context_push_scope_with_flags(context, SCOPE_NONE);
|
||||
}
|
||||
|
||||
static inline void context_pop_defers(Context *context)
|
||||
{
|
||||
|
||||
@@ -104,10 +104,6 @@ static bool sema_resolve_type_identifier(Context *context, TypeInfo *type_info)
|
||||
case DECL_ERR:
|
||||
case DECL_ENUM:
|
||||
case DECL_TYPEDEF:
|
||||
if (decl->resolve_status == RESOLVE_NOT_DONE)
|
||||
{
|
||||
if (!sema_analyse_decl(context, decl)) return decl_poison(decl);
|
||||
}
|
||||
type_info->type = decl->type;
|
||||
type_info->resolve_status = RESOLVE_DONE;
|
||||
DEBUG_LOG("Resolved %s.", TOKSTR(type_info->unresolved.name_loc));
|
||||
@@ -128,7 +124,6 @@ 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
|
||||
|
||||
@@ -6,12 +6,16 @@
|
||||
|
||||
void sema_shadow_error(Decl *decl, Decl *old)
|
||||
{
|
||||
SEMA_ERROR(decl, "The '%s' would shadow a previous declaration.", decl->name);
|
||||
SEMA_ERROR(decl, "'%s' would shadow a previous declaration.", decl->name);
|
||||
SEMA_PREV(old, "The previous use of '%s' was here.", decl->name);
|
||||
}
|
||||
|
||||
bool sema_resolve_type_info(Context *context, TypeInfo *type_info)
|
||||
{
|
||||
if (!sema_resolve_type_shallow(context, type_info)) return false;
|
||||
return true;
|
||||
Type *type = type_info->type;
|
||||
// usize and similar typedefs will not have a decl.
|
||||
if (type->type_kind == TYPE_TYPEDEF && type->decl == NULL) return true;
|
||||
if (!type_is_user_defined(type)) return true;
|
||||
return sema_analyse_decl(context, type->decl);
|
||||
}
|
||||
|
||||
@@ -122,8 +122,6 @@ const char *type_to_error_string(Type *type)
|
||||
}
|
||||
asprintf(&buffer, "%s*", type_to_error_string(type->pointer));
|
||||
return buffer;
|
||||
case TYPE_MEMBER:
|
||||
return "member";
|
||||
case TYPE_STRING:
|
||||
return "string";
|
||||
case TYPE_ARRAY:
|
||||
@@ -191,8 +189,6 @@ size_t type_size(Type *type)
|
||||
case ALL_FLOATS:
|
||||
case TYPE_ERR_UNION:
|
||||
return type->builtin.bytesize;
|
||||
case TYPE_MEMBER:
|
||||
return type_size(type->decl->var.type_info->type);
|
||||
case TYPE_FUNC:
|
||||
case TYPE_POINTER:
|
||||
case TYPE_VARARRAY:
|
||||
@@ -228,8 +224,6 @@ unsigned int type_abi_alignment(Type *type)
|
||||
case ALL_FLOATS:
|
||||
case TYPE_ERR_UNION:
|
||||
return type->builtin.abi_alignment;
|
||||
case TYPE_MEMBER:
|
||||
return type_abi_alignment(type->decl->var.type_info->type);
|
||||
case TYPE_FUNC:
|
||||
case TYPE_POINTER:
|
||||
case TYPE_VARARRAY:
|
||||
@@ -347,6 +341,22 @@ Type *type_get_vararray(Type *arr_type)
|
||||
return type_generate_subarray(arr_type, false);
|
||||
}
|
||||
|
||||
bool type_is_user_defined(Type *type)
|
||||
{
|
||||
switch (type->type_kind)
|
||||
{
|
||||
case TYPE_ENUM:
|
||||
case TYPE_FUNC:
|
||||
case TYPE_STRUCT:
|
||||
case TYPE_UNION:
|
||||
case TYPE_ERRTYPE:
|
||||
case TYPE_TYPEDEF:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Type *type_get_indexed_type(Type *type)
|
||||
{
|
||||
switch (type->type_kind)
|
||||
@@ -696,7 +706,6 @@ Type *type_find_max_type(Type *type, Type *other)
|
||||
case TYPE_ERRTYPE:
|
||||
if (other->type_kind == TYPE_ERRTYPE) return type_error;
|
||||
return NULL;
|
||||
case TYPE_MEMBER:
|
||||
case TYPE_FUNC:
|
||||
case TYPE_UNION:
|
||||
case TYPE_ERR_UNION:
|
||||
|
||||
Reference in New Issue
Block a user