Disallow aliasing of @local symbols with a higher visibility in the alias.

This commit is contained in:
Christoffer Lerno
2025-10-10 14:04:19 +02:00
parent df67b7dddd
commit 6f11260a5c
7 changed files with 29 additions and 8 deletions

View File

@@ -8,7 +8,8 @@
- Add new builtins `$$str_snakecase` `$$str_replace` and `$$str_pascalcase`.
- `"build-dir"` option now available for `project.json`, added to project. #2323
- Allow `..` ranges to use "a..a-1" in order to express zero length.
- Disallow aliasing of `@local` symbols with a higher visibility in the alias.
### Fixes
- Bug in `io::write_using_write_byte`.
- Bitstruct value cannot be used to index a const array in compile time. #2512
@@ -16,8 +17,8 @@
- Bitstruct truncated constant error escapes `$defined` #2515.
- Compiler segfault when accessing member of number cast to bitstruct #2516.
- Compiler assert when getting a member of a `bitstruct : char @bigendian` #2517.
- Incorrect visibility on local globals with public aliases. #2519
- Add ??? and +++= to list-precedence.
- Fix issues with linking when using symbol aliases. #2519
### Stdlib changes
- Sorting functions correctly took slices by value, but also other types by value. Now, only slices are accepted by value, other containers are always by ref.

View File

@@ -142,6 +142,7 @@ bool context_is_macro(SemaContext *context)
void unit_register_external_symbol(SemaContext *context, Decl *decl)
{
decl = decl_flatten(decl);
if (decl->is_external_visible) return;
Module *active_module = context->current_macro ? context->original_module : context->compilation_unit->module;
if (decl->unit->module == active_module) return;

View File

@@ -5302,6 +5302,11 @@ static inline bool sema_analyse_alias(SemaContext *context, Decl *decl, bool *er
}
decl->type = symbol->type;
decl->define_decl.alias = symbol;
if (symbol->visibility == VISIBLE_LOCAL && decl->visibility < VISIBLE_LOCAL)
{
RETURN_SEMA_ERROR(decl, "A local symbol like '%s' may not be aliased to 'private' or 'public' visibility, please change it to at least be '@private'", symbol->name);
}
// If the symbol is more hidden than the alias, then we must increase the visibility.
if (decl_is_externally_visible(decl) && !decl_is_externally_visible(symbol))
{
symbol->is_external_visible = true;

View File

@@ -10614,7 +10614,7 @@ static inline bool sema_expr_analyse_lambda(SemaContext *context, Type *target_t
{
decl->var.is_read = true;
}
decl->is_external_visible = true;
decl_flatten(decl)->is_external_visible = true;
vec_add(unit->module->lambdas_to_evaluate, decl);
}
else

View File

@@ -830,7 +830,7 @@ INLINE bool sema_resolve_symbol_common(SemaContext *context, NameResolve *name_r
SEMA_NOTE(found, "'%s' is defined here.", found->name);
return false;
}
unit_register_external_symbol(context, found);
if (found->decl_kind != DECL_ALIAS) unit_register_external_symbol(context, found);
if (found->unit->module->is_generic)
{
if (name_resolve->is_parameterized) return true;

View File

@@ -1,20 +1,32 @@
// #target: macos-x64
module test1;
alias x = y;
int y @local = 1;
int y @private = 1;
module test2;
int z @private = 1;
module test;
import test1;
import test2 @public;
alias z = test2::z;
fn int main(String[] args)
{
return test1::x;
return test1::x + z;
}
/* #expect: test1.ll
@test1.y.10 = local_unnamed_addr global i32 1, align 4
@test1.y = local_unnamed_addr global i32 1, align 4
/* #expect: test2.ll
@test2.z = local_unnamed_addr global i32 1, align 4
// #expect: test.ll
@test1.y.10 = external global i32, align 4
@test1.y = external global i32, align 4
@test2.z = external global i32, align 4

View File

@@ -0,0 +1,2 @@
alias x @private = y; // #error: A local symbol like
int y @local = 1;