diff --git a/releasenotes.md b/releasenotes.md index 6b695ac9d..b1f8f082d 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -28,6 +28,7 @@ - Struct members declared in a single line declaration were not sharing attributes. #1266 - `opt` project setting now properly documented. - Incorrect justify formatting of integers. +- Assertion with duplicate function pointer signatures #1286 ### Stdlib changes diff --git a/src/compiler/codegen_internal.h b/src/compiler/codegen_internal.h index cd860f8e2..3694d3eef 100644 --- a/src/compiler/codegen_internal.h +++ b/src/compiler/codegen_internal.h @@ -36,6 +36,11 @@ static inline Type *type_lowering(Type *type) case TYPE_ENUM: type = type->decl->enums.type_info->type; continue; + case TYPE_FUNC_PTR: + if (type->pointer->function.prototype->raw_type == type->pointer) return type; + return type_get_func_ptr(type->pointer->function.prototype->raw_type); + case TYPE_FUNC_RAW: + return type->function.prototype->raw_type; case TYPE_INTERFACE: return type_any; case TYPE_ANYFAULT: diff --git a/test/test_suite/functions/function_alias_llvm_check.c3t b/test/test_suite/functions/function_alias_llvm_check.c3t new file mode 100644 index 000000000..7214c2e14 --- /dev/null +++ b/test/test_suite/functions/function_alias_llvm_check.c3t @@ -0,0 +1,50 @@ +// #target: macos-x64 +module repro; + +import std::collections::list; + +def FnA = fn void(Foo*); +def FnB = fn void(Foo*); + +struct Foo +{ + List() aFuncs; + List() bFuncs; +} + +fn void! Foo.deinit(&self) +{ + self.aFuncs.free(); + self.bFuncs.free(); +} + +fn void Foo.add_fn_a(&self, FnA f) => self.aFuncs.push(f); +fn void Foo.add_fn_b(&self, FnB f) => self.bFuncs.push(f); + +fn void a_func(Foo* foo) {} +fn void b_func(Foo* foo) {} + +fn void! main() +{ + Foo foo; + defer foo.deinit()!!; + foo.add_fn_a(&a_func); + foo.add_fn_b(&b_func); +} + +/* #expect: repro.ll + +define i64 @repro.main() #0 { +entry: + %foo = alloca %Foo, align 8 + %error_var = alloca i64, align 8 + %varargslots = alloca [1 x %any], align 16 + %indirectarg = alloca %"any[]", align 8 + call void @llvm.memset.p0.i64(ptr align 8 %foo, i8 0, i64 80, i1 false) + call void @repro.Foo.add_fn_a(ptr %foo, ptr @repro.a_func) + call void @repro.Foo.add_fn_b(ptr %foo, ptr @repro.b_func) + %0 = call i64 @repro.Foo.deinit(ptr %foo) + %not_err = icmp eq i64 %0, 0 + %1 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %1, label %after_check, label %assign_optional +