! RUN: %flang_fc1 -emit-hlfir %s -o - | FileCheck %s ! Test allocatable dummy argument on callee side ! CHECK-LABEL: func @_QPtest_scalar( ! CHECK-SAME: %[[arg0:.*]]: !fir.ref>>{{.*}}) subroutine test_scalar(x) real, allocatable :: x print *, x ! CHECK: %[[x:.*]]:2 = hlfir.declare %[[arg0]]{{.*}}allocatable ! CHECK: %[[box:.*]] = fir.load %[[x]]#0 : !fir.ref>> ! CHECK: %[[addr:.*]] = fir.box_addr %[[box]] : (!fir.box>) -> !fir.heap ! CHECK: %[[val:.*]] = fir.load %[[addr]] : !fir.heap end subroutine ! CHECK-LABEL: func @_QPtest_array( ! CHECK-SAME: %[[arg0:.*]]: !fir.ref>>>{{.*}}) subroutine test_array(x) integer, allocatable :: x(:,:) print *, x(1,2) ! CHECK: %[[x:.*]]:2 = hlfir.declare %[[arg0]]{{.*}}allocatable ! CHECK: %[[box:.*]] = fir.load %[[x]]#0 : !fir.ref>>> ! CHECK: %[[elem:.*]] = hlfir.designate %[[box]] (%{{.*}}, %{{.*}}) : (!fir.box>>, index, index) -> !fir.ref ! CHECK: fir.load %[[elem]] : !fir.ref end subroutine ! CHECK-LABEL: func @_QPtest_char_scalar_deferred( ! CHECK-SAME: %[[arg0:.*]]: !fir.ref>>>{{.*}}) subroutine test_char_scalar_deferred(c) character(:), allocatable :: c external foo1 call foo1(c) ! CHECK: %[[c:.*]]:2 = hlfir.declare %[[arg0]]{{.*}}allocatable ! CHECK: %[[box:.*]] = fir.load %[[c]]#0 : !fir.ref>>> ! CHECK-DAG: %[[addr:.*]] = fir.box_addr %[[box]] : (!fir.box>>) -> !fir.heap> ! CHECK-DAG: %[[box1:.*]] = fir.load %[[c]]#0 : !fir.ref>>> ! CHECK-DAG: %[[len:.*]] = fir.box_elesize %[[box1]] : (!fir.box>>) -> index ! CHECK: %[[boxchar:.*]] = fir.emboxchar %[[addr]], %[[len]] : (!fir.heap>, index) -> !fir.boxchar<1> ! CHECK: fir.call @_QPfoo1(%[[boxchar]]) {{.*}}: (!fir.boxchar<1>) -> () end subroutine ! CHECK-LABEL: func @_QPtest_char_scalar_explicit_cst( ! CHECK-SAME: %[[arg0:.*]]: !fir.ref>>>{{.*}}) subroutine test_char_scalar_explicit_cst(c) character(10), allocatable :: c external foo1 call foo1(c) ! CHECK: %[[c:.*]]:2 = hlfir.declare %[[arg0]]{{.*}}allocatable ! CHECK: %[[box:.*]] = fir.load %[[c]]#0 : !fir.ref>>> ! CHECK: %[[addr:.*]] = fir.box_addr %[[box]] : (!fir.box>>) -> !fir.heap> ! CHECK: %[[cast:.*]] = fir.convert %[[addr]] : (!fir.heap>) -> !fir.ref> ! CHECK: %[[boxchar:.*]] = fir.emboxchar %[[cast]], %c10{{.*}} : (!fir.ref>, index) -> !fir.boxchar<1> ! CHECK: fir.call @_QPfoo1(%[[boxchar]]) {{.*}}: (!fir.boxchar<1>) -> () end subroutine ! CHECK-LABEL: func @_QPtest_char_scalar_explicit_dynamic( ! CHECK-SAME: %[[arg0:.*]]: !fir.ref>>>{{.*}}, %[[arg1:.*]]: !fir.ref{{.*}}) subroutine test_char_scalar_explicit_dynamic(c, n) integer :: n character(n), allocatable :: c external foo1 ! Check that the length expr was evaluated before the execution parts. ! CHECK: %[[n:.*]]:2 = hlfir.declare %[[arg1]] ! CHECK: %[[raw_len:.*]] = fir.load %[[n]]#0 : !fir.ref ! CHECK: %[[c0_i32:.*]] = arith.constant 0 : i32 ! CHECK: %[[cmp:.*]] = arith.cmpi sgt, %[[raw_len]], %[[c0_i32]] : i32 ! CHECK: %[[len:.*]] = arith.select %[[cmp]], %[[raw_len]], %[[c0_i32]] : i32 ! CHECK: %[[c:.*]]:2 = hlfir.declare %[[arg0]] typeparams %[[len]]{{.*}}allocatable n = n + 1 ! CHECK: hlfir.assign %{{.*}} to %[[n]]#0 : i32, !fir.ref call foo1(c) ! CHECK: %[[box:.*]] = fir.load %[[c]]#0 : !fir.ref>>> ! CHECK: %[[addr:.*]] = fir.box_addr %[[box]] : (!fir.box>>) -> !fir.heap> ! CHECK: %[[boxchar:.*]] = fir.emboxchar %[[addr]], %[[len]] : (!fir.heap>, i32) -> !fir.boxchar<1> ! CHECK: fir.call @_QPfoo1(%[[boxchar]]) {{.*}}: (!fir.boxchar<1>) -> () end subroutine ! CHECK-LABEL: func @_QPtest_char_array_deferred( ! CHECK-SAME: %[[arg0:.*]]: !fir.ref>>>>{{.*}}) subroutine test_char_array_deferred(c) character(:), allocatable :: c(:) external foo1 call foo1(c(10)) ! CHECK: %[[c:.*]]:2 = hlfir.declare %[[arg0]]{{.*}}allocatable ! CHECK: %[[box:.*]] = fir.load %[[c]]#0 : !fir.ref>>>> ! CHECK: %[[len:.*]] = fir.box_elesize %[[box]] : (!fir.box>>>) -> index ! CHECK: %[[boxchar:.*]] = hlfir.designate %[[box]] (%{{.*}}) typeparams %[[len]] : (!fir.box>>>, index, index) -> !fir.boxchar<1> ! CHECK: fir.call @_QPfoo1(%[[boxchar]]) {{.*}}: (!fir.boxchar<1>) -> () end subroutine ! CHECK-LABEL: func @_QPtest_char_array_explicit_cst( ! CHECK-SAME: %[[arg0:.*]]: !fir.ref>>>>{{.*}}) subroutine test_char_array_explicit_cst(c) character(10), allocatable :: c(:) external foo1 call foo1(c(3)) ! CHECK: %[[c:.*]]:2 = hlfir.declare %[[arg0]]{{.*}}allocatable ! CHECK: %[[box:.*]] = fir.load %[[c]]#0 : !fir.ref>>>> ! CHECK: %[[elem:.*]] = hlfir.designate %[[box]] (%{{.*}}) typeparams %c10{{.*}} : (!fir.box>>>, index, index) -> !fir.ref> ! CHECK: %[[boxchar:.*]] = fir.emboxchar %[[elem]], %c10{{.*}} : (!fir.ref>, index) -> !fir.boxchar<1> ! CHECK: fir.call @_QPfoo1(%[[boxchar]]) {{.*}}: (!fir.boxchar<1>) -> () end subroutine ! CHECK-LABEL: func @_QPtest_char_array_explicit_dynamic( ! CHECK-SAME: %[[arg0:.*]]: !fir.ref>>>>{{.*}}, %[[arg1:.*]]: !fir.ref{{.*}}) subroutine test_char_array_explicit_dynamic(c, n) integer :: n character(n), allocatable :: c(:) external foo1 ! Check that the length expr was evaluated before the execution parts. ! CHECK: %[[n:.*]]:2 = hlfir.declare %[[arg1]] ! CHECK: %[[raw_len:.*]] = fir.load %[[n]]#0 : !fir.ref ! CHECK: %[[c0_i32:.*]] = arith.constant 0 : i32 ! CHECK: %[[cmp:.*]] = arith.cmpi sgt, %[[raw_len]], %[[c0_i32]] : i32 ! CHECK: %[[len:.*]] = arith.select %[[cmp]], %[[raw_len]], %[[c0_i32]] : i32 ! CHECK: %[[c:.*]]:2 = hlfir.declare %[[arg0]] typeparams %[[len]]{{.*}}allocatable n = n + 1 ! CHECK: hlfir.assign %{{.*}} to %[[n]]#0 : i32, !fir.ref call foo1(c(1)) ! CHECK: %[[box:.*]] = fir.load %[[c]]#0 : !fir.ref>>>> ! CHECK: %[[boxchar:.*]] = hlfir.designate %[[box]] (%{{.*}}) typeparams %[[len]] : (!fir.box>>>, index, i32) -> !fir.boxchar<1> ! CHECK: fir.call @_QPfoo1(%[[boxchar]]) {{.*}}: (!fir.boxchar<1>) -> () end subroutine ! Check that when reading allocatable length from descriptor, the width is taking ! into account when the kind is not 1. ! CHECK-LABEL: func @_QPtest_char_scalar_deferred_k2( ! CHECK-SAME: %[[arg0:.*]]: !fir.ref>>>{{.*}}) subroutine test_char_scalar_deferred_k2(c) character(kind=2, len=:), allocatable :: c external foo2 call foo2(c) ! CHECK: %[[c:.*]]:2 = hlfir.declare %[[arg0]]{{.*}}allocatable ! CHECK: %[[box:.*]] = fir.load %[[c]]#0 : !fir.ref>>> ! CHECK-DAG: %[[addr:.*]] = fir.box_addr %[[box]] : (!fir.box>>) -> !fir.heap> ! CHECK-DAG: %[[box1:.*]] = fir.load %[[c]]#0 : !fir.ref>>> ! CHECK-DAG: %[[size:.*]] = fir.box_elesize %[[box1]] : (!fir.box>>) -> index ! CHECK-DAG: %[[len:.*]] = arith.divsi %[[size]], %c2{{.*}} : index ! CHECK: %[[boxchar:.*]] = fir.emboxchar %[[addr]], %[[len]] : (!fir.heap>, index) -> !fir.boxchar<2> ! CHECK: fir.call @_QPfoo2(%[[boxchar]]) {{.*}}: (!fir.boxchar<2>) -> () end subroutine ! Check that assumed length character allocatables are reading the length from ! the descriptor. ! CHECK-LABEL: _QPtest_char_assumed( ! CHECK-SAME: %[[arg0:.*]]: !fir.ref>>>{{.*}} subroutine test_char_assumed(a) integer :: n character(len=*), allocatable :: a ! CHECK: %[[argLoad:.*]] = fir.load %[[arg0]] : !fir.ref>>> ! CHECK: %[[argLen:.*]] = fir.box_elesize %[[argLoad]] : (!fir.box>>) -> index ! CHECK: hlfir.declare %[[arg0]] typeparams %[[argLen]]{{.*}}allocatable n = len(a) ! CHECK: %[[argLenCast:.*]] = fir.convert %[[argLen]] : (index) -> i32 ! CHECK: hlfir.assign %[[argLenCast]] to %{{.*}} : i32, !fir.ref end subroutine ! CHECK-LABEL: _QPtest_char_assumed_optional( ! CHECK-SAME: %[[arg0:.*]]: !fir.ref>>>{{.*}} subroutine test_char_assumed_optional(a) integer :: n character(len=*), allocatable, optional :: a ! CHECK: %[[argPresent:.*]] = fir.is_present %[[arg0]] : (!fir.ref>>>) -> i1 ! CHECK: %[[argLen:.*]] = fir.if %[[argPresent]] -> (index) { ! CHECK: %[[argLoad:.*]] = fir.load %[[arg0]] : !fir.ref>>> ! CHECK: %[[argEleSz:.*]] = fir.box_elesize %[[argLoad]] : (!fir.box>>) -> index ! CHECK: fir.result %[[argEleSz]] : index ! CHECK: } else { ! CHECK: %[[undef:.*]] = fir.undefined index ! CHECK: fir.result %[[undef]] : index ! CHECK: %[[a:.*]]:2 = hlfir.declare %[[arg0]] typeparams %[[argLen]]{{.*}}allocatable, optional if (present(a)) then n = len(a) ! CHECK: %[[argLenCast:.*]] = fir.convert %[[argLen]] : (index) -> i32 ! CHECK: hlfir.assign %[[argLenCast]] to %{{.*}} : i32, !fir.ref endif end subroutine