! RUN: bbc -emit-fir -hlfir=false %s -o - | FileCheck %s

module callee
implicit none
contains
! CHECK-LABEL: func @_QMcalleePreturn_cst_array() -> !fir.array<20x30xf32>
function return_cst_array()
  real :: return_cst_array(20, 30)
end function

! CHECK-LABEL: func @_QMcalleePreturn_dyn_array(
! CHECK-SAME: %{{.*}}: !fir.ref<i32>{{.*}}, %{{.*}}: !fir.ref<i32>{{.*}}) -> !fir.array<?x?xf32>
function return_dyn_array(m, n)
  integer :: m, n
  real :: return_dyn_array(m, n)
end function

! CHECK-LABEL: func @_QMcalleePreturn_cst_char_cst_array() -> !fir.array<20x30x!fir.char<1,10>>
function return_cst_char_cst_array()
  character(10) :: return_cst_char_cst_array(20, 30)
end function

! CHECK-LABEL: func @_QMcalleePreturn_dyn_char_cst_array(
! CHECK-SAME: %{{.*}}: !fir.ref<i32>{{.*}}) -> !fir.array<20x30x!fir.char<1,?>>
function return_dyn_char_cst_array(l)
  integer :: l
  character(l) :: return_dyn_char_cst_array(20, 30)
end function

! CHECK-LABEL: func @_QMcalleePreturn_cst_char_dyn_array(
! CHECK-SAME: %{{.*}}: !fir.ref<i32>{{.*}}, %{{.*}}: !fir.ref<i32>{{.*}}) -> !fir.array<?x?x!fir.char<1,10>>
function return_cst_char_dyn_array(m, n)
  integer :: m, n
  character(10) :: return_cst_char_dyn_array(m, n)
end function

! CHECK-LABEL: func @_QMcalleePreturn_dyn_char_dyn_array(
! CHECK-SAME: %{{.*}}: !fir.ref<i32>{{.*}}, %{{.*}}: !fir.ref<i32>{{.*}}, %{{.*}}: !fir.ref<i32>{{.*}}) -> !fir.array<?x?x!fir.char<1,?>>
function return_dyn_char_dyn_array(l, m, n)
  integer :: l, m, n
  character(l) :: return_dyn_char_dyn_array(m, n)
end function

! CHECK-LABEL: func @_QMcalleePreturn_alloc() -> !fir.box<!fir.heap<!fir.array<?xf32>>>
function return_alloc()
  real, allocatable :: return_alloc(:)
end function

! CHECK-LABEL: func @_QMcalleePreturn_cst_char_alloc() -> !fir.box<!fir.heap<!fir.array<?x!fir.char<1,10>>>>
function return_cst_char_alloc()
  character(10), allocatable :: return_cst_char_alloc(:)
end function

! CHECK-LABEL: func @_QMcalleePreturn_dyn_char_alloc(
! CHECK-SAME: %{{.*}}: !fir.ref<i32>{{.*}}) -> !fir.box<!fir.heap<!fir.array<?x!fir.char<1,?>>>>
function return_dyn_char_alloc(l)
  integer :: l
  character(l), allocatable :: return_dyn_char_alloc(:)
end function

! CHECK-LABEL: func @_QMcalleePreturn_def_char_alloc() -> !fir.box<!fir.heap<!fir.array<?x!fir.char<1,?>>>>
function return_def_char_alloc()
  character(:), allocatable :: return_def_char_alloc(:)
end function

! CHECK-LABEL: func @_QMcalleePreturn_pointer() -> !fir.box<!fir.ptr<!fir.array<?xf32>>>
function return_pointer()
  real, pointer :: return_pointer(:)
end function

! CHECK-LABEL: func @_QMcalleePreturn_cst_char_pointer() -> !fir.box<!fir.ptr<!fir.array<?x!fir.char<1,10>>>>
function return_cst_char_pointer()
  character(10), pointer :: return_cst_char_pointer(:)
end function

! CHECK-LABEL: func @_QMcalleePreturn_dyn_char_pointer(
! CHECK-SAME: %{{.*}}: !fir.ref<i32>{{.*}}) -> !fir.box<!fir.ptr<!fir.array<?x!fir.char<1,?>>>>
function return_dyn_char_pointer(l)
  integer :: l
  character(l), pointer :: return_dyn_char_pointer(:)
