Skip to content

Commit

Permalink
[flang][hlfir] Fixed NULL() handling in structure constructor.
Browse files Browse the repository at this point in the history
When an initializer value is missing for an allocatable component
in a structure constructor, the RHS is NULL() expression.
We should just skip this part of the initializer, since the component
must become unallocated (as it is from the initialization).
Runtime detected rank mismatch when we tried to pass NULL() box
RHS for assigning it to the unallocated component of rank 1, 2, etc.

Reviewed By: tblah

Differential Revision: https://reviews.llvm.org/D154906
  • Loading branch information
vzakhari committed Jul 11, 2023
1 parent 5c42807 commit 07593a3
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 1 deletion.
10 changes: 9 additions & 1 deletion flang/lib/Lower/ConvertExprToHLFIR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1748,14 +1748,22 @@ class HlfirBuilder {
attrs &&
bitEnumContainsAny(attrs.getFlags(),
fir::FortranVariableFlagsEnum::allocatable);
hlfir::Entity rhs = gen(expr);
// If the component is allocatable, then we have to check
// whether the RHS value is allocatable or not.
// If it is not allocatable, then AssignOp can be used directly.
// If it is allocatable, then using AssignOp for unallocated RHS
// will cause illegal dereference. When an unallocated allocatable
// value is used to construct an allocatable component, the component
// must just stay unallocated.

// If the component is allocatable and RHS is NULL() expression, then
// we can just skip it: the LHS must remain unallocated with its
// defined rank.
if (allowRealloc &&
Fortran::evaluate::UnwrapExpr<Fortran::evaluate::NullPointer>(expr))
continue;

hlfir::Entity rhs = gen(expr);
if (!allowRealloc || !rhs.isMutableBox()) {
rhs = hlfir::loadTrivialScalar(loc, builder, rhs);
builder.create<hlfir::AssignOp>(loc, rhs, lhs, allowRealloc,
Expand Down
41 changes: 41 additions & 0 deletions flang/test/Lower/HLFIR/structure-constructor.f90
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ module types
type, extends(t5) :: t6
type(t1) :: t6m(1)
end type t6
type t7
integer :: c1
real, allocatable :: c2(:)
end type t7
end module types

subroutine test1(x)
Expand Down Expand Up @@ -299,3 +303,40 @@ end subroutine test6
! CHECK: hlfir.destroy %[[VAL_72]] : !hlfir.expr<1x!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>
! CHECK: return
! CHECK: }

! Test that NULL() expression passed as the component "value"
! for the missing component initializer in the structure constructor
! is handled properly: the component is just left unallocated with its
! defined rank and there is no hlfir.assign for this part
! of the constructor.
subroutine test7(n)
use types
integer, intent(in) :: n
type(t7) :: x
x = t7(n)
end subroutine test7
! CHECK-LABEL: func.func @_QPtest7(
! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<i32> {fir.bindc_name = "n"}) {
! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.type<_QMtypesTt7{c1:i32,c2:!fir.box<!fir.heap<!fir.array<?xf32>>>}>
! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QFtest7En"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
! CHECK: %[[VAL_3:.*]] = fir.alloca !fir.type<_QMtypesTt7{c1:i32,c2:!fir.box<!fir.heap<!fir.array<?xf32>>>}> {bindc_name = "x", uniq_name = "_QFtest7Ex"}
! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFtest7Ex"} : (!fir.ref<!fir.type<_QMtypesTt7{c1:i32,c2:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>) -> (!fir.ref<!fir.type<_QMtypesTt7{c1:i32,c2:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>, !fir.ref<!fir.type<_QMtypesTt7{c1:i32,c2:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>)
! CHECK: %[[VAL_5:.*]] = fir.embox %[[VAL_4]]#1 : (!fir.ref<!fir.type<_QMtypesTt7{c1:i32,c2:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>) -> !fir.box<!fir.type<_QMtypesTt7{c1:i32,c2:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>
! CHECK: %[[VAL_6:.*]] = fir.address_of(@_QQcl.{{.*}}) : !fir.ref<!fir.char<1,{{[0-9]*}}>>
! CHECK: %[[VAL_7:.*]] = arith.constant {{[0-9]*}} : i32
! CHECK: %[[VAL_8:.*]] = fir.convert %[[VAL_5]] : (!fir.box<!fir.type<_QMtypesTt7{c1:i32,c2:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>) -> !fir.box<none>
! CHECK: %[[VAL_9:.*]] = fir.convert %[[VAL_6]] : (!fir.ref<!fir.char<1,{{[0-9]*}}>>) -> !fir.ref<i8>
! CHECK: %[[VAL_10:.*]] = fir.call @_FortranAInitialize(%[[VAL_8]], %[[VAL_9]], %[[VAL_7]]) fastmath<contract> : (!fir.box<none>, !fir.ref<i8>, i32) -> none
! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "ctor.temp"} : (!fir.ref<!fir.type<_QMtypesTt7{c1:i32,c2:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>) -> (!fir.ref<!fir.type<_QMtypesTt7{c1:i32,c2:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>, !fir.ref<!fir.type<_QMtypesTt7{c1:i32,c2:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>)
! CHECK: %[[VAL_12:.*]] = fir.embox %[[VAL_11]]#0 : (!fir.ref<!fir.type<_QMtypesTt7{c1:i32,c2:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>) -> !fir.box<!fir.type<_QMtypesTt7{c1:i32,c2:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>
! CHECK: %[[VAL_13:.*]] = fir.address_of(@_QQcl.{{.*}}) : !fir.ref<!fir.char<1,{{[0-9]*}}>>
! CHECK: %[[VAL_14:.*]] = arith.constant {{[0-9]*}} : i32
! CHECK: %[[VAL_15:.*]] = fir.convert %[[VAL_12]] : (!fir.box<!fir.type<_QMtypesTt7{c1:i32,c2:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>) -> !fir.box<none>
! CHECK: %[[VAL_16:.*]] = fir.convert %[[VAL_13]] : (!fir.ref<!fir.char<1,{{[0-9]*}}>>) -> !fir.ref<i8>
! CHECK: %[[VAL_17:.*]] = fir.call @_FortranAInitialize(%[[VAL_15]], %[[VAL_16]], %[[VAL_14]]) fastmath<contract> : (!fir.box<none>, !fir.ref<i8>, i32) -> none
! CHECK: %[[VAL_18:.*]] = hlfir.designate %[[VAL_11]]#0{"c1"} : (!fir.ref<!fir.type<_QMtypesTt7{c1:i32,c2:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>) -> !fir.ref<i32>
! CHECK: %[[VAL_19:.*]] = fir.load %[[VAL_2]]#0 : !fir.ref<i32>
! CHECK: hlfir.assign %[[VAL_19]] to %[[VAL_18]] temporary_lhs : i32, !fir.ref<i32>
! CHECK: hlfir.assign %[[VAL_11]]#0 to %[[VAL_4]]#0 : !fir.ref<!fir.type<_QMtypesTt7{c1:i32,c2:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>, !fir.ref<!fir.type<_QMtypesTt7{c1:i32,c2:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>
! CHECK: return
! CHECK: }

0 comments on commit 07593a3

Please sign in to comment.