! RUN: %flang_fc1 -emit-fir -flang-deprecated-no-hlfir %s -o - | fir-opt --array-value-copy | fir-opt --stack-arrays | FileCheck %s

! In order to verify the whole MLIR pipeline, make the driver generate LLVM IR.
! This is only to check that -fstack-arrays enables the stack-arrays pass so
! only check the first example
! RUN: %flang_fc1 -emit-llvm -flang-deprecated-no-hlfir -o - -fstack-arrays %s | FileCheck --check-prefix=LLVM-IR %s

! check simple array value copy case
subroutine array_value_copy_simple(arr)
  integer, intent(inout) :: arr(4)
  arr(3:4) = arr(1:2)
end subroutine
! CHECK-LABEL: func.func @_QParray_value_copy_simple(%arg0: !fir.ref<!fir.array<4xi32>>
! CHECK-NOT: fir.allocmem
! CHECK-NOT: fir.freemem
! CHECK: fir.alloca !fir.array<4xi32>
! CHECK-NOT: fir.allocmem
! CHECK-NOT: fir.freemem
! CHECK: return
! CHECK-NEXT: }

! LLVM-IR: array_value_copy_simple
! LLVM-IR-NOT: malloc
! LLVM-IR-NOT: free
! LLVM-IR: alloca [4 x i32]
! LLVM-IR-NOT: malloc
! LLVM-IR-NOT: free
! LLVM-IR: ret void
! LLVM-IR-NEXT: }

! check complex array value copy case
module stuff
  type DerivedWithAllocatable
    integer, dimension(:), allocatable :: dat
  end type

  contains
  subroutine array_value_copy_complex(arr)
    type(DerivedWithAllocatable), intent(inout) :: arr(:)
    arr(3:4) = arr(1:2)
  end subroutine
end module
! CHECK: func.func
! CHECK-SAME: array_value_copy_complex
! CHECK-NOT: fir.allocmem
! CHECK-NOT: fir.freemem
! CHECK: fir.alloca !fir.array<?x!fir.type<_QMstuffTderivedwithallocatable
! CHECK-NOT: fir.allocmem
! CHECK-NOT: fir.freemem
! CHECK: return
! CHECK-NEXT: }

subroutine parameter_array_init
  integer, parameter :: p(100) = 42
  call use_p(p)
end subroutine
! CHECK: func.func
! CHECK-SAME: parameter_array_init
! CHECK-NOT: fir.allocmem
! CHECK-NOT: fir.freemem
! CHECK: fir.alloca !fir.array<100xi32>
! CHECK-NOT: fir.allocmem
! CHECK-NOT: fir.freemem
! CHECK: return
! CHECK-NEXT: }

subroutine test_vector_subscripted_section_to_box(v, x)
  interface
    subroutine takes_box(y)
      real :: y(:)
    end subroutine
  end interface

  integer :: v(:)
  real :: x(:)
  call takes_box(x(v))
end subroutine
! CHECK: func.func
! CHECK-SAME: test_vector_subscripted_section_to_box
! CHECK-NOT: fir.allocmem
! CHECK: fir.alloca !fir.array<?xf32>
! CHECK-NOT: fir.allocmem
! CHECK: fir.call @_QPtakes_box
! CHECK-NOT: fir.freemem
! CHECK: return
! CHECK-NEXT: }

subroutine call_parenthesized_arg(x)
  integer :: x(100)
  call bar((x))
end subroutine
! CHECK: func.func
! CHECK-SAME: call_parenthesized_arg
! CHECK-NOT: fir.allocmem
! CHECK: fir.alloca !fir.array<100xi32>
! CHECK-NOT: fir.allocmem
! CHECK: fir.call @_QPbar
! CHECK-NOT: fir.freemem
! CHECK: return
! CHECK-NEXT: }

subroutine where_allocatable_assignments(a, b)
  integer :: a(:)
  integer, allocatable :: b(:)
  where(b > 0)
    b = a
  elsewhere
    b(:) = 0
  end where
end subroutine
! TODO: broken: passing allocation through fir.result
! CHECK: func.func
! CHECK-SAME: where_allocatable_assignments
! CHECK: return
! CHECK-NEXT: }

subroutine array_constructor(a, b)
  real :: a(5), b
  real, external :: f
  a = [f(b), f(b+1), f(b+2), f(b+5), f(b+11)]
end subroutine
! TODO: broken: realloc
! CHECK: func.func
! CHECK-SAME: array_constructor
! CHECK: return
! CHECK-NEXT: }

subroutine sequence(seq, n)
  integer :: n, seq(n)
  seq = [(i,i=1,n)]
end subroutine
! TODO: broken: realloc
! CHECK: func.func
! CHECK-SAME: sequence
! CHECK: return
! CHECK-NEXT: }

subroutine CFGLoop(x)
  integer, parameter :: k = 100, m=1000000, n = k*m
  integer :: x(n)
  logical :: has_error

  do i=0,m-1
    x(k*i+1:k*(i+1)) = x(k*(i+1):k*i+1:-1)
    if (has_error(x, k)) stop
  end do
end subroutine
! CHECK: func.func
! CHECK-SAME: cfgloop
! CHECK-NEXT: %[[MEM:.*]] = fir.alloca !fir.array<100000000xi32>
! CHECK-NOT: fir.allocmem
! CHECK-NOT: fir.freemem
! CHECK: return
! CHECK-NEXT: }
