mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
- Empty struct after @if processing was not detected, causing a crash instead of an error.
- Comparing an uint and int[<4>] was incorrectly assumed to be uint compared to int, causing a crash instead of an error. - When an `int[*][6]` was given too few values, the compiler would assert instead of giving an error.
This commit is contained in:
@@ -81,6 +81,9 @@
|
||||
- Mixing struct splat, non-named params and named params would crash rather than to print an error. #2771
|
||||
- Creating a char vector from bytes would crash. #2771
|
||||
- Using $$wstr16 with an illegal argument would crash instead of printing an error. #2771
|
||||
- Empty struct after `@if` processing was not detected, causing a crash instead of an error. #2771
|
||||
- Comparing an uint and int[<4>] was incorrectly assumed to be uint compared to int, causing a crash instead of an error. #2771
|
||||
- When an `int[*][6]` was given too few values, the compiler would assert instead of giving an error. #2771
|
||||
|
||||
### Stdlib changes
|
||||
- Add `ThreadPool` join function to wait for all threads to finish in the pool without destroying the threads.
|
||||
|
||||
@@ -2739,7 +2739,7 @@ INLINE bool type_is_arraylike(Type *type);
|
||||
INLINE bool type_is_any_arraylike(Type *type);
|
||||
INLINE bool type_is_promotable_float(Type *type);
|
||||
INLINE bool type_is_promotable_int_bool(Type *type);
|
||||
INLINE bool type_is_signed(Type *type);
|
||||
INLINE bool type_is_signed_any(Type *type);
|
||||
INLINE bool type_ok(Type *type);
|
||||
INLINE bool type_is_unsigned(Type *type);
|
||||
INLINE bool type_is_union_or_strukt(Type *type);
|
||||
@@ -2820,6 +2820,7 @@ INLINE Type *type_from_inferred(Type *flattened, Type *element_type, unsigned co
|
||||
case TYPE_INFERRED_VECTOR:
|
||||
return type_get_vector(element_type, TYPE_VECTOR, count);
|
||||
case TYPE_ARRAY:
|
||||
|
||||
ASSERT(flattened->array.len == count);
|
||||
FALLTHROUGH;
|
||||
case TYPE_INFERRED_ARRAY:
|
||||
@@ -3519,11 +3520,12 @@ INLINE bool type_kind_is_unsigned(TypeKind kind) { return kind >= TYPE_U8 && kin
|
||||
INLINE bool type_kind_is_any_integer(TypeKind kind) { return kind >= TYPE_I8 && kind <= TYPE_U128; }
|
||||
INLINE bool type_kind_is_enum_or_fault(TypeKind kind) { return kind == TYPE_ENUM || kind == TYPE_ANYFAULT; }
|
||||
INLINE bool type_is_unsigned(Type *type) { return type->type_kind >= TYPE_U8 && type->type_kind <= TYPE_U128; }
|
||||
INLINE bool type_is_signed(Type *type) { return type->type_kind >= TYPE_I8 && type->type_kind <= TYPE_I128; }
|
||||
INLINE bool type_ok(Type *type) { return !type || type->type_kind != TYPE_POISONED; }
|
||||
INLINE bool type_info_ok(TypeInfo *type_info) { return !type_info || type_info->kind != TYPE_INFO_POISON; }
|
||||
bool type_is_scalar(Type *type);
|
||||
|
||||
INLINE bool type_is_signed(Type *type)
|
||||
INLINE bool type_is_signed_any(Type *type)
|
||||
{
|
||||
TypeKind kind = type->type_kind;
|
||||
if (kind >= TYPE_I8 && kind < TYPE_U8) return true;
|
||||
|
||||
@@ -707,7 +707,7 @@ static void llvm_emit_overflow_builtin(GenContext *c, BEValue *be_value, Expr *e
|
||||
// Note that we can make additional improvements here!
|
||||
llvm_value_set_address(c, &ref, ref.value, ref.type->pointer, type_abi_alignment(ref.type->pointer));
|
||||
LLVMTypeRef call_type[1] = { LLVMTypeOf(arg_slots[0]) };
|
||||
unsigned intrinsic = type_is_signed(type_lowering(args[0]->type)) ? intrinsic_signed : intrinsic_unsigned;
|
||||
unsigned intrinsic = type_is_signed_any(type_lowering(args[0]->type)) ? intrinsic_signed : intrinsic_unsigned;
|
||||
LLVMValueRef result = llvm_emit_call_intrinsic(c, intrinsic, call_type, 1, arg_slots, 2);
|
||||
LLVMValueRef failed = llvm_emit_extract_value(c, result, 1);
|
||||
LLVMValueRef value = llvm_emit_extract_value(c, result, 0);
|
||||
@@ -739,7 +739,7 @@ static void llvm_emit_wrap_builtin(GenContext *c, BEValue *result_value, Expr *e
|
||||
res = LLVMBuildMul(c->builder, arg_slots[0], arg_slots[1], "emul");
|
||||
break;
|
||||
case BUILTIN_EXACT_DIV:
|
||||
if (type_is_signed(base_type))
|
||||
if (type_is_signed_any(base_type))
|
||||
{
|
||||
res = LLVMBuildSDiv(c->builder, arg_slots[0], arg_slots[1], "esdiv");
|
||||
}
|
||||
@@ -749,7 +749,7 @@ static void llvm_emit_wrap_builtin(GenContext *c, BEValue *result_value, Expr *e
|
||||
}
|
||||
break;
|
||||
case BUILTIN_EXACT_MOD:
|
||||
if (type_is_signed(base_type))
|
||||
if (type_is_signed_any(base_type))
|
||||
{
|
||||
res = LLVMBuildSRem(c->builder, arg_slots[0], arg_slots[1], "eumod");
|
||||
}
|
||||
|
||||
@@ -2094,7 +2094,7 @@ static inline LLVMValueRef llvm_emit_inc_dec_value(GenContext *c, SourceSpan spa
|
||||
LLVMValueRef diff_value = LLVMConstInt(llvm_type, 1, false);
|
||||
if (!allow_wrap)
|
||||
{
|
||||
if (type_is_signed(type))
|
||||
if (type_is_signed_any(type))
|
||||
{
|
||||
return diff > 0
|
||||
? LLVMBuildNSWAdd(c->builder, original->value, diff_value, "addnsw")
|
||||
@@ -3119,8 +3119,8 @@ void llvm_emit_int_comp_raw(GenContext *c, BEValue *result, Type *lhs_type, Type
|
||||
Type *vector_type = type_vector_type(lhs_type);
|
||||
if (vector_type)
|
||||
{
|
||||
lhs_signed = type_is_signed(vector_type);
|
||||
rhs_signed = type_is_signed(type_vector_type(rhs_type));
|
||||
lhs_signed = type_is_signed_any(vector_type);
|
||||
rhs_signed = type_is_signed_any(type_vector_type(rhs_type));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -7167,7 +7167,7 @@ void llvm_emit_expr(GenContext *c, BEValue *value, Expr *expr)
|
||||
case EXPR_FLOAT_TO_INT:
|
||||
llvm_emit_expr(c, value, expr->inner_expr);
|
||||
llvm_value_rvalue(c, value);
|
||||
if (type_is_signed(type_lowering(expr->type)))
|
||||
if (type_is_signed_any(type_lowering(expr->type)))
|
||||
{
|
||||
llvm_value_set(value, LLVMBuildFPToSI(c->builder, value->value, llvm_get_type(c, expr->type), "fpsi"), expr->type);
|
||||
return;
|
||||
@@ -7177,7 +7177,7 @@ void llvm_emit_expr(GenContext *c, BEValue *value, Expr *expr)
|
||||
case EXPR_INT_TO_FLOAT:
|
||||
llvm_emit_expr(c, value, expr->inner_expr);
|
||||
llvm_value_rvalue(c, value);
|
||||
if (type_is_signed(value->type))
|
||||
if (type_is_signed_any(value->type))
|
||||
{
|
||||
llvm_value_set(value, LLVMBuildSIToFP(c->builder, value->value, llvm_get_type(c, expr->type), "sifp"), expr->type);
|
||||
}
|
||||
|
||||
@@ -387,7 +387,10 @@ static bool sema_analyse_union_members(SemaContext *context, Decl *decl)
|
||||
// Offset is always 0
|
||||
member->offset = 0;
|
||||
}
|
||||
|
||||
if (!member_count)
|
||||
{
|
||||
RETURN_SEMA_ERROR(decl, "No union members exist after processing attributes, this is not allowed. Please make sure it has at least one member.");
|
||||
}
|
||||
ASSERT(decl_ok(decl));
|
||||
|
||||
// 1. If packed, then the alignment is zero, unless previously given
|
||||
@@ -644,6 +647,11 @@ static bool sema_analyse_struct_members(SemaContext *context, Decl *decl)
|
||||
if (offset < sz || offset > MAX_STRUCT_SIZE) RETURN_SEMA_ERROR(member, "Struct member '%s' would cause the struct to become too large (exceeding 2 GB).", member->name);
|
||||
}
|
||||
|
||||
if (!member_count)
|
||||
{
|
||||
RETURN_SEMA_ERROR(decl, "No members exist for this struct after processing attributes, creating an invalid empty struct. Please make sure every struct/inner struct has at least one member.");
|
||||
}
|
||||
|
||||
// Set the alignment:
|
||||
|
||||
// 1. If packed, use the alignment given, otherwise set to 1.
|
||||
|
||||
@@ -7688,7 +7688,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(flat_max))
|
||||
if (type_is_signed_any(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;
|
||||
|
||||
@@ -348,6 +348,10 @@ static inline bool sema_expr_analyse_array_plain_initializer(SemaContext *contex
|
||||
// Generate a nice error message for zero.
|
||||
RETURN_SEMA_ERROR(elements[0], "Too many elements in initializer, it must be empty.");
|
||||
}
|
||||
if (expected_members > 0 && count > 0 && count != expected_members)
|
||||
{
|
||||
RETURN_SEMA_ERROR(elements[0], "Too %s elements in initializer, expected %u.", count > expected_members ? "many" : "few", expected_members);
|
||||
}
|
||||
|
||||
bool optional = false;
|
||||
bool is_vector = type_flat_is_vector(assigned);
|
||||
|
||||
8
test/test_suite/arrays/array_of_inferred_array.c3
Normal file
8
test/test_suite/arrays/array_of_inferred_array.c3
Normal file
@@ -0,0 +1,8 @@
|
||||
import std;
|
||||
macro void test(int[*][6] a)
|
||||
{
|
||||
}
|
||||
fn void main()
|
||||
{
|
||||
test({ { 1, 2 } }); // #error: Too few elements in initializer
|
||||
}
|
||||
16
test/test_suite/struct/empty_struct_if.c3
Normal file
16
test/test_suite/struct/empty_struct_if.c3
Normal file
@@ -0,0 +1,16 @@
|
||||
import std;
|
||||
const bool FOO = false;
|
||||
struct Foo
|
||||
{
|
||||
struct
|
||||
{
|
||||
struct // #error: members exist for this struct after processing
|
||||
{
|
||||
char d_pad0 @if(FOO);
|
||||
}
|
||||
}
|
||||
}
|
||||
fn void main()
|
||||
{
|
||||
Foo f;
|
||||
}
|
||||
7
test/test_suite/vector/vec_compare_int.c3
Normal file
7
test/test_suite/vector/vec_compare_int.c3
Normal file
@@ -0,0 +1,7 @@
|
||||
import std;
|
||||
fn void main()
|
||||
{
|
||||
Win32_UINT v1 = 1;
|
||||
int[<4>] v2 = 2;
|
||||
bool[<4>] vb = (v1 == v2); // #error: 'Win32_UINT' (uint) to 'int[<4>]' is not permitted, but you may do an explicit cast by placing
|
||||
}
|
||||
@@ -10,11 +10,6 @@ fn void main()
|
||||
|
||||
/* #expect: test.ll
|
||||
|
||||
; ModuleID = 'test'
|
||||
source_filename = "test"
|
||||
target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
|
||||
target triple = "x86_64-apple-macosx10.13.0"
|
||||
|
||||
@test.fooy = local_unnamed_addr global [2 x i8] c"\DE\AD", align 2
|
||||
@test.fooy2 = local_unnamed_addr global <2 x i8> <i8 -34, i8 -83>, align 2
|
||||
|
||||
|
||||
Reference in New Issue
Block a user