mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
- Too deeply nested scopes was a fatal crash and not a regular semantic error. #2796
This commit is contained in:
@@ -1714,7 +1714,7 @@ INLINE bool sema_set_default_argument(SemaContext *context, CalledDecl *callee,
|
||||
new_context->inlined_at = &inlined_at;
|
||||
}
|
||||
bool success;
|
||||
SCOPE_START
|
||||
SCOPE_START(arg->span)
|
||||
new_context->original_module = context->original_module;
|
||||
success = sema_analyse_parameter(new_context, arg, param, callee->definition, optional, no_match_ref,
|
||||
callee->macro, false);
|
||||
@@ -2869,7 +2869,7 @@ static inline bool sema_expr_setup_call_analysis(SemaContext *context, CalledDec
|
||||
|
||||
macro_context->block_exit_ref = block_exit_ref;
|
||||
|
||||
context_change_scope_with_flags(macro_context, SCOPE_MACRO);
|
||||
context_change_scope_with_flags(macro_context, SCOPE_MACRO, call_expr->span);
|
||||
macro_context->block_return_defer = macro_context->active_scope.defer_last;
|
||||
|
||||
return true;
|
||||
@@ -3051,7 +3051,7 @@ bool sema_expr_analyse_macro_call(SemaContext *context, Expr *call_expr, Expr *s
|
||||
|
||||
DynamicScope old_scope = context->active_scope;
|
||||
// Create a scope, since the macro itself will not.
|
||||
context_change_scope_with_flags(context, SCOPE_NONE);
|
||||
context_change_scope_with_flags(context, SCOPE_NONE, call_expr->span);
|
||||
SemaContext macro_context;
|
||||
|
||||
Type *rtype = typeget(sig->rtype);
|
||||
@@ -3371,7 +3371,7 @@ static bool sema_call_analyse_body_expansion(SemaContext *macro_context, Expr *c
|
||||
call->body_expansion_expr.values = args;
|
||||
call->body_expansion_expr.declarations = macro_context->yield_params;
|
||||
AstId last_defer = context->active_scope.defer_last;
|
||||
SCOPE_START
|
||||
SCOPE_START(call->span);
|
||||
unsigned ct_context = sema_context_push_ct_stack(context);
|
||||
if (macro_defer)
|
||||
{
|
||||
@@ -8586,7 +8586,7 @@ static inline bool sema_rewrite_expr_as_macro_block(SemaContext *context, Expr *
|
||||
bool success;
|
||||
Ast *compound_stmt = ast_new(AST_COMPOUND_STMT, expr->span);
|
||||
compound_stmt->compound_stmt.first_stmt = start;
|
||||
SCOPE_START_WITH_FLAGS(SCOPE_MACRO)
|
||||
SCOPE_START_WITH_FLAGS(SCOPE_MACRO, compound_stmt->span)
|
||||
success = sema_analyse_stmt_chain(context, compound_stmt);
|
||||
SCOPE_END;
|
||||
context->expected_block_type = old_expected_block;
|
||||
|
||||
@@ -23,11 +23,11 @@
|
||||
#define RETURN_VAL_SEMA_ERROR(val__, _node, ...) do { sema_error_at(context, (_node)->span, __VA_ARGS__); return (val__); } while (0)
|
||||
#define RETURN_NULL_SEMA_ERROR(_node, ...) do { sema_error_at(context, (_node)->span, __VA_ARGS__); return NULL; } while (0)
|
||||
#define RETURN_SEMA_ERROR_AT(span__, ...) do { sema_error_at(context, 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_START(span__) do { DynamicScope stored_scope = context->active_scope; context_change_scope_with_flags(context, SCOPE_NONE, span__);
|
||||
#define SCOPE_OUTER_END ASSERT(context->active_scope.defer_last == context->active_scope.defer_start); context->active_scope = stored_scope; } while(0)
|
||||
#define SCOPE_START SCOPE_START_WITH_FLAGS(SCOPE_NONE)
|
||||
#define SCOPE_START_WITH_FLAGS(flags) do { DynamicScope old_scope = context->active_scope; context_change_scope_with_flags(context, flags);
|
||||
#define SCOPE_START_WITH_LABEL(label) do { DynamicScope old_scope = context->active_scope; context_change_scope_for_label(context, label);
|
||||
#define SCOPE_START(span__) SCOPE_START_WITH_FLAGS(SCOPE_NONE, span__)
|
||||
#define SCOPE_START_WITH_FLAGS(flags, span__) do { DynamicScope old_scope = context->active_scope; context_change_scope_with_flags(context, flags, span__);
|
||||
#define SCOPE_START_WITH_LABEL(label, span__) do { DynamicScope old_scope = context->active_scope; context_change_scope_for_label(context, label, span__);
|
||||
#define SCOPE_END ASSERT(context->active_scope.defer_last == context->active_scope.defer_start); context->active_scope = old_scope; } while(0)
|
||||
#define SCOPE_POP_ERROR() ((bool)(context->active_scope = old_scope, false))
|
||||
#define SCOPE_ERROR_END_OUTER() do { context->active_scope = stored_scope; } while(0)
|
||||
@@ -51,8 +51,8 @@ const char *context_filename(SemaContext *context);
|
||||
AstId context_get_defers(SemaContext *context, AstId defer_bottom, bool is_success);
|
||||
void context_pop_defers(SemaContext *context, AstId *next);
|
||||
void context_pop_defers_and_replace_ast(SemaContext *context, Ast *ast);
|
||||
void context_change_scope_for_label(SemaContext *context, DeclId label);
|
||||
void context_change_scope_with_flags(SemaContext *context, ScopeFlags flags);
|
||||
void context_change_scope_for_label(SemaContext *context, DeclId label, SourceSpan span);
|
||||
void context_change_scope_with_flags(SemaContext *context, ScopeFlags flags, SourceSpan span);
|
||||
SemaContext *context_transform_for_eval(SemaContext *context, SemaContext *temp_context, CompilationUnit *eval_unit);
|
||||
|
||||
TokenType sema_splitpathref(const char *string, ArraySize len, Path **path_ref, const char **ident_ref);
|
||||
|
||||
@@ -247,7 +247,7 @@ static inline bool sema_analyse_compound_stmt(SemaContext *context, Ast *stateme
|
||||
{
|
||||
bool success;
|
||||
EndJump ends_with_jump;
|
||||
SCOPE_START
|
||||
SCOPE_START(statement->span)
|
||||
success = sema_analyse_compound_statement_no_scope(context, statement);
|
||||
ends_with_jump = context->active_scope.end_jump;
|
||||
SCOPE_END;
|
||||
@@ -532,7 +532,7 @@ static bool sema_analyse_macro_constant_ensures(SemaContext *context, Expr *ret_
|
||||
// And set our new one.
|
||||
context->return_expr = ret_expr;
|
||||
bool success = true;
|
||||
SCOPE_START_WITH_FLAGS(SCOPE_ENSURE_MACRO);
|
||||
SCOPE_START_WITH_FLAGS(SCOPE_ENSURE_MACRO, ret_expr->span);
|
||||
while (doc_directive)
|
||||
{
|
||||
Ast *directive = astptr(doc_directive);
|
||||
@@ -757,7 +757,7 @@ static inline bool sema_analyse_return_stmt(SemaContext *context, Ast *statement
|
||||
if (directive->contract_stmt.kind == CONTRACT_ENSURE)
|
||||
{
|
||||
bool success;
|
||||
SCOPE_START_WITH_FLAGS(SCOPE_ENSURE);
|
||||
SCOPE_START_WITH_FLAGS(SCOPE_ENSURE, statement->span);
|
||||
success = assert_create_from_contract(context, directive, &append_id, statement->span);
|
||||
SCOPE_END;
|
||||
if (!success) return false;
|
||||
@@ -1347,7 +1347,7 @@ bool sema_analyse_defer_stmt_body(SemaContext *context, Ast *statement)
|
||||
}
|
||||
body->compound_stmt.parent_defer = astid(statement);
|
||||
bool success = true;
|
||||
SCOPE_START
|
||||
SCOPE_START(statement->span)
|
||||
|
||||
context->active_scope.defer_last = 0;
|
||||
context->active_scope.defer_start = 0;
|
||||
@@ -1434,7 +1434,7 @@ static inline bool sema_analyse_for_stmt(SemaContext *context, Ast *statement)
|
||||
RETURN_SEMA_ERROR(body, "A do loop must use { } around its body.");
|
||||
}
|
||||
// Enter for scope
|
||||
SCOPE_OUTER_START
|
||||
SCOPE_OUTER_START(statement->span)
|
||||
|
||||
if (statement->for_stmt.init)
|
||||
{
|
||||
@@ -1442,7 +1442,7 @@ static inline bool sema_analyse_for_stmt(SemaContext *context, Ast *statement)
|
||||
}
|
||||
|
||||
// Conditional scope start
|
||||
SCOPE_START_WITH_LABEL(statement->for_stmt.flow.label)
|
||||
SCOPE_START_WITH_LABEL(statement->for_stmt.flow.label, statement->span)
|
||||
|
||||
if (!do_loop)
|
||||
{
|
||||
@@ -1466,7 +1466,7 @@ static inline bool sema_analyse_for_stmt(SemaContext *context, Ast *statement)
|
||||
|
||||
if (statement->for_stmt.flow.skip_first)
|
||||
{
|
||||
SCOPE_START
|
||||
SCOPE_START(statement->span)
|
||||
if (!sema_analyse_for_cond(context, &statement->for_stmt.cond, &is_infinite) || !success)
|
||||
{
|
||||
SCOPE_ERROR_END_OUTER();
|
||||
@@ -1484,7 +1484,7 @@ static inline bool sema_analyse_for_stmt(SemaContext *context, Ast *statement)
|
||||
if (success && statement->for_stmt.incr)
|
||||
{
|
||||
// Incr scope start
|
||||
SCOPE_START
|
||||
SCOPE_START(statement->span)
|
||||
success = sema_analyse_expr_rvalue(context, exprptr(statement->for_stmt.incr));
|
||||
// Incr scope end
|
||||
SCOPE_END;
|
||||
@@ -1537,7 +1537,7 @@ static inline bool sema_analyse_foreach_stmt(SemaContext *context, Ast *statemen
|
||||
}
|
||||
}
|
||||
// Conditional scope start
|
||||
SCOPE_START
|
||||
SCOPE_START(statement->span)
|
||||
|
||||
// In the case of foreach (int x : { 1, 2, 3 }) we will infer the int[] type, so pick out the number of elements.
|
||||
Type *inferred_type = variable_type_info ? type_get_inferred_array(type_no_optional(variable_type_info->type)) : NULL;
|
||||
@@ -1984,7 +1984,7 @@ static inline bool sema_analyse_if_stmt(SemaContext *context, Ast *statement)
|
||||
CondResult result = COND_MISSING;
|
||||
bool is_invalid = false;
|
||||
bool reverse = false;
|
||||
SCOPE_OUTER_START
|
||||
SCOPE_OUTER_START(statement->span)
|
||||
|
||||
success = sema_analyse_cond(context, cond, COND_TYPE_UNWRAP_BOOL, &result);
|
||||
if (success && cond->expr_kind == EXPR_COND)
|
||||
@@ -2027,7 +2027,7 @@ static inline bool sema_analyse_if_stmt(SemaContext *context, Ast *statement)
|
||||
}
|
||||
}
|
||||
|
||||
SCOPE_START_WITH_LABEL(statement->if_stmt.flow.label);
|
||||
SCOPE_START_WITH_LABEL(statement->if_stmt.flow.label, then->span);
|
||||
if (result == COND_FALSE) context->active_scope.is_dead = true;
|
||||
success = success && sema_analyse_statement(context, then);
|
||||
then_jump = context->active_scope.end_jump.active && !(statement->if_stmt.flow.label && statement->if_stmt.flow.has_break);
|
||||
@@ -2039,11 +2039,11 @@ static inline bool sema_analyse_if_stmt(SemaContext *context, Ast *statement)
|
||||
{
|
||||
bool store_break = statement->if_stmt.flow.has_break;
|
||||
statement->if_stmt.flow.has_break = false;
|
||||
SCOPE_START_WITH_LABEL(statement->if_stmt.flow.label);
|
||||
SCOPE_START_WITH_LABEL(statement->if_stmt.flow.label, statement->span);
|
||||
if (result == COND_TRUE) context->active_scope.is_dead = true;
|
||||
sema_remove_unwraps_from_try(context, cond);
|
||||
sema_unwrappable_from_catch_in_else(context, cond);
|
||||
success = success && sema_analyse_statement(context, else_body);
|
||||
success = sema_analyse_statement(context, else_body);
|
||||
else_jump = context->active_scope.end_jump.active && !(statement->if_stmt.flow.label && statement->if_stmt.flow.has_break);
|
||||
SCOPE_END;
|
||||
statement->if_stmt.flow.has_break |= store_break;
|
||||
@@ -2636,7 +2636,7 @@ FOUND:;
|
||||
for (unsigned i = 0; i < case_count; i++)
|
||||
{
|
||||
Ast *stmt = cases[i];
|
||||
SCOPE_START
|
||||
SCOPE_START(statement->span)
|
||||
PUSH_BREAK(statement);
|
||||
Ast *next = (i < case_count - 1) ? cases[i + 1] : NULL;
|
||||
PUSH_NEXT(next, statement);
|
||||
@@ -2984,7 +2984,7 @@ static inline bool sema_analyse_switch_stmt(SemaContext *context, Ast *statement
|
||||
{
|
||||
statement->switch_stmt.scope_defer = context->active_scope.in_defer;
|
||||
|
||||
SCOPE_START_WITH_LABEL(statement->switch_stmt.flow.label);
|
||||
SCOPE_START_WITH_LABEL(statement->switch_stmt.flow.label, statement->span);
|
||||
|
||||
Expr *cond = exprptrzero(statement->switch_stmt.cond);
|
||||
Type *switch_type;
|
||||
@@ -3471,7 +3471,7 @@ bool sema_analyse_function_body(SemaContext *context, Decl *func)
|
||||
|
||||
Ast *body = astptr(func->func_decl.body);
|
||||
Decl **lambda_params = NULL;
|
||||
SCOPE_START
|
||||
SCOPE_START(func->span)
|
||||
ASSERT(context->active_scope.depth == 1);
|
||||
FOREACH(Decl *, param, signature->params)
|
||||
{
|
||||
|
||||
@@ -8,12 +8,13 @@
|
||||
char swizzle[256] = { ['x'] = 0x01, ['y'] = 0x02, ['z'] = 0x03, ['w'] = 0x04,
|
||||
['r'] = 0x11, ['g'] = 0x12, ['b'] = 0x13, ['a'] = 0x14 };
|
||||
|
||||
void context_change_scope_with_flags(SemaContext *context, ScopeFlags flags)
|
||||
void context_change_scope_with_flags(SemaContext *context, ScopeFlags flags, SourceSpan span)
|
||||
{
|
||||
unsigned depth = context->active_scope.depth + 1;
|
||||
if (depth > MAX_SCOPE_DEPTH)
|
||||
{
|
||||
FATAL_ERROR("Too deeply nested scopes.");
|
||||
sema_error_at(context, span, "Resolution failed due to too deeply nested scopes (%u).", depth);
|
||||
exit_compiler(COMPILER_SUCCESS_EXIT);
|
||||
}
|
||||
|
||||
bool scope_is_dead = context->active_scope.is_dead;
|
||||
@@ -57,9 +58,9 @@ const char *context_filename(SemaContext *context)
|
||||
return file->full_path;
|
||||
}
|
||||
|
||||
void context_change_scope_for_label(SemaContext *context, DeclId label_id)
|
||||
void context_change_scope_for_label(SemaContext *context, DeclId label_id, SourceSpan span)
|
||||
{
|
||||
context_change_scope_with_flags(context, SCOPE_NONE);
|
||||
context_change_scope_with_flags(context, SCOPE_NONE, span);
|
||||
|
||||
if (label_id)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user