|
@@ -676,20 +676,45 @@ gb_internal bool check_vet_unused(Checker *c, Entity *e, VettedEntity *ve) {
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
-gb_internal void check_scope_usage(Checker *c, Scope *scope, u64 vet_flags) {
|
|
|
|
- bool vet_unused = (vet_flags & VetFlag_Unused) != 0;
|
|
|
|
- bool vet_shadowing = (vet_flags & (VetFlag_Shadowing|VetFlag_Using)) != 0;
|
|
|
|
-
|
|
|
|
|
|
+gb_internal void check_scope_usage_internal(Checker *c, Scope *scope, u64 vet_flags, bool per_entity) {
|
|
|
|
+ u64 original_vet_flags = vet_flags;
|
|
Array<VettedEntity> vetted_entities = {};
|
|
Array<VettedEntity> vetted_entities = {};
|
|
array_init(&vetted_entities, heap_allocator());
|
|
array_init(&vetted_entities, heap_allocator());
|
|
|
|
+ defer (array_free(&vetted_entities));
|
|
|
|
|
|
rw_mutex_shared_lock(&scope->mutex);
|
|
rw_mutex_shared_lock(&scope->mutex);
|
|
for (auto const &entry : scope->elements) {
|
|
for (auto const &entry : scope->elements) {
|
|
Entity *e = entry.value;
|
|
Entity *e = entry.value;
|
|
if (e == nullptr) continue;
|
|
if (e == nullptr) continue;
|
|
|
|
+
|
|
|
|
+ vet_flags = original_vet_flags;
|
|
|
|
+ if (per_entity) {
|
|
|
|
+ vet_flags = ast_file_vet_flags(e->file);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ bool vet_unused = (vet_flags & VetFlag_Unused) != 0;
|
|
|
|
+ bool vet_shadowing = (vet_flags & (VetFlag_Shadowing|VetFlag_Using)) != 0;
|
|
|
|
+ bool vet_unused_procedures = (vet_flags & VetFlag_UnusedProcedures) != 0;
|
|
|
|
+
|
|
VettedEntity ve_unused = {};
|
|
VettedEntity ve_unused = {};
|
|
VettedEntity ve_shadowed = {};
|
|
VettedEntity ve_shadowed = {};
|
|
- bool is_unused = vet_unused && check_vet_unused(c, e, &ve_unused);
|
|
|
|
|
|
+ bool is_unused = false;
|
|
|
|
+ if (vet_unused && check_vet_unused(c, e, &ve_unused)) {
|
|
|
|
+ is_unused = true;
|
|
|
|
+ } else if (vet_unused_procedures &&
|
|
|
|
+ e->kind == Entity_Procedure) {
|
|
|
|
+ if (e->flags&EntityFlag_Used) {
|
|
|
|
+ is_unused = false;
|
|
|
|
+ } else if (e->flags & EntityFlag_Require) {
|
|
|
|
+ is_unused = false;
|
|
|
|
+ } else if (e->pkg && e->pkg->kind == Package_Init && e->token.string == "main") {
|
|
|
|
+ is_unused = false;
|
|
|
|
+ } else {
|
|
|
|
+ is_unused = true;
|
|
|
|
+ ve_unused.kind = VettedEntity_Unused;
|
|
|
|
+ ve_unused.entity = e;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
bool is_shadowed = vet_shadowing && check_vet_shadowing(c, e, &ve_shadowed);
|
|
bool is_shadowed = vet_shadowing && check_vet_shadowing(c, e, &ve_shadowed);
|
|
if (is_unused && is_shadowed) {
|
|
if (is_unused && is_shadowed) {
|
|
VettedEntity ve_both = ve_shadowed;
|
|
VettedEntity ve_both = ve_shadowed;
|
|
@@ -712,13 +737,18 @@ gb_internal void check_scope_usage(Checker *c, Scope *scope, u64 vet_flags) {
|
|
}
|
|
}
|
|
rw_mutex_shared_unlock(&scope->mutex);
|
|
rw_mutex_shared_unlock(&scope->mutex);
|
|
|
|
|
|
- gb_sort(vetted_entities.data, vetted_entities.count, gb_size_of(VettedEntity), vetted_entity_variable_pos_cmp);
|
|
|
|
|
|
+ array_sort(vetted_entities, vetted_entity_variable_pos_cmp);
|
|
|
|
|
|
for (auto const &ve : vetted_entities) {
|
|
for (auto const &ve : vetted_entities) {
|
|
Entity *e = ve.entity;
|
|
Entity *e = ve.entity;
|
|
Entity *other = ve.other;
|
|
Entity *other = ve.other;
|
|
String name = e->token.string;
|
|
String name = e->token.string;
|
|
|
|
|
|
|
|
+ vet_flags = original_vet_flags;
|
|
|
|
+ if (per_entity) {
|
|
|
|
+ vet_flags = ast_file_vet_flags(e->file);
|
|
|
|
+ }
|
|
|
|
+
|
|
if (ve.kind == VettedEntity_Shadowed_And_Unused) {
|
|
if (ve.kind == VettedEntity_Shadowed_And_Unused) {
|
|
error(e->token, "'%.*s' declared but not used, possibly shadows declaration at line %d", LIT(name), other->token.pos.line);
|
|
error(e->token, "'%.*s' declared but not used, possibly shadows declaration at line %d", LIT(name), other->token.pos.line);
|
|
} else if (vet_flags) {
|
|
} else if (vet_flags) {
|
|
@@ -727,6 +757,9 @@ gb_internal void check_scope_usage(Checker *c, Scope *scope, u64 vet_flags) {
|
|
if (e->kind == Entity_Variable && (vet_flags & VetFlag_UnusedVariables) != 0) {
|
|
if (e->kind == Entity_Variable && (vet_flags & VetFlag_UnusedVariables) != 0) {
|
|
error(e->token, "'%.*s' declared but not used", LIT(name));
|
|
error(e->token, "'%.*s' declared but not used", LIT(name));
|
|
}
|
|
}
|
|
|
|
+ if (e->kind == Entity_Procedure && (vet_flags & VetFlag_UnusedProcedures) != 0) {
|
|
|
|
+ error(e->token, "'%.*s' declared but not used", LIT(name));
|
|
|
|
+ }
|
|
if ((e->kind == Entity_ImportName || e->kind == Entity_LibraryName) && (vet_flags & VetFlag_UnusedImports) != 0) {
|
|
if ((e->kind == Entity_ImportName || e->kind == Entity_LibraryName) && (vet_flags & VetFlag_UnusedImports) != 0) {
|
|
error(e->token, "'%.*s' declared but not used", LIT(name));
|
|
error(e->token, "'%.*s' declared but not used", LIT(name));
|
|
}
|
|
}
|
|
@@ -744,7 +777,11 @@ gb_internal void check_scope_usage(Checker *c, Scope *scope, u64 vet_flags) {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- array_free(&vetted_entities);
|
|
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+gb_internal void check_scope_usage(Checker *c, Scope *scope, u64 vet_flags) {
|
|
|
|
+ check_scope_usage_internal(c, scope, vet_flags, false);
|
|
|
|
|
|
for (Scope *child = scope->head_child; child != nullptr; child = child->next) {
|
|
for (Scope *child = scope->head_child; child != nullptr; child = child->next) {
|
|
if (child->flags & (ScopeFlag_Proc|ScopeFlag_Type|ScopeFlag_File)) {
|
|
if (child->flags & (ScopeFlag_Proc|ScopeFlag_Type|ScopeFlag_File)) {
|
|
@@ -6495,6 +6532,10 @@ gb_internal void check_parsed_files(Checker *c) {
|
|
u64 vet_flags = ast_file_vet_flags(f);
|
|
u64 vet_flags = ast_file_vet_flags(f);
|
|
check_scope_usage(c, f->scope, vet_flags);
|
|
check_scope_usage(c, f->scope, vet_flags);
|
|
}
|
|
}
|
|
|
|
+ for (auto const &entry : c->info.packages) {
|
|
|
|
+ AstPackage *pkg = entry.value;
|
|
|
|
+ check_scope_usage_internal(c, pkg->scope, 0, true);
|
|
|
|
+ }
|
|
|
|
|
|
TIME_SECTION("add basic type information");
|
|
TIME_SECTION("add basic type information");
|
|
// Add "Basic" type information
|
|
// Add "Basic" type information
|