From 8ca7fc481fad1a335b5ca46b9f997396df9be1aa Mon Sep 17 00:00:00 2001 From: Krzesimir Nowak Date: Sun, 21 Dec 2025 18:59:21 +0100 Subject: Fix misleading error messages for init, fini and test attributes These look like copy-pasta from the private attribute. --- src/checker.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/checker.cpp') diff --git a/src/checker.cpp b/src/checker.cpp index 4d5482933..33121b453 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -3581,7 +3581,7 @@ gb_internal DECL_ATTRIBUTE_PROC(proc_decl_attribute) { return true; } else if (name == "test") { if (value != nullptr) { - error(value, "'%.*s' expects no parameter, or a string literal containing \"file\" or \"package\"", LIT(name)); + error(value, "Expected no value for '%.*s'", LIT(name)); } ac->test = true; return true; @@ -3629,13 +3629,13 @@ gb_internal DECL_ATTRIBUTE_PROC(proc_decl_attribute) { return true; } else if (name == "init") { if (value != nullptr) { - error(value, "'%.*s' expects no parameter, or a string literal containing \"file\" or \"package\"", LIT(name)); + error(value, "Expected no value for '%.*s'", LIT(name)); } ac->init = true; return true; } else if (name == "fini") { if (value != nullptr) { - error(value, "'%.*s' expects no parameter, or a string literal containing \"file\" or \"package\"", LIT(name)); + error(value, "Expected no value for '%.*s'", LIT(name)); } ac->fini = true; return true; -- cgit v1.2.3 From 93d7e2a4526bc1075f6eef26b3e1ba6345450f05 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 30 Dec 2025 13:08:30 +0000 Subject: Add `globaldynamic` `thread_local` model (same as the current `default`) --- src/checker.cpp | 2 ++ src/llvm_backend_general.cpp | 2 ++ 2 files changed, 4 insertions(+) (limited to 'src/checker.cpp') diff --git a/src/checker.cpp b/src/checker.cpp index 33121b453..13d02c512 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -4027,6 +4027,7 @@ gb_internal DECL_ATTRIBUTE_PROC(var_decl_attribute) { } else if (ev.kind == ExactValue_String) { String model = ev.value_string; if (model == "default" || + model == "globaldynamic" || model == "localdynamic" || model == "initialexec" || model == "localexec") { @@ -4035,6 +4036,7 @@ gb_internal DECL_ATTRIBUTE_PROC(var_decl_attribute) { ERROR_BLOCK(); error(elem, "Invalid thread local model '%.*s'. Valid models:", LIT(model)); error_line("\tdefault\n"); + error_line("\tglobaldynamic\n"); error_line("\tlocaldynamic\n"); error_line("\tinitialexec\n"); error_line("\tlocalexec\n"); diff --git a/src/llvm_backend_general.cpp b/src/llvm_backend_general.cpp index 4ebb40d96..c0e57143d 100644 --- a/src/llvm_backend_general.cpp +++ b/src/llvm_backend_general.cpp @@ -2628,6 +2628,8 @@ gb_internal bool lb_apply_thread_local_model(LLVMValueRef value, String model) { LLVMThreadLocalMode mode = LLVMGeneralDynamicTLSModel; if (model == "default") { mode = LLVMGeneralDynamicTLSModel; + } else if (model == "globaldynamic") { + mode = LLVMGeneralDynamicTLSModel; } else if (model == "localdynamic") { mode = LLVMLocalDynamicTLSModel; } else if (model == "initialexec") { -- cgit v1.2.3 From 7fa05f16bfc55a3380c758bdedaf3da351774713 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 3 Jan 2026 20:14:15 +0000 Subject: Minor change from `make_checker_context` to `init_checker_context` --- src/checker.cpp | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) (limited to 'src/checker.cpp') diff --git a/src/checker.cpp b/src/checker.cpp index 13d02c512..ab3ba50dd 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -1530,17 +1530,16 @@ gb_internal void destroy_checker_info(CheckerInfo *i) { map_destroy(&i->load_directory_map); } -gb_internal CheckerContext make_checker_context(Checker *c) { - CheckerContext ctx = {}; - ctx.checker = c; - ctx.info = &c->info; - ctx.scope = builtin_pkg->scope; - ctx.pkg = builtin_pkg; +gb_internal void init_checker_context(CheckerContext *ctx, Checker *c) { + ctx->checker = c; + ctx->info = &c->info; + ctx->scope = builtin_pkg->scope; + ctx->pkg = builtin_pkg; - ctx.type_path = new_checker_type_path(heap_allocator()); - ctx.type_level = 0; - return ctx; + ctx->type_path = new_checker_type_path(heap_allocator()); + ctx->type_level = 0; } + gb_internal void destroy_checker_context(CheckerContext *ctx) { destroy_checker_type_path(ctx->type_path, heap_allocator()); } @@ -1605,7 +1604,7 @@ gb_internal void init_checker(Checker *c) { mpsc_init(&c->global_untyped_queue, a); // , 1<<20); mpsc_init(&c->soa_types_to_complete, a); // , 1<<20); - c->builtin_ctx = make_checker_context(c); + init_checker_context(&c->builtin_ctx, c); } gb_internal void destroy_checker(Checker *c) { @@ -4964,7 +4963,7 @@ gb_internal void check_collect_entities(CheckerContext *c, Slice const &n gb_internal CheckerContext *create_checker_context(Checker *c) { CheckerContext *ctx = gb_alloc_item(permanent_allocator(), CheckerContext); - *ctx = make_checker_context(c); + init_checker_context(ctx, c); return ctx; } @@ -5409,7 +5408,8 @@ gb_internal DECL_ATTRIBUTE_PROC(foreign_import_decl_attribute) { } gb_internal void check_foreign_import_fullpaths(Checker *c) { - CheckerContext ctx = make_checker_context(c); + CheckerContext ctx = {}; + init_checker_context(&ctx, c); UntypedExprInfoMap untyped = {}; defer (map_destroy(&untyped)); @@ -5792,7 +5792,7 @@ gb_internal void check_collect_entities_all(Checker *c) { for (isize i = 0; i < thread_count; i++) { auto *wd = &collect_entity_worker_data[i]; wd->c = c; - wd->ctx = make_checker_context(c); + init_checker_context(&wd->ctx, c); map_init(&wd->untyped); } @@ -5833,7 +5833,7 @@ gb_internal void check_export_entities(Checker *c) { for (isize i = 0; i < thread_count; i++) { auto *wd = &collect_entity_worker_data[i]; map_clear(&wd->untyped); - wd->ctx = make_checker_context(c); + init_checker_context(&wd->ctx, c); } for (auto const &entry : c->info.packages) { @@ -5900,7 +5900,8 @@ gb_internal void check_import_entities(Checker *c) { } TIME_SECTION("check_import_entities - collect file decls"); - CheckerContext ctx = make_checker_context(c); + CheckerContext ctx = {}; + init_checker_context(&ctx, c); UntypedExprInfoMap untyped = {}; defer (map_destroy(&untyped)); @@ -6249,7 +6250,8 @@ gb_internal bool check_proc_info(Checker *c, ProcInfo *pi, UntypedExprInfoMap *u } } - CheckerContext ctx = make_checker_context(c); + CheckerContext ctx = {}; + init_checker_context(&ctx, c); defer (destroy_checker_context(&ctx)); reset_checker_context(&ctx, pi->file, untyped); ctx.decl = pi->decl; -- cgit v1.2.3 From f4a7e0b279043357a550c26f1972835f9f5688a1 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 15 Jan 2026 18:06:25 +0000 Subject: Add `@(no_sanitize_thread)` --- src/check_decl.cpp | 1 + src/checker.cpp | 6 ++++++ src/checker.hpp | 1 + src/entity.cpp | 1 + src/llvm_backend_proc.cpp | 2 +- 5 files changed, 10 insertions(+), 1 deletion(-) (limited to 'src/checker.cpp') diff --git a/src/check_decl.cpp b/src/check_decl.cpp index 27babd255..8019d00c3 100644 --- a/src/check_decl.cpp +++ b/src/check_decl.cpp @@ -1473,6 +1473,7 @@ gb_internal void check_proc_decl(CheckerContext *ctx, Entity *e, DeclInfo *d) { e->Procedure.no_sanitize_address = ac.no_sanitize_address; e->Procedure.no_sanitize_memory = ac.no_sanitize_memory; + e->Procedure.no_sanitize_thread = ac.no_sanitize_thread; e->deprecated_message = ac.deprecated_message; e->warning_message = ac.warning_message; diff --git a/src/checker.cpp b/src/checker.cpp index ab3ba50dd..453f3e241 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -3990,6 +3990,12 @@ gb_internal DECL_ATTRIBUTE_PROC(proc_decl_attribute) { } ac->no_sanitize_memory = true; return true; + } else if (name == "no_sanitize_thread") { + if (value != nullptr) { + error(value, "'%.*s' expects no parameter", LIT(name)); + } + ac->no_sanitize_thread = true; + return true; } return false; } diff --git a/src/checker.hpp b/src/checker.hpp index bda7b2746..f9c279a51 100644 --- a/src/checker.hpp +++ b/src/checker.hpp @@ -141,6 +141,7 @@ struct AttributeContext { bool instrumentation_exit : 1; bool no_sanitize_address : 1; bool no_sanitize_memory : 1; + bool no_sanitize_thread : 1; bool rodata : 1; bool ignore_duplicates : 1; u32 optimization_mode; // ProcedureOptimizationMode diff --git a/src/entity.cpp b/src/entity.cpp index 2b21fdcac..55aca8069 100644 --- a/src/entity.cpp +++ b/src/entity.cpp @@ -268,6 +268,7 @@ struct Entity { bool is_anonymous : 1; bool no_sanitize_address : 1; bool no_sanitize_memory : 1; + bool no_sanitize_thread : 1; bool is_objc_impl_or_import : 1; bool is_objc_class_method : 1; } Procedure; diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp index 9ac51bba3..524c37186 100644 --- a/src/llvm_backend_proc.cpp +++ b/src/llvm_backend_proc.cpp @@ -347,7 +347,7 @@ gb_internal lbProcedure *lb_create_procedure(lbModule *m, Entity *entity, bool i if (build_context.sanitizer_flags & SanitizerFlag_Memory && !entity->Procedure.no_sanitize_memory) { lb_add_attribute_to_proc(m, p->value, "sanitize_memory"); } - if (build_context.sanitizer_flags & SanitizerFlag_Thread) { + if (build_context.sanitizer_flags & SanitizerFlag_Thread && !entity->Procedure.no_sanitize_thread) { lb_add_attribute_to_proc(m, p->value, "sanitize_thread"); } } -- cgit v1.2.3