diff --git a/src/compiler/compiler_internal.h b/src/compiler/compiler_internal.h index 83b2dae30..b84bb2af8 100644 --- a/src/compiler/compiler_internal.h +++ b/src/compiler/compiler_internal.h @@ -2355,7 +2355,7 @@ bool sema_expr_analyse_general_call(SemaContext *context, Expr *expr, Decl *decl Decl *sema_decl_stack_resolve_symbol(const char *symbol); Decl *sema_find_decl_in_modules(Module **module_list, Path *path, const char *interned_name); -Decl *unit_resolve_parameterized_symbol(CompilationUnit *unit, NameResolve *name_resolve); +Decl *unit_resolve_parameterized_symbol(SemaContext *context, CompilationUnit *unit, NameResolve *name_resolve); Decl *sema_resolve_type_method(CompilationUnit *unit, Type *type, const char *method_name, Decl **ambiguous_ref, Decl **private_ref); Decl *sema_resolve_method(CompilationUnit *unit, Decl *type, const char *method_name, Decl **ambiguous_ref, Decl **private_ref); Decl *sema_find_extension_method_in_list(Decl **extensions, Type *type, const char *method_name); diff --git a/src/compiler/sema_decls.c b/src/compiler/sema_decls.c index 5c4a7ffdc..e4f37fafb 100644 --- a/src/compiler/sema_decls.c +++ b/src/compiler/sema_decls.c @@ -2363,37 +2363,31 @@ static bool sema_analyse_attribute(SemaContext *context, Decl *decl, Attr *attr, } return true; FAILED_OP_TYPE: - SEMA_ERROR(attr, "'operator' requires an operator type argument: '[]', '[]=', '&[]' or 'len'."); - return false; + RETURN_SEMA_ERROR(attr, "'operator' requires an operator type argument: '[]', '[]=', '&[]' or 'len'."); } case ATTRIBUTE_ALIGN: if (!expr) { - print_error_at(attr->span, "'align' requires an power-of-2 argument, e.g. align(8)."); - return false; + RETURN_SEMA_ERROR(attr, "'align' requires an power-of-2 argument, e.g. align(8)."); } if (!sema_analyse_expr(context, expr)) return false; if (!expr_is_const_int(expr)) { - SEMA_ERROR(expr, "Expected a constant integer value as argument."); - return false; + RETURN_SEMA_ERROR(expr, "Expected a constant integer value as argument."); } { if (int_ucomp(expr->const_expr.ixx, MAX_ALIGNMENT, BINARYOP_GT)) { - SEMA_ERROR(expr, "Alignment must be less or equal to %ull.", MAX_ALIGNMENT); - return false; + RETURN_SEMA_ERROR(expr, "Alignment must be less or equal to %ull.", MAX_ALIGNMENT); } if (int_ucomp(expr->const_expr.ixx, 0, BINARYOP_LE)) { - SEMA_ERROR(expr, "Alignment must be greater than zero."); - return false; + RETURN_SEMA_ERROR(expr, "Alignment must be greater than zero."); } uint64_t align = int_to_u64(expr->const_expr.ixx); if (!is_power_of_two(align)) { - SEMA_ERROR(expr, "Alignment must be a power of two."); - return false; + RETURN_SEMA_ERROR(expr, "Alignment must be a power of two."); } decl->alignment = (AlignSize)align; return true; @@ -2401,21 +2395,18 @@ static bool sema_analyse_attribute(SemaContext *context, Decl *decl, Attr *attr, case ATTRIBUTE_EXPORT: if (context->unit->module->is_generic) { - print_error_at(attr->span, "'@export' is not allowed in generic modules."); - return false; + RETURN_SEMA_ERROR(attr, "'@export' is not allowed in generic modules."); } if (expr) { if (!sema_analyse_expr(context, expr)) return false; if (!expr_is_const_string(expr)) { - SEMA_ERROR(expr, "Expected a constant string value as argument."); - return false; + RETURN_SEMA_ERROR(expr, "Expected a constant string value as argument."); } if (decl->has_extname) { - SEMA_ERROR(expr, "An external name is already defined, please use '@extern` without an argument."); - return false; + RETURN_SEMA_ERROR(expr, "An external name is already defined, please use '@extern` without an argument."); } decl->has_extname = true; decl->extname = expr->const_expr.bytes.ptr; @@ -2481,19 +2472,16 @@ static bool sema_analyse_attribute(SemaContext *context, Decl *decl, Attr *attr, case ATTRIBUTE_EXTERN: if (context->unit->module->is_generic) { - print_error_at(attr->span, "'%s' attributes are not allowed in generic modules.", attr->name); - return false; + RETURN_SEMA_ERROR(attr, "'%s' attributes are not allowed in generic modules.", attr->name); } if (!expr) { - print_error_at(attr->span, "'%s' requires a string argument, e.g. %s(\"foo\").", attr->name, attr->name); - return false; + RETURN_SEMA_ERROR(attr, "'%s' requires a string argument, e.g. %s(\"foo\").", attr->name, attr->name); } if (!sema_analyse_expr(context, expr)) return false; if (!expr_is_const_string(expr)) { - SEMA_ERROR(expr, "Expected a constant string value as argument."); - return false; + RETURN_SEMA_ERROR(expr, "Expected a constant string value as argument."); } switch (type) { @@ -2548,7 +2536,7 @@ static bool sema_analyse_attribute(SemaContext *context, Decl *decl, Attr *attr, case ATTRIBUTE_BIGENDIAN: if (decl->bitstruct.little_endian) { - print_error_at(attr->span, "Attribute cannot be combined with @littleendian"); + SEMA_ERROR(attr, "Attribute cannot be combined with @littleendian"); return decl_poison(decl); } decl->bitstruct.big_endian = true; @@ -2556,7 +2544,7 @@ static bool sema_analyse_attribute(SemaContext *context, Decl *decl, Attr *attr, case ATTRIBUTE_LITTLEENDIAN: if (decl->bitstruct.big_endian) { - print_error_at(attr->span, "Attribute cannot be combined with @bigendian"); + SEMA_ERROR(attr, "Attribute cannot be combined with @bigendian"); return decl_poison(decl); } decl->bitstruct.little_endian = true; @@ -3343,20 +3331,19 @@ bool sema_analyse_decl_type(SemaContext *context, Type *type, SourceSpan span) case STORAGE_WILDCARD: if (type_is_optional(type)) { - print_error_at(span, "The use of 'void!' as a variable type is not permitted, use %s instead.", + sema_error_at(context, span, "The use of 'void!' as a variable type is not permitted, use %s instead.", type_quoted_error_string(type_anyfault)); - } - else + } else { - print_error_at(span, "The use of 'void' as a variable type is not permitted."); + sema_error_at(context, span, "The use of 'void' as a variable type is not permitted."); } return false; case STORAGE_COMPILE_TIME: - print_error_at(span, "The variable cannot have an compile time %s type.", + sema_error_at(context, span, "The variable cannot have an compile time %s type.", type_quoted_error_string(type)); return false; case STORAGE_UNKNOWN: - print_error_at(span, "%s has unknown size, and so it cannot be a variable type.", + sema_error_at(context, span, "%s has unknown size, and so it cannot be a variable type.", type_quoted_error_string(type)); return false; } @@ -3878,12 +3865,13 @@ static bool sema_analyse_generic_module_contracts(SemaContext *c, Module *module if (res == COND_TRUE) continue; if (ast->contract_stmt.contract.comment) { - print_error_at(error_span, + sema_error_at(c, error_span, "Parameter(s) would violate constraint: %s.", ast->contract_stmt.contract.comment); - } else + } + else { - print_error_at(error_span, "Parameter(s) failed validation: %s", + sema_error_at(c, error_span, "Parameter(s) failed validation: %s", ast->contract_stmt.contract.expr_string); } FAIL: @@ -3933,7 +3921,7 @@ Decl *sema_analyse_parameterized_identifier(SemaContext *c, Path *decl_path, con .symbol = name }; - Decl *alias = unit_resolve_parameterized_symbol(c->unit, &name_resolve); + Decl *alias = unit_resolve_parameterized_symbol(NULL, c->unit, &name_resolve); if (!decl_ok(alias)) return poisoned_decl; Module *module = decl_module(alias); @@ -3942,7 +3930,7 @@ Decl *sema_analyse_parameterized_identifier(SemaContext *c, Path *decl_path, con if (parameter_count != vec_size(params)) { assert(vec_size(params)); - print_error_at(extend_span_with_token(params[0]->span, vectail(params)->span), + sema_error_at(c, extend_span_with_token(params[0]->span, vectail(params)->span), "The generic module expected %d arguments, but you supplied %d, did you make a mistake?", parameter_count, vec_size(params)); @@ -3978,7 +3966,7 @@ Decl *sema_analyse_parameterized_identifier(SemaContext *c, Path *decl_path, con Decl *symbol = module_find_symbol(instantiated_module, name); if (!symbol) { - print_error_at(span, "The generic module '%s' does not have '%s' for this parameterization.", module->name->module, name); + sema_error_at(c, span, "The generic module '%s' does not have '%s' for this parameterization.", module->name->module, name); return poisoned_decl; } if (was_initiated && instantiated_module->contracts) diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index 4b1ba885b..edd559dbd 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -1070,7 +1070,12 @@ static inline bool sema_expr_analyse_hash_identifier(SemaContext *context, Type expr_replace(expr, copy_expr_single(decl->var.init_expr)); if (infer_type) { - if (!sema_analyse_inferred_expr(decl->var.hash_var.context, infer_type, expr)) return decl_poison(decl); + SemaContext *hash_context = decl->var.hash_var.context; + InliningSpan *old_span = hash_context->inlined_at; + hash_context->inlined_at = context->inlined_at; + bool success = sema_analyse_inferred_expr(decl->var.hash_var.context, infer_type, expr); + hash_context->inlined_at = old_span; + if (!success) return decl_poison(decl); } else { @@ -7122,11 +7127,7 @@ static inline bool sema_expr_analyse_decl_element(SemaContext *context, Designat bool *is_missing) { DesignatorType kind = element->kind; - if (kind == DESIGNATOR_RANGE) - { - SEMA_ERROR(element->index_expr, "Ranges are not allowed."); - return false; - } + if (kind == DESIGNATOR_RANGE) RETURN_SEMA_ERROR(element->index_expr, "Ranges are not allowed."); Type *actual_type = type_flatten(type); if (kind == DESIGNATOR_ARRAY) { @@ -7138,31 +7139,24 @@ static inline bool sema_expr_analyse_decl_element(SemaContext *context, Designat *is_missing = true; return false; } - SEMA_ERROR(inner, "It's not possible to constant index into something that is not an array nor vector."); - return false; + RETURN_SEMA_ERROR(inner, "It's not possible to constant index into something that is not an array nor vector."); } if (!sema_analyse_expr(context, inner)) return false; if (!type_is_integer(inner->type)) { - SEMA_ERROR(inner, "Expected an integer index."); - return false; + RETURN_SEMA_ERROR(inner, "Expected an integer index."); } if (!sema_flattened_expr_is_const(context, inner)) { - SEMA_ERROR(inner, "Expected a constant index."); - return false; + RETURN_SEMA_ERROR(inner, "Expected a constant index."); } Int value = inner->const_expr.ixx; if (!int_fits(value, type_isz->canonical->type_kind)) { - SEMA_ERROR(inner, "The index is out of range for a %s.", type_quoted_error_string(type_isz)); - return false; - } - if (int_is_neg(value)) - { - SEMA_ERROR(inner, "The index must be zero or greater."); - return false; + RETURN_SEMA_ERROR(inner, "The index is out of range for a %s.", type_quoted_error_string(type_isz)); } + if (int_is_neg(value)) RETURN_SEMA_ERROR(inner, "The index must be zero or greater."); + type = actual_type->array.base; ArraySize len = actual_type->array.len; int64_t index = int_to_i64(value); @@ -7174,8 +7168,7 @@ static inline bool sema_expr_analyse_decl_element(SemaContext *context, Designat *index_ref = 0; return false; } - SEMA_ERROR(inner, "Index exceeds array bounds."); - return false; + RETURN_SEMA_ERROR(inner, "Index exceeds array bounds."); } *return_type = type; *index_ref = index; @@ -7184,11 +7177,7 @@ static inline bool sema_expr_analyse_decl_element(SemaContext *context, Designat } Expr *field = sema_expr_resolve_access_child(context, element->field_expr, is_missing); if (!field) return false; - if (field->expr_kind != EXPR_IDENTIFIER) - { - SEMA_ERROR(field, "Expected an identifier here."); - return false; - } + if (field->expr_kind != EXPR_IDENTIFIER) RETURN_SEMA_ERROR(field, "Expected an identifier here."); const char *kw = field->identifier_expr.ident; if (kw == kw_ptr) { @@ -7228,11 +7217,11 @@ static inline bool sema_expr_analyse_decl_element(SemaContext *context, Designat } if (i == 0) { - print_error_at(loc, "%s has no members.", type_quoted_error_string(type)); + sema_error_at(context, loc, "%s has no members.", type_quoted_error_string(type)); } else { - print_error_at(loc, "There is no such member in %s.", type_quoted_error_string(type)); + sema_error_at(context, loc, "There is no such member in %s.", type_quoted_error_string(type)); } return false; } @@ -7244,7 +7233,7 @@ static inline bool sema_expr_analyse_decl_element(SemaContext *context, Designat member = sema_resolve_method(context->unit, actual_type->decl, kw, &ambiguous, &private); if (ambiguous) { - print_error_at(loc, "'%s' is an ambiguous name and so cannot be resolved, it may refer to method defined in '%s' or one in '%s'", + sema_error_at(context, loc, "'%s' is an ambiguous name and so cannot be resolved, it may refer to method defined in '%s' or one in '%s'", kw, decl_module(member)->name->module, decl_module(ambiguous)->name->module); return false; } @@ -7253,7 +7242,7 @@ static inline bool sema_expr_analyse_decl_element(SemaContext *context, Designat *is_missing = true; return false; } - print_error_at(loc, "There is no such member in %s.", type_quoted_error_string(type)); + sema_error_at(context, loc, "There is no such member in %s.", type_quoted_error_string(type)); return false; } *member_ref = member; diff --git a/src/compiler/sema_internal.h b/src/compiler/sema_internal.h index fa015c194..065067bd9 100644 --- a/src/compiler/sema_internal.h +++ b/src/compiler/sema_internal.h @@ -7,8 +7,8 @@ #include "compiler_internal.h" -#define SEMA_ERROR(_node, ...) print_error_at((_node)->span, __VA_ARGS__); sema_print_inline(context); -#define RETURN_SEMA_ERROR(_node, ...) do { print_error_at((_node)->span, __VA_ARGS__); sema_print_inline(context); return false; } while (0) +#define SEMA_ERROR(_node, ...) sema_error_at(context, (_node)->span, __VA_ARGS__) +#define RETURN_SEMA_ERROR(_node, ...) do { sema_error_at(context, (_node)->span, __VA_ARGS__); return false; } while (0) #define SCOPE_OUTER_START do { DynamicScope stored_scope = context->active_scope; context_change_scope_with_flags(context, SCOPE_NONE); #define SCOPE_OUTER_END assert(context->active_scope.defer_last == context->active_scope.defer_start); context->active_scope = stored_scope; } while(0) @@ -44,6 +44,7 @@ SemaContext *context_transform_for_eval(SemaContext *context, SemaContext *temp_ TokenType sema_splitpathref(const char *string, ArraySize len, Path **path_ref, const char **ident_ref); void sema_print_inline(SemaContext *context); +void sema_error_at(SemaContext *context, SourceSpan span, const char *message, ...); void sema_context_init(SemaContext *context, CompilationUnit *unit); void sema_context_destroy(SemaContext *context); diff --git a/src/compiler/sema_name_resolution.c b/src/compiler/sema_name_resolution.c index 0621cdd8f..a2a392ff5 100644 --- a/src/compiler/sema_name_resolution.c +++ b/src/compiler/sema_name_resolution.c @@ -426,7 +426,7 @@ static Decl *sema_resolve_no_path_symbol(SemaContext *context, NameResolve *name } -static void sema_report_error_on_decl(Decl *found, NameResolve *name_resolve) +static void sema_report_error_on_decl(SemaContext *context, Decl *found, NameResolve *name_resolve) { assert(!name_resolve->suppress_error); const char *symbol = name_resolve->symbol; @@ -437,14 +437,13 @@ static void sema_report_error_on_decl(Decl *found, NameResolve *name_resolve) const char *private_name = decl_to_name(name_resolve->private_decl); if (path_name) { - print_error_at(span, "The %s '%s::%s' is not visible from this module.", - private_name, path_name, - symbol); - } - else + sema_error_at(context, span, "The %s '%s::%s' is not visible from this module.", + private_name, path_name, + symbol); + } else { - print_error_at(span, "The %s '%s' is not visible from this module.", - private_name, symbol); + sema_error_at(context, span, "The %s '%s' is not visible from this module.", + private_name, symbol); } return; } @@ -454,14 +453,13 @@ static void sema_report_error_on_decl(Decl *found, NameResolve *name_resolve) const char *module_name = decl_module(name_resolve->maybe_decl)->name->module; if (path_name) { - print_error_at(span, "Did you mean the %s '%s::%s' in module %s? If so please add 'import %s'.", - maybe_name, module_name, symbol, module_name, module_name); + sema_error_at(context, span, "Did you mean the %s '%s::%s' in module %s? If so please add 'import %s'.", + maybe_name, module_name, symbol, module_name, module_name); - } - else + } else { - print_error_at(span, "Did you mean the %s '%s' in module %s? If so please add 'import %s'.", - maybe_name, symbol, module_name, module_name); + sema_error_at(context, span, "Did you mean the %s '%s' in module %s? If so please add 'import %s'.", + maybe_name, symbol, module_name, module_name); } return; } @@ -474,35 +472,34 @@ static void sema_report_error_on_decl(Decl *found, NameResolve *name_resolve) const char *other_path = decl_module(name_resolve->ambiguous_other_decl)->name->module; if (path_name) { - print_error_at(span, - "The %s '%s::%s' is defined in both '%s' and '%s', " - "please use either %s::%s or %s::%s to resolve the ambiguity.", - symbol_type, path_name, symbol, found_path, other_path, - found_path, symbol, other_path, symbol); - } - else + sema_error_at(context, span, + "The %s '%s::%s' is defined in both '%s' and '%s', " + "please use either %s::%s or %s::%s to resolve the ambiguity.", + symbol_type, path_name, symbol, found_path, other_path, + found_path, symbol, other_path, symbol); + } else { if (decl_needs_prefix(found)) { - print_error_at(span, "The %s needs a path prefix (e.g. '%s::%s').", symbol_type, found_path, symbol); + sema_error_at(context, span, "The %s needs a path prefix (e.g. '%s::%s').", symbol_type, found_path, + symbol); return; } - print_error_at(span, - "The %s '%s' is defined in both '%s' and '%s', please use either " - "%s::%s or %s::%s to resolve the ambiguity.", - symbol_type, symbol, found_path, other_path, - found_path, symbol, other_path, symbol); + sema_error_at(context, span, + "The %s '%s' is defined in both '%s' and '%s', please use either " + "%s::%s or %s::%s to resolve the ambiguity.", + symbol_type, symbol, found_path, other_path, + found_path, symbol, other_path, symbol); } return; } assert(!found); if (path_name) { - print_error_at(span, "'%s::%s' could not be found, did you spell it right?", path_name, symbol); - } - else + sema_error_at(context, span, "'%s::%s' could not be found, did you spell it right?", path_name, symbol); + } else { - print_error_at(span, "'%s' could not be found, did you spell it right?", symbol); + sema_error_at(context, span, "'%s' could not be found, did you spell it right?", symbol); } } @@ -539,7 +536,7 @@ INLINE Decl *sema_resolve_symbol_common(SemaContext *context, NameResolve *name_ } if (module_with_path) { - print_error_at(name_resolve->span, "'%s' could not be found in %s.", name_resolve->symbol, module_with_path->name->module); + SEMA_ERROR(name_resolve, "'%s' could not be found in %s.", name_resolve->symbol, module_with_path->name->module); } else { @@ -556,13 +553,13 @@ INLINE Decl *sema_resolve_symbol_common(SemaContext *context, NameResolve *name_ if (!decl || name_resolve->ambiguous_other_decl) { if (name_resolve->suppress_error) return NULL; - sema_report_error_on_decl(decl, name_resolve); + sema_report_error_on_decl(context, decl, name_resolve); return poisoned_decl; } unit_register_external_symbol(context->compilation_unit, decl); if (decl->is_if && context->call_env.in_if_resolution.a) { - print_error_at(context->call_env.in_if_resolution, "This @if expression is dependent on '%s' which is also conditional.", decl->name); + sema_error_at(context, context->call_env.in_if_resolution, "This @if expression is dependent on '%s' which is also conditional.", decl->name); SEMA_NOTE(decl, "'%s' is defined here.", decl->name); return poisoned_decl; } @@ -793,7 +790,7 @@ Decl *sema_resolve_type_method(CompilationUnit *unit, Type *type, const char *me return found; } -Decl *unit_resolve_parameterized_symbol(CompilationUnit *unit, NameResolve *name_resolve) +Decl *unit_resolve_parameterized_symbol(SemaContext *context, CompilationUnit *unit, NameResolve *name_resolve) { name_resolve->ambiguous_other_decl = NULL; name_resolve->private_decl = NULL; @@ -811,13 +808,13 @@ Decl *unit_resolve_parameterized_symbol(CompilationUnit *unit, NameResolve *name if (!decl || name_resolve->ambiguous_other_decl) { if (name_resolve->suppress_error) return poisoned_decl; - sema_report_error_on_decl(decl, name_resolve); + sema_report_error_on_decl(context, decl, name_resolve); return poisoned_decl; } if (!decl_is_user_defined_type(decl) && !name_resolve->path) { if (name_resolve->suppress_error) return poisoned_decl; - print_error_at(name_resolve->span, "Function and variables must be prefixed with a path, e.g. 'foo::%s'.", name_resolve->symbol); + SEMA_ERROR(name_resolve, "Function and variables must be prefixed with a path, e.g. 'foo::%s'.", name_resolve->symbol); return poisoned_decl; } diff --git a/src/compiler/sema_stmts.c b/src/compiler/sema_stmts.c index 2ddbc8aed..017dc8f79 100644 --- a/src/compiler/sema_stmts.c +++ b/src/compiler/sema_stmts.c @@ -311,7 +311,7 @@ static inline bool assert_create_from_contract(SemaContext *context, Ast *direct if (result == COND_TRUE) continue; if (result == COND_FALSE) { - print_error_at(evaluation_location.a ? evaluation_location : expr->span, "%s", comment); + sema_error_at(context, evaluation_location.a ? evaluation_location : expr->span, "%s", comment); return false; } Ast *assert = new_ast(AST_ASSERT_STMT, expr->span); @@ -2293,7 +2293,7 @@ static inline bool sema_check_value_case(SemaContext *context, Type *switch_type } if (is_range && (!expr_is_const_int(expr) || !expr_is_const(to_expr))) { - print_error_at(extend_span_with_token(expr->span, to_expr->span), "Ranges must be constant integers."); + sema_error_at(context, extend_span_with_token(expr->span, to_expr->span), "Ranges must be constant integers."); return false; } ExprConst *const_expr = &expr->const_expr; @@ -2303,7 +2303,7 @@ static inline bool sema_check_value_case(SemaContext *context, Type *switch_type { if (int_comp(const_expr->ixx, to_const_expr->ixx, BINARYOP_GT)) { - print_error_at(extend_span_with_token(expr->span, to_expr->span), + sema_error_at(context, extend_span_with_token(expr->span, to_expr->span), "The range is not valid because the first value (%s) is greater than the second (%s). " "It would work if you swapped their order.", int_to_str(const_expr->ixx, 10), @@ -2382,7 +2382,7 @@ static bool sema_analyse_switch_body(SemaContext *context, Ast *statement, Sourc bool use_type_id = false; if (!type_is_comparable(switch_type)) { - print_error_at(expr_span, "You cannot test '%s' for equality, and only values that supports '==' for comparison can be used in a switch.", type_to_error_string(switch_type)); + sema_error_at(context, expr_span, "You cannot test '%s' for equality, and only values that supports '==' for comparison can be used in a switch.", type_to_error_string(switch_type)); return false; } // We need an if-chain if this isn't an enum/integer type. @@ -2846,13 +2846,12 @@ bool sema_analyse_ct_assert_stmt(SemaContext *context, Ast *statement) { if (message_expr) { - print_error_at(span, "%.*s", EXPAND_EXPR_STRING(message_expr)); + sema_error_at(context, span, "%.*s", EXPAND_EXPR_STRING(message_expr)); } else { - print_error_at(span, "Compile time assert failed."); + sema_error_at(context, span, "Compile time assert failed."); } - sema_print_inline(context); return false; } statement->ast_kind = AST_NOP_STMT; diff --git a/src/compiler/semantic_analyser.c b/src/compiler/semantic_analyser.c index 038bed455..f3df99f81 100644 --- a/src/compiler/semantic_analyser.c +++ b/src/compiler/semantic_analyser.c @@ -525,4 +525,13 @@ void sema_print_inline(SemaContext *context) sema_error_prev_at(inlined_at->span, "Inlined from here."); inlined_at = inlined_at->prev; } -} \ No newline at end of file +} + +void sema_error_at(SemaContext *context, SourceSpan span, const char *message, ...) +{ + va_list list; + va_start(list, message); + sema_verror_range(span, message, list); + va_end(list); + sema_print_inline(context); +}