! Tests that "loop-local values" are properly handled by localizing them to the
! body of the loop nest. See `collectLoopLocalValues` and `localizeLoopLocalValue`
! for a definition of "loop-local values" and how they are handled.

! RUN: %flang_fc1 -emit-hlfir -fopenmp -fdo-concurrent-to-openmp=host %s -o - \
! RUN:   | FileCheck %s --check-prefixes=COMMON

! RUN: %flang_fc1 -emit-hlfir -fopenmp -fdo-concurrent-to-openmp=device %s -o - \
! RUN:   | FileCheck %s --check-prefixes=COMMON,DEVICE
module struct_mod
    type test_struct
        integer, allocatable :: x_
    end type

    interface test_struct
        pure module function construct_from_components(x) result(struct)
            implicit none
            integer, intent(in) :: x
            type(test_struct) struct
        end function
    end interface
end module

submodule(struct_mod) struct_sub
    implicit none

contains
    module procedure construct_from_components
        struct%x_ = x
    end procedure
end submodule struct_sub

program main
    use struct_mod, only : test_struct

    implicit none
    type(test_struct), dimension(10) :: a
    integer :: i
    integer :: total

    do concurrent (i=1:10)
        a(i) = test_struct(i)
    end do

    do i=1,10
        total = total + a(i)%x_
    end do

    print *, "total =", total
end program main

! DEVICE: omp.target {{.*}} {
! DEVICE: omp.teams {
! COMMON: omp.parallel {
! COMMON:   %[[LOCAL_TEMP:.*]] = fir.alloca !fir.type<_QMstruct_modTtest_struct{x_:!fir.box<!fir.heap<i32>>}> {bindc_name = ".result"}
! DEVICE:   omp.distribute {
! COMMON:   omp.wsloop {
! COMMON:     omp.loop_nest {{.*}} {
! COMMON:       %[[TEMP_VAL:.*]] = fir.call @_QMstruct_modPconstruct_from_components
! COMMON:       fir.save_result %[[TEMP_VAL]] to %[[LOCAL_TEMP]]
! COMMON:       %[[EMBOXED_LOCAL:.*]] = fir.embox %[[LOCAL_TEMP]]
! COMMON:       %[[CONVERTED_LOCAL:.*]] = fir.convert %[[EMBOXED_LOCAL]]
! COMMON:       fir.call @_FortranADestroy(%[[CONVERTED_LOCAL]])
! COMMON:       omp.yield
! COMMON:     }
! COMMON:   }
! DEVICE:   }
! COMMON:   omp.terminator
! COMMON: }
! DEVICE: omp.terminator
! DEVICE: }
! DEVICE: omp.terminator
! DEVICE: }
