mirror of
https://github.com/odin-lang/Odin.git
synced 2026-07-22 23:42:33 +00:00
Merge branch 'master' into bill/bedrock
This commit is contained in:
132
src/checker.cpp
132
src/checker.cpp
@@ -791,7 +791,10 @@ gb_internal void check_scope_usage_internal(Checker *c, Scope *scope, u64 vet_fl
|
||||
array_add(&vetted_entities, ve_unused);
|
||||
} else if (is_shadowed) {
|
||||
array_add(&vetted_entities, ve_shadowed);
|
||||
} else if (e->kind == Entity_Variable && (e->flags & (EntityFlag_Param|EntityFlag_Using|EntityFlag_Static|EntityFlag_Field)) == 0 && !e->Variable.is_global) {
|
||||
} else if (e->kind == Entity_Variable &&
|
||||
((e->flags & (EntityFlag_Param|EntityFlag_Using|EntityFlag_Static|EntityFlag_Field)) == 0 ||
|
||||
(e->flags & EntityFlag_Result) != 0) &&
|
||||
!e->Variable.is_global) {
|
||||
i64 sz = type_size_of(e->type);
|
||||
// TODO(bill): When is a good size warn?
|
||||
// Is >256 KiB good enough?
|
||||
@@ -1042,14 +1045,14 @@ struct GlobalEnumValue {
|
||||
i64 value;
|
||||
};
|
||||
|
||||
gb_internal Slice<Entity *> add_global_enum_type(String const &type_name, GlobalEnumValue *values, isize value_count, Type **enum_type_ = nullptr, Type *base_type = t_int) {
|
||||
gb_internal Slice<Entity *> add_global_enum_type(String const &type_name, GlobalEnumValue *values, isize value_count, Type **enum_type_ = nullptr, Type *backing_type = nullptr) {
|
||||
Scope *scope = create_scope(nullptr, builtin_pkg->scope);
|
||||
Entity *entity = alloc_entity_type_name(scope, make_token_ident(type_name), nullptr, EntityState_Resolved);
|
||||
|
||||
Type *enum_type = alloc_type_enum();
|
||||
Type *named_type = alloc_type_named(type_name, enum_type, entity);
|
||||
set_base_type(named_type, enum_type);
|
||||
enum_type->Enum.base_type = base_type;
|
||||
enum_type->Enum.base_type = backing_type ? backing_type : t_int;
|
||||
enum_type->Enum.scope = scope;
|
||||
entity->type = named_type;
|
||||
|
||||
@@ -1181,7 +1184,6 @@ gb_internal void init_universal(void) {
|
||||
{"Darwin", TargetOs_darwin},
|
||||
{"Linux", TargetOs_linux},
|
||||
{"FreeBSD", TargetOs_freebsd},
|
||||
{"Haiku", TargetOs_haiku},
|
||||
{"OpenBSD", TargetOs_openbsd},
|
||||
{"NetBSD", TargetOs_netbsd},
|
||||
{"WASI", TargetOs_wasi},
|
||||
@@ -1261,6 +1263,41 @@ gb_internal void init_universal(void) {
|
||||
add_global_enum_constant(fields, "ODIN_ERROR_POS_STYLE", build_context.ODIN_ERROR_POS_STYLE);
|
||||
}
|
||||
|
||||
{
|
||||
GlobalEnumValue values[OdinFastMath_COUNT] = {};
|
||||
for (unsigned i = 0; i < OdinFastMath_COUNT; i++) {
|
||||
values[i] = {OdinFastMathFlag_strings[i], i};
|
||||
}
|
||||
|
||||
auto fields = add_global_enum_type(str_lit("Fast_Math_Flag"), values, gb_count_of(values), &t_fast_math_flag, t_u8);
|
||||
|
||||
GB_ASSERT(t_fast_math_flag->kind == Type_Named);
|
||||
scope_insert(intrinsics_pkg->scope, t_fast_math_flag->Named.type_name);
|
||||
|
||||
Type *bs = alloc_type_bit_set();
|
||||
bs->BitSet.elem = t_fast_math_flag;
|
||||
bs->BitSet.underlying = t_u32;
|
||||
bs->BitSet.lower = 0;
|
||||
bs->BitSet.upper = OdinFastMath_COUNT-1;
|
||||
bs->BitSet.node = nullptr;
|
||||
|
||||
|
||||
{
|
||||
String type_name = str_lit("Fast_Math_Flags");
|
||||
|
||||
Scope *scope = create_scope(nullptr, builtin_pkg->scope);
|
||||
Entity *entity = alloc_entity_type_name(scope, make_token_ident(type_name), nullptr, EntityState_Resolved);
|
||||
|
||||
Type *named_type = alloc_type_named(type_name, bs, entity);
|
||||
set_base_type(named_type, bs);
|
||||
entity->type = named_type;
|
||||
|
||||
t_fast_math_flags = named_type;
|
||||
|
||||
scope_insert(intrinsics_pkg->scope, entity);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
GlobalEnumValue values[OdinAtomicMemoryOrder_COUNT] = {
|
||||
{OdinAtomicMemoryOrder_strings[OdinAtomicMemoryOrder_relaxed], OdinAtomicMemoryOrder_relaxed},
|
||||
@@ -2877,9 +2914,11 @@ gb_internal void collect_testing_procedures_of_package(Checker *c, AstPackage *p
|
||||
InternedString interned = string_interner_insert(str_lit("Test_Signature"), 0, &hash);
|
||||
Entity *test_signature = scope_lookup_current(testing_scope, interned, hash);
|
||||
|
||||
Scope *s = pkg->scope;
|
||||
for (auto const &entry : s->elements) {
|
||||
Entity *e = entry.value;
|
||||
for_array(i, c->info.entities) {
|
||||
Entity *e = c->info.entities[i];
|
||||
if (e->pkg != pkg) {
|
||||
continue;
|
||||
}
|
||||
if (e->kind != Entity_Procedure) {
|
||||
continue;
|
||||
}
|
||||
@@ -3591,11 +3630,17 @@ gb_internal void init_preload(Checker *c) {
|
||||
init_core_objc_c(c);
|
||||
}
|
||||
|
||||
gb_internal ExactValue check_decl_attribute_value(CheckerContext *c, Ast *value) {
|
||||
gb_internal void check_expr_with_type_hint(CheckerContext *c, Operand *o, Ast *e, Type *t);
|
||||
|
||||
gb_internal ExactValue check_decl_attribute_value(CheckerContext *c, Ast *value, Type *type_hint = nullptr) {
|
||||
ExactValue ev = {};
|
||||
if (value != nullptr) {
|
||||
Operand op = {};
|
||||
check_expr(c, &op, value);
|
||||
if (type_hint != nullptr) {
|
||||
check_expr_with_type_hint(c, &op, value, type_hint);
|
||||
} else {
|
||||
check_expr(c, &op, value);
|
||||
}
|
||||
if (op.mode) {
|
||||
if (op.mode == Addressing_Constant) {
|
||||
ev = op.value;
|
||||
@@ -3607,6 +3652,52 @@ gb_internal ExactValue check_decl_attribute_value(CheckerContext *c, Ast *value)
|
||||
return ev;
|
||||
}
|
||||
|
||||
gb_internal bool is_foreign_name_valid(String const &name) {
|
||||
if (name.len == 0) {
|
||||
return false;
|
||||
}
|
||||
isize offset = 0;
|
||||
while (offset < name.len) {
|
||||
Rune rune;
|
||||
isize remaining = name.len - offset;
|
||||
isize width = utf8_decode(name.text+offset, remaining, &rune);
|
||||
if (rune == GB_RUNE_INVALID && width == 1) {
|
||||
return false;
|
||||
} else if (rune == GB_RUNE_BOM && remaining > 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO(bill, 2026-06-02): This entire logic needs to be completely figured out
|
||||
// as to what should be allowed or not
|
||||
// The original limitations of `-$._ +` and alphanumeric was more of an assumption
|
||||
// than the actual technical limitations of all linkers.
|
||||
if (offset == 0) {
|
||||
switch (rune) {
|
||||
case '-':
|
||||
case '$':
|
||||
case '.':
|
||||
case '_':
|
||||
case ':':
|
||||
break;
|
||||
default:
|
||||
if (!gb_char_is_alpha(cast(char)rune))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
int n = utf8proc_charwidth(rune);
|
||||
if (n <= 0) {
|
||||
// not a printable character
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
offset += width;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#define ATTRIBUTE_USER_TAG_NAME "tag"
|
||||
|
||||
@@ -3967,6 +4058,17 @@ gb_internal DECL_ATTRIBUTE_PROC(proc_decl_attribute) {
|
||||
error(elem, "Expected a string value for '%.*s'", LIT(name));
|
||||
}
|
||||
return true;
|
||||
} else if (name == "link_section") {
|
||||
ExactValue ev = check_decl_attribute_value(c, value);
|
||||
if (ev.kind == ExactValue_String) {
|
||||
ac->link_section = ev.value_string;
|
||||
if (!is_foreign_name_valid(ac->link_section)) {
|
||||
error(elem, "Invalid link section: %.*s", LIT(ac->link_section));
|
||||
}
|
||||
} else {
|
||||
error(elem, "Expected a string value for '%.*s'", LIT(name));
|
||||
}
|
||||
return true;
|
||||
} else if (name == "deprecated") {
|
||||
ExactValue ev = check_decl_attribute_value(c, value);
|
||||
|
||||
@@ -4163,6 +4265,18 @@ gb_internal DECL_ATTRIBUTE_PROC(proc_decl_attribute) {
|
||||
}
|
||||
ac->no_sanitize_thread = true;
|
||||
return true;
|
||||
} else if (name == "fast_math") {
|
||||
if (value == nullptr) {
|
||||
error(elem, "Expected a constant bit_set of type 'intrinsics.Fast_Math_Flags' for '%.*s'", LIT(name));
|
||||
} else {
|
||||
ExactValue ev = check_decl_attribute_value(c, value, t_fast_math_flags);
|
||||
if (ev.kind != ExactValue_Integer) {
|
||||
error(elem, "Expected a constant bit_set of type 'intrinsics.Fast_Math_Flags' for '%.*s'", LIT(name));
|
||||
} else {
|
||||
ac->fast_math_flags = exact_value_to_u64(ev);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user