From 2a2d3273eae791c5c21eb77374f4818c2a76ae1b Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 12 Mar 2020 14:40:13 +0000 Subject: [PATCH] Add `@require` for global variables --- src/check_decl.cpp | 5 +++++ src/checker.cpp | 22 ++++++++++++++++++---- src/checker.hpp | 3 ++- src/ir.cpp | 2 ++ 4 files changed, 27 insertions(+), 5 deletions(-) diff --git a/src/check_decl.cpp b/src/check_decl.cpp index ece38e84f..0e12a2822 100644 --- a/src/check_decl.cpp +++ b/src/check_decl.cpp @@ -843,6 +843,11 @@ void check_global_variable_decl(CheckerContext *ctx, Entity *e, Ast *type_expr, check_decl_attributes(ctx, decl->attributes, var_decl_attribute, &ac); } + if (ac.require_declaration) { + array_add(&ctx->info->required_global_variables, e); + } + + e->Variable.thread_local_model = ac.thread_local_model; e->Variable.is_export = ac.is_export; if (ac.is_static) { diff --git a/src/checker.cpp b/src/checker.cpp index 3f9d3ba71..c840faa45 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -805,6 +805,7 @@ void init_checker_info(CheckerInfo *i) { map_init(&i->packages, a); array_init(&i->variable_init_order, a); array_init(&i->required_foreign_imports_through_force, a); + array_init(&i->required_global_variables, a); i->allow_identifier_uses = build_context.query_data_set_settings.kind == QueryDataSet_GoToDefinitions; if (i->allow_identifier_uses) { @@ -826,6 +827,7 @@ void destroy_checker_info(CheckerInfo *i) { array_free(&i->variable_init_order); array_free(&i->identifier_uses); array_free(&i->required_foreign_imports_through_force); + array_free(&i->required_global_variables); } @@ -1744,6 +1746,12 @@ void generate_minimum_dependency_set(Checker *c, Entity *start) { add_dependency_to_set(c, e); } + for_array(i, c->info.required_global_variables) { + Entity *e = c->info.required_global_variables[i]; + e->flags |= EntityFlag_Used; + add_dependency_to_set(c, e); + } + add_dependency_to_set(c, start); } @@ -2330,7 +2338,13 @@ DECL_ATTRIBUTE_PROC(var_decl_attribute) { return true; } - if (name == "export") { + if (name == "require") { + if (value != nullptr) { + error(elem, "'static' does not have any parameters"); + } + ac->require_declaration = true; + return true; + } else if (name == "export") { ExactValue ev = check_decl_attribute_value(c, value); if (ev.kind == ExactValue_Invalid) { ac->is_export = true; @@ -3293,11 +3307,11 @@ void check_add_import_decl(CheckerContext *ctx, Ast *decl) { } DECL_ATTRIBUTE_PROC(foreign_import_decl_attribute) { - if (name == "force") { + if (name == "force" || name == "require") { if (value != nullptr) { error(elem, "Expected no parameter for '%.*s'", LIT(name)); } - ac->force_foreign_import = true; + ac->require_declaration = true; return true; } return false; @@ -3350,7 +3364,7 @@ void check_add_foreign_import_decl(CheckerContext *ctx, Ast *decl) { AttributeContext ac = {}; check_decl_attributes(ctx, fl->attributes, foreign_import_decl_attribute, &ac); - if (ac.force_foreign_import) { + if (ac.require_declaration) { array_add(&ctx->info->required_foreign_imports_through_force, e); add_entity_use(ctx, nullptr, e); } diff --git a/src/checker.hpp b/src/checker.hpp index 8ad0c0481..afa16e261 100644 --- a/src/checker.hpp +++ b/src/checker.hpp @@ -98,7 +98,7 @@ struct AttributeContext { bool is_export; bool is_static; bool require_results; - bool force_foreign_import; + bool require_declaration; bool has_disabled_proc; bool disabled_proc; String link_name; @@ -259,6 +259,7 @@ struct CheckerInfo { PtrSet minimum_dependency_type_info_set; Array required_foreign_imports_through_force; + Array required_global_variables; bool allow_identifier_uses; diff --git a/src/ir.cpp b/src/ir.cpp index da0075ec8..867a28259 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -11844,6 +11844,8 @@ void ir_gen_tree(irGen *s) { if (!ir_min_dep_entity(m, e)) { continue; } + + DeclInfo *decl = decl_info_of_entity(e); if (decl == nullptr) { continue;