diff --git a/lib/std/hash/fnv32a.c3 b/lib/std/hash/fnv32a.c3 index a0eddaeca..ad185d811 100644 --- a/lib/std/hash/fnv32a.c3 +++ b/lib/std/hash/fnv32a.c3 @@ -5,8 +5,8 @@ module std::hash::fnv32a; typedef Fnv32a = uint; -const FNV32A_START @private = 0x811c9dc5; -const FNV32A_MUL @private = 0x01000193; +const FNV32A_START @private = (Fnv32a)0x811c9dc5; +const FNV32A_MUL @private = (Fnv32a)0x01000193; macro void update(h, char x) @private => *h = (*h ^ ($typeof(*h))x) * FNV32A_MUL; @@ -32,10 +32,10 @@ macro void Fnv32a.update_char(&self, char c) fn uint hash(char[] data) { - uint h = FNV32A_START; + Fnv32a h = FNV32A_START; foreach (char x : data) { update(&h, x); } - return h; + return (uint)h; } diff --git a/lib/std/hash/fnv64a.c3 b/lib/std/hash/fnv64a.c3 index cd108710a..6500f90c4 100644 --- a/lib/std/hash/fnv64a.c3 +++ b/lib/std/hash/fnv64a.c3 @@ -5,10 +5,10 @@ module std::hash::fnv64a; typedef Fnv64a = ulong; -const FNV64A_START @private = 0xcbf29ce484222325; -const FNV64A_MUL @private = 0x00000100000001b3; +const Fnv64a FNV64A_START @private = (Fnv64a)0xcbf29ce484222325; +const Fnv64a FNV64A_MUL @private = (Fnv64a)0x00000100000001b3; -macro void update(h, char x) @private => *h = (*h ^ ($typeof(*h))x) * FNV64A_MUL; +macro Fnv64a update(Fnv64a h, char x) @nodiscard @private => (h ^ (Fnv64a)x) * FNV64A_MUL; fn void Fnv64a.init(&self) { @@ -20,22 +20,22 @@ fn void Fnv64a.update(&self, char[] data) Fnv64a h = *self; foreach (char x : data) { - update(&h, x); + h = update(h, x); } *self = h; } macro void Fnv64a.update_char(&self, char c) { - update(self, c); + *self = update(*self, c); } fn ulong hash(char[] data) { - ulong h = FNV64A_START; + Fnv64a h = FNV64A_START; foreach (char x : data) { - update(&h, x); + h = update(h, x); } - return h; + return (ulong)h; } diff --git a/lib/std/os/win32/shell32.c3 b/lib/std/os/win32/shell32.c3 index 504c3e586..9a2a40d66 100644 --- a/lib/std/os/win32/shell32.c3 +++ b/lib/std/os/win32/shell32.c3 @@ -1,6 +1,6 @@ module std::os::win32 @if(env::WIN32) @link("shell32"); -typedef Win32_REFKNOWNFOLDERID = Win32_KNOWNFOLDERID*; +alias Win32_REFKNOWNFOLDERID = Win32_KNOWNFOLDERID*; typedef Win32_KNOWNFOLDERID = Win32_GUID; extern fn Win32_HRESULT shGetKnownFolderPath(Win32_REFKNOWNFOLDERID rfid, Win32_DWORD dwFlags, Win32_HANDLE hToken, Win32_PWSTR* ppszPath) @cname("SHGetKnownFolderPath"); diff --git a/lib/std/threads/os/thread_none.c3 b/lib/std/threads/os/thread_none.c3 index b46457b06..65b1d731d 100644 --- a/lib/std/threads/os/thread_none.c3 +++ b/lib/std/threads/os/thread_none.c3 @@ -8,9 +8,9 @@ typedef NativeThread = int; fn void NativeOnceFlag.call_once(&flag, OnceFn func) { - if (*flag == 0) + if (*flag == (NativeOnceFlag)0) { - *flag = 1; + *flag = (NativeOnceFlag)1; func(); } } diff --git a/releasenotes.md b/releasenotes.md index 6de1552e9..06b4d134f 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -12,6 +12,8 @@ - New const enum declaration syntax. - New enum associated value syntax. - Individual warning settings added. +- Change typedef and const enums to not convert from literals by default. +- Add `@constinit` to allow old typedef behaviour. ### Stdlib changes - Summarize sort macros as generic function wrappers to reduce the amount of generated code. #2831 diff --git a/src/compiler/compiler_internal.h b/src/compiler/compiler_internal.h index 81e530339..0c7a6cef1 100644 --- a/src/compiler/compiler_internal.h +++ b/src/compiler/compiler_internal.h @@ -717,6 +717,7 @@ typedef struct Decl_ bool resolved_attributes : 1; bool allow_deprecated : 1; bool attr_structlike : 1; + bool attr_constinit : 1; bool is_template : 1; bool is_templated : 1; bool is_method_checked : 1; diff --git a/src/compiler/enums.h b/src/compiler/enums.h index 4ba0ff942..e35c9a0f8 100644 --- a/src/compiler/enums.h +++ b/src/compiler/enums.h @@ -628,6 +628,7 @@ typedef enum ATTRIBUTE_CNAME, ATTRIBUTE_COMPACT, ATTRIBUTE_CONST, + ATTRIBUTE_CONSTINIT, ATTRIBUTE_DEPRECATED, ATTRIBUTE_DYNAMIC, ATTRIBUTE_EXPORT, diff --git a/src/compiler/sema_casts.c b/src/compiler/sema_casts.c index 878b84686..2ea4ea2ad 100644 --- a/src/compiler/sema_casts.c +++ b/src/compiler/sema_casts.c @@ -1459,15 +1459,24 @@ static bool rule_to_distinct(CastContext *cc, bool is_explicit, bool is_silent) { is_const = true; } - if (is_const && (cc->is_binary_conversion || !cc->to->decl->attr_structlike)) + if (is_const && (cc->is_binary_conversion || cc->to->decl->attr_constinit || !cc->to->decl->attr_structlike)) { + Type *to_type = cc->to; cc->to = flat; cc->to_group = flat_group; // If it's silent or explicit, just run it: if (is_silent || is_explicit) return cast_is_allowed(cc, is_explicit, is_silent); // Loud and implicit: - if (cast_is_allowed(cc, false, true)) return true; + if (cast_is_allowed(cc, false, true)) + { + if (!cc->is_binary_conversion && !to_type->decl->attr_constinit && !expr_is_const_untyped_list(cc->expr)) + { + to_type->decl->attr_constinit = true; + SEMA_DEPRECATED(cc->expr, "Implicit conversion of constants to distinct types is deprecated, use @constinit if %s should cast constants to its own type.", type_quoted_error_string(to_type)); + } + return true; + } return sema_cast_error(cc, cast_is_allowed(cc, true, true), is_silent); } diff --git a/src/compiler/sema_decls.c b/src/compiler/sema_decls.c index a6bd06834..4560424f4 100644 --- a/src/compiler/sema_decls.c +++ b/src/compiler/sema_decls.c @@ -3128,6 +3128,7 @@ static bool sema_analyse_attribute(SemaContext *context, ResolvedAttrData *attr_ [ATTRIBUTE_CNAME] = ATTR_FUNC | ATTR_GLOBAL | ATTR_CONST | USER_DEFINED_TYPES, [ATTRIBUTE_COMPACT] = ATTR_STRUCT | ATTR_UNION, [ATTRIBUTE_CONST] = ATTR_MACRO, + [ATTRIBUTE_CONSTINIT] = ATTR_TYPEDEF | ATTR_ENUM, [ATTRIBUTE_DEPRECATED] = USER_DEFINED_TYPES | CALLABLE_TYPE | ATTR_CONST | ATTR_GLOBAL | ATTR_MEMBER | ATTR_BITSTRUCT_MEMBER | ATTR_INTERFACE | ATTR_ALIAS, [ATTRIBUTE_DYNAMIC] = ATTR_FUNC, [ATTRIBUTE_EXPORT] = ATTR_FUNC | ATTR_GLOBAL | ATTR_CONST | USER_DEFINED_TYPES | ATTR_ALIAS, @@ -3471,6 +3472,9 @@ static bool sema_analyse_attribute(SemaContext *context, ResolvedAttrData *attr_ case ATTRIBUTE_STRUCTLIKE: decl->attr_structlike = true; return true; + case ATTRIBUTE_CONSTINIT: + decl->attr_constinit = true; + return true; case ATTRIBUTE_SIMD: RETURN_SEMA_ERROR(attr, "'@simd' is only allowed on typedef types."); case ATTRIBUTE_SECTION: diff --git a/src/compiler/symtab.c b/src/compiler/symtab.c index bcc4bd296..ec5bbc754 100644 --- a/src/compiler/symtab.c +++ b/src/compiler/symtab.c @@ -347,6 +347,7 @@ void symtab_init(uint32_t capacity) attribute_list[ATTRIBUTE_CNAME] = KW_DEF("@cname"); attribute_list[ATTRIBUTE_COMPACT] = KW_DEF("@compact"); attribute_list[ATTRIBUTE_CONST] = KW_DEF("@const"); + attribute_list[ATTRIBUTE_CONSTINIT] = KW_DEF("@constinit"); attribute_list[ATTRIBUTE_DEPRECATED] = KW_DEF("@deprecated"); attribute_list[ATTRIBUTE_DYNAMIC] = KW_DEF("@dynamic"); attribute_list[ATTRIBUTE_EXPORT] = KW_DEF("@export"); diff --git a/test/test_suite/distinct/test_ops_on_int.c3 b/test/test_suite/distinct/test_ops_on_int.c3 index 853195695..331c1b854 100644 --- a/test/test_suite/distinct/test_ops_on_int.c3 +++ b/test/test_suite/distinct/test_ops_on_int.c3 @@ -1,6 +1,6 @@ module test; -typedef Foo = int; +typedef Foo @constinit = int; fn int test1() { diff --git a/test/test_suite/enumerations/enum_const.c3t b/test/test_suite/enumerations/enum_const.c3t index 304867db2..147ffc728 100644 --- a/test/test_suite/enumerations/enum_const.c3t +++ b/test/test_suite/enumerations/enum_const.c3t @@ -24,7 +24,7 @@ const enum Bde2 : int BAR = 100 } -typedef Bde3 = int; +typedef Bde3 @constinit = int; const BDE3_FOO = 2; const BDE3_BAR = 100;