end function

! CHECK-LABEL: func @_QMcalleePreturn_def_char_pointer() -> !fir.box<!fir.ptr<!fir.array<?x!fir.char<1,?>>>>
function return_def_char_pointer()
  character(:), pointer :: return_def_char_pointer(:)
end function
end module

module caller
  use callee
contains

! CHECK-LABEL: func @_QMcallerPcst_array()
subroutine cst_array()
  ! CHECK: %[[alloc:.*]] = fir.alloca !fir.array<20x30xf32> {{{.*}}bindc_name = ".result"}
  ! CHECK: %[[shape:.*]] = fir.shape %{{.*}}, {{.*}} : (index, index) -> !fir.shape<2>
  ! CHECK: %[[res:.*]] = fir.call @_QMcalleePreturn_cst_array() {{.*}}: () -> !fir.array<20x30xf32>
  ! CHECK: fir.save_result %[[res]] to %[[alloc]](%[[shape]]) : !fir.array<20x30xf32>, !fir.ref<!fir.array<20x30xf32>>, !fir.shape<2>
  print *, return_cst_array()
end subroutine

! CHECK-LABEL: func @_QMcallerPcst_char_cst_array()
subroutine cst_char_cst_array()
  ! CHECK: %[[alloc:.*]] = fir.alloca !fir.array<20x30x!fir.char<1,10>> {{{.*}}bindc_name = ".result"}
  ! CHECK: %[[shape:.*]] = fir.shape %{{.*}}, {{.*}} : (index, index) -> !fir.shape<2>
  ! CHECK: %[[res:.*]] = fir.call @_QMcalleePreturn_cst_char_cst_array() {{.*}}: () -> !fir.array<20x30x!fir.char<1,10>>
  ! CHECK: fir.save_result %[[res]] to %[[alloc]](%[[shape]]) typeparams %{{.*}} : !fir.array<20x30x!fir.char<1,10>>, !fir.ref<!fir.array<20x30x!fir.char<1,10>>>, !fir.shape<2>, index
  print *, return_cst_char_cst_array()
end subroutine

