! RUN: bbc -emit-fir -hlfir=false %s -o - | FileCheck %s
! Test procedure declarations. Change appearance order of definition and usages
! (passing a procedure and calling it), with and without definitions.
! Check that the definition type prevail if available and that casts are inserted to
! accommodate for the signature mismatch in the different location due to implicit
! typing rules and Fortran loose interface compatibility rule history.
! Note: all the cases where their is a definition are exactly the same,
! since definition should be processed first regardless.
! pass, call, define
! CHECK-LABEL: func @_QPpass_foo() {
subroutine pass_foo()
external :: foo
! CHECK: %[[f:.*]] = fir.address_of(@_QPfoo)
! CHECK: fir.emboxproc %[[f]] : ((!fir.ref<!fir.array<2x5xi32>>) -> ()) -> !fir.boxproc<() -> ()>
call bar(foo)
end subroutine
! CHECK-LABEL: func @_QPcall_foo(
! CHECK-SAME: %{{.*}}: !fir.ref<!fir.array<10xi32>>{{.*}}) {
subroutine call_foo(i)
integer :: i(10)
! %[[argconvert:*]] = fir.convert %arg0 :
! fir.call @_QPfoo(%[[argconvert]]) {{.*}}: (!fir.ref<!fir.array<2x5xi32>>) -> ()
call foo(i)
end subroutine
! CHECK-LABEL: func @_QPfoo(
! CHECK-SAME: %{{.*}}: !fir.ref<!fir.array<2x5xi32>>{{.*}}) {
subroutine foo(i)
integer :: i(2, 5)
call do_something(i)
end subroutine
! call, pass, define
! CHECK-LABEL: func @_QPcall_foo2(
! CHECK-SAME: %{{.*}}: !fir.ref<!fir.array<10xi32>>{{.*}}) {
subroutine call_foo2(i)
integer :: i(10)
! %[[argconvert:*]] = fir.convert %arg0 :
! fir.call @_QPfoo2(%[[argconvert]]) {{.*}}: (!fir.ref<!fir.array<2x5xi32>>) -> ()
call foo2(i)
end subroutine
! CHECK-LABEL: func @_QPpass_foo2() {
subroutine pass_foo2()
external :: foo2
! CHECK: %[[f:.*]] = fir.address_of(@_QPfoo2)
! CHECK: fir.emboxproc %[[f]] : ((!fir.ref<!fir.array<2x5xi32>>) -> ()) -> !fir.boxproc<() -> ()>
call bar(foo2)
end subroutine
! CHECK-LABEL: func @_QPfoo2(
! CHECK-SAME: %{{.*}}: !fir.ref<!fir.array<2x5xi32>>{{.*}}) {
subroutine foo2(i)
integer :: i(2, 5)
call do_something(i)
end subroutine
! call, define, pass
! CHECK-LABEL: func @_QPcall_foo3(
! CHECK-SAME: %{{.*}}: !fir.ref<!fir.array<10xi32>>{{.*}}) {
subroutine call_foo3(i)
integer :: i(10)
! %[[argconvert:*]] = fir.convert %arg0 :
! fir.call @_QPfoo3(%[[argconvert]]) {{.*}}: (!fir.ref<!fir.array<2x5xi32>>) -> ()
call foo3(i)
end subroutine
! CHECK-LABEL: func @_QPfoo3(
! CHECK-SAME: %{{.*}}: !fir.ref<!fir.array<2x5xi32>>{{.*}}) {
subroutine foo3(i)
integer :: i(2, 5)
call do_something(i)
end subroutine
! CHECK-LABEL: func @_QPpass_foo3() {
subroutine pass_foo3()
external :: foo3
! CHECK: %[[f:.*]] = fir.address_of(@_QPfoo3)
! CHECK: fir.emboxproc %[[f]] : ((!fir.ref<!fir.array<2x5xi32>>) -> ()) -> !fir.boxproc<() -> ()>
call bar(foo3)
end subroutine
! define, call, pass
! CHECK-LABEL: func @_QPfoo4(
! CHECK-SAME: %{{.*}}: !fir.ref<!fir.array<2x5xi32>>{{.*}}) {
subroutine foo4(i)
integer :: i(2, 5)
call do_something(i)
end subroutine
! CHECK-LABEL: func @_QPcall_foo4(
! CHECK-SAME: %{{.*}}: !fir.ref<!fir.array<10xi32>>{{.*}}) {
subroutine call_foo4(i)
integer :: i(10)
! %[[argconvert:*]] = fir.convert %arg0 :
! fir.call @_QPfoo4(%[[argconvert]]) {{.*}}: (!fir.ref<!fir.array<2x5xi32>>) -> ()
call foo4(i)
end subroutine
! CHECK-LABEL: func @_QPpass_foo4() {
subroutine pass_foo4()
external :: foo4
! CHECK: %[[f:.*]] = fir.address_of(@_QPfoo4)
! CHECK: fir.emboxproc %[[f]] : ((!fir.ref<!fir.array<2x5xi32>>) -> ()) -> !fir.boxproc<() -> ()>
call bar(foo4)
end subroutine
! define, pass, call
! CHECK-LABEL: func @_QPfoo5(
! CHECK-SAME: %{{.*}}: !fir.ref<!fir.array<2x5xi32>>{{.*}}) {
subroutine foo5(i)
integer :: i(2, 5)
call do_something(i)
end subroutine
! CHECK-LABEL: func @_QPpass_foo5() {
subroutine pass_foo5()
external :: foo5
! CHECK: %[[f:.*]] = fir.address_of(@_QPfoo5)
! CHECK: fir.emboxproc %[[f]] : ((!fir.ref<!fir.array<2x5xi32>>) -> ()) -> !fir.boxproc<() -> ()>
call bar(foo5)
end subroutine
! CHECK-LABEL: func @_QPcall_foo5(
! CHECK-SAME: %{{.*}}: !fir.ref<!fir.array<10xi32>>{{.*}}) {
subroutine call_foo5(i)
integer :: i(10)
! %[[argconvert:*]] = fir.convert %arg0 :
! fir.call @_QPfoo5(%[[argconvert]]) {{.*}}: (!fir.ref<!fir.array<2x5xi32>>) -> ()
call foo5(i)
end subroutine
! Test when there is no definition (declaration at the end of the mlir module)
! First use gives the function type
! call, pass
! CHECK-LABEL: func @_QPcall_foo6(
! CHECK-SAME: %{{.*}}: !fir.ref<!fir.array<10xi32>>{{.*}}) {
subroutine call_foo6(i)
integer :: i(10)
! CHECK-NOT: convert
call foo6(i)
end subroutine
! CHECK-LABEL: func @_QPpass_foo6() {
subroutine pass_foo6()
external :: foo6
! CHECK: %[[f:.*]] = fir.address_of(@_QPfoo6) : (!fir.ref<!fir.array<10xi32>>) -> ()
! CHECK: fir.emboxproc %[[f]] : ((!fir.ref<!fir.array<10xi32>>) -> ()) -> !fir.boxproc<() -> ()>
call bar(foo6)
end subroutine
! pass, call
! CHECK-LABEL: func @_QPpass_foo7() {
subroutine pass_foo7()
external :: foo7
! CHECK-NOT: convert
call bar(foo7)
end subroutine
! CHECK-LABEL: func @_QPcall_foo7(
! CHECK-SAME: %{{.*}}: !fir.ref<!fir.array<10xi32>>{{.*}}) -> f32 {
function call_foo7(i)
integer :: i(10)
! CHECK: %[[f:.*]] = fir.address_of(@_QPfoo7) : () -> ()
! CHECK: %[[funccast:.*]] = fir.convert %[[f]] : (() -> ()) -> ((!fir.ref<!fir.array<10xi32>>) -> f32)
! CHECK: fir.call %[[funccast]](%arg0) {{.*}}: (!fir.ref<!fir.array<10xi32>>) -> f32
call_foo7 = foo7(i)
end function
! call, call with different type
! CHECK-LABEL: func @_QPcall_foo8(
! CHECK-SAME: %{{.*}}: !fir.ref<!fir.array<10xi32>>{{.*}}) {
subroutine call_foo8(i)
integer :: i(10)
! CHECK-NOT: convert
call foo8(i)
end subroutine
! CHECK-LABEL: func @_QPcall_foo8_2(
! CHECK-SAME: %{{.*}}: !fir.ref<!fir.array<2x5xi32>>{{.*}}) {
subroutine call_foo8_2(i)
integer :: i(2, 5)
! %[[argconvert:*]] = fir.convert %arg0 :
call foo8(i)
end subroutine
! Test that target attribute is lowered in declaration of functions that are
! not defined in this file.
! CHECK-LABEL:func @_QPtest_target_in_iface
subroutine test_target_in_iface()
interface
subroutine test_target(i, x)
integer, target :: i
real, target :: x(:)
end subroutine
end interface
integer :: i
real :: x(10)
! CHECK: fir.call @_QPtest_target
call test_target(i, x)
end subroutine
! CHECK: func private @_QPfoo6(!fir.ref<!fir.array<10xi32>>)
! CHECK: func private @_QPfoo7()
! Test declaration from test_target_in_iface
! CHECK-LABEL: func private @_QPtest_target(!fir.ref<i32> {fir.target}, !fir.box<!fir.array<?xf32>> {fir.target})