diff --git a/stage1/spl_ast2ir.c b/stage1/spl_ast2ir.c index 9b209b2..0e95a48 100644 --- a/stage1/spl_ast2ir.c +++ b/stage1/spl_ast2ir.c @@ -1917,7 +1917,9 @@ static spl_ir_node_ref_t emit_implicit_cast(spl_ast2ir_t *a, spl_ast_node_t *n, if (fs->kind == SPL_TYPE_BOOL && ts->kind == SPL_TYPE_INT) return spl_ir_builder_cast_bool2int(a->ir, ft, tt, v); - if (fs->kind == SPL_TYPE_PTR && ts->kind == SPL_TYPE_PTR) + bool fs_ptr_like = fs->kind == SPL_TYPE_PTR || fs->kind == SPL_TYPE_FN; + bool ts_ptr_like = ts->kind == SPL_TYPE_PTR || ts->kind == SPL_TYPE_FN; + if (fs_ptr_like && ts_ptr_like) return v; if (fs->kind == SPL_TYPE_PTR && ts->kind == SPL_TYPE_INT) diff --git a/stage1/spl_ir2vm.c b/stage1/spl_ir2vm.c index 8f2873c..a7145c2 100644 --- a/stage1/spl_ir2vm.c +++ b/stage1/spl_ir2vm.c @@ -1182,6 +1182,10 @@ int spl_ir2vm_run(spl_ir2vm_t *ctx) { } } + /* 保留 insn 0 作为哨兵:确保真实函数入口地址非零, + 从而 0 可唯一表示 null 函数指针(函数指针与 null 比较)。 */ + spl_prog_add_instr(&ctx->prog, SPL_HALT, SPL_VOID, 0); + /* Pass 2:翻译非 extern 的函数 */ usize *fid_ip = calloc(n, sizeof(usize)); fix_vec_t all_fixups; diff --git a/stage1/spl_lang_type.c b/stage1/spl_lang_type.c index 39c8e17..24ef851 100644 --- a/stage1/spl_lang_type.c +++ b/stage1/spl_lang_type.c @@ -482,6 +482,13 @@ bool spl_lang_type_is_subtype(const spl_lang_type_t *type, spl_lang_type_id_t su return ir_sub->float_type.bits == 0; } + /* null(*never)可隐式转换为函数指针:函数值按指针布局,可空。 */ + if (nsuper->kind == SPL_LANG_TYPE_FN && nsub->kind == SPL_LANG_TYPE_PTR) { + spl_lang_type_node_t *sub_elem = spl_lang_type_node(type, nsub->extra.elem); + if (sub_elem && sub_elem->kind == SPL_LANG_TYPE_NEVER) + return true; + } + if (nsub->kind == SPL_LANG_TYPE_PTR && nsuper->kind == SPL_LANG_TYPE_PTR) { if (nsub->extra.elem == nsuper->extra.elem) return true; @@ -568,6 +575,18 @@ spl_lang_type_id_t spl_lang_type_join(const spl_lang_type_t *type, spl_lang_type return 0; } + /* 函数指针可空:fn 与 null(*never)求交得到 fn。 */ + if (na->kind == SPL_LANG_TYPE_FN && nb->kind == SPL_LANG_TYPE_PTR) { + spl_lang_type_node_t *eb = spl_lang_type_node(type, nb->extra.elem); + if (eb && eb->kind == SPL_LANG_TYPE_NEVER) + return a; + } + if (na->kind == SPL_LANG_TYPE_PTR && nb->kind == SPL_LANG_TYPE_FN) { + spl_lang_type_node_t *ea = spl_lang_type_node(type, na->extra.elem); + if (ea && ea->kind == SPL_LANG_TYPE_NEVER) + return b; + } + if (na->kind == SPL_LANG_TYPE_PTR && nb->kind == SPL_LANG_TYPE_PTR) { if (na->extra.elem == nb->extra.elem) return a; diff --git a/stage1/spl_sema.c b/stage1/spl_sema.c index 6cd331f..99c086c 100644 --- a/stage1/spl_sema.c +++ b/stage1/spl_sema.c @@ -1775,6 +1775,16 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) { return bt; } case SPL_UNARY_OP_ADDRESS: { + spl_ast_node_t *operand = spl_ast_node(sema->ast, n->unary.operand); + if (operand && operand->kind == SPL_AST_EXPR_IDENT) { + spl_def_node_t *def = spl_def_node(sema->type, operand->resolved_def_id); + if (def && def->kind == SPL_DEF_FN) { + spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg, + "cannot take address of a function: the function name " + "itself is a function pointer"); + return 0; + } + } spl_lang_type_id_t p = spl_lang_make_ptr(sema->type, op); n->resolved_lang_tid = p; return p;