Index: flang/lib/Lower/ConvertExpr.cpp =================================================================== --- flang/lib/Lower/ConvertExpr.cpp +++ flang/lib/Lower/ConvertExpr.cpp @@ -3367,7 +3367,13 @@ semant = ConstituentSemantics::RefTransparent; ExtValue exv = lowerArrayExpression(rhs); if (explicitSpaceIsActive()) { - explicitSpace->finalizeContext(); + if constexpr (std::is_same_v) { + if (rhs.Rank() > 0) + explicitSpace->finalizeContext(); + } else if constexpr (std::is_same_v) { + if (rhs.rank() > 0) + explicitSpace->finalizeContext(); + } builder.create(loc, fir::getBase(exv)); } else { builder.create( @@ -3483,7 +3489,8 @@ assert(destination && "destination must have been set"); ExtValue exv = lowerArrayExpression(rhsCC, resultTy); if (explicitSpaceIsActive()) { - explicitSpace->finalizeContext(); + if (rhs.Rank() > 0) + explicitSpace->finalizeContext(); builder.create(loc, fir::getBase(exv)); } else { builder.create( @@ -3668,7 +3675,8 @@ semant = ConstituentSemantics::RefTransparent; auto exv = lowerArrayExpression(rhs); if (explicitSpaceIsActive()) { - explicitSpace->finalizeContext(); + if (rhs.Rank() > 0) + explicitSpace->finalizeContext(); builder.create(loc, fir::getBase(exv)); } else { builder.create( @@ -3979,6 +3987,8 @@ : defaultStoreToDestination(/*substring=*/nullptr); mlir::Value updVal = fir::getBase(lambda(iterSpace)); finalizeElementCtx(); + if (explicitSpaceIsActive() && !resultTy.isa()) + explicitSpace->finalizeContext(); builder.create(loc, updVal); builder.restoreInsertionPoint(insPt); return abstractArrayExtValue(iterSpace.outerResult()); Index: flang/test/Lower/forall/forall-3.f90 =================================================================== --- /dev/null +++ flang/test/Lower/forall/forall-3.f90 @@ -0,0 +1,66 @@ +! Test forall lowering for explicit space finalization + +! RUN: bbc -emit-fir %s -o - | FileCheck %s + +! CHECK-LABEL: func @_QPforall_scalar_to_array_section +! CHECK: %{{.*}} = fir.do_loop +! CHECK: %[[VAL_0:.*]] = fir.do_loop +! CHECK: %[[VAL_1:.*]] = fir.allocmem !fir.array<1xi32> +! CHECK: %[[VAL_2:.*]] = fir.if %{{.*}} -> (!fir.heap>) { +! CHECK: %[[VAL_3:.*]] = fir.convert %[[VAL_1]] : (!fir.heap>) -> !fir.ref +! CHECK: %[[VAL_4:.*]] = fir.call @realloc(%[[VAL_3]], %{{.*}}) : (!fir.ref, i64) -> !fir.ref +! CHECK: %[[VAL_5:.*]] = fir.convert %[[VAL_4]] : (!fir.ref) -> !fir.heap> +! CHECK: fir.result %[[VAL_5]] : !fir.heap> +! CHECK: } else { +! CHECK: fir.result %[[VAL_1:.*]] : !fir.heap> +! CHECK: } +! CHECK: %[[VAL_6:.*]] = fir.allocmem !fir.array<1xi32> +! CHECK: fir.freemem %[[VAL_6]] : !fir.heap> +! CHECK: fir.freemem %[[VAL_2]] : !fir.heap> +! CHECK: fir.result %{{.*}} : !fir.array<6xi32> +! CHECK: } +! CHECK: fir.result %[[VAL_0]] : !fir.array<6xi32> +! CHECK: } +subroutine forall_scalar_to_array_section() + integer :: arr(6), i + forall (i=1:6) + arr(i:i+1) = func((/i/)) + end forall + +contains + pure function func(a) result(res) + integer, intent(in) :: a(:) + integer :: res + res = a(1) + end function +end subroutine + +! CHECK-LABEL: func @_QPforall_array_to_array_section +! CHECK: %{{.*}} = fir.do_loop +! CHECK: %[[VAL_0:.*]] = fir.allocmem !fir.array<1xi32> +! CHECK: %[[VAL_1:.*]] = fir.if %{{.*}} -> (!fir.heap>) { +! CHECK: %[[VAL_2:.*]] = fir.convert %[[VAL_0]] : (!fir.heap>) -> !fir.ref +! CHECK: %[[VAL_3:.*]] = fir.call @realloc(%[[VAL_2]], %{{.*}}) : (!fir.ref, i64) -> !fir.ref +! CHECK: %[[VAL_4:.*]] = fir.convert %[[VAL_3]] : (!fir.ref) -> !fir.heap> +! CHECK: fir.result %[[VAL_4]] : !fir.heap> +! CHECK: } else { +! CHECK: fir.result %[[VAL_0]] : !fir.heap> +! CHECK: } +! CHECK: %[[VAL_5:.*]] = fir.allocmem !fir.array<1xi32> +! CHECK: fir.freemem %[[VAL_5]] : !fir.heap> +! CHECK: fir.freemem %[[VAL_1]] : !fir.heap> +! CHECK: fir.result %{{.*}} : !fir.array<6xi32> +! CHECK: } +subroutine forall_array_to_array_section() + integer :: arr(6), i + forall (i=1:6) + arr(i:i+1) = func((/i/)) + end forall + +contains + pure function func(a) result(res) + integer, intent(in) :: a(:) + integer :: res(2) + res = a(1) + end function +end subroutine