! CHECK-LABEL: func @_QMcallerPalloc()
subroutine alloc()
  ! CHECK: %[[alloc:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<?xf32>>> {{{.*}}bindc_name = ".result"}
  ! CHECK: %[[res:.*]] = fir.call @_QMcalleePreturn_alloc() {{.*}}: () -> !fir.box<!fir.heap<!fir.array<?xf32>>>
  ! CHECK: fir.save_result %[[res]] to %[[alloc]] : !fir.box<!fir.heap<!fir.array<?xf32>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
  print *, return_alloc()
  ! CHECK: _FortranAioOutputDescriptor
  ! CHECK: %[[load:.*]] = fir.load %[[alloc]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
  ! CHECK: %[[addr:.*]] = fir.box_addr %[[load]] : (!fir.box<!fir.heap<!fir.array<?xf32>>>) -> !fir.heap<!fir.array<?xf32>>
  ! CHECK: %[[cmpi:.*]] = arith.cmpi
  ! CHECK: fir.if %[[cmpi]]
  ! CHECK: fir.freemem %[[addr]] : !fir.heap<!fir.array<?xf32>>
end subroutine

! CHECK-LABEL: func @_QMcallerPcst_char_alloc()
subroutine cst_char_alloc()
  ! CHECK: %[[alloc:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<?x!fir.char<1,10>>>> {{{.*}}bindc_name = ".result"}
  ! CHECK: %[[res:.*]] = fir.call @_QMcalleePreturn_cst_char_alloc() {{.*}}: () -> !fir.box<!fir.heap<!fir.array<?x!fir.char<1,10>>>>
  ! CHECK: fir.save_result %[[res]] to %[[alloc]] : !fir.box<!fir.heap<!fir.array<?x!fir.char<1,10>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,10>>>>>
  print *, return_cst_char_alloc()
  ! CHECK: _FortranAioOutputDescriptor
  ! CHECK: %[[load:.*]] = fir.load %[[alloc]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,10>>>>>
  ! CHECK: %[[addr:.*]] = fir.box_addr %[[load]] : (!fir.box<!fir.heap<!fir.array<?x!fir.char<1,10>>>>) -> !fir.heap<!fir.array<?x!fir.char<1,10>>>
  ! CHECK: %[[cmpi:.*]] = arith.cmpi
  ! CHECK: fir.if %[[cmpi]]
  ! CHECK: fir.freemem %[[addr]] : !fir.heap<!fir.array<?x!fir.char<1,10>>>
end subroutine

! CHECK-LABEL: func @_QMcallerPdef_char_alloc()
subroutine def_char_alloc()
  ! CHECK: %[[alloc:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<?x!fir.char<1,?>>>> {{{.*}}bindc_name = ".result"}
  ! CHECK: %[[res:.*]] = fir.call @_QMcalleePreturn_def_char_alloc() {{.*}}: () -> !fir.box<!fir.heap<!fir.array<?x!fir.char<1,?>>>>
  ! CHECK: fir.save_result %[[res]] to %[[alloc]] : !fir.box<!fir.heap<!fir.array<?x!fir.char<1,?>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,?>>>>>
  print *, return_def_char_alloc()
  ! CHECK: _FortranAioOutputDescriptor
  ! CHECK: %[[load:.*]] = fir.load %[[alloc]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,?>>>>>
  ! CHECK: %[[addr:.*]] = fir.box_addr %[[load]] : (!fir.box<!fir.heap<!fir.array<?x!fir.char<1,?>>>>) -> !fir.heap<!fir.array<?x!fir.char<1,?>>>
  ! CHECK: %[[cmpi:.*]] = arith.cmpi
  ! CHECK: fir.if %[[cmpi]]
  ! CHECK: fir.freemem %[[addr]] : !fir.heap<!fir.array<?x!fir.char<1,?>>>
end subroutine

! CHECK-LABEL: func @_QMcallerPpointer_test()
subroutine pointer_test()
  ! CHECK: %[[alloc:.*]] = fir.alloca !fir.box<!fir.ptr<!fir.array<?xf32>>> {{{.*}}bindc_name = ".result"}
  ! CHECK: %[[res:.*]] = fir.call @_QMcalleePreturn_pointer() {{.*}}: () -> !fir.box<!fir.ptr<!fir.array<?xf32>>>
  ! CHECK: fir.save_result %[[res]] to %[[alloc]] : !fir.box<!fir.ptr<!fir.array<?xf32>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>
  print *, return_pointer()
  ! CHECK-NOT: fir.freemem
end subroutine

! CHECK-LABEL: func @_QMcallerPcst_char_pointer()
subroutine cst_char_pointer()
  ! CHECK: %[[alloc:.*]] = fir.alloca !fir.box<!fir.ptr<!fir.array<?x!fir.char<1,10>>>> {{{.*}}bindc_name = ".result"}
  ! CHECK: %[[res:.*]] = fir.call @_QMcalleePreturn_cst_char_pointer() {{.*}}: () -> !fir.box<!fir.ptr<!fir.array<?x!fir.char<1,10>>>>
  ! CHECK: fir.save_result %[[res]] to %[[alloc]] : !fir.box<!fir.ptr<!fir.array<?x!fir.char<1,10>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.char<1,10>>>>>
  print *, return_cst_char_pointer()
  ! CHECK-NOT: fir.freemem
end subroutine

! CHECK-LABEL: func @_QMcallerPdef_char_pointer()
subroutine def_char_pointer()
  ! CHECK: %[[alloc:.*]] = fir.alloca !fir.box<!fir.ptr<!fir.array<?x!fir.char<1,?>>>> {{{.*}}bindc_name = ".result"}
  ! CHECK: %[[res:.*]] = fir.call @_QMcalleePreturn_def_char_pointer() {{.*}}: () -> !fir.box<!fir.ptr<!fir.array<?x!fir.char<1,?>>>>
  ! CHECK: fir.save_result %[[res]] to %[[alloc]] : !fir.box<!fir.ptr<!fir.array<?x!fir.char<1,?>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.char<1,?>>>>>
  print *, return_def_char_pointer()
  ! CHECK-NOT: fir.freemem
end subroutine

! CHECK-LABEL: func @_QMcallerPdyn_array(
! CHECK-SAME: %[[m:.*]]: !fir.ref<i32>{{.*}}, %[[n:.*]]: !fir.ref<i32>{{.*}}) {
subroutine dyn_array(m, n)
  integer :: m, n
  ! CHECK-DAG: %[[mload:.*]] = fir.load %[[m]] : !fir.ref<i32>
  ! CHECK-DAG: %[[mcast:.*]] = fir.convert %[[mload]] : (i32) -> i64
  ! CHECK-DAG: %[[msub:.*]] = arith.subi %[[mcast]], %c1{{.*}} : i64
  ! CHECK-DAG: %[[madd:.*]] = arith.addi %[[msub]], %c1{{.*}} : i64
  ! CHECK-DAG: %[[mcast2:.*]] = fir.convert %[[madd]] : (i64) -> index
  ! CHECK-DAG: %[[mcmpi:.*]] = arith.cmpi sgt, %[[mcast2]], %{{.*}} : index
  ! CHECK-DAG: %[[mselect:.*]] = arith.select %[[mcmpi]], %[[mcast2]], %{{.*}} : index
  ! CHECK-DAG: %[[nload:.*]] = fir.load %[[n]] : !fir.ref<i32>
  ! CHECK-DAG: %[[ncast:.*]] = fir.convert %[[nload]] : (i32) -> i64
  ! CHECK-DAG: %[[nsub:.*]] = arith.subi %[[ncast]], %c1{{.*}} : i64
  ! CHECK-DAG: %[[nadd:.*]] = arith.addi %[[nsub]], %c1{{.*}} : i64
  ! CHECK-DAG: %[[ncast2:.*]] = fir.convert %[[nadd]] : (i64) -> index
  ! CHECK-DAG: %[[ncmpi:.*]] = arith.cmpi sgt, %[[ncast2]], %{{.*}} : index
  ! CHECK-DAG: %[[nselect:.*]] = arith.select %[[ncmpi]], %[[ncast2]], %{{.*}} : index
  ! CHECK: %[[tmp:.*]] = fir.alloca !fir.array<?x?xf32>, %[[mselect]], %[[nselect]]
  ! CHECK: %[[shape:.*]] = fir.shape %[[mselect]], %[[nselect]] : (index, index) -> !fir.shape<2>
  ! CHECK: %[[res:.*]] = fir.call @_QMcalleePreturn_dyn_array(%[[m]], %[[n]]) {{.*}}: (!fir.ref<i32>, !fir.ref<i32>) -> !fir.array<?x?xf32>
  ! CHECK: fir.save_result %[[res]] to %[[tmp]](%[[shape]]) : !fir.array<?x?xf32>, !fir.ref<!fir.array<?x?xf32>>, !fir.shape<2>
  print *, return_dyn_array(m, n)
end subroutine

! CHECK-LABEL: func @_QMcallerPdyn_char_cst_array(
! CHECK-SAME: %[[l:.*]]: !fir.ref<i32>{{.*}}) {
subroutine dyn_char_cst_array(l)
  integer :: l
  ! CHECK: %[[lload:.*]] = fir.load %[[l]] : !fir.ref<i32>
  ! CHECK: %[[lcast:.*]] = fir.convert %[[lload]] : (i32) -> i64
  ! CHECK: %[[lcast2:.*]] = fir.convert %[[lcast]] : (i64) -> index
  ! CHECK: %[[cmpi:.*]] = arith.cmpi sgt, %[[lcast2]], %{{.*}} : index
  ! CHECK: %[[select:.*]] = arith.select %[[cmpi]], %[[lcast2]], %{{.*}} : index
  ! CHECK: %[[tmp:.*]] = fir.alloca !fir.array<20x30x!fir.char<1,?>>(%[[select]] : index)
  ! CHECK: %[[shape:.*]] = fir.shape %{{.*}}, %{{.*}} : (index, index) -> !fir.shape<2>
  ! CHECK: %[[res:.*]] = fir.call @_QMcalleePreturn_dyn_char_cst_array(%[[l]]) {{.*}}: (!fir.ref<i32>) -> !fir.array<20x30x!fir.char<1,?>>
  ! CHECK: fir.save_result %[[res]] to %[[tmp]](%[[shape]]) typeparams %[[select]] : !fir.array<20x30x!fir.char<1,?>>, !fir.ref<!fir.array<20x30x!fir.char<1,?>>>, !fir.shape<2>, index
  print *, return_dyn_char_cst_array(l)
end subroutine

! CHECK-LABEL: func @_QMcallerPcst_char_dyn_array(
! CHECK-SAME: %[[m:.*]]: !fir.ref<i32>{{.*}}, %[[n:.*]]: !fir.ref<i32>{{.*}}) {
subroutine cst_char_dyn_array(m, n)
  integer :: m, n
  ! CHECK-DAG: %[[mload:.*]] = fir.load %[[m]] : !fir.ref<i32>
  ! CHECK-DAG: %[[mcast:.*]] = fir.convert %[[mload]] : (i32) -> i64
  ! CHECK-DAG: %[[msub:.*]] = arith.subi %[[mcast]], %c1{{.*}} : i64
  ! CHECK-DAG: %[[madd:.*]] = arith.addi %[[msub]], %c1{{.*}} : i64
  ! CHECK-DAG: %[[mcast2:.*]] = fir.convert %[[madd]] : (i64) -> index
  ! CHECK-DAG: %[[mcmpi:.*]] = arith.cmpi sgt, %[[mcast2]], %{{.*}} : index
  ! CHECK-DAG: %[[mselect:.*]] = arith.select %[[mcmpi]], %[[mcast2]], %{{.*}} : index
  ! CHECK-DAG: %[[nload:.*]] = fir.load %[[n]] : !fir.ref<i32>
  ! CHECK-DAG: %[[ncast:.*]] = fir.convert %[[nload]] : (i32) -> i64
  ! CHECK-DAG: %[[nsub:.*]] = arith.subi %[[ncast]], %c1{{.*}} : i64
  ! CHECK-DAG: %[[nadd:.*]] = arith.addi %[[nsub]], %c1{{.*}} : i64
  ! CHECK-DAG: %[[ncast2:.*]] = fir.convert %[[nadd]] : (i64) -> index
  ! CHECK-DAG: %[[ncmpi:.*]] = arith.cmpi sgt, %[[ncast2]], %{{.*}} : index
  ! CHECK-DAG: %[[nselect:.*]] = arith.select %[[ncmpi]], %[[ncast2]], %{{.*}} : index
  ! CHECK: %[[tmp:.*]] = fir.alloca !fir.array<?x?x!fir.char<1,10>>, %[[mselect]], %[[nselect]]
  ! CHECK: %[[shape:.*]] = fir.shape %[[mselect]], %[[nselect]] : (index, index) -> !fir.shape<2>
  ! CHECK: %[[res:.*]] = fir.call @_QMcalleePreturn_cst_char_dyn_array(%[[m]], %[[n]]) {{.*}}: (!fir.ref<i32>, !fir.ref<i32>) -> !fir.array<?x?x!fir.char<1,10>>
  ! CHECK: fir.save_result %[[res]] to %[[tmp]](%[[shape]]) typeparams {{.*}} : !fir.array<?x?x!fir.char<1,10>>, !fir.ref<!fir.array<?x?x!fir.char<1,10>>>, !fir.shape<2>, index
  print *, return_cst_char_dyn_array(m, n)
end subroutine

! CHECK-LABEL: func @_QMcallerPdyn_char_dyn_array(
! CHECK-SAME: %[[l:.*]]: !fir.ref<i32>{{.*}}, %[[m:.*]]: !fir.ref<i32>{{.*}}, %[[n:.*]]: !fir.ref<i32>{{.*}}) {
subroutine dyn_char_dyn_array(l, m, n)
  ! CHECK-DAG: %[[mload:.*]] = fir.load %[[m]] : !fir.ref<i32>
  ! CHECK-DAG: %[[mcast:.*]] = fir.convert %[[mload]] : (i32) -> i64
  ! CHECK-DAG: %[[msub:.*]] = arith.subi %[[mcast]], %c1{{.*}} : i64
  ! CHECK-DAG: %[[madd:.*]] = arith.addi %[[msub]], %c1{{.*}} : i64
  ! CHECK-DAG: %[[mcast2:.*]] = fir.convert %[[madd]] : (i64) -> index
  ! CHECK-DAG: %[[mcmpi:.*]] = arith.cmpi sgt, %[[mcast2]], %{{.*}} : index
  ! CHECK-DAG: %[[mselect:.*]] = arith.select %[[mcmpi]], %[[mcast2]], %{{.*}} : index

  ! CHECK-DAG: %[[nload:.*]] = fir.load %[[n]] : !fir.ref<i32>
  ! CHECK-DAG: %[[ncast:.*]] = fir.convert %[[nload]] : (i32) -> i64
  ! CHECK-DAG: %[[nsub:.*]] = arith.subi %[[ncast]], %c1{{.*}} : i64
  ! CHECK-DAG: %[[nadd:.*]] = arith.addi %[[nsub]], %c1{{.*}} : i64
  ! CHECK-DAG: %[[ncast2:.*]] = fir.convert %[[nadd]] : (i64) -> index
  ! CHECK-DAG: %[[ncmpi:.*]] = arith.cmpi sgt, %[[ncast2]], %{{.*}} : index
  ! CHECK-DAG: %[[nselect:.*]] = arith.select %[[ncmpi]], %[[ncast2]], %{{.*}} : index

  ! CHECK-DAG: %[[lload:.*]] = fir.load %[[l]] : !fir.ref<i32>
  ! CHECK-DAG: %[[lcast:.*]] = fir.convert %[[lload]] : (i32) -> i64
  ! CHECK-DAG: %[[lcast2:.*]] = fir.convert %[[lcast]] : (i64) -> index
  ! CHECK-DAG: %[[lcmpi:.*]] = arith.cmpi sgt, %[[lcast2]], %{{.*}} : index
  ! CHECK-DAG: %[[lselect:.*]] = arith.select %[[lcmpi]], %[[lcast2]], %{{.*}} : index
  ! CHECK: %[[tmp:.*]] = fir.alloca !fir.array<?x?x!fir.char<1,?>>(%[[lselect]] : index), %[[mselect]], %[[nselect]]
  ! CHECK: %[[shape:.*]] = fir.shape %[[mselect]], %[[nselect]] : (index, index) -> !fir.shape<2>
  ! CHECK: %[[res:.*]] = fir.call @_QMcalleePreturn_dyn_char_dyn_array(%[[l]], %[[m]], %[[n]]) {{.*}}: (!fir.ref<i32>, !fir.ref<i32>, !fir.ref<i32>) -> !fir.array<?x?x!fir.char<1,?>>
  ! CHECK: fir.save_result %[[res]] to %[[tmp]](%[[shape]]) typeparams {{.*}} : !fir.array<?x?x!fir.char<1,?>>, !fir.ref<!fir.array<?x?x!fir.char<1,?>>>, !fir.shape<2>, index
  integer :: l, m, n
  print *, return_dyn_char_dyn_array(l, m, n)
end subroutine

! CHECK-LABEL: @_QMcallerPdyn_char_alloc
subroutine dyn_char_alloc(l)
  integer :: l
  ! CHECK: %[[alloc:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<?x!fir.char<1,?>>>> {{{.*}}bindc_name = ".result"}
  ! CHECK: %[[res:.*]] = fir.call @_QMcalleePreturn_dyn_char_alloc({{.*}}) {{.*}}: (!fir.ref<i32>) -> !fir.box<!fir.heap<!fir.array<?x!fir.char<1,?>>>>
  ! CHECK: fir.save_result %[[res]] to %[[alloc]] : !fir.box<!fir.heap<!fir.array<?x!fir.char<1,?>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,?>>>>>
  print *, return_dyn_char_alloc(l)
  ! CHECK: _FortranAioOutputDescriptor
  ! CHECK: %[[load:.*]] = fir.load %[[alloc]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,?>>>>>
  ! CHECK: %[[addr:.*]] = fir.box_addr %[[load]] : (!fir.box<!fir.heap<!fir.array<?x!fir.char<1,?>>>>) -> !fir.heap<!fir.array<?x!fir.char<1,?>>>
  ! CHECK: %[[cmpi:.*]] = arith.cmpi
  ! CHECK: fir.if %[[cmpi]]
  ! CHECK: fir.freemem %[[addr]] : !fir.heap<!fir.array<?x!fir.char<1,?>>>
end subroutine

! CHECK-LABEL: @_QMcallerPdyn_char_pointer
subroutine dyn_char_pointer(l)
  integer :: l
  ! CHECK: %[[alloc:.*]] = fir.alloca !fir.box<!fir.ptr<!fir.array<?x!fir.char<1,?>>>> {{{.*}}bindc_name = ".result"}
  ! CHECK: %[[res:.*]] = fir.call @_QMcalleePreturn_dyn_char_pointer({{.*}}) {{.*}}: (!fir.ref<i32>) -> !fir.box<!fir.ptr<!fir.array<?x!fir.char<1,?>>>>
  ! CHECK: fir.save_result %[[res]] to %[[alloc]] : !fir.box<!fir.ptr<!fir.array<?x!fir.char<1,?>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.char<1,?>>>>>
  print *, return_dyn_char_pointer(l)
  ! CHECK-NOT: fir.freemem
end subroutine

end module


! Test more complex symbol dependencies in the result specification expression

module m_with_equiv
  integer(8) :: l
  integer(8) :: array(3)
  equivalence (array(2), l)
contains
  function result_depends_on_equiv_sym()
    character(l) :: result_depends_on_equiv_sym
    call set_result_with_some_value(result_depends_on_equiv_sym)
  end function  
end module

! CHECK-LABEL: func @_QPtest_result_depends_on_equiv_sym
subroutine test_result_depends_on_equiv_sym()
  use m_with_equiv, only : result_depends_on_equiv_sym
  ! CHECK: %[[equiv:.*]] = fir.address_of(@_QMm_with_equivEarray) : !fir.ref<!fir.array<24xi8>>
  ! CHECK: %[[coor:.*]] = fir.coordinate_of %[[equiv]], %c{{.*}} : (!fir.ref<!fir.array<24xi8>>, index) -> !fir.ref<i8>
  ! CHECK: %[[l:.*]] = fir.convert %[[coor]] : (!fir.ref<i8>) -> !fir.ptr<i64>
  ! CHECK: %[[load:.*]] = fir.load %[[l]] : !fir.ptr<i64>
  ! CHECK: %[[lcast:.*]] = fir.convert %[[load]] : (i64) -> index
  ! CHECK: %[[cmpi:.*]] = arith.cmpi sgt, %[[lcast]], %{{.*}} : index
  ! CHECK: %[[select:.*]] = arith.select %[[cmpi]], %[[lcast]], %{{.*}} : index
  ! CHECK: fir.alloca !fir.char<1,?>(%[[select]] : index)
  print *, result_depends_on_equiv_sym()
end subroutine

! CHECK-LABEL: func @_QPtest_depends_on_descriptor(
! CHECK-SAME: %[[x:.*]]: !fir.box<!fir.array<?xf32>>{{.*}}) {
subroutine test_depends_on_descriptor(x)
  interface
    function depends_on_descriptor(x)
      real :: x(:)
      character(size(x,1, KIND=8)) :: depends_on_descriptor
    end function
  end interface
  real :: x(:)
  ! CHECK: %[[dims:.*]]:3 = fir.box_dims %arg0, %c0 : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index)
  ! CHECK: %[[extentCast:.*]] = fir.convert %[[dims]]#1 : (index) -> i64
  ! CHECK: %[[extent:.*]] = fir.convert %[[extentCast]] : (i64) -> index
  ! CHECK: %[[cmpi:.*]] = arith.cmpi sgt, %[[extent]], %{{.*}} : index
  ! CHECK: %[[select:.*]] = arith.select %[[cmpi]], %[[extent]], %{{.*}} : index
  ! CHECK: fir.alloca !fir.char<1,?>(%[[select]] : index)
  print *, depends_on_descriptor(x)
end subroutine

! CHECK-LABEL: func @_QPtest_symbol_indirection(
! CHECK-SAME: %[[n:.*]]: !fir.ref<i64>{{.*}}) {
subroutine test_symbol_indirection(n)
  interface
    function symbol_indirection(c, n)
      integer(8) :: n
      character(n) :: c
      character(len(c, KIND=8)) :: symbol_indirection
    end function
  end interface
  integer(8) :: n
  character(n) :: c
  ! CHECK: BeginExternalListOutput
  ! CHECK: %[[nload:.*]] = fir.load %[[n]] : !fir.ref<i64>
  ! CHECK: %[[n_is_positive:.*]] = arith.cmpi sgt, %[[nload]], %c0{{.*}} : i64
  ! CHECK: %[[len:.*]] = arith.select %[[n_is_positive]], %[[nload]], %c0{{.*}} : i64
  ! CHECK: %[[len_cast:.*]] = fir.convert %[[len]] : (i64) -> index
  ! CHECK: %[[cmpi:.*]] = arith.cmpi sgt, %[[len_cast]], %{{.*}} : index
  ! CHECK: %[[select:.*]] = arith.select %[[cmpi]], %[[len_cast]], %{{.*}} : index
  ! CHECK: fir.alloca !fir.char<1,?>(%[[select]] : index)
  print *, symbol_indirection(c, n)
end subroutine

! CHECK-LABEL: func @_QPtest_recursion(
! CHECK-SAME: %[[res:.*]]: !fir.ref<!fir.char<1,?>>{{.*}}, %[[resLen:.*]]: index{{.*}}, %[[n:.*]]: !fir.ref<i64>{{.*}}) -> !fir.boxchar<1> {
function test_recursion(n) result(res)
  integer(8) :: n
  character(n) :: res
  ! some_local is here to verify that local symbols that are visible in the
  ! function interface are not instantiated by accident (that only the
  ! symbols needed for the result are instantiated before the call).
  ! CHECK: fir.alloca !fir.array<?xi32>, {{.*}}some_local
  ! CHECK-NOT: fir.alloca !fir.array<?xi32>
  integer :: some_local(n)
  some_local(1) = n + 64
  if (n.eq.1) then
    res = char(some_local(1))
  ! CHECK: else
  else 
    ! CHECK-NOT: fir.alloca !fir.array<?xi32>

    ! verify that the actual argument for symbol n ("n-1") is used to allocate
    ! the result, and not the local value of symbol n.

    ! CHECK: %[[nLoad:.*]] = fir.load %[[n]] : !fir.ref<i64>
    ! CHECK: %[[sub:.*]] = arith.subi %[[nLoad]], %c1{{.*}} : i64
    ! CHECK: fir.store %[[sub]] to %[[nInCall:.*]] : !fir.ref<i64>

    ! CHECK-NOT: fir.alloca !fir.array<?xi32>

    ! CHECK: %[[nInCallLoad:.*]] = fir.load %[[nInCall]] : !fir.ref<i64>
    ! CHECK: %[[nInCallCast:.*]] = fir.convert %[[nInCallLoad]] : (i64) -> index
    ! CHECK: %[[cmpi:.*]] = arith.cmpi sgt, %[[nInCallCast]], %{{.*}} : index
    ! CHECK: %[[select:.*]] = arith.select %[[cmpi]], %[[nInCallCast]], %{{.*}} : index
    ! CHECK: %[[tmp:.*]] = fir.alloca !fir.char<1,?>(%[[select]] : index)

    ! CHECK-NOT: fir.alloca !fir.array<?xi32>
    ! CHECK: fir.call @_QPtest_recursion(%[[tmp]], {{.*}}
    res = char(some_local(1)) // test_recursion(n-1)

    ! Verify that symbol n was not remapped to the actual argument passed
    ! to n in the call (that the temporary mapping was cleaned-up).

    ! CHECK: %[[nLoad2:.*]] = fir.load %[[n]] : !fir.ref<i64>
    ! CHECK: OutputInteger64(%{{.*}}, %[[nLoad2]])
    print *, n
  end if
end function

! Test call to character function for which only the result type is explicit
! CHECK-LABEL:func @_QPtest_not_entirely_explicit_interface(
! CHECK-SAME: %[[n_arg:.*]]: !fir.ref<i64>{{.*}}) {
subroutine test_not_entirely_explicit_interface(n)
  integer(8) :: n
  character(n) :: return_dyn_char_2
  print *, return_dyn_char_2(10)
  ! CHECK: %[[n:.*]] = fir.load %[[n_arg]] : !fir.ref<i64>
  ! CHECK: %[[len:.*]] = fir.convert %[[n]] : (i64) -> index
  ! CHECK: %[[cmpi:.*]] = arith.cmpi sgt, %[[len]], %{{.*}} : index
  ! CHECK: %[[select:.*]] = arith.select %[[cmpi]], %[[len]], %{{.*}} : index
  ! CHECK: %[[result:.*]] = fir.alloca !fir.char<1,?>(%[[select]] : index) {bindc_name = ".result"}
  ! CHECK: fir.call @_QPreturn_dyn_char_2(%[[result]], %[[select]], %{{.*}}) {{.*}}: (!fir.ref<!fir.char<1,?>>, index, !fir.ref<i32>) -> !fir.boxchar<1>
end subroutine
