mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Fixes #786, constant initialization with constants sometimes causing an error lowering to LLVM. Fixes bug passing void as a vararg argument to an any vararg.
This commit is contained in:
@@ -123,6 +123,8 @@
|
||||
- Added `Clock` and `DateTime`.
|
||||
|
||||
### Fixes
|
||||
- Fixes bug initializing a const struct with a const struct value
|
||||
- Fixes bug when `void` is passed to an "any"-vararg.
|
||||
- Fixed defer/return value ordering in certain cases.
|
||||
- Fixes to the x64 ABI.
|
||||
- Updates to how variadics are implemented.
|
||||
|
||||
@@ -2826,9 +2826,12 @@ bool sema_analyse_var_decl(SemaContext *context, Decl *decl, bool local)
|
||||
if (init_expr->type == type_wildcard_optional || init_expr->type == type_wildcard)
|
||||
{
|
||||
SEMA_ERROR(init_expr, "No type can be inferred from the optional result.");
|
||||
return false;
|
||||
}
|
||||
if (init_expr->type == type_untypedlist)
|
||||
else if (init_expr->type == type_void)
|
||||
{
|
||||
SEMA_ERROR(init_expr, "You cannot initialize a value to 'void'.");
|
||||
}
|
||||
else if (init_expr->type == type_untypedlist)
|
||||
{
|
||||
SEMA_ERROR(init_expr, "The type of an untyped list cannot be inferred, you can try adding an explicit type to solve this.");
|
||||
}
|
||||
@@ -3018,25 +3021,31 @@ static bool sema_append_generate_parameterized_name(SemaContext *c, Module *modu
|
||||
}
|
||||
if (param->expr_kind == EXPR_TYPEINFO)
|
||||
{
|
||||
TypeInfo *type = param->type_expr;
|
||||
if (!sema_resolve_type_info(c, type)) return decl_poison(decl);
|
||||
if (type->type->type_kind == TYPE_OPTIONAL)
|
||||
TypeInfo *type_info = param->type_expr;
|
||||
if (!sema_resolve_type_info(c, type_info)) return decl_poison(decl);
|
||||
Type *type = type_info->type->canonical;
|
||||
if (type->type_kind == TYPE_OPTIONAL)
|
||||
{
|
||||
SEMA_ERROR(type, "Expected a non-optional type.");
|
||||
SEMA_ERROR(type_info, "Expected a non-optional type.");
|
||||
return poisoned_decl;
|
||||
}
|
||||
if (type_is_invalid_storage_type(type->type))
|
||||
if (type == type_void)
|
||||
{
|
||||
SEMA_ERROR(type, "Expected a runtime type.");
|
||||
SEMA_ERROR(type_info, "A 'void' type cannot be used as a parameter type.");
|
||||
return poisoned_decl;
|
||||
}
|
||||
if (type_is_invalid_storage_type(type))
|
||||
{
|
||||
SEMA_ERROR(type_info, "Expected a runtime type.");
|
||||
return poisoned_decl;
|
||||
}
|
||||
if (mangled)
|
||||
{
|
||||
type_mangle_introspect_name_to_buffer(type->type->canonical);
|
||||
type_mangle_introspect_name_to_buffer(type);
|
||||
}
|
||||
else
|
||||
{
|
||||
scratch_buffer_append(type->type->name);
|
||||
scratch_buffer_append(type_info->type->name);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -1257,10 +1257,11 @@ INLINE bool sema_call_expand_arguments(SemaContext *context, CalledDecl *callee,
|
||||
else if (variadic == VARIADIC_ANY)
|
||||
{
|
||||
if (!sema_analyse_expr(context, arg)) return false;
|
||||
if (type_is_invalid_storage_type(arg->type))
|
||||
Type *type = arg->type;
|
||||
if (type_is_invalid_storage_type(type) || type == type_void)
|
||||
{
|
||||
SEMA_ERROR(arg, "A value of type %s cannot be passed as a variadic argument.",
|
||||
type_quoted_error_string(arg->type));
|
||||
type_quoted_error_string(type));
|
||||
return false;
|
||||
}
|
||||
expr_insert_addr(arg);
|
||||
@@ -1471,7 +1472,7 @@ static inline bool sema_call_analyse_invocation(SemaContext *context, Expr *call
|
||||
else
|
||||
{
|
||||
if (!sema_analyse_expr(context, val)) return false;
|
||||
if (type_is_invalid_storage_type(val->type))
|
||||
if (type_is_invalid_storage_type(val->type) || val->type == type_void)
|
||||
{
|
||||
SEMA_ERROR(val, "A value of type %s cannot be passed as a variadic argument.",
|
||||
type_quoted_error_string(val->type));
|
||||
@@ -1538,7 +1539,7 @@ static inline bool sema_call_analyse_invocation(SemaContext *context, Expr *call
|
||||
if (!sema_expr_check_assign(context, arg)) return false;
|
||||
*optional |= IS_OPTIONAL(arg);
|
||||
if (!sema_call_check_contract_param_match(context, param, arg)) return false;
|
||||
if (type_is_invalid_storage_type(type))
|
||||
if (type_is_invalid_storage_type(type) || type == type_void)
|
||||
{
|
||||
SEMA_ERROR(arg, "A value of type %s cannot be passed by reference.", type_quoted_error_string(type));
|
||||
return false;
|
||||
@@ -1563,6 +1564,7 @@ static inline bool sema_call_analyse_invocation(SemaContext *context, Expr *call
|
||||
case VARDECL_PARAM:
|
||||
// foo
|
||||
if (!sema_analyse_expr_rhs(context, type, arg, true)) return false;
|
||||
if (type_no_optional(arg->type) == type_void) RETURN_SEMA_ERROR(arg, "A 'void' value cannot be passed as a parameter.");
|
||||
if (IS_OPTIONAL(arg)) *optional = true;
|
||||
if (type_is_invalid_storage_type(arg->type))
|
||||
{
|
||||
@@ -5892,10 +5894,11 @@ static inline bool sema_expr_analyse_taddr(SemaContext *context, Expr *expr)
|
||||
Expr *inner = expr->unary_expr.expr;
|
||||
if (!sema_analyse_expr(context, inner)) return false;
|
||||
|
||||
if (type_is_invalid_storage_type(inner->type))
|
||||
Type *type = inner->type;
|
||||
if (type_is_invalid_storage_type(type) || type == type_void)
|
||||
{
|
||||
SEMA_ERROR(expr, "It is not possible to take the address from a value of the type %s.",
|
||||
type_quoted_error_string(inner->type));
|
||||
SEMA_ERROR(expr, "It is not possible to take the address from a value of type %s.",
|
||||
type_quoted_error_string(type));
|
||||
return false;
|
||||
}
|
||||
// 2. The type is the resulting type of the expression.
|
||||
@@ -6584,7 +6587,7 @@ static inline bool sema_expr_analyse_ct_alignof(SemaContext *context, Expr *expr
|
||||
Decl *decl = sema_expr_analyse_var_path(context, main_var);
|
||||
if (!decl) return false;
|
||||
Type *type = decl->type;
|
||||
if (type_is_invalid_storage_type(type))
|
||||
if (type_is_invalid_storage_type(type) || type == type_void)
|
||||
{
|
||||
SEMA_ERROR(main_var, "Cannot use '$alignof' on type %s.", type_quoted_error_string(type));
|
||||
return false;
|
||||
|
||||
@@ -637,6 +637,14 @@ static void sema_create_const_initializer_value(ConstInitializer *const_init, Ex
|
||||
value->const_expr.initializer = const_init;
|
||||
return;
|
||||
}
|
||||
if (value->expr_kind == EXPR_IDENTIFIER)
|
||||
{
|
||||
Decl *ident = value->identifier_expr.decl;
|
||||
assert(ident->decl_kind == DECL_VAR);
|
||||
assert(ident->var.kind == VARDECL_CONST);
|
||||
sema_create_const_initializer_value(const_init, expr_copy(ident->var.init_expr));
|
||||
return;
|
||||
}
|
||||
const_init->init_value = value;
|
||||
const_init->type = type_flatten(value->type);
|
||||
const_init->kind = CONST_INIT_VALUE;
|
||||
|
||||
@@ -1 +1 @@
|
||||
#define COMPILER_VERSION "0.4.531"
|
||||
#define COMPILER_VERSION "0.4.532"
|
||||
18
test/test_suite/constants/constant_struct.c3
Normal file
18
test/test_suite/constants/constant_struct.c3
Normal file
@@ -0,0 +1,18 @@
|
||||
import std::io;
|
||||
|
||||
struct Abc
|
||||
{
|
||||
int a;
|
||||
}
|
||||
|
||||
struct Bcd
|
||||
{
|
||||
Abc x;
|
||||
}
|
||||
|
||||
const Abc FOO = { 2 };
|
||||
|
||||
fn void! main()
|
||||
{
|
||||
Bcd a = { FOO };
|
||||
}
|
||||
33
test/test_suite/expressions/void_arg.c3
Normal file
33
test/test_suite/expressions/void_arg.c3
Normal file
@@ -0,0 +1,33 @@
|
||||
import std::io;
|
||||
|
||||
fn void test1()
|
||||
{
|
||||
foo(test1()); // #error: A 'void' value cannot be passed as a parameter
|
||||
}
|
||||
|
||||
fn void test2()
|
||||
{
|
||||
bar(test2()); // #error: You cannot cast 'void' into 'int' even with an explicit cast
|
||||
}
|
||||
|
||||
fn void test3()
|
||||
{
|
||||
baz(test3()); // #error: A value of type 'void' cannot be passed as a variadic argumen
|
||||
}
|
||||
|
||||
fn void test4()
|
||||
{
|
||||
abc(test4());
|
||||
}
|
||||
|
||||
macro void abc(...) {}
|
||||
|
||||
extern fn void baz(...);
|
||||
|
||||
macro void foo(x)
|
||||
{
|
||||
}
|
||||
|
||||
fn void bar(int x)
|
||||
{}
|
||||
|
||||
Reference in New Issue
Block a user