Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions spec/compiler/codegen/proc_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -862,6 +862,59 @@ describe "Code gen: proc" do
))
end

it "returns proc as function pointer inside top-level fun (#14691)" do
run(<<-CRYSTAL, Int32).should eq(8)
def raise(msg)
while true
end
end

fun add : Int32, Int32 -> Int32
->(x : Int32, y : Int32) { x &+ y }
end

add.call(3, 5)
CRYSTAL
end

it "returns ProcPointer inside top-level fun (#14691)" do
run(<<-CRYSTAL, Int32).should eq(8)
def raise(msg)
while true
end
end

fun foo(x : Int32) : Int32
x &+ 5
end

fun bar : Int32 -> Int32
->foo(Int32)
end

bar.call(3)
CRYSTAL
end

it "raises if returning closure from top-level fun (#14691)" do
run(<<-CRYSTAL).to_b.should be_true
require "prelude"

@[Raises]
fun foo(x : Int32) : -> Int32
-> { x }
end

begin
foo(1)
rescue
true
else
false
end
CRYSTAL
end

it "closures var on ->var.call (#8584)" do
run(%(
def bar(x)
Expand Down
13 changes: 9 additions & 4 deletions src/compiler/crystal/codegen/fun.cr
Original file line number Diff line number Diff line change
Expand Up @@ -236,17 +236,22 @@ class Crystal::CodeGenVisitor
# Check if this def must use the C calling convention and the return
# value must be either casted or passed by sret
if target_def.c_calling_convention? && target_def.abi_info?
return_type = target_def.body.type
if return_type.proc?
@last = check_proc_is_not_closure(@last, return_type)
end

abi_info = abi_info(target_def)
ret_type = abi_info.return_type
if cast = ret_type.cast
abi_ret_type = abi_info.return_type
if cast = abi_ret_type.cast
casted_last = pointer_cast @last, cast.pointer
last = load cast, casted_last
ret last
return
end

if (attr = ret_type.attr) && attr == LLVM::Attribute::StructRet
store load(llvm_type(target_def.body.type), @last), context.fun.params[0]
if (attr = abi_ret_type.attr) && attr == LLVM::Attribute::StructRet
store load(llvm_type(return_type), @last), context.fun.params[0]
ret
return
end
Expand Down