diff --git a/flang/lib/Lower/ConvertExprToHLFIR.cpp b/flang/lib/Lower/ConvertExprToHLFIR.cpp index 29e85231a61d5..5f8b8ec1cafdb 100644 --- a/flang/lib/Lower/ConvertExprToHLFIR.cpp +++ b/flang/lib/Lower/ConvertExprToHLFIR.cpp @@ -1748,7 +1748,6 @@ 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. @@ -1756,6 +1755,15 @@ class HlfirBuilder { // 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(expr)) + continue; + + hlfir::Entity rhs = gen(expr); if (!allowRealloc || !rhs.isMutableBox()) { rhs = hlfir::loadTrivialScalar(loc, builder, rhs); builder.create(loc, rhs, lhs, allowRealloc, diff --git a/flang/test/Lower/HLFIR/structure-constructor.f90 b/flang/test/Lower/HLFIR/structure-constructor.f90 index 3c8699543ee6c..356b8a75ac86a 100644 --- a/flang/test/Lower/HLFIR/structure-constructor.f90 +++ b/flang/test/Lower/HLFIR/structure-constructor.f90 @@ -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) @@ -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 {fir.bindc_name = "n"}) { +! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.type<_QMtypesTt7{c1:i32,c2:!fir.box>>}> +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] {fortran_attrs = #fir.var_attrs, uniq_name = "_QFtest7En"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_3:.*]] = fir.alloca !fir.type<_QMtypesTt7{c1:i32,c2:!fir.box>>}> {bindc_name = "x", uniq_name = "_QFtest7Ex"} +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFtest7Ex"} : (!fir.ref>>}>>) -> (!fir.ref>>}>>, !fir.ref>>}>>) +! CHECK: %[[VAL_5:.*]] = fir.embox %[[VAL_4]]#1 : (!fir.ref>>}>>) -> !fir.box>>}>> +! CHECK: %[[VAL_6:.*]] = fir.address_of(@_QQcl.{{.*}}) : !fir.ref> +! CHECK: %[[VAL_7:.*]] = arith.constant {{[0-9]*}} : i32 +! CHECK: %[[VAL_8:.*]] = fir.convert %[[VAL_5]] : (!fir.box>>}>>) -> !fir.box +! CHECK: %[[VAL_9:.*]] = fir.convert %[[VAL_6]] : (!fir.ref>) -> !fir.ref +! CHECK: %[[VAL_10:.*]] = fir.call @_FortranAInitialize(%[[VAL_8]], %[[VAL_9]], %[[VAL_7]]) fastmath : (!fir.box, !fir.ref, i32) -> none +! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "ctor.temp"} : (!fir.ref>>}>>) -> (!fir.ref>>}>>, !fir.ref>>}>>) +! CHECK: %[[VAL_12:.*]] = fir.embox %[[VAL_11]]#0 : (!fir.ref>>}>>) -> !fir.box>>}>> +! CHECK: %[[VAL_13:.*]] = fir.address_of(@_QQcl.{{.*}}) : !fir.ref> +! CHECK: %[[VAL_14:.*]] = arith.constant {{[0-9]*}} : i32 +! CHECK: %[[VAL_15:.*]] = fir.convert %[[VAL_12]] : (!fir.box>>}>>) -> !fir.box +! CHECK: %[[VAL_16:.*]] = fir.convert %[[VAL_13]] : (!fir.ref>) -> !fir.ref +! CHECK: %[[VAL_17:.*]] = fir.call @_FortranAInitialize(%[[VAL_15]], %[[VAL_16]], %[[VAL_14]]) fastmath : (!fir.box, !fir.ref, i32) -> none +! CHECK: %[[VAL_18:.*]] = hlfir.designate %[[VAL_11]]#0{"c1"} : (!fir.ref>>}>>) -> !fir.ref +! CHECK: %[[VAL_19:.*]] = fir.load %[[VAL_2]]#0 : !fir.ref +! CHECK: hlfir.assign %[[VAL_19]] to %[[VAL_18]] temporary_lhs : i32, !fir.ref +! CHECK: hlfir.assign %[[VAL_11]]#0 to %[[VAL_4]]#0 : !fir.ref>>}>>, !fir.ref>>}>> +! CHECK: return +! CHECK: }