diff --git a/lib/std/compression/qoi.c3 b/lib/std/compression/qoi.c3 index 6376d3bb0..3c3358820 100644 --- a/lib/std/compression/qoi.c3 +++ b/lib/std/compression/qoi.c3 @@ -292,17 +292,17 @@ fn char[]? decode(Allocator allocator, char[] data, QOIDesc* desc, QOIChannels c if (bswap(header.be_magic) != 'qoif') return INVALID_DATA~; // copy header data to desc - desc.width = bswap(header.be_width); - desc.height = bswap(header.be_height); - desc.channels = header.channels; + uint width = desc.width = bswap(header.be_width); + uint height = desc.height = bswap(header.be_height); + QOIChannels desc_channels = desc.channels = header.channels; desc.colorspace = header.colorspace; - if (desc.channels == AUTO) return INVALID_DATA~; // Channels must be specified in the header + if (desc_channels == AUTO) return INVALID_DATA~; // Channels must be specified in the header // check width and height - if (desc.width == 0 || desc.height == 0) return INVALID_DATA~; + if (width == 0 || height == 0) return INVALID_DATA~; // check pixel count - ulong pixels = (ulong)desc.width * (ulong)desc.height; + ulong pixels = (ulong)width * (ulong)height; if (pixels > PIXELS_MAX) return TOO_MANY_PIXELS~; uint pos = Header.sizeof; // Current position in data @@ -313,7 +313,7 @@ fn char[]? decode(Allocator allocator, char[] data, QOIDesc* desc, QOIChannels c Pixel[64] palette; // Zero-initialized by default Pixel p = { 0, 0, 0, 255 }; - if (channels == AUTO) channels = desc.channels; + if (channels == AUTO) channels = desc_channels; // allocate memory for image data usz image_size = (usz)pixels * channels; diff --git a/lib/std/math/bigint.c3 b/lib/std/math/bigint.c3 index d5b4f2aaf..b0af70dfd 100644 --- a/lib/std/math/bigint.c3 +++ b/lib/std/math/bigint.c3 @@ -930,9 +930,9 @@ module std::math::bigint @private; <* - @param [&out] quotient + @param [&inout] quotient @param [&in] bi2 - @param [&out] remainder + @param [&inout] remainder *> fn void BigInt.single_byte_divide(&self, BigInt* bi2, BigInt* quotient, BigInt* remainder) { @@ -982,9 +982,9 @@ fn void BigInt.single_byte_divide(&self, BigInt* bi2, BigInt* quotient, BigInt* } <* - @param [&out] quotient + @param [&inout] quotient @param [&in] other - @param [&out] remainder + @param [&inout] remainder *> fn void BigInt.multi_byte_divide(&self, BigInt* other, BigInt* quotient, BigInt* remainder) { diff --git a/releasenotes.md b/releasenotes.md index 67fc1f7ba..38bb6f391 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -116,7 +116,11 @@ - Constant shifting incorrectly doesn't flatten the underlying vector base #2825 - String not set as attributes resolved breaking has_tagof #2824 - Self referencing forward resolved const enum fails to be properly detected #2823 - +- Incorrectly try compile time int check on vector #2815 +- Generating typeid from function gives incorrect typeid #2816 +- Recursive definitions not discovered when initializer is access on other const #2817 +- Slice overrun detected late hit codegen assert #2822 + ### Stdlib changes - Add `ThreadPool` join function to wait for all threads to finish in the pool without destroying the threads. - Add `@in` compile-time macro to check for a value in a variable list of constants. #2662 diff --git a/src/compiler/llvm_codegen_stmt.c b/src/compiler/llvm_codegen_stmt.c index 4af1364fc..4100f1144 100644 --- a/src/compiler/llvm_codegen_stmt.c +++ b/src/compiler/llvm_codegen_stmt.c @@ -1597,16 +1597,27 @@ void llvm_emit_panic(GenContext *c, const char *message, SourceSpan loc, const c void llvm_emit_panic_if_true(GenContext *c, BEValue *value, const char *panic_name, SourceSpan loc, const char *fmt, BEValue *value_1, BEValue *value_2) { + bool always_panic = false; if (LLVMIsAConstantInt(value->value)) { - ASSERT_AT(loc, !LLVMConstIntGetZExtValue(value->value) && "Unexpected bounds check failed."); - return; + if (!LLVMConstIntGetZExtValue(value->value)) + { + return; + } + sema_warning_at(loc, "The code here was detected to always panic at runtime."); + always_panic = true; } LLVMBasicBlockRef panic_block = llvm_basic_block_new(c, "panic"); LLVMBasicBlockRef ok_block = llvm_basic_block_new(c, "checkok"); - value->value = llvm_emit_expect_false(c, value); - llvm_emit_cond_br(c, value, panic_block, ok_block); - + if (always_panic) + { + llvm_emit_br(c, panic_block); + } + else + { + value->value = llvm_emit_expect_false(c, value); + llvm_emit_cond_br(c, value, panic_block, ok_block); + } llvm_emit_block(c, panic_block); vec_add(c->panic_blocks, panic_block); BEValue *values = NULL; diff --git a/src/compiler/llvm_codegen_value.c b/src/compiler/llvm_codegen_value.c index 9ffb8e884..7035b11d9 100644 --- a/src/compiler/llvm_codegen_value.c +++ b/src/compiler/llvm_codegen_value.c @@ -129,10 +129,6 @@ void llvm_value_rvalue(GenContext *c, BEValue *value) void llvm_emit_jump_to_optional_exit(GenContext *c, LLVMValueRef opt_value) { - if (!c->catch.block) - { - puts("foekf"); - } ASSERT_AT(c->last_emitted_loc, c->catch.block && "unexpected emit"); bool is_constant_opt = llvm_is_const(opt_value); diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index 34480aa65..4444fc004 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -6326,7 +6326,7 @@ static inline void sema_expr_flatten_const_ident(Expr *expr) return; } Expr *init_expr = ident->var.init_expr; - if (!init_expr) return; + if (!init_expr || init_expr->resolve_status != RESOLVE_DONE) return; sema_expr_flatten_const_ident(init_expr); if (expr_is_const(init_expr)) { @@ -6364,7 +6364,7 @@ static inline bool sema_expr_analyse_access(SemaContext *context, Expr *expr, bo expr->type = type_typeid; expr->expr_kind = EXPR_CONST; expr->const_expr.const_kind = CONST_TYPEID; - expr->const_expr.typeid = parent->type; + expr->const_expr.typeid = type_get_func_ptr(parent->type); expr->resolve_status = RESOLVE_DONE; return true; } @@ -7723,7 +7723,7 @@ static bool sema_binary_arithmetic_promotion(SemaContext *context, Expr *left, E } RETURN_SEMA_ERROR(parent, error_message, type_quoted_error_string(left->type), type_quoted_error_string(right->type)); } - if (type_is_signed_any(flat_max)) + if (type_is_signed(flat_max)) { if (!sema_check_untyped_promotion(context, left, true, flat_max, max)) return false; if (!sema_check_untyped_promotion(context, right, false, flat_max, max)) return false; @@ -12046,7 +12046,11 @@ static inline bool sema_cast_rvalue(SemaContext *context, Expr *expr, bool mutat RETURN_SEMA_ERROR(expr, "A macro name must be followed by '('."); } // We may have kept FOO.x.y as a reference, fold it now if y is not an aggregate. - if (mutate) sema_expr_flatten_const_ident(expr->access_resolved_expr.parent); + if (mutate) + { + sema_expr_flatten_const_ident(expr->access_resolved_expr.parent); + if (!sema_cast_rvalue(context, expr->access_resolved_expr.parent, mutate)) return false; + } return true; case EXPR_TYPEINFO: switch (expr->type_expr->type->type_kind) diff --git a/src/compiler/types.c b/src/compiler/types.c index ffefc0959..1ddc75bd9 100644 --- a/src/compiler/types.c +++ b/src/compiler/types.c @@ -1066,10 +1066,6 @@ Type *type_get_optional(Type *optional_type) Type *type_get_slice(Type *arr_type) { - if (!type_is_valid_for_array(arr_type)) - { - puts("ofek"); - } ASSERT(type_is_valid_for_array(arr_type)); return type_generate_slice(arr_type, false); } diff --git a/test/test_suite/arrays/bad_slice.c3t b/test/test_suite/arrays/bad_slice.c3t new file mode 100644 index 000000000..911b28130 --- /dev/null +++ b/test/test_suite/arrays/bad_slice.c3t @@ -0,0 +1,7 @@ +fn int main() +{ + int[] x; + int a; + x[(a = 52)..2] = 5; + return 0; +} \ No newline at end of file diff --git a/test/test_suite/compile_time/typeid_from_function.c3 b/test/test_suite/compile_time/typeid_from_function.c3 new file mode 100644 index 000000000..8408701cf --- /dev/null +++ b/test/test_suite/compile_time/typeid_from_function.c3 @@ -0,0 +1,7 @@ +fn int main() +{ + var $foo = main.typeid; + $typefrom($foo) a; + a = &main; + return 0; +} \ No newline at end of file diff --git a/test/test_suite/constants/self_ref_through_access.c3 b/test/test_suite/constants/self_ref_through_access.c3 new file mode 100644 index 000000000..864a35194 --- /dev/null +++ b/test/test_suite/constants/self_ref_through_access.c3 @@ -0,0 +1,7 @@ +struct Abc +{ + int a; + int b; +} +const Abc X = { 2, Y }; +const Y = X.b; // #error: This looks like the initialization of the variable was circular \ No newline at end of file diff --git a/test/test_suite/expressions/casts/implicit_cast_to_int_vec.c3 b/test/test_suite/expressions/casts/implicit_cast_to_int_vec.c3 new file mode 100644 index 000000000..0f52ee0f0 --- /dev/null +++ b/test/test_suite/expressions/casts/implicit_cast_to_int_vec.c3 @@ -0,0 +1,4 @@ +fn int main() +{ + ulong x1 = (int[<2>]){ 10, 20 } + ulong.max; // #error: is out of range for +} \ No newline at end of file