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:
Christoffer Lerno
2020-07-23 17:59:42 +02:00
parent f45d6ef84b
commit ed01616f1e
49 changed files with 1289 additions and 314 deletions

View File

@@ -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)

View File

@@ -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);

View File

@@ -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);

View File

@@ -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";

View File

@@ -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;

View File

@@ -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);
}
/*

View File

@@ -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

View File

@@ -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
}

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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:

View File

@@ -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:

View File

@@ -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);

View File

@@ -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))
{

View File

@@ -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.

View File

@@ -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:

View File

@@ -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)

View File

@@ -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)

View File

@@ -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);
}

View File

@@ -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]);

View File

@@ -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)
{

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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: