1*f35f863aSjeanPerier! RUN: bbc -emit-fir -hlfir=false %s -o - | FileCheck %s 2*f35f863aSjeanPerier! RUN: %flang_fc1 -fdefault-integer-8 -emit-fir -flang-deprecated-no-hlfir %s -o - | FileCheck %s 3baa42c16SValentin Clement 4baa42c16SValentin Clement! Test OPTIONAL lowering on caller/callee and PRESENT intrinsic. 5baa42c16SValentin Clementmodule opt 6baa42c16SValentin Clement implicit none 7baa42c16SValentin Clement type t 8baa42c16SValentin Clement real, allocatable :: p(:) 9baa42c16SValentin Clement end type 10baa42c16SValentin Clementcontains 11baa42c16SValentin Clement 12baa42c16SValentin Clement! Test simple scalar optional 13baa42c16SValentin Clement! CHECK-LABEL: func @_QMoptPintrinsic_scalar( 14baa42c16SValentin Clement! CHECK-SAME: %[[arg0:.*]]: !fir.ref<f32> {fir.bindc_name = "x", fir.optional}) { 15baa42c16SValentin Clementsubroutine intrinsic_scalar(x) 16baa42c16SValentin Clement real, optional :: x 17baa42c16SValentin Clement ! CHECK: fir.is_present %[[arg0]] : (!fir.ref<f32>) -> i1 18baa42c16SValentin Clement print *, present(x) 19baa42c16SValentin Clementend subroutine 20baa42c16SValentin Clement! CHECK-LABEL: @_QMoptPcall_intrinsic_scalar() 21baa42c16SValentin Clementsubroutine call_intrinsic_scalar() 22baa42c16SValentin Clement ! CHECK: %[[x:.*]] = fir.alloca f32 23baa42c16SValentin Clement real :: x 244cc9437aSTom Eccles ! CHECK: fir.call @_QMoptPintrinsic_scalar(%[[x]]) {{.*}}: (!fir.ref<f32>) -> () 25baa42c16SValentin Clement call intrinsic_scalar(x) 26baa42c16SValentin Clement ! CHECK: %[[absent:.*]] = fir.absent !fir.ref<f32> 274cc9437aSTom Eccles ! CHECK: fir.call @_QMoptPintrinsic_scalar(%[[absent]]) {{.*}}: (!fir.ref<f32>) -> () 28baa42c16SValentin Clement call intrinsic_scalar() 29baa42c16SValentin Clementend subroutine 30baa42c16SValentin Clement 31baa42c16SValentin Clement! Test explicit shape array optional 32baa42c16SValentin Clement! CHECK-LABEL: func @_QMoptPintrinsic_f77_array( 33baa42c16SValentin Clement! CHECK-SAME: %[[arg0:.*]]: !fir.ref<!fir.array<100xf32>> {fir.bindc_name = "x", fir.optional}) { 34baa42c16SValentin Clementsubroutine intrinsic_f77_array(x) 35baa42c16SValentin Clement real, optional :: x(100) 36baa42c16SValentin Clement ! CHECK: fir.is_present %[[arg0]] : (!fir.ref<!fir.array<100xf32>>) -> i1 37baa42c16SValentin Clement print *, present(x) 38baa42c16SValentin Clementend subroutine 39baa42c16SValentin Clement! CHECK-LABEL: func @_QMoptPcall_intrinsic_f77_array() 40baa42c16SValentin Clementsubroutine call_intrinsic_f77_array() 41baa42c16SValentin Clement ! CHECK: %[[x:.*]] = fir.alloca !fir.array<100xf32> 42baa42c16SValentin Clement real :: x(100) 434cc9437aSTom Eccles ! CHECK: fir.call @_QMoptPintrinsic_f77_array(%[[x]]) {{.*}}: (!fir.ref<!fir.array<100xf32>>) -> () 44baa42c16SValentin Clement call intrinsic_f77_array(x) 45baa42c16SValentin Clement ! CHECK: %[[absent:.*]] = fir.absent !fir.ref<!fir.array<100xf32>> 464cc9437aSTom Eccles ! CHECK: fir.call @_QMoptPintrinsic_f77_array(%[[absent]]) {{.*}}: (!fir.ref<!fir.array<100xf32>>) -> () 47baa42c16SValentin Clement call intrinsic_f77_array() 48baa42c16SValentin Clementend subroutine 49baa42c16SValentin Clement 50baa42c16SValentin Clement! Test optional character scalar 51baa42c16SValentin Clement! CHECK-LABEL: func @_QMoptPcharacter_scalar( 52baa42c16SValentin Clement! CHECK-SAME: %[[arg0:.*]]: !fir.boxchar<1> {fir.bindc_name = "x", fir.optional}) { 53baa42c16SValentin Clementsubroutine character_scalar(x) 54baa42c16SValentin Clement ! CHECK: %[[unboxed:.*]]:2 = fir.unboxchar %[[arg0]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) 558df59132SSlava Zakharin ! CHECK: %[[ref:.*]] = fir.convert %[[unboxed]]#0 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<!fir.char<1,10>> 56baa42c16SValentin Clement character(10), optional :: x 578df59132SSlava Zakharin ! CHECK: fir.is_present %[[ref]] : (!fir.ref<!fir.char<1,10>>) -> i1 58baa42c16SValentin Clement print *, present(x) 59baa42c16SValentin Clementend subroutine 60baa42c16SValentin Clement! CHECK-LABEL: func @_QMoptPcall_character_scalar() 61baa42c16SValentin Clementsubroutine call_character_scalar() 62baa42c16SValentin Clement ! CHECK: %[[addr:.*]] = fir.alloca !fir.char<1,10> 63baa42c16SValentin Clement character(10) :: x 64c0cb8f73SjeanPerier ! CHECK: %[[x:.*]] = fir.emboxchar %[[addr]], {{.*}} 654cc9437aSTom Eccles ! CHECK: fir.call @_QMoptPcharacter_scalar(%[[x]]) {{.*}}: (!fir.boxchar<1>) -> () 66baa42c16SValentin Clement call character_scalar(x) 67baa42c16SValentin Clement ! CHECK: %[[absent:.*]] = fir.absent !fir.boxchar<1> 684cc9437aSTom Eccles ! CHECK: fir.call @_QMoptPcharacter_scalar(%[[absent]]) {{.*}}: (!fir.boxchar<1>) -> () 69baa42c16SValentin Clement call character_scalar() 70baa42c16SValentin Clementend subroutine 71baa42c16SValentin Clement 7266ec3263SLeandro Lupori! Test optional character function 7366ec3263SLeandro Lupori! CHECK-LABEL: func @_QMoptPchar_proc( 7466ec3263SLeandro Lupori! CHECK-SAME: %[[arg0:.*]]: !fir.ref<!fir.char<1,3>>, 7566ec3263SLeandro Luporicharacter(len=3) function char_proc(i) 7666ec3263SLeandro Lupori integer :: i 7766ec3263SLeandro Lupori char_proc = "XYZ" 7866ec3263SLeandro Luporiend function 7966ec3263SLeandro Lupori! CHECK-LABEL: func @_QMoptPuse_char_proc( 8066ec3263SLeandro Lupori! CHECK-SAME: %[[arg0:.*]]: tuple<!fir.boxproc<() -> ()>, i64> {fir.char_proc}, 8166ec3263SLeandro Luporisubroutine use_char_proc(f, c) 8266ec3263SLeandro Lupori optional :: f 8366ec3263SLeandro Lupori interface 8466ec3263SLeandro Lupori character(len=3) function f(i) 8566ec3263SLeandro Lupori integer :: i 8666ec3263SLeandro Lupori end function 8766ec3263SLeandro Lupori end interface 8866ec3263SLeandro Lupori character(len=3) :: c 8966ec3263SLeandro Lupori! CHECK: %[[boxProc:.*]] = fir.extract_value %[[arg0]], [0 : index] : (tuple<!fir.boxproc<() -> ()>, i64>) -> !fir.boxproc<() -> ()> 9066ec3263SLeandro Lupori! CHECK: %[[procAddr:.*]] = fir.box_addr %[[boxProc]] : (!fir.boxproc<() -> ()>) -> (() -> ()) 9166ec3263SLeandro Lupori! CHECK: %{{.*}} = fir.is_present %[[procAddr]] : (() -> ()) -> i1 9266ec3263SLeandro Lupori if (present(f)) then 9366ec3263SLeandro Lupori c = f(0) 9466ec3263SLeandro Lupori else 9566ec3263SLeandro Lupori c = "ABC" 9666ec3263SLeandro Lupori end if 9766ec3263SLeandro Luporiend subroutine 9866ec3263SLeandro Lupori! CHECK-LABEL: func @_QMoptPcall_use_char_proc( 9966ec3263SLeandro Luporisubroutine call_use_char_proc() 10066ec3263SLeandro Lupori character(len=3) :: c 10166ec3263SLeandro Lupori! CHECK: %[[boxProc:.*]] = fir.absent !fir.boxproc<() -> ()> 10266ec3263SLeandro Lupori! CHECK: %[[undef:.*]] = fir.undefined index 10366ec3263SLeandro Lupori! CHECK: %[[charLen:.*]] = fir.convert %[[undef]] : (index) -> i64 10466ec3263SLeandro Lupori! CHECK: %[[tuple:.*]] = fir.undefined tuple<!fir.boxproc<() -> ()>, i64> 10566ec3263SLeandro Lupori! CHECK: %[[tuple2:.*]] = fir.insert_value %[[tuple]], %[[boxProc]], [0 : index] : (tuple<!fir.boxproc<() -> ()>, i64>, !fir.boxproc<() -> ()>) -> tuple<!fir.boxproc<() -> ()>, i64> 10666ec3263SLeandro Lupori! CHECK: %[[tuple3:.*]] = fir.insert_value %[[tuple2]], %[[charLen]], [1 : index] : (tuple<!fir.boxproc<() -> ()>, i64>, i64) -> tuple<!fir.boxproc<() -> ()>, i64> 10766ec3263SLeandro Lupori! CHECK: fir.call @_QMoptPuse_char_proc(%[[tuple3]], %{{.*}}){{.*}} : (tuple<!fir.boxproc<() -> ()>, i64>, !fir.boxchar<1>) -> () 10866ec3263SLeandro Lupori call use_char_proc(c=c) 10966ec3263SLeandro Lupori! CHECK: %[[funcAddr:.*]] = fir.address_of(@_QMoptPchar_proc) : (!fir.ref<!fir.char<1,3>>, index, {{.*}}) -> !fir.boxchar<1> 11066ec3263SLeandro Lupori! CHECK: %[[c3:.*]] = arith.constant 3 : i64 11166ec3263SLeandro Lupori! CHECK: %[[boxProc2:.*]] = fir.emboxproc %[[funcAddr]] : ((!fir.ref<!fir.char<1,3>>, index, {{.*}}) -> !fir.boxchar<1>) -> !fir.boxproc<() -> ()> 11266ec3263SLeandro Lupori! CHECK: %[[tuple4:.*]] = fir.undefined tuple<!fir.boxproc<() -> ()>, i64> 11366ec3263SLeandro Lupori! CHECK: %[[tuple5:.*]] = fir.insert_value %[[tuple4]], %[[boxProc2]], [0 : index] : (tuple<!fir.boxproc<() -> ()>, i64>, !fir.boxproc<() -> ()>) -> tuple<!fir.boxproc<() -> ()>, i64> 11466ec3263SLeandro Lupori! CHECK: %[[tuple6:.*]] = fir.insert_value %[[tuple5]], %[[c3]], [1 : index] : (tuple<!fir.boxproc<() -> ()>, i64>, i64) -> tuple<!fir.boxproc<() -> ()>, i64> 11566ec3263SLeandro Lupori! CHECK: fir.call @_QMoptPuse_char_proc(%[[tuple6]], {{.*}}){{.*}} : (tuple<!fir.boxproc<() -> ()>, i64>, !fir.boxchar<1>) -> () 11666ec3263SLeandro Lupori call use_char_proc(char_proc, c) 11766ec3263SLeandro Luporiend subroutine 11866ec3263SLeandro Lupori 119baa42c16SValentin Clement! Test optional assumed shape 120baa42c16SValentin Clement! CHECK-LABEL: func @_QMoptPassumed_shape( 121baa42c16SValentin Clement! CHECK-SAME: %[[arg0:.*]]: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "x", fir.optional}) { 122baa42c16SValentin Clementsubroutine assumed_shape(x) 123baa42c16SValentin Clement real, optional :: x(:) 124baa42c16SValentin Clement ! CHECK: fir.is_present %[[arg0]] : (!fir.box<!fir.array<?xf32>>) -> i1 125baa42c16SValentin Clement print *, present(x) 126baa42c16SValentin Clementend subroutine 127baa42c16SValentin Clement! CHECK: func @_QMoptPcall_assumed_shape() 128baa42c16SValentin Clementsubroutine call_assumed_shape() 129baa42c16SValentin Clement ! CHECK: %[[addr:.*]] = fir.alloca !fir.array<100xf32> 130baa42c16SValentin Clement real :: x(100) 131baa42c16SValentin Clement ! CHECK: %[[embox:.*]] = fir.embox %[[addr]] 132baa42c16SValentin Clement ! CHECK: %[[x:.*]] = fir.convert %[[embox]] : (!fir.box<!fir.array<100xf32>>) -> !fir.box<!fir.array<?xf32>> 1334cc9437aSTom Eccles ! CHECK: fir.call @_QMoptPassumed_shape(%[[x]]) {{.*}}: (!fir.box<!fir.array<?xf32>>) -> () 134baa42c16SValentin Clement call assumed_shape(x) 135baa42c16SValentin Clement ! CHECK: %[[absent:.*]] = fir.absent !fir.box<!fir.array<?xf32>> 1364cc9437aSTom Eccles ! CHECK: fir.call @_QMoptPassumed_shape(%[[absent]]) {{.*}}: (!fir.box<!fir.array<?xf32>>) -> () 137baa42c16SValentin Clement call assumed_shape() 138baa42c16SValentin Clementend subroutine 139baa42c16SValentin Clement 140baa42c16SValentin Clement! Test optional allocatable 141baa42c16SValentin Clement! CHECK: func @_QMoptPallocatable_array( 142baa42c16SValentin Clement! CHECK-SAME: %[[arg0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> {fir.bindc_name = "x", fir.optional}) { 143baa42c16SValentin Clementsubroutine allocatable_array(x) 144baa42c16SValentin Clement real, allocatable, optional :: x(:) 145baa42c16SValentin Clement ! CHECK: fir.is_present %[[arg0]] : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) -> i1 146baa42c16SValentin Clement print *, present(x) 147baa42c16SValentin Clementend subroutine 148baa42c16SValentin Clement! CHECK: func @_QMoptPcall_allocatable_array() 149baa42c16SValentin Clementsubroutine call_allocatable_array() 150baa42c16SValentin Clement ! CHECK: %[[x:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<?xf32>>> 151baa42c16SValentin Clement real, allocatable :: x(:) 1524cc9437aSTom Eccles ! CHECK: fir.call @_QMoptPallocatable_array(%[[x]]) {{.*}}: (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) -> () 153baa42c16SValentin Clement call allocatable_array(x) 154baa42c16SValentin Clement ! CHECK: %[[absent:.*]] = fir.absent !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> 1554cc9437aSTom Eccles ! CHECK: fir.call @_QMoptPallocatable_array(%[[absent]]) {{.*}}: (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) -> () 156baa42c16SValentin Clement call allocatable_array() 157baa42c16SValentin Clementend subroutine 158baa42c16SValentin Clement 159baa42c16SValentin Clement! CHECK: func @_QMoptPallocatable_to_assumed_optional_array( 160baa42c16SValentin Clement! CHECK-SAME: %[[arg0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>{{.*}}) { 161baa42c16SValentin Clementsubroutine allocatable_to_assumed_optional_array(x) 162baa42c16SValentin Clement real, allocatable :: x(:) 163baa42c16SValentin Clement 164baa42c16SValentin Clement ! CHECK: %[[xboxload:.*]] = fir.load %[[arg0]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> 165baa42c16SValentin Clement ! CHECK: %[[xptr:.*]] = fir.box_addr %[[xboxload]] : (!fir.box<!fir.heap<!fir.array<?xf32>>>) -> !fir.heap<!fir.array<?xf32>> 166baa42c16SValentin Clement ! CHECK: %[[xaddr:.*]] = fir.convert %[[xptr]] : (!fir.heap<!fir.array<?xf32>>) -> i64 167baa42c16SValentin Clement ! CHECK: %[[isAlloc:.*]] = arith.cmpi ne, %[[xaddr]], %c0{{.*}} : i64 168baa42c16SValentin Clement ! CHECK: %[[absent:.*]] = fir.absent !fir.box<!fir.array<?xf32>> 169baa42c16SValentin Clement ! CHECK: %[[embox:.*]] = fir.embox %{{.*}} 170baa42c16SValentin Clement ! CHECK: %[[actual:.*]] = arith.select %[[isAlloc]], %[[embox]], %[[absent]] : !fir.box<!fir.array<?xf32>> 1714cc9437aSTom Eccles ! CHECK: fir.call @_QMoptPassumed_shape(%[[actual]]) {{.*}}: (!fir.box<!fir.array<?xf32>>) -> () 172baa42c16SValentin Clement call assumed_shape(x) 173baa42c16SValentin Clementend subroutine 174baa42c16SValentin Clement 175baa42c16SValentin Clement! CHECK-LABEL: func @_QMoptPalloc_component_to_optional_assumed_shape( 176baa42c16SValentin Clementsubroutine alloc_component_to_optional_assumed_shape(x) 177baa42c16SValentin Clement type(t) :: x(100) 178baa42c16SValentin Clement ! CHECK-DAG: %[[isAlloc:.*]] = arith.cmpi ne 179baa42c16SValentin Clement ! CHECK-DAG: %[[absent:.*]] = fir.absent !fir.box<!fir.array<?xf32>> 180baa42c16SValentin Clement ! CHECK: %[[select:.*]] = arith.select %[[isAlloc]], %{{.*}}, %[[absent]] : !fir.box<!fir.array<?xf32>> 181baa42c16SValentin Clement ! CHECK: fir.call @_QMoptPassumed_shape(%[[select]]) 182baa42c16SValentin Clement call assumed_shape(x(55)%p) 183baa42c16SValentin Clementend subroutine 184baa42c16SValentin Clement 185baa42c16SValentin Clement! CHECK-LABEL: func @_QMoptPalloc_component_eval_only_once( 186baa42c16SValentin Clementsubroutine alloc_component_eval_only_once(x) 187baa42c16SValentin Clement integer, external :: ifoo 188baa42c16SValentin Clement type(t) :: x(100) 189baa42c16SValentin Clement ! Verify that the index in the component reference are not evaluated twice 190baa42c16SValentin Clement ! because if the optional handling logic. 191baa42c16SValentin Clement ! CHECK: fir.call @_QPifoo() 192baa42c16SValentin Clement ! CHECK-NOT: fir.call @_QPifoo() 193baa42c16SValentin Clement call assumed_shape(x(ifoo())%p) 194baa42c16SValentin Clementend subroutine 195baa42c16SValentin Clement 196baa42c16SValentin Clement! CHECK-LABEL: func @_QMoptPnull_as_optional() { 197baa42c16SValentin Clementsubroutine null_as_optional 198cb3f1e2dSJean Perier ! CHECK: %[[null_ptr:.*]] = fir.alloca !fir.box<!fir.ptr<none>> 199cb3f1e2dSJean Perier ! CHECK: %[[null:.*]] = fir.zero_bits !fir.ptr<none> 200cb3f1e2dSJean Perier ! CHECK: %[[null_box:.*]] = fir.embox %[[null]] : (!fir.ptr<none>) -> !fir.box<!fir.ptr<none>> 201cb3f1e2dSJean Perier ! CHECK: fir.store %[[null_box]] to %[[null_ptr]] : !fir.ref<!fir.box<!fir.ptr<none>>> 2024cc9437aSTom Eccles ! CHECK: fir.call @_QMoptPassumed_shape(%{{.*}}) {{.*}}: (!fir.box<!fir.array<?xf32>>) -> () 203baa42c16SValentin Clement call assumed_shape(null()) 204baa42c16SValentin Clementend subroutine null_as_optional 205baa42c16SValentin Clement 206baa42c16SValentin Clementend module 207