@@ -912,37 +912,16 @@ static PreparedDummyArgument preparePresentUserCallActualArgument(
912912 // element if this is an array in an elemental call.
913913 hlfir::Entity actual = preparedActual.getActual (loc, builder);
914914
915- // Handle the procedure pointer actual arguments.
916- if (actual.isProcedurePointer ()) {
917- // Procedure pointer actual to procedure pointer dummy.
918- if (fir::isBoxProcAddressType (dummyType))
919- return PreparedDummyArgument{actual, /* cleanups=*/ {}};
915+ // Handle procedure arguments (procedure pointers should go through
916+ // prepareProcedurePointerActualArgument).
917+ if (hlfir::isFortranProcedureValue (dummyType)) {
920918 // Procedure pointer actual to procedure dummy.
921- if (hlfir::isFortranProcedureValue (dummyType )) {
919+ if (actual. isProcedurePointer ( )) {
922920 actual = hlfir::derefPointersAndAllocatables (loc, builder, actual);
923921 return PreparedDummyArgument{actual, /* cleanups=*/ {}};
924922 }
925- }
926-
927- // NULL() actual to procedure pointer dummy
928- if (Fortran::evaluate::IsNullProcedurePointer (expr) &&
929- fir::isBoxProcAddressType (dummyType)) {
930- auto boxTy{Fortran::lower::getUntypedBoxProcType (builder.getContext ())};
931- auto tempBoxProc{builder.createTemporary (loc, boxTy)};
932- hlfir::Entity nullBoxProc (
933- fir::factory::createNullBoxProc (builder, loc, boxTy));
934- builder.create <fir::StoreOp>(loc, nullBoxProc, tempBoxProc);
935- return PreparedDummyArgument{tempBoxProc, /* cleanups=*/ {}};
936- }
937-
938- if (actual.isProcedure ()) {
939- // Procedure actual to procedure pointer dummy.
940- if (fir::isBoxProcAddressType (dummyType)) {
941- auto tempBoxProc{builder.createTemporary (loc, actual.getType ())};
942- builder.create <fir::StoreOp>(loc, actual, tempBoxProc);
943- return PreparedDummyArgument{tempBoxProc, /* cleanups=*/ {}};
944- }
945923 // Procedure actual to procedure dummy.
924+ assert (actual.isProcedure ());
946925 // Do nothing if this is a procedure argument. It is already a
947926 // fir.boxproc/fir.tuple<fir.boxproc, len> as it should.
948927 if (actual.getType () != dummyType)
@@ -1219,6 +1198,34 @@ static PreparedDummyArgument prepareUserCallActualArgument(
12191198 return result;
12201199}
12211200
1201+ // / Prepare actual argument for a procedure pointer dummy.
1202+ static PreparedDummyArgument prepareProcedurePointerActualArgument (
1203+ mlir::Location loc, fir::FirOpBuilder &builder,
1204+ const Fortran::lower::PreparedActualArgument &preparedActual,
1205+ mlir::Type dummyType,
1206+ const Fortran::lower::CallerInterface::PassedEntity &arg,
1207+ const Fortran::lower::SomeExpr &expr, CallContext &callContext) {
1208+
1209+ // NULL() actual to procedure pointer dummy
1210+ if (Fortran::evaluate::UnwrapExpr<Fortran::evaluate::NullPointer>(expr) &&
1211+ fir::isBoxProcAddressType (dummyType)) {
1212+ auto boxTy{Fortran::lower::getUntypedBoxProcType (builder.getContext ())};
1213+ auto tempBoxProc{builder.createTemporary (loc, boxTy)};
1214+ hlfir::Entity nullBoxProc (
1215+ fir::factory::createNullBoxProc (builder, loc, boxTy));
1216+ builder.create <fir::StoreOp>(loc, nullBoxProc, tempBoxProc);
1217+ return PreparedDummyArgument{tempBoxProc, /* cleanups=*/ {}};
1218+ }
1219+ hlfir::Entity actual = preparedActual.getActual (loc, builder);
1220+ if (actual.isProcedurePointer ())
1221+ return PreparedDummyArgument{actual, /* cleanups=*/ {}};
1222+ assert (actual.isProcedure ());
1223+ // Procedure actual to procedure pointer dummy.
1224+ auto tempBoxProc{builder.createTemporary (loc, actual.getType ())};
1225+ builder.create <fir::StoreOp>(loc, actual, tempBoxProc);
1226+ return PreparedDummyArgument{tempBoxProc, /* cleanups=*/ {}};
1227+ }
1228+
12221229// / Lower calls to user procedures with actual arguments that have been
12231230// / pre-lowered but not yet prepared according to the interface.
12241231// / This can be called for elemental procedures, but only with scalar
@@ -1284,14 +1291,21 @@ genUserCall(Fortran::lower::PreparedActualArguments &loweredActuals,
12841291 case PassBy::CharBoxValueAttribute:
12851292 case PassBy::Box:
12861293 case PassBy::BaseAddress:
1287- case PassBy::BoxProcRef:
12881294 case PassBy::BoxChar: {
12891295 PreparedDummyArgument preparedDummy = prepareUserCallActualArgument (
12901296 loc, builder, *preparedActual, argTy, arg, *expr, callContext);
12911297 callCleanUps.append (preparedDummy.cleanups .rbegin (),
12921298 preparedDummy.cleanups .rend ());
12931299 caller.placeInput (arg, preparedDummy.dummy );
12941300 } break ;
1301+ case PassBy::BoxProcRef: {
1302+ PreparedDummyArgument preparedDummy =
1303+ prepareProcedurePointerActualArgument (loc, builder, *preparedActual,
1304+ argTy, arg, *expr, callContext);
1305+ callCleanUps.append (preparedDummy.cleanups .rbegin (),
1306+ preparedDummy.cleanups .rend ());
1307+ caller.placeInput (arg, preparedDummy.dummy );
1308+ } break ;
12951309 case PassBy::AddressAndLength:
12961310 // PassBy::AddressAndLength is only used for character results. Results
12971311 // are not handled here.
0 commit comments