mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Improved checks of aliased "void".
This commit is contained in:
@@ -163,7 +163,7 @@ ABIArgInfo *x86_classify_return(CallABI call, Regs *regs, Type *type)
|
||||
type = type_lowering(type);
|
||||
|
||||
// 2. Void is ignored
|
||||
if (type == type_void) return abi_arg_ignore();
|
||||
if (type_is_void(type)) return abi_arg_ignore();
|
||||
|
||||
// 3. In the case of a vector or regcall, a homogenous aggregate
|
||||
// should be passed directly in a register.
|
||||
|
||||
@@ -2834,6 +2834,7 @@ INLINE const char *type_invalid_storage_type_name(Type *type)
|
||||
INLINE bool type_is_invalid_storage_type(Type *type)
|
||||
{
|
||||
if (!type) return false;
|
||||
RETRY:
|
||||
if (type == type_wildcard_optional) return true;
|
||||
switch (type->type_kind)
|
||||
{
|
||||
@@ -2843,6 +2844,9 @@ INLINE bool type_is_invalid_storage_type(Type *type)
|
||||
case TYPE_TYPEINFO:
|
||||
case TYPE_WILDCARD:
|
||||
return true;
|
||||
case TYPE_TYPEDEF:
|
||||
type = type->canonical;
|
||||
goto RETRY;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -51,6 +51,7 @@ LLVMValueRef llvm_store_to_ptr_aligned(GenContext *c, LLVMValueRef destination,
|
||||
LLVMValueRef llvm_store(GenContext *c, BEValue *destination, BEValue *value)
|
||||
{
|
||||
if (value->type == type_void) return NULL;
|
||||
assert(!type_is_void(value->type));
|
||||
assert(llvm_value_is_addr(destination));
|
||||
return llvm_store_to_ptr_aligned(c, destination->value, value, destination->alignment);
|
||||
}
|
||||
|
||||
@@ -227,8 +227,8 @@ static bool sema_expr_analyse_compare_exchange(SemaContext *context, Expr *expr)
|
||||
for (int i = 1; i < 3; i++)
|
||||
{
|
||||
Expr *arg = args[i];
|
||||
if (!sema_analyse_expr_rhs(context, pointee == type_void ? NULL : pointee, arg, true, NULL)) return false;
|
||||
if (pointee == type_void) pointee = arg->type->canonical;
|
||||
if (!sema_analyse_expr_rhs(context, type_is_void(pointee) ? NULL : pointee, arg, true, NULL)) return false;
|
||||
if (type_is_void(pointee)) pointee = arg->type->canonical;
|
||||
if (!type_is_atomic(type_flatten(arg->type)))
|
||||
{
|
||||
RETURN_SEMA_ERROR(arg, "%s may not be used with atomics.", type_quoted_error_string(arg->type));
|
||||
|
||||
@@ -286,7 +286,7 @@ static bool cast_if_valid(SemaContext *context, Expr *expr, Type *to_type, bool
|
||||
|
||||
if (from_type == to_type) return true;
|
||||
|
||||
bool is_void_silence = to_type == type_void && is_explicit;
|
||||
bool is_void_silence = type_is_void(to_type) && is_explicit;
|
||||
bool add_optional = type_is_optional(to_type) || type_is_optional(from_type);
|
||||
from_type = type_no_optional(from_type);
|
||||
to_type = type_no_optional(to_type);
|
||||
|
||||
@@ -900,7 +900,7 @@ static inline bool sema_analyse_signature(SemaContext *context, Signature *sig,
|
||||
rtype = rtype_info->type;
|
||||
if (sig->attrs.nodiscard)
|
||||
{
|
||||
if (rtype == type_void)
|
||||
if (type_is_void(rtype))
|
||||
{
|
||||
SEMA_ERROR(rtype_info, "@nodiscard cannot be used on %s returning 'void'.", is_macro ? "macros" : "functions");
|
||||
return false;
|
||||
@@ -1565,7 +1565,7 @@ static inline bool sema_analyse_operator_element_at(Decl *method)
|
||||
TypeInfo *rtype;
|
||||
Decl **params;
|
||||
if (!sema_analyse_operator_common(method, &rtype, ¶ms, 2)) return false;
|
||||
if (rtype->type->canonical == type_void)
|
||||
if (type_is_void(rtype->type))
|
||||
{
|
||||
SEMA_ERROR(rtype, "The return type cannot be 'void'.");
|
||||
return false;
|
||||
@@ -2842,7 +2842,7 @@ static inline bool sema_analyse_func(SemaContext *context, Decl *decl, bool *era
|
||||
SEMA_ERROR(rtype_info, "'@test' and '@benchmark' functions may only return 'void' or 'void!'.");
|
||||
return decl_poison(decl);
|
||||
}
|
||||
if (rtype->canonical == type_void)
|
||||
if (type_is_void(rtype))
|
||||
{
|
||||
rtype_info->type = type_get_optional(rtype);
|
||||
}
|
||||
@@ -2856,7 +2856,7 @@ static inline bool sema_analyse_func(SemaContext *context, Decl *decl, bool *era
|
||||
Type *rtype = rtype_info->type->canonical;
|
||||
if (sig->attrs.nodiscard)
|
||||
{
|
||||
if (rtype == type_void)
|
||||
if (type_is_void(rtype))
|
||||
{
|
||||
SEMA_ERROR(rtype_info, "@nodiscard cannot be used on functions returning 'void'.");
|
||||
return decl_poison(decl);
|
||||
@@ -3079,7 +3079,7 @@ bool sema_analyse_decl_type(SemaContext *context, Type *type, SourceSpan span)
|
||||
break;
|
||||
}
|
||||
if (!type_is_optional(type)) return true;
|
||||
if (type == type_wildcard_optional || type->optional == type_void)
|
||||
if (type == type_wildcard_optional || type_is_void(type->optional))
|
||||
{
|
||||
sema_error_at(span, "The use of 'void!' as a variable type is not permitted, use %s instead.",
|
||||
type_quoted_error_string(type_anyfault));
|
||||
@@ -3262,7 +3262,7 @@ bool sema_analyse_var_decl(SemaContext *context, Decl *decl, bool local)
|
||||
{
|
||||
SEMA_ERROR(init_expr, "No type can be inferred from the optional result.");
|
||||
}
|
||||
else if (init_expr->type == type_void)
|
||||
else if (type_is_void(init_expr->type))
|
||||
{
|
||||
SEMA_ERROR(init_expr, "You cannot initialize a value to 'void'.");
|
||||
}
|
||||
@@ -3470,7 +3470,7 @@ static bool sema_append_generate_parameterized_name(SemaContext *c, Module *modu
|
||||
if (!sema_resolve_type_info(c, type_info, RESOLVE_TYPE_DEFAULT)) return false;
|
||||
Type *type = type_info->type->canonical;
|
||||
if (type->type_kind == TYPE_OPTIONAL) RETURN_SEMA_ERROR(type_info, "Expected a non-optional type.");
|
||||
if (type == type_void) RETURN_SEMA_ERROR(type_info, "A 'void' type cannot be used as a parameter type.");
|
||||
if (type_is_void(type)) RETURN_SEMA_ERROR(type_info, "A 'void' type cannot be used as a parameter type.");
|
||||
if (type_is_invalid_storage_type(type)) RETURN_SEMA_ERROR(type_info, "Expected a runtime type.");
|
||||
if (type_is_func_ptr(type))
|
||||
{
|
||||
|
||||
@@ -1596,7 +1596,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, no_match_ref)) return false;
|
||||
if (type_no_optional(arg->type) == type_void) RETURN_SEMA_ERROR(arg, "A 'void' value cannot be passed as a parameter.");
|
||||
if (type_is_void(type_no_optional(arg->type))) 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))
|
||||
{
|
||||
@@ -1748,7 +1748,7 @@ static inline Type *context_unify_returns(SemaContext *context)
|
||||
}
|
||||
|
||||
// 3. Same type -> we're done.
|
||||
if (common_type == rtype || (common_type == type_void && rtype == type_wildcard)) continue;
|
||||
if (common_type == rtype || (type_is_void(common_type) && rtype == type_wildcard)) continue;
|
||||
|
||||
// 4. Find the max of the old and new.
|
||||
Type *max = type_find_max_type(common_type, rtype);
|
||||
@@ -1783,7 +1783,7 @@ static inline Type *context_unify_returns(SemaContext *context)
|
||||
Expr *ret_expr = return_stmt->return_stmt.expr;
|
||||
if (!ret_expr)
|
||||
{
|
||||
if (common_type == type_void) continue;
|
||||
if (type_is_void(common_type)) continue;
|
||||
context_unify_returns(context);
|
||||
}
|
||||
// 8. All casts should work.
|
||||
@@ -2023,7 +2023,7 @@ bool sema_expr_analyse_macro_call(SemaContext *context, Expr *call_expr, Expr *s
|
||||
Expr *ret_expr = return_stmt->return_stmt.expr;
|
||||
if (!ret_expr)
|
||||
{
|
||||
if (rtype == type_void) continue;
|
||||
if (type_is_void(rtype)) continue;
|
||||
SEMA_ERROR(return_stmt, "Expected returning a value of type %s.", type_quoted_error_string(rtype));
|
||||
goto EXIT_FAIL;
|
||||
}
|
||||
@@ -5977,7 +5977,7 @@ static inline bool sema_expr_analyse_deref(SemaContext *context, Expr *expr, boo
|
||||
RETURN_SEMA_ERROR(inner, "Cannot dereference a value of type %s, it must be a pointer.",
|
||||
type_quoted_error_string(inner_type_nofail));
|
||||
}
|
||||
if (canonical->pointer == type_void)
|
||||
if (type_is_void(canonical->pointer))
|
||||
{
|
||||
if (failed_ref) goto ON_FAILED;
|
||||
RETURN_SEMA_ERROR(inner, "A 'void*' cannot be dereferenced, you need to first cast it to a concrete type.");
|
||||
@@ -8172,7 +8172,7 @@ static inline bool sema_expr_analyse_retval(SemaContext *c, Expr *expr)
|
||||
else
|
||||
{
|
||||
expr->type = type_no_optional(c->rtype);
|
||||
if (expr->type == type_void)
|
||||
if (type_is_void(expr->type))
|
||||
{
|
||||
SEMA_ERROR(expr, "'return' cannot be used on void functions.");
|
||||
return false;
|
||||
|
||||
@@ -1069,7 +1069,7 @@ static inline bool sema_analyse_cond(SemaContext *context, Expr *expr, CondType
|
||||
// 3a. Check for optional in case of an expression.
|
||||
if (IS_OPTIONAL(last))
|
||||
{
|
||||
if (type_no_optional(last->type) == type_void && cast_to_bool)
|
||||
if (type_is_void(type_no_optional(last->type)) && cast_to_bool)
|
||||
{
|
||||
SEMA_ERROR(last, "Use '@ok(<expr>)' or '@catch(<expr>)' to explicitly convert a 'void!' to a boolean.");
|
||||
return false;
|
||||
|
||||
@@ -1391,7 +1391,7 @@ static inline Type *func_create_new_func_proto(Signature *sig, CallABI abi, uint
|
||||
proto->is_optional = true;
|
||||
Type *real_return_type = rtype->optional;
|
||||
proto->ret_by_ref_type = rtype->optional;
|
||||
proto->ret_by_ref = real_return_type->type_kind != TYPE_VOID;
|
||||
proto->ret_by_ref = !type_is_void(real_return_type);
|
||||
proto->abi_ret_type = type_anyfault;
|
||||
}
|
||||
else
|
||||
@@ -1773,7 +1773,7 @@ TypeCmpResult type_array_element_is_equivalent(SemaContext *context, Type *eleme
|
||||
element2 = element2->canonical;
|
||||
}
|
||||
if (element1 == element2) return TYPE_SAME;
|
||||
if ((element1 == type_void && element2 == type_char) || (element1 == type_char && element2 == type_void))
|
||||
if ((type_is_void(element1) && element2 == type_char) || (element1 == type_char && type_is_void(element2)))
|
||||
{
|
||||
return TYPE_SAME;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,11 @@ struct Foo {
|
||||
void bar; // #error: Members cannot be of
|
||||
}
|
||||
|
||||
def Void = void;
|
||||
struct Foo2 {
|
||||
Void bar; // #error: Members cannot be of
|
||||
}
|
||||
fn void main(String[] args) {
|
||||
Foo foo;
|
||||
Foo2 foo2;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user