diff --git a/core/fmt/fmt.odin b/core/fmt/fmt.odin index d05fc98f0..b137e0eb8 100644 --- a/core/fmt/fmt.odin +++ b/core/fmt/fmt.odin @@ -125,7 +125,7 @@ bprintf :: proc(buf: []byte, fmt: string, args: ..any) -> string { } -assertf :: proc "contextless" (condition: bool, fmt: string, args: ..any, loc := #caller_location) -> bool { +assertf :: proc(condition: bool, fmt: string, args: ..any, loc := #caller_location) -> bool { if !condition { p := context.assertion_failure_proc; if p == nil { @@ -137,7 +137,7 @@ assertf :: proc "contextless" (condition: bool, fmt: string, args: ..any, loc := return condition; } -panicf :: proc "contextless" (fmt: string, args: ..any, loc := #caller_location) { +panicf :: proc(fmt: string, args: ..any, loc := #caller_location) { p := context.assertion_failure_proc; if p == nil { p = runtime.default_assertion_failure_proc; diff --git a/core/runtime/core.odin b/core/runtime/core.odin index d3cccd02a..c1ecc4b9c 100644 --- a/core/runtime/core.odin +++ b/core/runtime/core.odin @@ -440,6 +440,12 @@ default_logger :: proc() -> Logger { } +default_context :: proc "contextless" () -> Context { + c: Context; + __init_context(&c); + return c; +} + @private __init_context_from_ptr :: proc "contextless" (c: ^Context, other: ^Context) { if c == nil do return; diff --git a/src/check_expr.cpp b/src/check_expr.cpp index d55692a41..159ae5e3a 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -7724,6 +7724,15 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type return kind; } + if (unparen_expr(c->assignment_lhs_hint) == node) { + c->scope->flags |= ScopeFlag_ContextDefined; + } + + if ((c->scope->flags & ScopeFlag_ContextDefined) == 0) { + error(node, "'context' has not been defined within this scope"); + // Continue with value + } + init_core_context(c->checker); o->mode = Addressing_Context; o->type = t_context; diff --git a/src/check_type.cpp b/src/check_type.cpp index 976c945fd..8d8bae1a7 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -2501,6 +2501,19 @@ bool check_procedure_type(CheckerContext *ctx, Type *type, Ast *proc_type_node, c->curr_proc_sig = type; c->in_proc_sig = true; + + ProcCallingConvention cc = pt->calling_convention; + if (cc == ProcCC_ForeignBlockDefault) { + cc = ProcCC_CDecl; + if (c->foreign_context.default_cc > 0) { + cc = c->foreign_context.default_cc; + } + } + GB_ASSERT(cc > 0); + if (cc == ProcCC_Odin) { + c->scope->flags |= ScopeFlag_ContextDefined; + } + bool variadic = false; isize variadic_index = -1; bool success = true; @@ -2534,14 +2547,7 @@ bool check_procedure_type(CheckerContext *ctx, Type *type, Ast *proc_type_node, } - ProcCallingConvention cc = pt->calling_convention; - if (cc == ProcCC_ForeignBlockDefault) { - cc = ProcCC_CDecl; - if (c->foreign_context.default_cc > 0) { - cc = c->foreign_context.default_cc; - } - } - GB_ASSERT(cc > 0); + bool optional_ok = (pt->tags & ProcTag_optional_ok) != 0; if (optional_ok) { diff --git a/src/checker.cpp b/src/checker.cpp index 992aeb9b3..2bf79134d 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -231,6 +231,11 @@ Scope *create_scope(Scope *parent, gbAllocator allocator, isize init_elements_ca if (parent != nullptr && parent != builtin_pkg->scope) { DLIST_APPEND(parent->first_child, parent->last_child, s); } + + if (parent != nullptr && parent->flags & ScopeFlag_ContextDefined) { + s->flags |= ScopeFlag_ContextDefined; + } + return s; } diff --git a/src/checker.hpp b/src/checker.hpp index 5f5486fe2..efd6aae54 100644 --- a/src/checker.hpp +++ b/src/checker.hpp @@ -158,7 +158,7 @@ struct ProcInfo { -enum ScopeFlag { +enum ScopeFlag : i32 { ScopeFlag_Pkg = 1<<1, ScopeFlag_Global = 1<<2, ScopeFlag_File = 1<<3, @@ -167,6 +167,8 @@ enum ScopeFlag { ScopeFlag_Type = 1<<6, ScopeFlag_HasBeenImported = 1<<10, // This is only applicable to file scopes + + ScopeFlag_ContextDefined = 1<<16, }; struct Scope {