mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Improve error message when using functions as values #2856
This commit is contained in:
@@ -65,7 +65,8 @@ void compiler_init(BuildOptions *build_options)
|
||||
|
||||
INFO_LOG("Version: %s", COMPILER_VERSION);
|
||||
|
||||
compiler.context = (GlobalContext) { .in_panic_mode = false };
|
||||
GlobalContext new_context = { .in_panic_mode = false };
|
||||
compiler.context = new_context;
|
||||
// Skip library detection.
|
||||
//compiler.lib_dir = find_lib_dir();
|
||||
//DEBUG_LOG("Found std library: %s", compiler.lib_dir);
|
||||
|
||||
@@ -592,7 +592,7 @@ void expr_insert_addr(Expr *original)
|
||||
Expr *inner = expr_copy(original);
|
||||
original->expr_kind = EXPR_UNARY;
|
||||
original->type = new_type;
|
||||
original->unary_expr = (ExprUnary) { .operator = UNARYOP_ADDR, .expr = inner };
|
||||
original->unary_expr = (ExprUnary) { .operator = UNARYOP_ADDR, .expr = inner, .no_wrap = false, .no_read = false };
|
||||
}
|
||||
|
||||
Expr *expr_generated_local(Expr *assign, Decl **decl_ref)
|
||||
@@ -1189,6 +1189,6 @@ void expr_rewrite_const_string(Expr *expr_to_rewrite, const char *string)
|
||||
|
||||
void expr_rewrite_to_binary(Expr *expr_to_rewrite, Expr *left, Expr *right, BinaryOp op)
|
||||
{
|
||||
expr_to_rewrite->binary_expr = (ExprBinary) { .operator = op, .left = exprid(left), .right = exprid(right) };
|
||||
expr_to_rewrite->binary_expr = (ExprBinary) { .operator = op, .left = exprid(left), .right = exprid(right), .grouped = false };
|
||||
expr_to_rewrite->expr_kind = EXPR_BINARY;
|
||||
}
|
||||
|
||||
@@ -3691,7 +3691,8 @@ static inline bool sema_analyse_custom_attribute(SemaContext *context, ResolvedA
|
||||
SemaContext eval_context;
|
||||
sema_context_init(&eval_context, attr_decl->unit);
|
||||
eval_context.macro_call_depth = context->macro_call_depth + 1;
|
||||
eval_context.call_env = (CallEnv) { .kind = CALL_ENV_ATTR, .attr_declaration = decl, };
|
||||
CallEnv eval_env = { .kind = CALL_ENV_ATTR, .attr_declaration = decl, };
|
||||
eval_context.call_env = eval_env;
|
||||
// We copy the compilation unit.
|
||||
eval_context.compilation_unit = context->unit;
|
||||
|
||||
@@ -5372,7 +5373,8 @@ FOUND:;
|
||||
{
|
||||
SemaContext context_gen;
|
||||
sema_context_init(&context_gen, decl->unit);
|
||||
context_gen.active_scope = (DynamicScope) { .depth = 0 };
|
||||
DynamicScope empty = { .depth = 0 };
|
||||
context_gen.active_scope = empty;
|
||||
sema_analyse_decl(&context_gen, decl);
|
||||
context_gen.generic_instance = instance;
|
||||
sema_analyse_inner_func_ptr(&context_gen, decl);
|
||||
|
||||
@@ -953,9 +953,8 @@ static inline bool sema_cast_ident_rvalue(SemaContext *context, Expr *expr)
|
||||
decl = decl_flatten(decl);
|
||||
switch (decl->decl_kind)
|
||||
{
|
||||
case DECL_FNTYPE:
|
||||
case DECL_FUNC:
|
||||
SEMA_ERROR(expr, "Expected function followed by (...) or prefixed by &.");
|
||||
SEMA_ERROR(expr, "A function name cannot be used as a value, did you want to pass it by pointer? If so then you need to add '&', like '&%s'.", decl->span);
|
||||
return expr_poison(expr);
|
||||
case DECL_MACRO:
|
||||
SEMA_ERROR(expr, "Expected a macro followed by (...).");
|
||||
@@ -968,6 +967,7 @@ static inline bool sema_cast_ident_rvalue(SemaContext *context, Expr *expr)
|
||||
case DECL_FAULT:
|
||||
expr_rewrite_const_fault(expr, decl);
|
||||
return true;
|
||||
case DECL_FNTYPE:
|
||||
case DECL_ALIAS:
|
||||
case DECL_ALIAS_PATH:
|
||||
case DECL_ATTRIBUTE:
|
||||
@@ -1647,7 +1647,8 @@ static bool sema_analyse_parameter(SemaContext *context, Expr *arg, Decl *param,
|
||||
{
|
||||
Expr *inner = expr_copy(arg);
|
||||
arg->expr_kind = EXPR_OTHER_CONTEXT;
|
||||
arg->expr_other_context = (ExprOtherContext) { .context = context, .inner = inner };
|
||||
ExprOtherContext other = { .context = context, .inner = inner };
|
||||
arg->expr_other_context = other;
|
||||
arg->resolve_status = RESOLVE_NOT_DONE;
|
||||
}
|
||||
break;
|
||||
@@ -3599,8 +3600,9 @@ FOUND:;
|
||||
new_path->module = kw_std__core__runtime;
|
||||
new_path->span = expr->span;
|
||||
new_path->len = strlen(kw_std__core__runtime);
|
||||
call->unresolved_ident_expr = (ExprUnresolvedIdentifier) { .ident = kw_at_enum_lookup, .path = new_path };
|
||||
expr->call_expr = (ExprCall) { .arguments = args, .function = exprid(call) };
|
||||
call->unresolved_ident_expr = (ExprUnresolvedIdentifier) { .ident = kw_at_enum_lookup, .path = new_path, .is_const = false };
|
||||
ExprCall call_expr = { .arguments = args, .function = exprid(call) };
|
||||
expr->call_expr = call_expr;
|
||||
expr->resolve_status = RESOLVE_NOT_DONE;
|
||||
return sema_analyse_expr_rvalue(context, expr);
|
||||
}
|
||||
@@ -7405,8 +7407,8 @@ AFTER_ADDR:;
|
||||
// init, expr -> lvalue = rvalue + a
|
||||
expr->expr_kind = EXPR_BINARY;
|
||||
left->expr_kind = EXPR_BINARY;
|
||||
left->binary_expr = (ExprBinary) { .left = exprid(left_lvalue), .right = exprid(right), new_op };
|
||||
expr->binary_expr = (ExprBinary) { .left = exprid(left_rvalue), .right = exprid(left), .operator = BINARYOP_ASSIGN, .grouped = false };
|
||||
left->binary_expr = (ExprBinary) { exprid(left_lvalue), exprid(right), new_op, false };
|
||||
expr->binary_expr = (ExprBinary) { exprid(left_rvalue), exprid(left), BINARYOP_ASSIGN, false };
|
||||
expr->resolve_status = RESOLVE_NOT_DONE;
|
||||
left->resolve_status = RESOLVE_NOT_DONE;
|
||||
Expr *binary = expr_copy(expr);
|
||||
|
||||
@@ -915,7 +915,7 @@ static inline bool sema_analyse_try_unwrap(SemaContext *context, Expr *expr)
|
||||
RETURN_SEMA_ERROR(ident, "Expected this variable to be an optional, otherwise it can't be used for unwrap, maybe you didn't intend to use 'try'?");
|
||||
}
|
||||
expr->expr_kind = EXPR_TRY;
|
||||
expr->try_expr = (ExprTry) { .decl = decl };
|
||||
expr->try_expr = (ExprTry) { .decl = decl, .assign_existing = false };
|
||||
expr->type = type_bool;
|
||||
sema_unwrap_var(context, decl);
|
||||
expr->resolve_status = RESOLVE_DONE;
|
||||
@@ -977,7 +977,7 @@ static inline bool sema_analyse_try_unwrap(SemaContext *context, Expr *expr)
|
||||
if (!sema_analyse_var_decl(context, decl, true, NULL)) return false;
|
||||
|
||||
expr->expr_kind = EXPR_TRY;
|
||||
expr->try_expr = (ExprTry) { .decl = decl, .optional = optional };
|
||||
expr->try_expr = (ExprTry) { .decl = decl, .optional = optional, .assign_existing = false };
|
||||
expr->type = type_bool;
|
||||
expr->resolve_status = RESOLVE_DONE;
|
||||
return true;
|
||||
@@ -3449,21 +3449,24 @@ bool sema_analyse_function_body(SemaContext *context, Decl *func)
|
||||
|
||||
// Set up the context for analysis
|
||||
context->original_module = NULL;
|
||||
context->call_env = (CallEnv) {
|
||||
CallEnv env = {
|
||||
.current_function = func,
|
||||
.is_naked_fn = func->func_decl.attr_naked,
|
||||
.kind = CALL_ENV_FUNCTION,
|
||||
.pure = func->func_decl.signature.attrs.is_pure,
|
||||
.ignore_deprecation = func->allow_deprecated || decl_is_deprecated(func)
|
||||
};
|
||||
context->call_env = env;
|
||||
|
||||
Type *rtype = context->rtype = typeget(signature->rtype);
|
||||
context->macro_call_depth = 0;
|
||||
context->active_scope = (DynamicScope) {
|
||||
.depth = 0,
|
||||
.label_start = 0,
|
||||
.current_local = 0
|
||||
DynamicScope new_scope = {
|
||||
.depth = 0,
|
||||
.label_start = 0,
|
||||
.current_local = 0
|
||||
};
|
||||
|
||||
context->active_scope = new_scope;
|
||||
vec_resize(context->ct_locals, 0);
|
||||
// Clear returns
|
||||
vec_resize(context->block_returns, 0);
|
||||
|
||||
@@ -35,18 +35,19 @@ void context_change_scope_with_flags(SemaContext *context, ScopeFlags flags, Sou
|
||||
if (is_macro) flags &= ~(SCOPE_ENSURE | SCOPE_ENSURE_MACRO);
|
||||
|
||||
unsigned label_start = new_label_scope ? last_local : context->active_scope.label_start;
|
||||
context->active_scope = (DynamicScope) {
|
||||
.allow_dead_code = false,
|
||||
.is_dead = scope_is_dead,
|
||||
.is_poisoned = scope_is_poisoned,
|
||||
.depth = depth,
|
||||
.current_local = last_local,
|
||||
.label_start = label_start,
|
||||
.in_defer = previous_defer,
|
||||
.defer_last = parent_defer,
|
||||
.defer_start = parent_defer,
|
||||
.flags = flags,
|
||||
DynamicScope new_scope = {
|
||||
.allow_dead_code = false,
|
||||
.is_dead = scope_is_dead,
|
||||
.is_poisoned = scope_is_poisoned,
|
||||
.depth = depth,
|
||||
.current_local = last_local,
|
||||
.label_start = label_start,
|
||||
.in_defer = previous_defer,
|
||||
.defer_last = parent_defer,
|
||||
.defer_start = parent_defer,
|
||||
.flags = flags,
|
||||
};
|
||||
context->active_scope = new_scope;
|
||||
}
|
||||
|
||||
const char *context_filename(SemaContext *context)
|
||||
@@ -144,7 +145,7 @@ void context_pop_defers_and_replace_ast(SemaContext *context, Ast *ast)
|
||||
ASSERT(ast->ast_kind != AST_COMPOUND_STMT);
|
||||
Ast *replacement = ast_copy(ast);
|
||||
ast->ast_kind = AST_COMPOUND_STMT;
|
||||
ast->compound_stmt = (AstCompoundStmt) { .first_stmt = astid(replacement) };
|
||||
ast->compound_stmt = (AstCompoundStmt) { .first_stmt = astid(replacement), .parent_defer = 0 };
|
||||
replacement->next = defer_first;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user