mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Fixes to function pointer conversion.
This commit is contained in:
@@ -2266,7 +2266,7 @@ Type *type_get_inferred_array(Type *arr_type);
|
||||
Type *type_get_inferred_vector(Type *arr_type);
|
||||
Type *type_get_flexible_array(Type *arr_type);
|
||||
Type *type_get_scaled_vector(Type *arr_type);
|
||||
Type *type_get_failable(Type *failable_type);
|
||||
Type *type_get_optional(Type *failable_type);
|
||||
Type *type_get_vector(Type *vector_type, unsigned len);
|
||||
Type *type_get_vector_bool(Type *original_type);
|
||||
Type *type_int_signed_by_bitsize(BitSize bitsize);
|
||||
@@ -2376,7 +2376,7 @@ INLINE bool type_is_pointer_sized(Type *type)
|
||||
INLINE Type *type_add_optional(Type *type, bool make_optional)
|
||||
{
|
||||
if (!make_optional || type->type_kind == TYPE_OPTIONAL || type->type_kind == TYPE_FAILABLE_ANY) return type;
|
||||
return type_get_failable(type);
|
||||
return type_get_optional(type);
|
||||
}
|
||||
|
||||
INLINE bool type_len_is_inferred(Type *type)
|
||||
|
||||
@@ -745,7 +745,7 @@ TypeInfo *parse_optional_type(ParseContext *c)
|
||||
info->failable = true;
|
||||
if (info->resolve_status == RESOLVE_DONE)
|
||||
{
|
||||
info->type = type_get_failable(info->type);
|
||||
info->type = type_get_optional(info->type);
|
||||
}
|
||||
RANGE_EXTEND_PREV(info);
|
||||
}
|
||||
|
||||
@@ -1437,7 +1437,7 @@ bool cast(Expr *expr, Type *to_type)
|
||||
|
||||
if (type_is_optional_any(from_type))
|
||||
{
|
||||
expr->type = type_get_failable(to_type);
|
||||
expr->type = type_get_optional(to_type);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1468,7 +1468,7 @@ bool cast(Expr *expr, Type *to_type)
|
||||
Type *result_type = expr->type;
|
||||
if (from_is_failable && !type_is_optional(result_type))
|
||||
{
|
||||
expr->type = type_get_failable(result_type);
|
||||
expr->type = type_get_optional(result_type);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1498,7 +1498,7 @@ static inline Type *context_unify_returns(SemaContext *context)
|
||||
if (failable)
|
||||
{
|
||||
// If there are only implicit returns, then we assume void!, otherwise it's an "anyfail"
|
||||
return no_return ? type_get_failable(type_void) : type_anyfail;
|
||||
return no_return ? type_get_optional(type_void) : type_anyfail;
|
||||
}
|
||||
// No failable => void.
|
||||
return type_void;
|
||||
|
||||
@@ -163,7 +163,7 @@ static inline bool sema_expr_analyse_struct_plain_initializer(SemaContext *conte
|
||||
failable = failable || IS_OPTIONAL(element);
|
||||
}
|
||||
assert(initializer->type);
|
||||
if (failable) initializer->type = type_get_failable(initializer->type);
|
||||
if (failable) initializer->type = type_get_optional(initializer->type);
|
||||
|
||||
// 6. There's the case of too few values as well. Mark the last field as wrong.
|
||||
assert(elements_needed <= size);
|
||||
@@ -251,7 +251,7 @@ static inline bool sema_expr_analyse_array_plain_initializer(SemaContext *contex
|
||||
failable = failable || IS_OPTIONAL(element);
|
||||
}
|
||||
assert(initializer->type);
|
||||
if (failable) initializer->type = type_get_failable(initializer->type);
|
||||
if (failable) initializer->type = type_get_optional(initializer->type);
|
||||
|
||||
if (expected_members > size)
|
||||
{
|
||||
|
||||
@@ -400,7 +400,7 @@ APPEND_QUALIFIERS:
|
||||
if (type_info->failable)
|
||||
{
|
||||
Type *type = type_info->type;
|
||||
if (!type_is_optional(type)) type_info->type = type_get_failable(type);
|
||||
if (!type_is_optional(type)) type_info->type = type_get_optional(type);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
|
||||
#include "compiler_internal.h"
|
||||
|
||||
static Type *flatten_raw_function_type(Type *type);
|
||||
|
||||
static struct
|
||||
{
|
||||
Type u0, u1, i8, i16, i32, i64, i128, ixx;
|
||||
@@ -839,7 +841,7 @@ Type *type_get_ptr_recurse(Type *ptr_type)
|
||||
if (ptr_type->type_kind == TYPE_OPTIONAL)
|
||||
{
|
||||
ptr_type = ptr_type->failable;
|
||||
return type_get_failable(type_get_ptr(ptr_type));
|
||||
return type_get_optional(type_get_ptr(ptr_type));
|
||||
}
|
||||
return type_get_ptr(ptr_type);
|
||||
|
||||
@@ -850,7 +852,7 @@ Type *type_get_ptr(Type *ptr_type)
|
||||
return type_generate_ptr(ptr_type, false);
|
||||
}
|
||||
|
||||
Type *type_get_failable(Type *failable_type)
|
||||
Type *type_get_optional(Type *failable_type)
|
||||
{
|
||||
assert(!type_is_optional(failable_type));
|
||||
return type_generate_failable(failable_type, false);
|
||||
@@ -1171,16 +1173,42 @@ void type_func_prototype_init(uint32_t capacity)
|
||||
static uint32_t hash_function(Signature *sig)
|
||||
{
|
||||
uintptr_t hash = (unsigned)sig->variadic;
|
||||
hash = hash * 31 + (uintptr_t)type_infoptr(sig->rtype)->type->canonical;
|
||||
hash = hash * 31 + (uintptr_t)flatten_raw_function_type(type_infoptr(sig->rtype)->type);
|
||||
Decl **params = sig->params;
|
||||
VECEACH(params, i)
|
||||
{
|
||||
Decl *param = params[i];
|
||||
hash = hash * 31 + (uintptr_t)param->type->canonical;
|
||||
hash = hash * 31 + (uintptr_t)flatten_raw_function_type(param->type->canonical);
|
||||
}
|
||||
return (uint32_t)((hash >> 16) ^ hash);
|
||||
}
|
||||
|
||||
static bool compare_func_param(Type *one, Type *other)
|
||||
{
|
||||
if (one == other) return true;
|
||||
one = one->canonical;
|
||||
other = other->canonical;
|
||||
if (one == other) return true;
|
||||
if (one->type_kind != other->type_kind) return false;
|
||||
switch (one->type_kind)
|
||||
{
|
||||
case TYPE_POINTER:
|
||||
return compare_func_param(one->pointer, other->pointer);
|
||||
case TYPE_ARRAY:
|
||||
if (one->array.len != other->array.len) return false;
|
||||
FALLTHROUGH;
|
||||
case TYPE_SUBARRAY:
|
||||
case TYPE_FLEXIBLE_ARRAY:
|
||||
return compare_func_param(one->array.base, other->array.base);
|
||||
case TYPE_FUNC:
|
||||
return one->function.prototype->raw_type == other->function.prototype->raw_type;
|
||||
case TYPE_OPTIONAL:
|
||||
return compare_func_param(one->failable, other->failable);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static int compare_function(Signature *sig, FunctionPrototype *proto)
|
||||
{
|
||||
if (sig->variadic != proto->variadic) return -1;
|
||||
@@ -1188,17 +1216,54 @@ static int compare_function(Signature *sig, FunctionPrototype *proto)
|
||||
Type **other_params = proto->param_types;
|
||||
unsigned param_count = vec_size(params);
|
||||
if (param_count != vec_size(other_params)) return -1;
|
||||
if (type_infoptr(sig->rtype)->type->canonical != proto->rtype->canonical) return -1;
|
||||
if (!compare_func_param(type_infoptr(sig->rtype)->type, proto->rtype)) return -1;
|
||||
VECEACH(params, i)
|
||||
{
|
||||
Decl *param = params[i];
|
||||
Type *other_param = other_params[i];
|
||||
if (param->type->canonical != other_param->canonical) return -1;
|
||||
if (!compare_func_param(param->type, other_param->canonical)) return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static Type *flatten_raw_function_type(Type *type)
|
||||
{
|
||||
Type *other;
|
||||
Type *current;
|
||||
switch (type->type_kind)
|
||||
{
|
||||
case TYPE_TYPEDEF:
|
||||
return flatten_raw_function_type(type->canonical);
|
||||
case TYPE_FUNC:
|
||||
return type->function.prototype->raw_type;
|
||||
case TYPE_OPTIONAL:
|
||||
current = type->failable;
|
||||
other = flatten_raw_function_type(current);
|
||||
return other == current ? type : type_get_optional(other);
|
||||
case TYPE_POINTER:
|
||||
current = type->pointer;
|
||||
other = flatten_raw_function_type(current);
|
||||
return other == current ? type : type_get_ptr(other);
|
||||
case TYPE_ARRAY:
|
||||
current = type->array.base;
|
||||
other = flatten_raw_function_type(current);
|
||||
return other == current ? type : type_get_array(other, type->array.len);
|
||||
case TYPE_SUBARRAY:
|
||||
current = type->array.base;
|
||||
other = flatten_raw_function_type(current);
|
||||
return other == current ? type : type_get_subarray(other);
|
||||
case TYPE_FLEXIBLE_ARRAY:
|
||||
current = type->array.base;
|
||||
other = flatten_raw_function_type(current);
|
||||
return other == current ? type : type_get_flexible_array(other);
|
||||
case TYPE_INFERRED_ARRAY:
|
||||
current = type->array.base;
|
||||
other = flatten_raw_function_type(current);
|
||||
return other == current ? type : type_get_inferred_array(other);
|
||||
default:
|
||||
return type;
|
||||
}
|
||||
}
|
||||
static inline Type *func_create_new_func_proto(Signature *sig, CallABI abi, uint32_t hash, FuncTypeEntry *entry)
|
||||
{
|
||||
unsigned param_count = vec_size(sig->params);
|
||||
|
||||
@@ -1 +1 @@
|
||||
#define COMPILER_VERSION "0.3.64"
|
||||
#define COMPILER_VERSION "0.3.65"
|
||||
20
test/test_suite/functions/func_ptr_conversion_alias.c3t
Normal file
20
test/test_suite/functions/func_ptr_conversion_alias.c3t
Normal file
@@ -0,0 +1,20 @@
|
||||
module test;
|
||||
|
||||
define Callback = fn void();
|
||||
define Callback2 = fn void();
|
||||
|
||||
define GetCallback = fn Callback2**[][123]*();
|
||||
|
||||
fn Callback**[][123]* tester()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
GetCallback x = &tester;
|
||||
|
||||
|
||||
define GetCallbackOpt = fn Callback2!();
|
||||
|
||||
fn Callback2! tester2() = null;
|
||||
|
||||
GetCallbackOpt y = &tester2;
|
||||
20
test/test_suite2/functions/func_ptr_conversion_alias.c3t
Normal file
20
test/test_suite2/functions/func_ptr_conversion_alias.c3t
Normal file
@@ -0,0 +1,20 @@
|
||||
module test;
|
||||
|
||||
define Callback = fn void();
|
||||
define Callback2 = fn void();
|
||||
|
||||
define GetCallback = fn Callback2**[][123]*();
|
||||
|
||||
fn Callback**[][123]* tester()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
GetCallback x = &tester;
|
||||
|
||||
|
||||
define GetCallbackOpt = fn Callback2!();
|
||||
|
||||
fn Callback2! tester2() = null;
|
||||
|
||||
GetCallbackOpt y = &tester2;
|
||||
Reference in New Issue
Block a user