@@ -494,10 +494,20 @@ Fortran::lower::genCallOpAndResult(
494494 // arguments of any type and vice versa.
495495 mlir::Value cast;
496496 auto *context = builder.getContext ();
497- if (mlir::isa<fir::BoxProcType>(snd) &&
498- mlir::isa<mlir::FunctionType>(fst.getType ())) {
499- auto funcTy = mlir::FunctionType::get (context, {}, {});
500- auto boxProcTy = builder.getBoxProcType (funcTy);
497+
498+ // Special handling for %VAL arguments: internal procedures expect
499+ // reference parameters. When %VAL is used, the argument should be
500+ // passed by value. So we need to create a temporary variable and
501+ // pass its address to avoid a type conversion error.
502+ if (fir::isa_ref_type (snd) && !fir::isa_ref_type (fst.getType ()) &&
503+ fir::dyn_cast_ptrEleTy (snd) == fst.getType ()) {
504+ mlir::Value temp = builder.createTemporary (loc, fst.getType ());
505+ builder.create <fir::StoreOp>(loc, fst, temp);
506+ cast = temp;
507+ } else if (mlir::isa<fir::BoxProcType>(snd) &&
508+ mlir::isa<mlir::FunctionType>(fst.getType ())) {
509+ mlir::FunctionType funcTy = mlir::FunctionType::get (context, {}, {});
510+ fir::BoxProcType boxProcTy = builder.getBoxProcType (funcTy);
501511 if (mlir::Value host = argumentHostAssocs (converter, fst)) {
502512 cast = fir::EmboxProcOp::create (builder, loc, boxProcTy,
503513 llvm::ArrayRef<mlir::Value>{fst, host});
@@ -1637,7 +1647,20 @@ void prepareUserCallArguments(
16371647 (*cleanup)();
16381648 break ;
16391649 }
1640- caller.placeInput (arg, builder.createConvert (loc, argTy, value));
1650+ // For %VAL arguments, we should pass the value directly without
1651+ // conversion to reference types. If argTy is different from value type,
1652+ // it might be due to signature mismatch with internal procedures.
1653+ if (argTy == value.getType ())
1654+ caller.placeInput (arg, value);
1655+ else if (fir::isa_ref_type (argTy) &&
1656+ fir::dyn_cast_ptrEleTy (argTy) == value.getType ()) {
1657+ // We're trying to convert value to reference - create temporary
1658+ mlir::Value temp = builder.createTemporary (loc, value.getType ());
1659+ builder.create <fir::StoreOp>(loc, value, temp);
1660+ caller.placeInput (arg, temp);
1661+ } else
1662+ caller.placeInput (arg, builder.createConvert (loc, argTy, value));
1663+
16411664 } break ;
16421665 case PassBy::BaseAddressValueAttribute:
16431666 case PassBy::CharBoxValueAttribute:
0 commit comments