mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
- Passing a non-conststring to module attributes like @cname would trigger an assert rather than printing an error.
- Passing different types to arg 1 and 2 for $$matrix_transpose would trigger an assert. - Zero init of optional compile time variable would crash the compiler. - Using multiple declaration for generics in generic module would fail. - Defining an extern const without a type would crash rather than print an error. - Typedef followed by brace would trigger an assert. - Union with too big member would trigger an assert.
This commit is contained in:
@@ -66,6 +66,13 @@
|
||||
- Too little memory reserved when printing backtrace on Darwin #2698.
|
||||
- In some cases, a type would not get implicitly converted to a typeid #2764.
|
||||
- Assert on defining a const fault enum with enumerator and fault of the same name. #2732
|
||||
- Passing a non-conststring to module attributes like @cname would trigger an assert rather than printing an error. #2771
|
||||
- Passing different types to arg 1 and 2 for $$matrix_transpose would trigger an assert. #2771
|
||||
- Zero init of optional compile time variable would crash the compiler. #2771
|
||||
- Using multiple declaration for generics in generic module would fail. #2771
|
||||
- Defining an extern const without a type would crash rather than print an error. #2771
|
||||
- Typedef followed by brace would trigger an assert. #2771
|
||||
- Union with too big member would trigger an assert. #2771
|
||||
|
||||
### Stdlib changes
|
||||
- Add `ThreadPool` join function to wait for all threads to finish in the pool without destroying the threads.
|
||||
|
||||
@@ -370,7 +370,7 @@ bool parse_module(ParseContext *c, AstId contracts)
|
||||
vec_size(attr->exprs));
|
||||
}
|
||||
Expr *expr = attr->exprs[0];
|
||||
if (!expr_is_const_string(expr)) RETURN_PRINT_ERROR_AT(false, expr, "Expected a constant string.");
|
||||
if (expr->resolve_status != RESOLVE_DONE || !expr_is_const_string(expr)) RETURN_PRINT_ERROR_AT(false, expr, "Expected a constant string.");
|
||||
if (c->unit->module->extname)
|
||||
{
|
||||
RETURN_PRINT_ERROR_AT(false, attr,
|
||||
@@ -388,7 +388,7 @@ bool parse_module(ParseContext *c, AstId contracts)
|
||||
vec_size(attr->exprs));
|
||||
}
|
||||
Expr *expr = attr->exprs[0];
|
||||
if (!expr_is_const_string(expr)) RETURN_PRINT_ERROR_AT(false, expr, "Expected a constant string.");
|
||||
if (expr->resolve_status != RESOLVE_DONE || !expr_is_const_string(expr)) RETURN_PRINT_ERROR_AT(false, expr, "Expected a constant string.");
|
||||
if (c->unit->module->extname)
|
||||
{
|
||||
RETURN_PRINT_ERROR_AT(false, attr,
|
||||
@@ -1533,6 +1533,7 @@ static inline Decl *parse_global_declaration(ParseContext *c)
|
||||
CONSUME_EOS_OR_RET(poisoned_decl);
|
||||
Attr **attributes = decl->attributes;
|
||||
// Copy the attributes to the other variables.
|
||||
|
||||
if (attributes)
|
||||
{
|
||||
FOREACH(Decl *, d, decls)
|
||||
@@ -1541,12 +1542,27 @@ static inline Decl *parse_global_declaration(ParseContext *c)
|
||||
d->attributes = copy_attributes_single(attributes);
|
||||
}
|
||||
}
|
||||
int generics_id = decl->is_template ? decl->generic_id : -1;
|
||||
if (generics_id > -1)
|
||||
{
|
||||
FOREACH(Decl *, d, decls)
|
||||
{
|
||||
if (d == decl) continue;
|
||||
d->generic_id = generics_id;
|
||||
d->is_template = true;
|
||||
}
|
||||
}
|
||||
// If we have multiple decls, then we return that as a bundled decl_globals
|
||||
if (decls)
|
||||
{
|
||||
decl = decl_calloc();
|
||||
decl->decl_kind = DECL_GROUP;
|
||||
decl->decls = decls;
|
||||
if (generics_id > -1)
|
||||
{
|
||||
decl->generic_id = generics_id;
|
||||
decl->is_template = true;
|
||||
}
|
||||
return decl;
|
||||
}
|
||||
return decl;
|
||||
@@ -2065,8 +2081,6 @@ static inline Decl *parse_typedef_declaration(ParseContext *c)
|
||||
// 2. Now parse the type which we know is here.
|
||||
ASSIGN_TYPE_OR_RET(decl->distinct, parse_optional_type(c), poisoned_decl);
|
||||
|
||||
ASSERT(!tok_is(c, TOKEN_LBRACE));
|
||||
|
||||
while (tok_is(c, TOKEN_AT_IDENT))
|
||||
{
|
||||
const char *name = symstr(c);
|
||||
|
||||
@@ -835,6 +835,7 @@ bool sema_expr_analyse_builtin_call(SemaContext *context, Expr *expr)
|
||||
if (!sema_check_builtin_args(context, args, (BuiltinArg[]) {BA_VEC, BA_INTEGER, BA_INTEGER}, 3)) return false;
|
||||
if (!sema_check_builtin_args_const(context, &args[1], 2)) return false;
|
||||
ArraySize vec_len = type_flatten(args[0]->type)->array.len;
|
||||
if (!cast_implicit(context, args[2], args[1]->type, false)) return false;
|
||||
Int sum = int_mul(args[1]->const_expr.ixx, args[2]->const_expr.ixx);
|
||||
if (!int_icomp(sum, vec_len, BINARYOP_EQ))
|
||||
{
|
||||
|
||||
@@ -362,6 +362,8 @@ static bool sema_analyse_union_members(SemaContext *context, Decl *decl)
|
||||
if (!sema_check_struct_holes(context, decl, member)) return false;
|
||||
|
||||
ByteSize member_size = type_size(member->type);
|
||||
if (member_size > MAX_STRUCT_SIZE) RETURN_SEMA_ERROR(member, "Union member '%s' would cause the union to become too large (exceeding 2 GB).", member->name);
|
||||
|
||||
ASSERT(member_size <= MAX_TYPE_SIZE);
|
||||
// Update max alignment
|
||||
if (member->alignment > member_alignment) member_alignment = member->alignment;
|
||||
@@ -4726,7 +4728,7 @@ bool sema_analyse_var_decl_ct(SemaContext *context, Decl *decl, bool *check_fail
|
||||
goto FAIL;
|
||||
}
|
||||
decl->var.init_expr = init = expr_new(EXPR_POISONED, decl->span);
|
||||
expr_rewrite_to_const_zero(init, decl->type);
|
||||
expr_rewrite_to_const_zero(init, type_no_optional(decl->type));
|
||||
}
|
||||
|
||||
// Analyse the expression.
|
||||
@@ -4813,6 +4815,11 @@ bool sema_analyse_var_decl(SemaContext *context, Decl *decl, bool local, bool *c
|
||||
TypeInfo *type_info = vartype(decl);
|
||||
// We expect a constant to actually be parsed correctly so that it has a value, so
|
||||
// this should always be true.
|
||||
if (!type_info && decl->is_extern)
|
||||
{
|
||||
SEMA_ERROR(decl, "A type is needed for the extern %s '%s'.", decl_to_name(decl), decl->name);
|
||||
return decl_poison(decl);
|
||||
}
|
||||
ASSERT(type_info || decl->var.init_expr);
|
||||
|
||||
bool erase_decl = false;
|
||||
|
||||
5
test/test_suite/attributes/string_module_attributes.c3
Normal file
5
test/test_suite/attributes/string_module_attributes.c3
Normal file
@@ -0,0 +1,5 @@
|
||||
module linux @cname(NETBSD ??? "" : ""); // #error: Expected a constant string
|
||||
fn int main()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
6
test/test_suite/builtins/matrix_builtin_cast.c3
Normal file
6
test/test_suite/builtins/matrix_builtin_cast.c3
Normal file
@@ -0,0 +1,6 @@
|
||||
fn int main()
|
||||
{
|
||||
int[<6>] c = 2;
|
||||
c = $$matrix_transpose(c, 0x10, 3); // #error: Expected row * col to equal 6
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
fn void main()
|
||||
{
|
||||
char? a, $b;
|
||||
}
|
||||
11
test/test_suite/generic/generic_multiple_decl.c3t
Normal file
11
test/test_suite/generic/generic_multiple_decl.c3t
Normal file
@@ -0,0 +1,11 @@
|
||||
module elastic_array <Type, MAX_SIZE>;
|
||||
int a, b, c;
|
||||
module bar;
|
||||
import elastic_array;
|
||||
fn int main()
|
||||
{
|
||||
int g = elastic_array::a{int, 2};
|
||||
int g2 = elastic_array::b{int, 2};
|
||||
elastic_array::b{int, 2} = 3;
|
||||
return 0;
|
||||
}
|
||||
1
test/test_suite/globals/extern_const_no_type.c3
Normal file
1
test/test_suite/globals/extern_const_no_type.c3
Normal file
@@ -0,0 +1 @@
|
||||
extern const FOO; // #error: A type is needed for the extern constant 'FOO'
|
||||
2
test/test_suite/types/typedef_followed_by_brace.c3
Normal file
2
test/test_suite/types/typedef_followed_by_brace.c3
Normal file
@@ -0,0 +1,2 @@
|
||||
typedef Bar = BacktraceList? // #error: Expected ';'
|
||||
{
|
||||
4
test/test_suite/union/union_too_big.c3
Normal file
4
test/test_suite/union/union_too_big.c3
Normal file
@@ -0,0 +1,4 @@
|
||||
union Xu
|
||||
{
|
||||
int[int.max] b; // #error: Union member 'b' would cause the union to become too large
|
||||
}
|
||||
Reference in New Issue
Block a user