diff --git a/lib/std/core/builtin.c3 b/lib/std/core/builtin.c3 index c148210ea..ecc187ec7 100644 --- a/lib/std/core/builtin.c3 +++ b/lib/std/core/builtin.c3 @@ -26,24 +26,25 @@ def VoidFn = fn void(); Stores a variable on the stack, then restores it at the end of the macro scope. - @param variable `the variable to store and restore` + @param #variable `the variable to store and restore` + @require values::@is_lvalue(#variable) *> -macro void @scope(&variable; @body) @builtin +macro void @scope(#variable; @body) @builtin { - var temp = *variable; - defer *variable = temp; + var temp = #variable; + defer #variable = temp; @body(); } <* Swap two variables - @require $assignable(*b, $typeof(*a)) && $assignable(*a, $typeof(*b)) + @require $defined(#a = #b, #b = #a) `The values must be mutually assignable` *> -macro void @swap(&a, &b) @builtin +macro void @swap(#a, #b) @builtin { - var temp = *a; - *a = *b; - *b = temp; + var temp = #a; + #a = #b; + #b = temp; } <* @@ -366,9 +367,12 @@ macro bool @ok(#expr) @builtin return true; } -macro char[] @as_char_view(&value) @builtin +<* + @require $defined(&#value, (char*)&#value) "This must be a value that can be viewed as a char array" + *> +macro char[] @as_char_view(#value) @builtin { - return ((char*)value)[:$sizeof(*value)]; + return ((char*)&#value)[:$sizeof(#value)]; } macro isz @str_find(String $string, String $needle) @builtin => $$str_find($string, $needle); diff --git a/lib/std/core/mem.c3 b/lib/std/core/mem.c3 index 1c90b3833..44b765a69 100644 --- a/lib/std/core/mem.c3 +++ b/lib/std/core/mem.c3 @@ -162,42 +162,55 @@ macro @scatter_aligned(ptrvec, value, bool[<*>] mask, usz $alignment) } <* - @param [in] x "The variable or dereferenced pointer to load." + @param #x "The variable or dereferenced pointer to load." @param $alignment "The alignment to assume for the load" - @return "The value of x" + @return "The value of the variable" @require @constant_is_power_of_2($alignment) : "The alignment must be a power of two" + @require $defined(&#x) : "This must be a variable or dereferenced pointer" *> -macro @unaligned_load(&x, usz $alignment) @builtin +macro @unaligned_load(#x, usz $alignment) @builtin { - return $$unaligned_load(x, $alignment); + return $$unaligned_load(&#x, $alignment); } <* - @param [out] x "The variable or dereferenced pointer to store to." + @param #x "The variable or dereferenced pointer to store to." @param value "The value to store." @param $alignment "The alignment to assume for the store" - @return "The value of x" + @return "The value stored" - @require $assignable(value, $typeof(*x)) : "The value doesn't match the variable" + @require $defined(&#x) : "This must be a variable or dereferenced pointer" + @require $defined(#x = value) : "The value doesn't match the variable" @require @constant_is_power_of_2($alignment) : "The alignment must be a power of two" *> -macro @unaligned_store(&x, value, usz $alignment) @builtin +macro @unaligned_store(#x, value, usz $alignment) @builtin { - return $$unaligned_store(x, ($typeof(*x))value, $alignment); -} - -macro @volatile_load(&x) @builtin -{ - return $$volatile_load(x); + return $$unaligned_store(&#x, ($typeof(#x))value, $alignment); } <* - @require $assignable(y, $typeof(*x)) : "The value doesn't match the variable" + @param #x "The variable or dereferenced pointer to load." + @return "The value of the variable" + + @require $defined(&#x) : "This must be a variable or dereferenced pointer" *> -macro @volatile_store(&x, y) @builtin +macro @volatile_load(#x) @builtin { - return $$volatile_store(x, ($typeof(*x))y); + return $$volatile_load(&#x); +} + +<* + @param #x "The variable or dereferenced pointer to store to." + @param value "The value to store." + @return "The value stored" + + @require $defined(&#x) : "This must be a variable or dereferenced pointer" + @require $defined(#x = value) : "The value doesn't match the variable" +*> +macro @volatile_store(#x, value) @builtin +{ + return $$volatile_store(&#x, ($typeof(#x))value); } enum AtomicOrdering : int @@ -212,34 +225,36 @@ enum AtomicOrdering : int } <* - @param [in] x "the variable or dereferenced pointer to load." + @param #x "the variable or dereferenced pointer to load." @param $ordering "atomic ordering of the load, defaults to SEQ_CONSISTENT" @param $volatile "whether the load should be volatile, defaults to 'false'" @return "returns the value of x" + @require $defined(&#x) : "This must be a variable or dereferenced pointer" @require $ordering != AtomicOrdering.RELEASE "Release ordering is not valid for load." @require $ordering != AtomicOrdering.ACQUIRE_RELEASE "Acquire release is not valid for load." - @require types::may_load_atomic($typeof(x)) "Only integer, float and pointers may be used." - @require @typekind(x) == POINTER "You can only load from a pointer" + @require types::may_load_atomic($typeof(#x)) "Only integer, float and pointers may be used." *> -macro @atomic_load(&x, AtomicOrdering $ordering = SEQ_CONSISTENT, $volatile = false) @builtin +macro @atomic_load(#x, AtomicOrdering $ordering = SEQ_CONSISTENT, $volatile = false) @builtin { - return $$atomic_load(x, $volatile, $ordering.ordinal); + return $$atomic_load(&#x, $volatile, $ordering.ordinal); } <* - @param [out] x "the variable or dereferenced pointer to store to." + @param #x "the variable or dereferenced pointer to store to." @param value "the value to store." @param $ordering "the atomic ordering of the store, defaults to SEQ_CONSISTENT" @param $volatile "whether the store should be volatile, defaults to 'false'" @require $ordering != AtomicOrdering.ACQUIRE "Acquire ordering is not valid for store." @require $ordering != AtomicOrdering.ACQUIRE_RELEASE "Acquire release is not valid for store." - @require types::may_load_atomic($typeof(x)) "Only integer, float and pointers may be used." + @require types::may_load_atomic($typeof(#x)) "Only integer, float and pointers may be used." + @require $defined(&#x) : "This must be a variable or dereferenced pointer" + @require $defined(#x = value) : "The value doesn't match the variable" *> -macro void @atomic_store(&x, value, AtomicOrdering $ordering = SEQ_CONSISTENT, $volatile = false) @builtin +macro void @atomic_store(#x, value, AtomicOrdering $ordering = SEQ_CONSISTENT, $volatile = false) @builtin { - $$atomic_store(x, value, $volatile, $ordering.ordinal); + $$atomic_store(&#x, value, $volatile, $ordering.ordinal); } <* diff --git a/lib/std/core/values.c3 b/lib/std/core/values.c3 index 4439d52b1..f77e286ce 100644 --- a/lib/std/core/values.c3 +++ b/lib/std/core/values.c3 @@ -16,6 +16,7 @@ macro bool @is_promotable_to_float(#value) @const => types::is_promotable_to_flo macro bool @is_vector(#value) @const => types::is_vector($typeof(#value)); macro bool @is_same_vector_type(#value1, #value2) @const => types::is_same_vector_type($typeof(#value1), $typeof(#value2)); macro bool @assign_to(#value1, #value2) @const => $assignable(#value1, $typeof(#value2)); +macro bool @is_lvalue(#value) => $defined(#value = #value); macro promote_int(x) { diff --git a/lib/std/hash/md5.c3 b/lib/std/hash/md5.c3 index 1b429131f..b0c3af751 100644 --- a/lib/std/hash/md5.c3 +++ b/lib/std/hash/md5.c3 @@ -106,7 +106,7 @@ macro @h(x, y, z) => (x ^ y) ^ z; macro @h2(x, y, z) => x ^ (y ^ z); macro @i(x, y, z) => y ^ (x | ~z); -macro @step(#f, &a, b, c, d, ptr, n, t, s) +macro @step(#f, a, b, c, d, ptr, n, t, s) { *a += #f(b, c, d) + *(uint *)&ptr[n * 4] + t; *a = (*a << s) | ((*a & 0xffffffff) >> (32 - s)); @@ -133,76 +133,76 @@ fn char* body(Md5* ctx, void* data, usz size) saved_d = d; /* Round 1 */ - @step(@f, a, b, c, d, ptr, 0, 0xd76aa478, 7) ; - @step(@f, d, a, b, c, ptr, 1, 0xe8c7b756, 12) ; - @step(@f, c, d, a, b, ptr, 2, 0x242070db, 17) ; - @step(@f, b, c, d, a, ptr, 3, 0xc1bdceee, 22) ; - @step(@f, a, b, c, d, ptr, 4, 0xf57c0faf, 7) ; - @step(@f, d, a, b, c, ptr, 5, 0x4787c62a, 12) ; - @step(@f, c, d, a, b, ptr, 6, 0xa8304613, 17) ; - @step(@f, b, c, d, a, ptr, 7, 0xfd469501, 22) ; - @step(@f, a, b, c, d, ptr, 8, 0x698098d8, 7) ; - @step(@f, d, a, b, c, ptr, 9, 0x8b44f7af, 12) ; - @step(@f, c, d, a, b, ptr, 10, 0xffff5bb1, 17); - @step(@f, b, c, d, a, ptr, 11, 0x895cd7be, 22); - @step(@f, a, b, c, d, ptr, 12, 0x6b901122, 7) ; - @step(@f, d, a, b, c, ptr, 13, 0xfd987193, 12); - @step(@f, c, d, a, b, ptr, 14, 0xa679438e, 17); - @step(@f, b, c, d, a, ptr, 15, 0x49b40821, 22); + @step(@f, &a, b, c, d, ptr, 0, 0xd76aa478, 7) ; + @step(@f, &d, a, b, c, ptr, 1, 0xe8c7b756, 12) ; + @step(@f, &c, d, a, b, ptr, 2, 0x242070db, 17) ; + @step(@f, &b, c, d, a, ptr, 3, 0xc1bdceee, 22) ; + @step(@f, &a, b, c, d, ptr, 4, 0xf57c0faf, 7) ; + @step(@f, &d, a, b, c, ptr, 5, 0x4787c62a, 12) ; + @step(@f, &c, d, a, b, ptr, 6, 0xa8304613, 17) ; + @step(@f, &b, c, d, a, ptr, 7, 0xfd469501, 22) ; + @step(@f, &a, b, c, d, ptr, 8, 0x698098d8, 7) ; + @step(@f, &d, a, b, c, ptr, 9, 0x8b44f7af, 12) ; + @step(@f, &c, d, a, b, ptr, 10, 0xffff5bb1, 17); + @step(@f, &b, c, d, a, ptr, 11, 0x895cd7be, 22); + @step(@f, &a, b, c, d, ptr, 12, 0x6b901122, 7) ; + @step(@f, &d, a, b, c, ptr, 13, 0xfd987193, 12); + @step(@f, &c, d, a, b, ptr, 14, 0xa679438e, 17); + @step(@f, &b, c, d, a, ptr, 15, 0x49b40821, 22); /* Round 2 */ - @step(@g, a, b, c, d, ptr, 1, 0xf61e2562, 5) ; - @step(@g, d, a, b, c, ptr, 6, 0xc040b340, 9) ; - @step(@g, c, d, a, b, ptr, 11, 0x265e5a51, 14); - @step(@g, b, c, d, a, ptr, 0, 0xe9b6c7aa, 20) ; - @step(@g, a, b, c, d, ptr, 5, 0xd62f105d, 5) ; - @step(@g, d, a, b, c, ptr, 10, 0x02441453, 9) ; - @step(@g, c, d, a, b, ptr, 15, 0xd8a1e681, 14); - @step(@g, b, c, d, a, ptr, 4, 0xe7d3fbc8, 20) ; - @step(@g, a, b, c, d, ptr, 9, 0x21e1cde6, 5) ; - @step(@g, d, a, b, c, ptr, 14, 0xc33707d6, 9) ; - @step(@g, c, d, a, b, ptr, 3, 0xf4d50d87, 14) ; - @step(@g, b, c, d, a, ptr, 8, 0x455a14ed, 20) ; - @step(@g, a, b, c, d, ptr, 13, 0xa9e3e905, 5) ; - @step(@g, d, a, b, c, ptr, 2, 0xfcefa3f8, 9) ; - @step(@g, c, d, a, b, ptr, 7, 0x676f02d9, 14) ; - @step(@g, b, c, d, a, ptr, 12, 0x8d2a4c8a, 20); + @step(@g, &a, b, c, d, ptr, 1, 0xf61e2562, 5) ; + @step(@g, &d, a, b, c, ptr, 6, 0xc040b340, 9) ; + @step(@g, &c, d, a, b, ptr, 11, 0x265e5a51, 14); + @step(@g, &b, c, d, a, ptr, 0, 0xe9b6c7aa, 20) ; + @step(@g, &a, b, c, d, ptr, 5, 0xd62f105d, 5) ; + @step(@g, &d, a, b, c, ptr, 10, 0x02441453, 9) ; + @step(@g, &c, d, a, b, ptr, 15, 0xd8a1e681, 14); + @step(@g, &b, c, d, a, ptr, 4, 0xe7d3fbc8, 20) ; + @step(@g, &a, b, c, d, ptr, 9, 0x21e1cde6, 5) ; + @step(@g, &d, a, b, c, ptr, 14, 0xc33707d6, 9) ; + @step(@g, &c, d, a, b, ptr, 3, 0xf4d50d87, 14) ; + @step(@g, &b, c, d, a, ptr, 8, 0x455a14ed, 20) ; + @step(@g, &a, b, c, d, ptr, 13, 0xa9e3e905, 5) ; + @step(@g, &d, a, b, c, ptr, 2, 0xfcefa3f8, 9) ; + @step(@g, &c, d, a, b, ptr, 7, 0x676f02d9, 14) ; + @step(@g, &b, c, d, a, ptr, 12, 0x8d2a4c8a, 20); /* Round 3 */ - @step(@h, a, b, c, d, ptr, 5, 0xfffa3942, 4); - @step(@h2, d, a, b, c, ptr, 8, 0x8771f681, 11); - @step(@h, c, d, a, b, ptr, 11, 0x6d9d6122, 16); - @step(@h2, b, c, d, a, ptr, 14, 0xfde5380c, 23); - @step(@h, a, b, c, d, ptr, 1, 0xa4beea44, 4); - @step(@h2, d, a, b, c, ptr, 4, 0x4bdecfa9, 11); - @step(@h, c, d, a, b, ptr, 7, 0xf6bb4b60, 16); - @step(@h2, b, c, d, a, ptr, 10, 0xbebfbc70, 23); - @step(@h, a, b, c, d, ptr, 13, 0x289b7ec6, 4) ; - @step(@h2, d, a, b, c, ptr, 0, 0xeaa127fa, 11) ; - @step(@h, c, d, a, b, ptr, 3, 0xd4ef3085, 16) ; - @step(@h2, b, c, d, a, ptr, 6, 0x04881d05, 23) ; - @step(@h, a, b, c, d, ptr, 9, 0xd9d4d039, 4) ; - @step(@h2, d, a, b, c, ptr, 12, 0xe6db99e5, 11) ; - @step(@h, c, d, a, b, ptr, 15, 0x1fa27cf8, 16) ; - @step(@h2, b, c, d, a, ptr, 2, 0xc4ac5665, 23) ; + @step(@h, &a, b, c, d, ptr, 5, 0xfffa3942, 4); + @step(@h2, &d, a, b, c, ptr, 8, 0x8771f681, 11); + @step(@h, &c, d, a, b, ptr, 11, 0x6d9d6122, 16); + @step(@h2, &b, c, d, a, ptr, 14, 0xfde5380c, 23); + @step(@h, &a, b, c, d, ptr, 1, 0xa4beea44, 4); + @step(@h2, &d, a, b, c, ptr, 4, 0x4bdecfa9, 11); + @step(@h, &c, d, a, b, ptr, 7, 0xf6bb4b60, 16); + @step(@h2, &b, c, d, a, ptr, 10, 0xbebfbc70, 23); + @step(@h, &a, b, c, d, ptr, 13, 0x289b7ec6, 4) ; + @step(@h2, &d, a, b, c, ptr, 0, 0xeaa127fa, 11) ; + @step(@h, &c, d, a, b, ptr, 3, 0xd4ef3085, 16) ; + @step(@h2, &b, c, d, a, ptr, 6, 0x04881d05, 23) ; + @step(@h, &a, b, c, d, ptr, 9, 0xd9d4d039, 4) ; + @step(@h2, &d, a, b, c, ptr, 12, 0xe6db99e5, 11) ; + @step(@h, &c, d, a, b, ptr, 15, 0x1fa27cf8, 16) ; + @step(@h2, &b, c, d, a, ptr, 2, 0xc4ac5665, 23) ; /* Round 4 */ - @step(@i, a, b, c, d, ptr, 0, 0xf4292244, 6) ; - @step(@i, d, a, b, c, ptr, 7, 0x432aff97, 10) ; - @step(@i, c, d, a, b, ptr, 14, 0xab9423a7, 15) ; - @step(@i, b, c, d, a, ptr, 5, 0xfc93a039, 21) ; - @step(@i, a, b, c, d, ptr, 12, 0x655b59c3, 6) ; - @step(@i, d, a, b, c, ptr, 3, 0x8f0ccc92, 10) ; - @step(@i, c, d, a, b, ptr, 10, 0xffeff47d, 15) ; - @step(@i, b, c, d, a, ptr, 1, 0x85845dd1, 21) ; - @step(@i, a, b, c, d, ptr, 8, 0x6fa87e4f, 6) ; - @step(@i, d, a, b, c, ptr, 15, 0xfe2ce6e0, 10) ; - @step(@i, c, d, a, b, ptr, 6, 0xa3014314, 15) ; - @step(@i, b, c, d, a, ptr, 13, 0x4e0811a1, 21) ; - @step(@i, a, b, c, d, ptr, 4, 0xf7537e82, 6) ; - @step(@i, d, a, b, c, ptr, 11, 0xbd3af235, 10) ; - @step(@i, c, d, a, b, ptr, 2, 0x2ad7d2bb, 15) ; - @step(@i, b, c, d, a, ptr, 9, 0xeb86d391, 21) ; + @step(@i, &a, b, c, d, ptr, 0, 0xf4292244, 6) ; + @step(@i, &d, a, b, c, ptr, 7, 0x432aff97, 10) ; + @step(@i, &c, d, a, b, ptr, 14, 0xab9423a7, 15) ; + @step(@i, &b, c, d, a, ptr, 5, 0xfc93a039, 21) ; + @step(@i, &a, b, c, d, ptr, 12, 0x655b59c3, 6) ; + @step(@i, &d, a, b, c, ptr, 3, 0x8f0ccc92, 10) ; + @step(@i, &c, d, a, b, ptr, 10, 0xffeff47d, 15) ; + @step(@i, &b, c, d, a, ptr, 1, 0x85845dd1, 21) ; + @step(@i, &a, b, c, d, ptr, 8, 0x6fa87e4f, 6) ; + @step(@i, &d, a, b, c, ptr, 15, 0xfe2ce6e0, 10) ; + @step(@i, &c, d, a, b, ptr, 6, 0xa3014314, 15) ; + @step(@i, &b, c, d, a, ptr, 13, 0x4e0811a1, 21) ; + @step(@i, &a, b, c, d, ptr, 4, 0xf7537e82, 6) ; + @step(@i, &d, a, b, c, ptr, 11, 0xbd3af235, 10) ; + @step(@i, &c, d, a, b, ptr, 2, 0x2ad7d2bb, 15) ; + @step(@i, &b, c, d, a, ptr, 9, 0xeb86d391, 21) ; a += saved_a; b += saved_b; diff --git a/lib/std/io/stream.c3 b/lib/std/io/stream.c3 index 04e0ceb50..987d1fc17 100644 --- a/lib/std/io/stream.c3 +++ b/lib/std/io/stream.c3 @@ -104,7 +104,7 @@ macro usz! write_all(stream, char[] buffer) return n; } -macro usz! @read_using_read_byte(&s, char[] buffer) +macro usz! @read_using_read_byte(&s, char[] buffer) @deprecated { return read_using_read_byte(*s, buffer); } @@ -137,7 +137,7 @@ macro void! @write_byte_using_write(&s, char c) @deprecated return write_byte_using_write(*s, c); } -macro char! @read_byte_using_read(&s) +macro char! @read_byte_using_read(&s) @deprecated { return read_byte_using_read(*s); } diff --git a/lib/std/net/socket.c3 b/lib/std/net/socket.c3 index d6b798288..bb6458792 100644 --- a/lib/std/net/socket.c3 +++ b/lib/std/net/socket.c3 @@ -132,7 +132,7 @@ $endif return (usz)n; } -fn char! Socket.read_byte(&self) @dynamic => io::@read_byte_using_read(self); +fn char! Socket.read_byte(&self) @dynamic => io::read_byte_using_read(self); fn usz! Socket.write(&self, char[] bytes) @dynamic { diff --git a/releasenotes.md b/releasenotes.md index 6b28b2780..dc885dd02 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -21,6 +21,7 @@ - Include `@name` when searching for possible matches to `name` in the error message. #1779 - Improve `@param` parse errors #1777 - Improved `#foo` resolution inside of the compiler. +- Deprecated '&' macro arguments. ### Fixes - Fix case trying to initialize a `char[*]*` from a String. diff --git a/resources/examples/swap.c3 b/resources/examples/swap.c3 index daef50dbc..4d034536c 100644 --- a/resources/examples/swap.c3 +++ b/resources/examples/swap.c3 @@ -1,14 +1,14 @@ module test; -import libc; +import std::io; <* - @require values::@assign_to(*b, *a) && values::@assign_to(*a, *b) + @require $defined(#a = #b, #b = #a) *> -macro void @swap(&a, &b) +macro void @swap(#a, #b) { - var temp = *a; - *a = *b; - *b = temp; + var temp = #a; + #a = #b; + #b = temp; } fn void main() @@ -16,5 +16,5 @@ fn void main() int x = 123; int y = 456; @swap(x, y); - libc::printf("x: %d y: %d\n", x, y); + io::printfn("x: %d y: %d", x, y); } \ No newline at end of file diff --git a/src/compiler/sema_decls.c b/src/compiler/sema_decls.c index 3cd2ea293..ea631f14b 100755 --- a/src/compiler/sema_decls.c +++ b/src/compiler/sema_decls.c @@ -11,7 +11,7 @@ static inline bool sema_analyse_func_macro(SemaContext *context, Decl *decl, AttributeDomain domain, bool *erase_decl); static inline bool sema_analyse_func(SemaContext *context, Decl *decl, bool *erase_decl); static inline bool sema_analyse_macro(SemaContext *context, Decl *decl, bool *erase_decl); -static inline bool sema_analyse_signature(SemaContext *context, Signature *sig, TypeInfo *method_parent, bool is_export); +static inline bool sema_analyse_signature(SemaContext *context, Signature *sig, TypeInfo *method_parent, bool is_export, bool is_deprecated); static inline bool sema_analyse_main_function(SemaContext *context, Decl *decl); static inline bool sema_check_param_uniqueness_and_type(SemaContext *context, Decl **decls, Decl *current, unsigned current_index, unsigned count); @@ -1085,7 +1085,7 @@ ERROR: return decl_poison(decl); } -static inline bool sema_analyse_signature(SemaContext *context, Signature *sig, TypeInfo *method_parent, bool is_export) +static inline bool sema_analyse_signature(SemaContext *context, Signature *sig, TypeInfo *method_parent, bool is_export, bool is_deprecated) { Variadic variadic_type = sig->variadic; Decl **params = sig->params; @@ -1149,7 +1149,7 @@ static inline bool sema_analyse_signature(SemaContext *context, Signature *sig, case VARDECL_PARAM_REF: inferred_type = type_get_ptr(method_parent->type); param->var.not_null = true; - if (!is_macro) param->var.kind = VARDECL_PARAM; + param->var.kind = VARDECL_PARAM; break; case VARDECL_PARAM: case VARDECL_PARAM_EXPR: @@ -1224,6 +1224,10 @@ static inline bool sema_analyse_signature(SemaContext *context, Signature *sig, switch (var_kind) { case VARDECL_PARAM_REF: + if ((i != 0 || !method_parent) && !is_deprecated) + { + SEMA_DEPRECATED(param, "Reference macro arguments are deprecated."); + } if (type_info && !type_is_pointer(param->type)) { SEMA_ERROR(type_info, "A pointer type was expected for a ref argument, did you mean %s?", @@ -1239,7 +1243,7 @@ static inline bool sema_analyse_signature(SemaContext *context, Signature *sig, } if (!is_macro_at_name && (!method_parent || i != 0 || var_kind != VARDECL_PARAM_REF)) { - SEMA_ERROR(param, "Ref and expression parameters are not allowed in function-like macros. Prefix the macro name with '@'."); + SEMA_ERROR(param, "Expression parameters are not allowed in function-like macros. Prefix the macro name with '@'."); return decl_poison(param); } FALLTHROUGH; @@ -1333,7 +1337,9 @@ bool sema_analyse_function_signature(SemaContext *context, Decl *func_decl, Type // Get param count and variadic type Decl **params = signature->params; - if (!sema_analyse_signature(context, signature, parent, func_decl->is_export)) return false; + bool deprecated = func_decl->resolved_attributes && func_decl->attrs_resolved && func_decl->attrs_resolved->deprecated; + + if (!sema_analyse_signature(context, signature, parent, func_decl->is_export, deprecated)) return false; Variadic variadic_type = signature->variadic; @@ -3696,9 +3702,12 @@ static inline bool sema_analyse_macro(SemaContext *context, Decl *decl, bool *er if (!sema_analyse_func_macro(context, decl, ATTR_MACRO, erase_decl)) return false; if (*erase_decl) return true; + + bool deprecated = decl->resolved_attributes && decl->attrs_resolved && decl->attrs_resolved->deprecated; + if (!sema_analyse_signature(context, &decl->func_decl.signature, type_infoptrzero(decl->func_decl.type_parent), - false)) return false; + false, deprecated)) return false; if (!decl->func_decl.signature.is_at_macro && decl->func_decl.body_param && !decl->func_decl.signature.is_safemacro) { diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index 2aa1e68c4..c31ba76cc 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -36,7 +36,7 @@ static inline bool sema_expr_analyse_slice(SemaContext *context, Expr *expr, Che static inline bool sema_expr_analyse_access(SemaContext *context, Expr *expr, bool *missing_ref, CheckType check); static inline bool sema_expr_analyse_compound_literal(SemaContext *context, Expr *expr); static inline bool sema_expr_analyse_builtin(SemaContext *context, Expr *expr, bool throw_error); -static inline bool sema_expr_analyse_binary(SemaContext *context, Expr *expr); +static inline bool sema_expr_analyse_binary(SemaContext *context, Expr *expr, bool *failed_ref); static inline bool sema_expr_analyse_ct_eval(SemaContext *context, Expr *expr, CheckType check); static inline bool sema_expr_analyse_identifier(SemaContext *context, Type *to, Expr *expr); static inline bool sema_expr_analyse_ct_identifier(SemaContext *context, Expr *expr, CheckType check); @@ -77,7 +77,7 @@ static bool sema_expr_analyse_add_sub_assign(SemaContext *context, Expr *expr, E static bool sema_expr_analyse_slice_assign(SemaContext *context, Expr *expr, Type *left_type, Expr *right, bool is_unwrapped); static bool sema_expr_analyse_ct_identifier_assign(SemaContext *context, Expr *expr, Expr *left, Expr *right); static bool sema_expr_analyse_ct_type_identifier_assign(SemaContext *context, Expr *expr, Expr *left, Expr *right); -static bool sema_expr_analyse_assign(SemaContext *context, Expr *expr, Expr *left, Expr *right); +static bool sema_expr_analyse_assign(SemaContext *context, Expr *expr, Expr *left, Expr *right, bool *failed_ref); static bool sema_expr_analyse_comp(SemaContext *context, Expr *expr, Expr *left, Expr *right); static bool sema_expr_analyse_op_assign(SemaContext *context, Expr *expr, Expr *left, Expr *right, bool int_only, bool allow_bitstruct, bool is_add_sub); @@ -124,7 +124,7 @@ static bool sema_binary_arithmetic_promotion(SemaContext *context, Expr *left, E Expr *parent, const char *error_message, bool allow_bool_vec); static bool sema_binary_is_unsigned_always_same_comparison(SemaContext *context, Expr *expr, Expr *left, Expr *right, Type *lhs_type, Type *rhs_type); -static bool sema_binary_is_expr_lvalue(SemaContext *context, Expr *top_expr, Expr *expr); +static bool sema_binary_is_expr_lvalue(SemaContext *context, Expr *top_expr, Expr *expr, bool *failed_ref); static void sema_binary_unify_voidptr(SemaContext *context, Expr *left, Expr *right, Type **left_type_ref, Type **right_type_ref); // -- function helper functions @@ -436,40 +436,45 @@ CondResult sema_check_comp_time_bool(SemaContext *context, Expr *expr) } -static bool sema_binary_is_expr_lvalue(SemaContext *context, Expr *top_expr, Expr *expr) +static bool sema_binary_is_expr_lvalue(SemaContext *context, Expr *top_expr, Expr *expr, bool *failed_ref) { switch (expr->expr_kind) { case EXPR_SWIZZLE: + if (failed_ref) goto FAILED_REF; RETURN_SEMA_ERROR(expr, "You cannot use swizzling to assign to multiple elements, use element-wise assign instead."); case EXPR_LAMBDA: case EXPR_EMBED: + if (failed_ref) goto FAILED_REF; RETURN_SEMA_ERROR(expr, "This expression is a value and cannot be assigned to."); case EXPR_CT_IDENT: return true; case EXPR_EXT_TRUNC: case EXPR_INT_TO_BOOL: case EXPR_DISCARD: - return false; + if (failed_ref) goto FAILED_REF; + goto ERR; case EXPR_OTHER_CONTEXT: - return sema_binary_is_expr_lvalue(context, top_expr, expr->expr_other_context.inner); + return sema_binary_is_expr_lvalue(context, top_expr, expr->expr_other_context.inner, failed_ref); case EXPR_IDENTIFIER: { Decl *decl = expr->identifier_expr.decl; if (decl->decl_kind != DECL_VAR) { + if (failed_ref) goto FAILED_REF; RETURN_SEMA_ERROR(top_expr, "You cannot assign a value to %s.", decl_to_a_name(decl)); } if (decl->var.kind == VARDECL_CONST) { + if (failed_ref) goto FAILED_REF; RETURN_SEMA_ERROR(top_expr, "You cannot assign to a constant."); } decl = decl_raw(decl); switch (decl->var.kind) { case VARDECL_PARAM_REF: - SEMA_ERROR(top_expr, "You cannot assign to a ref parameter."); - return false; + if (failed_ref) goto FAILED_REF; + RETURN_SEMA_ERROR(top_expr, "You cannot assign to a ref parameter."); case VARDECL_LOCAL_CT: case VARDECL_LOCAL_CT_TYPE: case VARDECL_LOCAL: @@ -495,13 +500,13 @@ static bool sema_binary_is_expr_lvalue(SemaContext *context, Expr *top_expr, Exp if (expr->unary_expr.operator != UNARYOP_DEREF) goto ERR; if (IS_OPTIONAL(expr)) { - SEMA_ERROR(top_expr, "You cannot assign to a dereferenced optional."); - return false; + if (failed_ref) goto FAILED_REF; + RETURN_SEMA_ERROR(top_expr, "You cannot assign to a dereferenced optional."); } return true; case EXPR_BITACCESS: case EXPR_ACCESS: - if (!sema_binary_is_expr_lvalue(context, top_expr, expr->access_expr.parent)) return false; + if (!sema_binary_is_expr_lvalue(context, top_expr, expr->access_expr.parent, failed_ref)) return false; goto CHECK_OPTIONAL; case EXPR_SUBSCRIPT: case EXPR_SLICE: @@ -509,12 +514,13 @@ static bool sema_binary_is_expr_lvalue(SemaContext *context, Expr *top_expr, Exp case EXPR_SUBSCRIPT_ADDR: goto CHECK_OPTIONAL; case EXPR_HASH_IDENT: + if (failed_ref) goto FAILED_REF; RETURN_SEMA_ERROR(top_expr, "You cannot assign to an unevaluated expression."); case EXPR_EXPRESSION_LIST: - if (!vec_size(expr->expression_list)) return false; - return sema_binary_is_expr_lvalue(context, top_expr, VECLAST(expr->expression_list)); - goto CHECK_OPTIONAL; + if (!vec_size(expr->expression_list)) goto ERR; + return sema_binary_is_expr_lvalue(context, top_expr, VECLAST(expr->expression_list), failed_ref); case EXPR_CONST: + if (failed_ref) goto FAILED_REF; RETURN_SEMA_ERROR(top_expr, "You cannot assign to a constant expression."); case EXPR_POISONED: case EXPR_ADDR_CONVERSION: @@ -594,15 +600,18 @@ static bool sema_binary_is_expr_lvalue(SemaContext *context, Expr *top_expr, Exp } UNREACHABLE ERR: - SEMA_ERROR(top_expr, "An assignable expression, like a variable, was expected here."); - return false; + if (failed_ref) goto FAILED_REF; + RETURN_SEMA_ERROR(top_expr, "An assignable expression, like a variable, was expected here."); CHECK_OPTIONAL: if (IS_OPTIONAL(expr)) { + if (failed_ref) goto FAILED_REF; RETURN_SEMA_ERROR(top_expr, "You cannot assign to an optional value."); } return true; - +FAILED_REF: + *failed_ref = true; + return false; } static bool expr_may_ref(Expr *expr) @@ -744,10 +753,10 @@ static bool expr_may_ref(Expr *expr) UNREACHABLE } -bool sema_expr_check_assign(SemaContext *context, Expr *expr) +bool sema_expr_check_assign(SemaContext *context, Expr *expr, bool *failed_ref) { Expr *inner; - if (!sema_binary_is_expr_lvalue(context, expr, expr)) return false; + if (!sema_binary_is_expr_lvalue(context, expr, expr, failed_ref)) return false; if (expr->expr_kind == EXPR_SUBSCRIPT) { inner = exprptr(expr->subscript_expr.expr); @@ -766,8 +775,7 @@ CHECK_INNER: Decl *decl = inner->identifier_expr.decl; if (decl->decl_kind != DECL_VAR) return true; if (!decl->var.in_param) return true; - SEMA_ERROR(inner, "'in' parameters may not be assigned to."); - return false; + RETURN_SEMA_ERROR(inner, "'in' parameters may not be assigned to."); } static inline bool sema_cast_ident_rvalue(SemaContext *context, Expr *expr) @@ -1309,7 +1317,7 @@ static bool sema_analyse_parameter(SemaContext *context, Expr *arg, Decl *param, break; } if (!sema_analyse_expr_address(context, arg)) return false; - if (sema_arg_is_pass_through_ref(arg) && !sema_expr_check_assign(context, arg)) + if (sema_arg_is_pass_through_ref(arg) && !sema_expr_check_assign(context, arg, NULL)) { SEMA_NOTE(definition, "The definition is here."); return false; @@ -3003,7 +3011,7 @@ static inline bool sema_expr_analyse_subscript(SemaContext *context, Expr *expr, if (!sema_analyse_expr_check(context, subscripted, CHECK_VALUE)) return false; // If it is an lvalue then check that it is assignable. - if (check == CHECK_LVALUE && !sema_expr_check_assign(context, expr)) return false; + if (check == CHECK_LVALUE && !sema_expr_check_assign(context, expr, NULL)) return false; // 2. Evaluate the index. Expr *index = exprptr(expr->subscript_expr.index.expr); @@ -5677,7 +5685,7 @@ static bool sema_expr_fold_hash(SemaContext *context, Expr *expr) * Analyse a = b * @return true if analysis works */ -static bool sema_expr_analyse_assign(SemaContext *context, Expr *expr, Expr *left, Expr *right) +static bool sema_expr_analyse_assign(SemaContext *context, Expr *expr, Expr *left, Expr *right, bool *failed_ref) { if (!sema_expr_fold_hash(context, left)) return false; // 1. Evaluate left side @@ -5698,7 +5706,7 @@ static bool sema_expr_analyse_assign(SemaContext *context, Expr *expr, Expr *lef break; } // 2. Check assignability - if (!sema_expr_check_assign(context, left)) return false; + if (!sema_expr_check_assign(context, left, failed_ref)) return false; bool is_unwrapped_var = expr_is_unwrapped_ident(left); @@ -5742,7 +5750,7 @@ static bool sema_binary_analyse_ct_common_assign(SemaContext *context, Expr *exp expr->binary_expr.operator = binaryop_assign_base_op(expr->binary_expr.operator); - if (!sema_expr_analyse_binary(context, expr)) return false; + if (!sema_expr_analyse_binary(context, expr, NULL)) return false; if (!sema_cast_const(expr)) { @@ -5771,7 +5779,7 @@ static bool sema_expr_analyse_op_assign(SemaContext *context, Expr *expr, Expr * if (!sema_analyse_expr_lvalue(context, left)) return false; // 2. Verify that the left side is assignable. - if (!sema_expr_check_assign(context, left)) return false; + if (!sema_expr_check_assign(context, left, NULL)) return false; Type *left_type_canonical = left->type->canonical; @@ -6620,7 +6628,7 @@ static bool sema_expr_analyse_shift_assign(SemaContext *context, Expr *expr, Exp bool optional = IS_OPTIONAL(left) || IS_OPTIONAL(right); // 2. Ensure the lhs side is assignable - if (!sema_expr_check_assign(context, left)) return false; + if (!sema_expr_check_assign(context, left, NULL)) return false; // 3. Only integers may be shifted. if (!expr_both_any_integer_or_integer_vector(left, right)) return sema_type_error_on_binop(context, expr); @@ -7397,7 +7405,7 @@ static inline bool sema_expr_analyse_incdec(SemaContext *context, Expr *expr) if (!sema_analyse_expr_lvalue(context, inner)) return false; // 2. Assert it's an l-value - if (!sema_expr_check_assign(context, inner)) return false; + if (!sema_expr_check_assign(context, inner, NULL)) return false; // 3. This might be a $foo, if to handle it. if (inner->expr_kind == EXPR_CT_IDENT) @@ -7587,7 +7595,7 @@ static inline bool sema_expr_analyse_ct_and_or(SemaContext *context, Expr *expr, return true; } -static inline bool sema_expr_analyse_binary(SemaContext *context, Expr *expr) +static inline bool sema_expr_analyse_binary(SemaContext *context, Expr *expr, bool *failed_ref) { if (expr->binary_expr.operator == BINARYOP_ELSE) return sema_expr_analyse_or_error(context, expr); ASSERT_SPAN(expr, expr->resolve_status == RESOLVE_RUNNING); @@ -7609,7 +7617,7 @@ static inline bool sema_expr_analyse_binary(SemaContext *context, Expr *expr) case BINARYOP_CT_AND: return sema_expr_analyse_ct_and_or(context, expr, left, right); case BINARYOP_ASSIGN: - return sema_expr_analyse_assign(context, expr, left, right); + return sema_expr_analyse_assign(context, expr, left, right, failed_ref); case BINARYOP_MULT: return sema_expr_analyse_mult(context, expr, left, right); case BINARYOP_ADD: @@ -8986,9 +8994,15 @@ static inline bool sema_expr_analyse_ct_defined(SemaContext *context, Expr *expr case EXPR_DEFAULT_ARG: case EXPR_NAMED_ARGUMENT: UNREACHABLE - case EXPR_CT_ARG: - FALLTHROUGH; case EXPR_BINARY: + main_expr->resolve_status = RESOLVE_RUNNING; + if (!sema_expr_analyse_binary(context, main_expr, &failed)) + { + if (!failed) goto FAIL; + success = false; + } + break; + case EXPR_CT_ARG: case EXPR_BITACCESS: case EXPR_BITASSIGN: case EXPR_COMPOUND_LITERAL: @@ -9546,7 +9560,7 @@ static inline bool sema_analyse_expr_dispatch(SemaContext *context, Expr *expr, case EXPR_CT_EVAL: return sema_expr_analyse_ct_eval(context, expr, check); case EXPR_BINARY: - return sema_expr_analyse_binary(context, expr); + return sema_expr_analyse_binary(context, expr, NULL); case EXPR_TERNARY: return sema_expr_analyse_ternary(context, NULL, expr); case EXPR_UNARY: diff --git a/src/compiler/sema_internal.h b/src/compiler/sema_internal.h index c1e3dd9c8..82912332f 100644 --- a/src/compiler/sema_internal.h +++ b/src/compiler/sema_internal.h @@ -109,7 +109,8 @@ bool sema_analyse_asm(SemaContext *context, AsmInlineBlock *block, Ast *asm_stmt bool sema_bit_assignment_check(SemaContext *context, Expr *right, Decl *member); CondResult sema_check_comp_time_bool(SemaContext *context, Expr *expr); -bool sema_expr_check_assign(SemaContext *context, Expr *expr); + +bool sema_expr_check_assign(SemaContext *context, Expr *expr, bool *failed_ref); bool sema_analyse_function_signature(SemaContext *context, Decl *func_decl, TypeInfo *parent, CallABI abi, Signature *signature); Expr *sema_create_struct_from_expressions(Decl *struct_decl, SourceSpan span, Expr **exprs); ConstInitializer *sema_merge_bitstruct_const_initializers(ConstInitializer *lhs, ConstInitializer *rhs, BinaryOp op); diff --git a/test/test_suite/builtins/unaligned_load_store.c3t b/test/test_suite/builtins/unaligned_load_store.c3t index 58b3d10c4..c4aa12992 100644 --- a/test/test_suite/builtins/unaligned_load_store.c3t +++ b/test/test_suite/builtins/unaligned_load_store.c3t @@ -9,12 +9,16 @@ fn void main() { Foo* foo; float[<4>] a @align(1) @noinit; + float[<4>] b @align(1) @noinit; a = *(float[<4>]*)&foo.a; *(float[<4>]*)&foo.a = a; a = $$unaligned_load((float[<4>]*)&foo.a, 1); $$unaligned_store((float[<4>]*)&foo.a, a, 1); + + b = @unaligned_load(*(float[<4>]*)&foo.a, 1); + @unaligned_store(*(float[<4>]*)&foo.a, b, 1); } /* #expect: test.ll @@ -23,6 +27,8 @@ define void @test.main() #0 { entry: %foo = alloca ptr, align 8 %a = alloca <4 x float>, align 1 + %b = alloca <4 x float>, align 1 + %value = alloca <4 x float>, align 16 store ptr null, ptr %foo, align 8 %0 = load ptr, ptr %foo, align 8 %1 = load <4 x float>, ptr %0, align 16 @@ -36,5 +42,13 @@ entry: %6 = load ptr, ptr %foo, align 8 %7 = load <4 x float>, ptr %a, align 1 store <4 x float> %7, ptr %6, align 1 + %8 = load ptr, ptr %foo, align 8 + %9 = load <4 x float>, ptr %8, align 1 + store <4 x float> %9, ptr %b, align 1 + %10 = load <4 x float>, ptr %b, align 1 + store <4 x float> %10, ptr %value, align 16 + %11 = load ptr, ptr %foo, align 8 + %12 = load <4 x float>, ptr %value, align 16 + store <4 x float> %12, ptr %11, align 1 ret void -} +} \ No newline at end of file diff --git a/test/test_suite/concurrency/atomic_load_store_debug.c3t b/test/test_suite/concurrency/atomic_load_store_debug.c3t index 019cd437d..8fd02ddb9 100644 --- a/test/test_suite/concurrency/atomic_load_store_debug.c3t +++ b/test/test_suite/concurrency/atomic_load_store_debug.c3t @@ -31,42 +31,30 @@ define void @test.main() #0 !dbg !8 { entry: %a = alloca i32, align 4 %x = alloca i32, align 4 - %x1 = alloca ptr, align 8 %y = alloca i32, align 4 - %x2 = alloca ptr, align 8 - %x3 = alloca ptr, align 8 %value = alloca i32, align 4 - %x4 = alloca ptr, align 8 - %value6 = alloca i32, align 4 + %value2 = alloca i32, align 4 %varargslots = alloca [1 x %any], align 16 %retparam = alloca i64, align 8 store i32 111, ptr %a, align 4, !dbg !15 - store ptr %a, ptr %x1, align 8 - %0 = load ptr, ptr %x1, align 8, !dbg !18 - %1 = load atomic i32, ptr %0 seq_cst, align 4, !dbg !18 - store i32 %1, ptr %x, align 4, !dbg !18 - store ptr %a, ptr %x2, align 8 - %2 = load ptr, ptr %x2, align 8, !dbg !24 - %3 = load atomic volatile i32, ptr %2 monotonic, align 4, !dbg !24 - store i32 %3, ptr %y, align 4, !dbg !24 - store ptr %a, ptr %x3, align 8 - %4 = load i32, ptr %x, align 4, !dbg !27 - %add = add i32 123, %4, !dbg !28 + %0 = load atomic i32, ptr %a seq_cst, align 4, !dbg !18 + store i32 %0, ptr %x, align 4, !dbg !18 + %1 = load atomic volatile i32, ptr %a monotonic, align 4, !dbg !24 + store i32 %1, ptr %y, align 4, !dbg !24 + %2 = load i32, ptr %x, align 4, !dbg !27 + %add = add i32 123, %2, !dbg !28 store i32 %add, ptr %value, align 4 - %5 = load ptr, ptr %x3, align 8, !dbg !29 - %6 = load i32, ptr %value, align 4, !dbg !29 - store atomic i32 %6, ptr %5 seq_cst, align 4, !dbg !29 - store ptr %a, ptr %x4, align 8 - %7 = load i32, ptr %y, align 4, !dbg !32 - %add5 = add i32 33, %7, !dbg !33 - store i32 %add5, ptr %value6, align 4 - %8 = load ptr, ptr %x4, align 8, !dbg !34 - %9 = load i32, ptr %value6, align 4, !dbg !34 - store atomic volatile i32 %9, ptr %8 monotonic, align 4, !dbg !34 - %10 = insertvalue %any undef, ptr %a, 0, !dbg !37 - %11 = insertvalue %any %10, i64 ptrtoint (ptr @"$ct.int" to i64), 1, !dbg !37 - store %any %11, ptr %varargslots, align 16, !dbg !37 - %12 = call i64 @std.io.printfn(ptr %retparam, ptr @.str, i64 2, ptr %varargslots, i64 1), !dbg !38 + %3 = load i32, ptr %value, align 4, !dbg !29 + store atomic i32 %3, ptr %a seq_cst, align 4, !dbg !29 + %4 = load i32, ptr %y, align 4, !dbg !32 + %add1 = add i32 33, %4, !dbg !33 + store i32 %add1, ptr %value2, align 4 + %5 = load i32, ptr %value2, align 4, !dbg !34 + store atomic volatile i32 %5, ptr %a monotonic, align 4, !dbg !34 + %6 = insertvalue %any undef, ptr %a, 0, !dbg !37 + %7 = insertvalue %any %6, i64 ptrtoint (ptr @"$ct.int" to i64), 1, !dbg !37 + store %any %7, ptr %varargslots, align 16, !dbg !37 + %8 = call i64 @std.io.printfn(ptr %retparam, ptr @.str, i64 2, ptr %varargslots, i64 1), !dbg !38 ret void, !dbg !38 } @@ -118,17 +106,17 @@ declare i1 @llvm.expect.i1(i1, i1) !22 = !DILocalVariable(name: "y", scope: !8, file: !7, line: 14, type: !13, align: 4) !23 = !DILocation(line: 14, column: 6, scope: !8) !24 = !DILocation( -!25 = distinct !DISubprogram(name: "@atomic_load", linkageName: "@atomic_load", scope: !20, file: !20, line: 225, scopeLine: 225, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !6) +!25 = distinct !DISubprogram(name: "@atomic_load", linkageName: "@atomic_load", scope: !20, file: !20 !26 = !DILocation(line: 14, column: 10, scope: !8) !27 = !DILocation(line: 15, column: 25, scope: !8) !28 = !DILocation(line: 15, column: 19, scope: !8) !29 = !DILocation( -!30 = distinct !DISubprogram(name: "@atomic_store", linkageName: "@atomic_store", scope: !20, file: !20, line: 240, scopeLine: 240, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !6) +!30 = distinct !DISubprogram(name: "@atomic_store", linkageName: "@atomic_store", scope: !20, file: !20 !31 = !DILocation(line: 15, column: 2, scope: !8) !32 = !DILocation(line: 16, column: 24, scope: !8) !33 = !DILocation(line: 16, column: 19, scope: !8) !34 = !DILocation( -!35 = distinct !DISubprogram(name: "@atomic_store", linkageName: "@atomic_store", scope: !20, file: !20, line: 240, scopeLine: 240, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !6) +!35 = distinct !DISubprogram(name: "@atomic_store", linkageName: "@atomic_store", scope: !20, file: !20 !36 = !DILocation(line: 16, column: 2, scope: !8) !37 = !DILocation(line: 17, column: 20, scope: !8) !38 = !DILocation(line: 17, column: 2, scope: !8) diff --git a/test/test_suite/debug_symbols/defer_macro.c3t b/test/test_suite/debug_symbols/defer_macro.c3t index 9886699ab..3a931e64a 100644 --- a/test/test_suite/debug_symbols/defer_macro.c3t +++ b/test/test_suite/debug_symbols/defer_macro.c3t @@ -664,7 +664,7 @@ no_match: ; preds = %compare !73 = !DILocalVariable(name: "name", arg: 3, scope: !66, file: !7, line: 33, type: !39) !74 = !DILocation(line: 33, column: 63, scope: !66) !75 = !DILocation(line: -!76 = distinct !DISubprogram(name: "new", linkageName: "new", scope: !77, file: !77, line: 624, scopeLine: 624, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !6) +!76 = distinct !DISubprogram(name: "new", linkageName: "new", scope: !77, file: !77, line: !77 = !DIFile(filename: "mem.c3" !78 = !DILocation(line: 34, column: 10, scope: !66) !79 = distinct !DISubprogram(name: "test", linkageName: "test.test", scope: !7, file: !7, line: 41, type: !80, scopeLine: 41, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !6, retainedNodes: !21) @@ -743,9 +743,9 @@ no_match: ; preds = %compare !152 = distinct !DISubprogram(name: "alloc_array_try", linkageName: "alloc_array_try", scope: !153, file: !153, line: 284, scopeLine: 284, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !6) !153 = !DIFile(filename: "mem_allocator.c3" !154 = !DILocation -!155 = distinct !DISubprogram(name: "alloc_array", linkageName: "alloc_array", scope: !153, file: !153, line: 267, scopeLine: 267, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !6) +!155 = distinct !DISubprogram(name: "alloc_array", linkageName: "alloc_array", scope: !153 !156 = !DILocation -!157 = distinct !DISubprogram(name: "alloc_array", linkageName: "alloc_array", scope: !77, file: !77, line: 710, scopeLine: 710, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !6) +!157 = distinct !DISubprogram(name: "alloc_array", linkageName: "alloc_array", scope: !77 !158 = !DILocation !159 = !DILocation !160 = !DILocation diff --git a/test/test_suite/functions/macro_arguments.c3 b/test/test_suite/functions/macro_arguments.c3 index fc205c9ee..10b217897 100644 --- a/test/test_suite/functions/macro_arguments.c3 +++ b/test/test_suite/functions/macro_arguments.c3 @@ -7,8 +7,6 @@ fn void foo3(bar) { } // #error: Only typed parameters are allowed for functions fn void foo4($Type) { } // #error: Only regular parameters are allowed for functions. -fn void foo8(int* &foo) {} // #error: Only regular parameters are allowed for functions. - fn void foo9(int x, int x) {} // #error: Duplicate parameter name 'x'. macro @foo($a, $b, $c, ...) {} \ No newline at end of file diff --git a/test/test_suite/macros/deref_macro_pointer.c3 b/test/test_suite/macros/deref_macro_pointer.c3 deleted file mode 100644 index 14741fd54..000000000 --- a/test/test_suite/macros/deref_macro_pointer.c3 +++ /dev/null @@ -1,15 +0,0 @@ -module test; - -fn void test(int* a) {} -macro @abc(&self) -{ - test(self); // #error: Implicitly casting 'int**' to 'int*' -} - -fn void! test1() -{ - int* a; - int b; - @abc(a); - @abc(b); -} diff --git a/test/test_suite/macros/macro_body_ref_hash_constant_type.c3t b/test/test_suite/macros/macro_body_ref_hash_constant_type.c3t index b5c4df429..e324965c2 100644 --- a/test/test_suite/macros/macro_body_ref_hash_constant_type.c3t +++ b/test/test_suite/macros/macro_body_ref_hash_constant_type.c3t @@ -4,17 +4,17 @@ import std::io; fn void main() { - @boba(;#hash_val, &foo, int $value, $Type) + @boba(;#hash_val, #foo, int $value, $Type) { io::printn("Now invoking hash"); #hash_val; #hash_val; - *foo += $value; + #foo += $value; io::printfn("The type was: %s", $Type.nameof); }; } -macro void @boba(;@body(#hash, &foo, $val, $Type)) +macro void @boba(;@body(#hash, #foo, $val, $Type)) { io::printn("Boba"); int a = 0; @@ -34,7 +34,6 @@ entry: %error_var8 = alloca i64, align 8 %a = alloca i32, align 4 %b = alloca i32, align 4 - %foo = alloca ptr, align 8 %len14 = alloca i64, align 8 %error_var15 = alloca i64, align 8 %retparam17 = alloca i64, align 8 @@ -54,17 +53,13 @@ entry: %not_err = icmp eq i64 %1, 0 %2 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) br i1 %2, label %after_check, label %assign_optional - assign_optional: ; preds = %entry store i64 %1, ptr %error_var, align 8 br label %guard_block - after_check: ; preds = %entry br label %noerr_block - guard_block: ; preds = %assign_optional br label %voiderr - noerr_block: ; preds = %after_check %3 = load i64, ptr %retparam, align 8 store i64 %3, ptr %len, align 8 @@ -72,58 +67,44 @@ noerr_block: ; preds = %after_check %not_err3 = icmp eq i64 %4, 0 %5 = call i1 @llvm.expect.i1(i1 %not_err3, i1 true) br i1 %5, label %after_check5, label %assign_optional4 - assign_optional4: ; preds = %noerr_block store i64 %4, ptr %error_var2, align 8 br label %guard_block6 - after_check5: ; preds = %noerr_block br label %noerr_block7 - guard_block6: ; preds = %assign_optional4 br label %voiderr - noerr_block7: ; preds = %after_check5 %6 = call i64 @std.io.File.flush(ptr %0) %not_err9 = icmp eq i64 %6, 0 %7 = call i1 @llvm.expect.i1(i1 %not_err9, i1 true) br i1 %7, label %after_check11, label %assign_optional10 - assign_optional10: ; preds = %noerr_block7 store i64 %6, ptr %error_var8, align 8 br label %guard_block12 - after_check11: ; preds = %noerr_block7 br label %noerr_block13 - guard_block12: ; preds = %assign_optional10 br label %voiderr - noerr_block13: ; preds = %after_check11 %8 = load i64, ptr %len, align 8 %add = add i64 %8, 1 br label %voiderr - voiderr: ; preds = %noerr_block13, %guard_block12, %guard_block6, %guard_block store i32 0, ptr %a, align 4 store i32 0, ptr %b, align 4 - store ptr %b, ptr %foo, align 8 %9 = call ptr @std.io.stdout() %10 = call i64 @std.io.File.write(ptr %retparam17, ptr %9, ptr @.str.1, i64 17) %not_err18 = icmp eq i64 %10, 0 %11 = call i1 @llvm.expect.i1(i1 %not_err18, i1 true) br i1 %11, label %after_check20, label %assign_optional19 - assign_optional19: ; preds = %voiderr store i64 %10, ptr %error_var15, align 8 br label %guard_block21 - after_check20: ; preds = %voiderr br label %noerr_block22 - guard_block21: ; preds = %assign_optional19 br label %voiderr36 - noerr_block22: ; preds = %after_check20 %12 = load i64, ptr %retparam17, align 8 store i64 %12, ptr %len14, align 8 @@ -131,38 +112,29 @@ noerr_block22: ; preds = %after_check20 %not_err24 = icmp eq i64 %13, 0 %14 = call i1 @llvm.expect.i1(i1 %not_err24, i1 true) br i1 %14, label %after_check26, label %assign_optional25 - assign_optional25: ; preds = %noerr_block22 store i64 %13, ptr %error_var23, align 8 br label %guard_block27 - after_check26: ; preds = %noerr_block22 br label %noerr_block28 - guard_block27: ; preds = %assign_optional25 br label %voiderr36 - noerr_block28: ; preds = %after_check26 %15 = call i64 @std.io.File.flush(ptr %9) %not_err30 = icmp eq i64 %15, 0 %16 = call i1 @llvm.expect.i1(i1 %not_err30, i1 true) br i1 %16, label %after_check32, label %assign_optional31 - assign_optional31: ; preds = %noerr_block28 store i64 %15, ptr %error_var29, align 8 br label %guard_block33 - after_check32: ; preds = %noerr_block28 br label %noerr_block34 - guard_block33: ; preds = %assign_optional31 br label %voiderr36 - noerr_block34: ; preds = %after_check32 %17 = load i64, ptr %len14, align 8 %add35 = add i64 %17, 1 br label %voiderr36 - voiderr36: ; preds = %noerr_block34, %guard_block33, %guard_block27, %guard_block21 %18 = insertvalue %any undef, ptr %a, 0 %19 = insertvalue %any %18, i64 ptrtoint (ptr @"$ct.int" to i64), 1 @@ -178,18 +150,17 @@ voiderr36: ; preds = %noerr_block34, %gua %25 = load i32, ptr %a, align 4 %add45 = add i32 %25, 1 store i32 %add45, ptr %a, align 4 - %26 = load ptr, ptr %foo, align 8 - %27 = load i32, ptr %26, align 4 - %add46 = add i32 %27, 3 - store i32 %add46, ptr %26, align 4 + %26 = load i32, ptr %b, align 4 + %add46 = add i32 %26, 3 + store i32 %add46, ptr %b, align 4 store %"char[]" { ptr @.str.5, i64 3 }, ptr %taddr, align 8 - %28 = insertvalue %any undef, ptr %taddr, 0 - %29 = insertvalue %any %28, i64 ptrtoint (ptr @"$ct.String" to i64), 1 - store %any %29, ptr %varargslots47, align 16 - %30 = call i64 @std.io.printfn(ptr %retparam48, ptr @.str.4, i64 16, ptr %varargslots47, i64 1) - %31 = insertvalue %any undef, ptr %b, 0 - %32 = insertvalue %any %31, i64 ptrtoint (ptr @"$ct.int" to i64), 1 - store %any %32, ptr %varargslots51, align 16 - %33 = call i64 @std.io.printfn(ptr %retparam52, ptr @.str.6, i64 2, ptr %varargslots51, i64 1) + %27 = insertvalue %any undef, ptr %taddr, 0 + %28 = insertvalue %any %27, i64 ptrtoint (ptr @"$ct.String" to i64), 1 + store %any %28, ptr %varargslots47, align 16 + %29 = call i64 @std.io.printfn(ptr %retparam48, ptr @.str.4, i64 16, ptr %varargslots47, i64 1) + %30 = insertvalue %any undef, ptr %b, 0 + %31 = insertvalue %any %30, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %31, ptr %varargslots51, align 16 + %32 = call i64 @std.io.printfn(ptr %retparam52, ptr @.str.6, i64 2, ptr %varargslots51, i64 1) ret void } diff --git a/test/test_suite/macros/macro_calls_prefix.c3 b/test/test_suite/macros/macro_calls_prefix.c3 index 6d93d08af..5723da636 100644 --- a/test/test_suite/macros/macro_calls_prefix.c3 +++ b/test/test_suite/macros/macro_calls_prefix.c3 @@ -2,10 +2,7 @@ macro foo(a, $b, $Type) {} macro @foo2(a, $b, $Type) {} -macro bar(&x) // #error: Ref and expression parameters -{} - -macro baz(#y) {} // #error: Ref and expression parameters +macro baz(#y) {} // #error: are not allowed in function-like macro baz2(a; @body()) {} // #error: Names of macros diff --git a/test/test_suite/macros/macro_ref_errors.c3 b/test/test_suite/macros/macro_ref_errors.c3 deleted file mode 100644 index b11b5ee78..000000000 --- a/test/test_suite/macros/macro_ref_errors.c3 +++ /dev/null @@ -1,28 +0,0 @@ -module test; - -import std::io; - -macro @foo(int* &hello) -{ - hello = hello; // #error: You cannot assign to a ref -} - -macro @bar(Foo* &f) -{ - f.a = 1; - int* x = &f.a; - Foo **ff = &f; // #error: You may not take the address -} - -struct Foo -{ - int a; -} - -fn void main() -{ - int a; - @foo(a); - Foo x; - @bar(x); -} \ No newline at end of file diff --git a/test/test_suite/macros/macro_with_body.c3t b/test/test_suite/macros/macro_with_body.c3t index cd68734d9..cb529d800 100644 --- a/test/test_suite/macros/macro_with_body.c3t +++ b/test/test_suite/macros/macro_with_body.c3t @@ -14,10 +14,10 @@ fn int Foo.mutate(Foo *foo) return 10 * ++foo.x; } -macro @macro_with_body(foo, &x; @body(x, y)) +macro @macro_with_body(foo, #x; @body(x, y)) { - *x = foo.x; - @body(foo.mutate(), *x); + #x = foo.x; + @body(foo.mutate(), #x); } macro @repeat(int times; @body(x)) diff --git a/test/test_suite/macros/macro_with_body_err.c3 b/test/test_suite/macros/macro_with_body_err.c3 index ccd565972..841cc1b9e 100644 --- a/test/test_suite/macros/macro_with_body_err.c3 +++ b/test/test_suite/macros/macro_with_body_err.c3 @@ -14,10 +14,10 @@ fn int Foo.mutate(Foo *foo) return 10 * ++foo.x; } -macro @macro_with_body(foo, &x; @body(x, y)) +macro @macro_with_body(foo, #x; @body(x, y)) { - *x = foo.x; - @body(foo.mutate(), x); // #error: 'int*' to 'int' + #x = foo.x; + @body(foo.mutate(), &#x); // #error: 'int*' to 'int' } diff --git a/test/test_suite/macros/ref_vector.c3t b/test/test_suite/macros/ref_vector.c3t index 2ee05ce85..f0b2e15cb 100644 --- a/test/test_suite/macros/ref_vector.c3t +++ b/test/test_suite/macros/ref_vector.c3t @@ -10,8 +10,8 @@ fn int main() { return 1; } -macro @foo(&ref) { - *ref += 1; +macro @foo(#ref) { + #ref += 1; } /* #expect: test.ll @@ -21,20 +21,34 @@ define i32 @main() #0 { entry: %vec = alloca <4 x i32>, align 16 store <4 x i32> zeroinitializer, ptr %vec, align 16 - %0 = load i32, ptr %vec, align 4 - %add = add i32 %0, 1 - store i32 %add, ptr %vec, align 4 - %ptradd = getelementptr inbounds i8, ptr %vec, i64 8 - %1 = load i32, ptr %ptradd, align 4 - %add1 = add i32 %1, 1 - store i32 %add1, ptr %ptradd, align 4 + %0 = load <4 x i32>, ptr %vec, align 16 + %elem = extractelement <4 x i32> %0, i64 0 + %add = add i32 %elem, 1 + %elemset = insertelement <4 x i32> %0, i32 %add, i64 0 + store <4 x i32> %elemset, ptr %vec, align 16 + %1 = load <4 x i32>, ptr %vec, align 16 + %elem1 = extractelement <4 x i32> %1, i64 2 + %add2 = add i32 %elem1, 1 + %elemset3 = insertelement <4 x i32> %1, i32 %add2, i64 2 + store <4 x i32> %elemset3, ptr %vec, align 16 %2 = load <4 x i32>, ptr %vec, align 16 %3 = extractelement <4 x i32> %2, i64 0 %eq = icmp eq i32 %3, 1 call void @llvm.assume(i1 %eq) %4 = load <4 x i32>, ptr %vec, align 16 %5 = extractelement <4 x i32> %4, i64 2 - %eq2 = icmp eq i32 %5, 1 - call void @llvm.assume(i1 %eq2) + %eq4 = icmp eq i32 %5, 1 + call void @llvm.assume(i1 %eq4) ret i32 1 } +; Function Attrs: nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write) +declare void @llvm.assume(i1 noundef) #1 +attributes #0 = { nounwind uwtable "no-trapping-math"="true" "stack-protector-buffer-size"="8" } +attributes #1 = { nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write) } +!llvm.module.flags = !{!0, !1, !2, !3, !4, !5} +!0 = !{i32 2, !"Dwarf Version", i32 4} +!1 = !{i32 2, !"Debug Info Version", i32 3} +!2 = !{i32 2, !"wchar_size", i32 4} +!3 = !{i32 4, !"PIC Level", i32 2} +!4 = !{i32 1, !"uwtable", i32 2} +!5 = !{i32 2, !"frame-pointer", i32 2} \ No newline at end of file diff --git a/test/test_suite/statements/default_macro_argc.c3t b/test/test_suite/statements/default_macro_argc.c3t index 1fe8b192f..1d14c8a77 100644 --- a/test/test_suite/statements/default_macro_argc.c3t +++ b/test/test_suite/statements/default_macro_argc.c3t @@ -4,9 +4,9 @@ import std, test2; int[2] x; -macro @test2(&a = x[1]) +macro @test2(#a = x[1]) { - *a = 123; + #a = 123; } macro test($Type = int) { io::printn($Type.nameof); } @@ -31,9 +31,9 @@ import std; int[2] x; -macro @test2(&a = x[1]) +macro @test2(#a = x[1]) { - *a = 12; + #a = 12; } macro test($Type = double) { io::printn($Type.nameof); } diff --git a/test/unit/stdlib/io/bytestream.c3 b/test/unit/stdlib/io/bytestream.c3 index a405fcad4..ed05fe155 100644 --- a/test/unit/stdlib/io/bytestream.c3 +++ b/test/unit/stdlib/io/bytestream.c3 @@ -68,4 +68,4 @@ fn usz! TestReader.read(&self, char[] bytes) @dynamic return n; } -fn char! TestReader.read_byte(&self) @dynamic => io::@read_byte_using_read(self); +fn char! TestReader.read_byte(&self) @dynamic => io::read_byte_using_read(self);