! RUN: bbc -emit-fir %s -o - | FileCheck %s ! Test for component-wise initialization of derived types to avoid ! generating large, fully-initialized global templates. module my_types ! Clean internal type: contains only allocatable and pointer components, ! without any default initialization. type :: InnerClean real, pointer :: p real, allocatable :: arr(:) end type InnerClean ! ============================================================================ ! Test Case 1: Type meeting all criteria for component-wise init (Target) ! No arrays of derived types, no default initialization. ! ============================================================================ type :: TargetType real, pointer :: q real(8) :: uninit_buffer(80, 100) type(InnerClean) :: nested_scalar end type TargetType ! ============================================================================ ! Test Case 2: Type triggering fallback A (contains an array of derived type) ! ============================================================================ type :: FallbackArrayType type(InnerClean) :: nested_arr(10) end type FallbackArrayType ! ============================================================================ ! Test Case 3: Type triggering fallback B (contains default initialization) ! ============================================================================ type :: FallbackDefaultInitType real, pointer :: p integer :: flag = 999 end type FallbackDefaultInitType ! ============================================================================ ! Test Case 4: Type triggering fallback C (contains default initialization) ! ============================================================================ type :: ProcPointerType real, pointer :: p procedure(), pointer, nopass :: pp => null() end type ProcPointerType ! ============================================================================ ! Test Case 5: Type with uninitialized procedure pointer. ! ============================================================================ type :: ProcPointerNoInitType real, pointer :: p procedure(), pointer, nopass :: pp end type ProcPointerNoInitType end module my_types ! ------------------------------------------------------------------------------ ! Test 1: FIR generation for component-wise initialization ! ------------------------------------------------------------------------------ subroutine test_target() use my_types type(TargetType) :: my_var call do_something_target(my_var) end subroutine test_target ! CHECK-LABEL: func.func @_QPtest_target() ! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.type<_QMmy_typesTtargettype{{.*}}> ! CHECK: %[[MY_VAR:.*]] = fir.declare %[[ALLOCA]] ! CHECK: %[[Q_ADDR:.*]] = fir.coordinate_of %[[MY_VAR]], q ! CHECK: fir.store %{{.*}} to %[[Q_ADDR]] ! CHECK: %[[NESTED_ADDR:.*]] = fir.coordinate_of %[[MY_VAR]], nested_scalar ! CHECK: %[[P_ADDR:.*]] = fir.coordinate_of %[[NESTED_ADDR]], p ! CHECK: fir.store %{{.*}} to %[[P_ADDR]] ! CHECK: %[[ARR_ADDR:.*]] = fir.coordinate_of %[[NESTED_ADDR]], arr ! CHECK: fir.store %{{.*}} to %[[ARR_ADDR]] ! CHECK-NOT: fir.call @_FortranAInitialize ! CHECK-NOT: fir.global internal @_QQ_QMmy_typesTtargettype.DerivedInit ! ------------------------------------------------------------------------------ ! Test 2: Fallback mechanism for arrays of derived types ! ------------------------------------------------------------------------------ subroutine test_fallback_array() use my_types type(FallbackArrayType) :: var_array call do_something_array(var_array) end subroutine test_fallback_array ! CHECK-LABEL: func.func @_QPtest_fallback_array() ! CHECK: %[[ALLOCA_ARR:.*]] = fir.alloca !fir.type<_QMmy_typesTfallbackarraytype{{.*}}> ! CHECK: %[[VAR_ARRAY:.*]] = fir.declare %[[ALLOCA_ARR]] ! CHECK: %[[GLOBAL_INIT_ARR:.*]] = fir.address_of(@_QQ_QMmy_typesTfallbackarraytype.DerivedInit) ! CHECK: fir.copy %[[GLOBAL_INIT_ARR]] to %[[VAR_ARRAY]] ! ------------------------------------------------------------------------------ ! Test 3: Fallback mechanism for default initialization ! ------------------------------------------------------------------------------ subroutine test_fallback_default_init() use my_types type(FallbackDefaultInitType) :: var_default_init call do_something_default_init(var_default_init) end subroutine test_fallback_default_init ! CHECK-LABEL: func.func @_QPtest_fallback_default_init() ! CHECK: %[[ALLOCA_DEFAULT:.*]] = fir.alloca !fir.type<_QMmy_typesTfallbackdefaultinittype{{.*}}> ! CHECK: %[[VAR_DEFAULT:.*]] = fir.declare %[[ALLOCA_DEFAULT]] ! CHECK: %[[GLOBAL_INIT_DEFAULT:.*]] = fir.address_of(@_QQ_QMmy_typesTfallbackdefaultinittype.DerivedInit) ! CHECK: fir.copy %[[GLOBAL_INIT_DEFAULT]] to %[[VAR_DEFAULT]] ! ------------------------------------------------------------------------------ ! Test 4: Procedure pointers ! Procedure pointers default initialized with '=> null()' trigger the ! default-initialization fallback safely. ! ------------------------------------------------------------------------------ subroutine test_proc_pointer() use my_types type(ProcPointerType) :: var_proc call do_something_proc(var_proc) end subroutine test_proc_pointer ! CHECK-LABEL: func.func @_QPtest_proc_pointer() ! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.type<_QMmy_typesTprocpointertype{{.*}}> ! CHECK: %[[VAR_DECL:.*]] = fir.declare %[[ALLOCA]] {{.*}} ! CHECK: %[[GLOBAL_INIT_PROC:.*]] = fir.address_of(@_QQ_QMmy_typesTprocpointertype.DerivedInit) ! CHECK: fir.copy %[[GLOBAL_INIT_PROC]] to %[[VAR_DECL]] ! ------------------------------------------------------------------------------ ! Test 5: Procedure pointers ! Procedure pointers without default initialization should be initialized ! component-wise, without falling back to template copy initialization. ! ------------------------------------------------------------------------------ subroutine test_proc_pointer_no_init() use my_types type(ProcPointerNoInitType) :: var_proc call do_something_proc_no_init(var_proc) end subroutine test_proc_pointer_no_init ! CHECK-LABEL: func.func @_QPtest_proc_pointer_no_init() ! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.type<_QMmy_typesTprocpointernoinittype{{.*}}> ! CHECK: %[[VAR_DECL:.*]] = fir.declare %[[ALLOCA]] {{.*}} ! CHECK: %[[COORD_P:.*]] = fir.coordinate_of %[[VAR_DECL]], p ! CHECK: %[[NULL_P:.*]] = fir.zero_bits !fir.ptr ! CHECK: %[[BOX_P:.*]] = fir.embox %[[NULL_P]] : (!fir.ptr) -> !fir.box> ! CHECK: fir.store %[[BOX_P]] to %[[COORD_P]] ! CHECK: %[[COORD_PP:.*]] = fir.coordinate_of %[[VAR_DECL]], pp ! CHECK: %[[NULL_FUNC:.*]] = fir.zero_bits () -> () ! CHECK: %[[BOX_PP:.*]] = fir.emboxproc %[[NULL_FUNC]] : (() -> ()) -> !fir.boxproc<() -> ()> ! CHECK: fir.store %[[BOX_PP]] to %[[COORD_PP]] ! CHECK-NOT: fir.copy