diff --git a/flang/lib/Lower/Allocatable.cpp b/flang/lib/Lower/Allocatable.cpp --- a/flang/lib/Lower/Allocatable.cpp +++ b/flang/lib/Lower/Allocatable.cpp @@ -566,11 +566,11 @@ if (alloc.type.IsPolymorphic()) { assert(sourceExpr->GetType() && "null type not expected"); if (alloc.type.IsUnlimitedPolymorphic() && - sourceExpr->GetType()->IsUnlimitedPolymorphic()) - TODO(loc, "allocate unlimited polymorphic entity from unlimited " - "polymorphic source"); - - if (sourceExpr->GetType()->category() == TypeCategory::Derived) { + sourceExpr->GetType()->IsUnlimitedPolymorphic()) { + // Use ApplyMold for unlimited polymorphic allocation from unlimited + // polymorphic source. + genRuntimeAllocateApplyMold(builder, loc, box, sourceExv); + } else if (sourceExpr->GetType()->category() == TypeCategory::Derived) { mlir::Type tdescType = fir::TypeDescType::get(mlir::NoneType::get(builder.getContext())); mlir::Value typeDescAddr = builder.create( diff --git a/flang/test/Lower/allocatable-polymorphic.f90 b/flang/test/Lower/allocatable-polymorphic.f90 --- a/flang/test/Lower/allocatable-polymorphic.f90 +++ b/flang/test/Lower/allocatable-polymorphic.f90 @@ -492,6 +492,22 @@ ! CHECK: %[[CORANK:.*]] = arith.constant 0 : i32 ! CHECK: %{{.*}} = fir.call @_FortranAPointerNullifyIntrinsic(%[[UP_BOX_NONE]], %[[CAT]], %[[KIND]], %[[RANK]], %[[CORANK]]) {{.*}} : (!fir.ref>, i32, i32, i32, i32) -> none + subroutine test_allocatable_up_from_up_mold(a, b) + class(*), allocatable :: a + class(*), pointer :: b + allocate(a, source = b) + end subroutine + +! CHECK-LABEL: func.func @_QMpolyPtest_allocatable_up_from_up_mold( +! CHECK-SAME: %[[A:.*]]: !fir.ref>> {fir.bindc_name = "a"}, %[[B:.*]]: !fir.ref>> {fir.bindc_name = "b"}) { +! CHECK: %[[LOAD_B:.*]] = fir.load %[[B]] : !fir.ref>> +! CHECK: %[[A_BOX_NONE:.*]] = fir.convert %[[A]] : (!fir.ref>>) -> !fir.ref> +! CHECK: %[[B_BOX_NONE:.*]] = fir.convert %[[LOAD_B]] : (!fir.class>) -> !fir.box +! CHECK: %{{.*}} = fir.call @_FortranAAllocatableApplyMold(%[[A_BOX_NONE]], %[[B_BOX_NONE]]) {{.*}} : (!fir.ref>, !fir.box) -> none +! CHECK: %[[A_BOX_NONE:.*]] = fir.convert %[[A]] : (!fir.ref>>) -> !fir.ref> +! CHECK: %[[B_BOX_NONE:.*]] = fir.convert %[[LOAD_B]] : (!fir.class>) -> !fir.box +! CHECK: %{{.*}} = fir.call @_FortranAAllocatableAllocateSource(%[[A_BOX_NONE]], %[[B_BOX_NONE]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}) {{.*}} : (!fir.ref>, !fir.box, i1, !fir.box, !fir.ref, i32) -> i32 + end module