xref: /llvm-project/flang/test/Lower/dummy-argument-optional.f90 (revision f35f863a88f83332bef9605ef4cfe4f05c066efb)
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