@@ -727,12 +727,15 @@ class TypeInfo {
727727 // Is the type inside a box?
728728 bool isBox () const { return inBox; }
729729
730+ bool isBoxChar () const { return inBoxChar; }
731+
730732private:
731733 void typeScan (mlir::Type type);
732734
733735 std::optional<fir::CharacterType::LenType> charLen;
734736 llvm::SmallVector<int64_t > shape;
735737 bool inBox = false ;
738+ bool inBoxChar = false ;
736739};
737740
738741void TypeInfo::typeScan (mlir::Type ty) {
@@ -748,6 +751,9 @@ void TypeInfo::typeScan(mlir::Type ty) {
748751 typeScan (cty.getEleTy ());
749752 } else if (auto cty = mlir::dyn_cast<fir::CharacterType>(ty)) {
750753 charLen = cty.getLen ();
754+ } else if (auto cty = mlir::dyn_cast<fir::BoxCharType>(ty)) {
755+ inBoxChar = true ;
756+ typeScan (cty.getEleTy ());
751757 } else if (auto hty = mlir::dyn_cast<fir::HeapType>(ty)) {
752758 typeScan (hty.getEleTy ());
753759 } else if (auto pty = mlir::dyn_cast<fir::PointerType>(ty)) {
@@ -791,12 +797,6 @@ createCopyFunc(mlir::Location loc, lower::AbstractConverter &converter,
791797 fir::FortranVariableFlagsAttr attrs;
792798 if (varAttrs != fir::FortranVariableFlagsEnum::None)
793799 attrs = fir::FortranVariableFlagsAttr::get (builder.getContext (), varAttrs);
794- llvm::SmallVector<mlir::Value> typeparams;
795- if (typeInfo.getCharLength ().has_value ()) {
796- mlir::Value charLen = builder.createIntegerConstant (
797- loc, builder.getCharacterLengthType (), *typeInfo.getCharLength ());
798- typeparams.push_back (charLen);
799- }
800800 mlir::Value shape;
801801 if (!typeInfo.isBox () && !typeInfo.getShape ().empty ()) {
802802 llvm::SmallVector<mlir::Value> extents;
@@ -805,11 +805,34 @@ createCopyFunc(mlir::Location loc, lower::AbstractConverter &converter,
805805 builder.createIntegerConstant (loc, builder.getIndexType (), extent));
806806 shape = builder.create <fir::ShapeOp>(loc, extents);
807807 }
808+ mlir::Value dst = funcOp.getArgument (0 );
809+ mlir::Value src = funcOp.getArgument (1 );
810+ llvm::SmallVector<mlir::Value> typeparams;
811+ if (typeInfo.isBoxChar ()) {
812+ // fir.boxchar will be passed here as fir.ref<fir.boxchar>
813+ auto loadDst = builder.create <fir::LoadOp>(loc, dst);
814+ auto loadSrc = builder.create <fir::LoadOp>(loc, src);
815+ // get the actual fir.ref<fir.char> type
816+ mlir::Type refType =
817+ fir::ReferenceType::get (mlir::cast<fir::BoxCharType>(eleTy).getEleTy ());
818+ auto unboxedDst = builder.create <fir::UnboxCharOp>(
819+ loc, refType, builder.getIndexType (), loadDst);
820+ auto unboxedSrc = builder.create <fir::UnboxCharOp>(
821+ loc, refType, builder.getIndexType (), loadSrc);
822+ // Add length to type parameters
823+ typeparams.push_back (unboxedDst.getResult (1 ));
824+ dst = unboxedDst.getResult (0 );
825+ src = unboxedSrc.getResult (0 );
826+ } else if (typeInfo.getCharLength ().has_value ()) {
827+ mlir::Value charLen = builder.createIntegerConstant (
828+ loc, builder.getCharacterLengthType (), *typeInfo.getCharLength ());
829+ typeparams.push_back (charLen);
830+ }
808831 auto declDst = builder.create <hlfir::DeclareOp>(
809- loc, funcOp. getArgument ( 0 ) , copyFuncName + " _dst" , shape, typeparams,
832+ loc, dst , copyFuncName + " _dst" , shape, typeparams,
810833 /* dummy_scope=*/ nullptr , attrs);
811834 auto declSrc = builder.create <hlfir::DeclareOp>(
812- loc, funcOp. getArgument ( 1 ) , copyFuncName + " _src" , shape, typeparams,
835+ loc, src , copyFuncName + " _src" , shape, typeparams,
813836 /* dummy_scope=*/ nullptr , attrs);
814837 converter.copyVar (loc, declDst.getBase (), declSrc.getBase (), varAttrs);
815838 builder.create <mlir::func::ReturnOp>(loc);
@@ -835,10 +858,13 @@ bool ClauseProcessor::processCopyprivate(
835858
836859 // CopyPrivate variables must be passed by reference. However, in the case
837860 // of assumed shapes/vla the type is not a !fir.ref, but a !fir.box.
838- // In these cases to retrieve the appropriate !fir.ref<!fir.box<...>> to
839- // access the data we need we must perform an alloca and then store to it
840- // and retrieve the data from the new alloca.
841- if (mlir::isa<fir::BaseBoxType>(symType)) {
861+ // In the case of character types, the passed in type can also be
862+ // !fir.boxchar. In these cases to retrieve the appropriate
863+ // !fir.ref<!fir.box<...>> or !fir.ref<!fir.boxchar<..>> to access the data
864+ // we need we must perform an alloca and then store to it and retrieve the
865+ // data from the new alloca.
866+ if (mlir::isa<fir::BaseBoxType>(symType) ||
867+ mlir::isa<fir::BoxCharType>(symType)) {
842868 fir::FirOpBuilder &builder = converter.getFirOpBuilder ();
843869 auto alloca = builder.create <fir::AllocaOp>(currentLocation, symType);
844870 builder.create <fir::StoreOp>(currentLocation, symVal, alloca);
0 commit comments