The bounds of a `switch` range case were checked against the tag but
never converted to its type, unlike a single case value, so untyped
bounds took their own default type. Against a `cstring` tag `"0"..="9"`
became `string` bounds, and converting a constant `string` to `cstring`
in the backend crashed the compiler. A `cstring16` or `string16` tag
failed with an invalid conversion from `string` instead. Convert the
bounds to the tag's type, which also gives an invalid bound the same
error as a single case value.
A constant `cstring` or `cstring16` tag forced the `string` comparison
procedures rather than its own, so it failed with a missing
`cstring_le` or `cstring16_le` even with typed bounds.
`lb_get_const_string` expected the data pointer of a constant string to
be a zero index GEP, which LLVM folds to the global itself, and it is
null for an empty string, so it read an invalid constant expression.
Handle both, and have a converted empty string point to its terminator
like a constant `cstring` rather than be nil.
Fixes#7853
With `-use-separate-modules`, modules are generated on parallel threads and
name the same entities (e.g. a struct from a shared package) at the same time.
`lb_get_entity_name` cached the name by writing plain `String` fields on the
shared `Entity` (`TypeName.ir_mangled_name`, `Procedure.link_name` and
`Variable.link_name`), so another thread could read a non-zero `len` with a
null or partially written `text` and crash in `alloc_cstring`.
Cache the name in an `std::atomic<String *>` on `Entity` published with a
compare-exchange, as `lb_local_proc_name` already does, and stop writing the
name back into `link_name`, which other threads also read whilst
canonicalizing names. `link_name` now only ever holds the checker's name.
Fixes#7862
example
```odin
Scope :: any_dec
any_dec :: union {
^type_incomplete_declaration,
^type_enum_declaration,
...
sym_scope :: struct {
syms : map[StrHandle][dynamic]symbol,
parent_scope : Scope,
}
sym_scope_make :: proc(parent : Scope, alloc : mem.Allocator) -> sym_scope {
return sym_scope{make(map[StrHandle][dynamic]symbol, 0, alloc), parent} ---sometimes error here
}
```
depending on where the alias was declared, can output
```
Error: Cannot assign value 'parent' of type 'any_dec' to 'union {^type_incomplete_declaration, ...}' in a structure literal
... sym_scope{make(map[StrHandle][dynamic]symbol, 0, alloc), parent}
```
haven't been able to recreate a minimal reproduceable test case yet