Index: flang/lib/Lower/ConvertCall.cpp =================================================================== --- flang/lib/Lower/ConvertCall.cpp +++ flang/lib/Lower/ConvertCall.cpp @@ -1593,6 +1593,30 @@ } assert(shape && "elemental array calls must have at least one array arguments"); + + // Evaluate the actual argument array expressions before the elemental + // call of an impure subprogram or a subprogram with intent(out) or + // intent(inout) arguments. Note that the scalar arguments are handled + // above. + if (mustBeOrdered) { + for (unsigned i = 0; i < numArgs; ++i) { + auto &preparedActual = loweredActuals[i]; + if (preparedActual) { + hlfir::Entity actual = preparedActual->getOriginalActual(); + if (!actual.isVariable() && actual.isArray()) { + mlir::Type storageType = actual.getType(); + hlfir::AssociateOp associate = hlfir::genAssociateExpr( + loc, builder, actual, storageType, "adapt.impure_arg_eval"); + preparedActual->setOriginalActual(hlfir::Entity{associate}); + + fir::FirOpBuilder *bldr = &builder; + callContext.stmtCtx.attachCleanup( + [=]() { bldr->create(loc, associate); }); + } + } + } + } + // Push a new local scope so that any temps made inside the elemental // iterations are cleaned up inside the iterations. if (!callContext.resultType) { Index: flang/test/Lower/HLFIR/elemental-user-procedure-ref.f90 =================================================================== --- flang/test/Lower/HLFIR/elemental-user-procedure-ref.f90 +++ flang/test/Lower/HLFIR/elemental-user-procedure-ref.f90 @@ -146,3 +146,38 @@ ! CHECK: } ! CHECK: return ! CHECK: } + +subroutine impure_elemental_arg_eval(x) + real :: x(10, 20) + interface + impure elemental subroutine impure_elem(a) + real, intent(in) :: a + end subroutine + end interface + call impure_elem((x)) +end subroutine +! CHECK-LABEL: func.func @_QPimpure_elemental_arg_eval( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref> {fir.bindc_name = "x"}) { +! CHECK: %[[VAL_1:.*]] = arith.constant 10 : index +! CHECK: %[[VAL_2:.*]] = arith.constant 20 : index +! CHECK: %[[VAL_3:.*]] = fir.shape %[[VAL_1]], %[[VAL_2]] : (index, index) -> !fir.shape<2> +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_3]]) {uniq_name = "_QFimpure_elemental_arg_evalEx"} : (!fir.ref>, !fir.shape<2>) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[VAL_5:.*]] = hlfir.elemental %[[VAL_3]] unordered : (!fir.shape<2>) -> !hlfir.expr<10x20xf32> { +! CHECK: ^bb0(%[[VAL_6:.*]]: index, %[[VAL_7:.*]]: index): +! CHECK: %[[VAL_8:.*]] = hlfir.designate %[[VAL_4]]#0 (%[[VAL_6]], %[[VAL_7]]) : (!fir.ref>, index, index) -> !fir.ref +! CHECK: %[[VAL_9:.*]] = fir.load %[[VAL_8]] : !fir.ref +! CHECK: %[[VAL_10:.*]] = hlfir.no_reassoc %[[VAL_9]] : f32 +! CHECK: hlfir.yield_element %[[VAL_10]] : f32 +! CHECK: } +! CHECK: %[[VAL_11:.*]]:3 = hlfir.associate %[[VAL_12:.*]](%[[VAL_3]]) {uniq_name = "adapt.impure_arg_eval"} : (!hlfir.expr<10x20xf32>, !fir.shape<2>) -> (!fir.ref>, !fir.ref>, i1) +! CHECK: %[[VAL_13:.*]] = arith.constant 1 : index +! CHECK: fir.do_loop %[[VAL_14:.*]] = %[[VAL_13]] to %[[VAL_2]] step %[[VAL_13]] { +! CHECK: fir.do_loop %[[VAL_15:.*]] = %[[VAL_13]] to %[[VAL_1]] step %[[VAL_13]] { +! CHECK: %[[VAL_16:.*]] = hlfir.designate %[[VAL_11]]#0 (%[[VAL_15]], %[[VAL_14]]) : (!fir.ref>, index, index) -> !fir.ref +! CHECK: fir.call @_QPimpure_elem(%[[VAL_16]]) fastmath : (!fir.ref) -> () +! CHECK: } +! CHECK: } +! CHECK: hlfir.end_associate %[[VAL_11]]#1, %[[VAL_11]]#2 : !fir.ref>, i1 +! CHECK: hlfir.destroy %[[VAL_12]] : !hlfir.expr<10x20xf32> +! CHECK: return +! CHECK: }