diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp --- a/flang/lib/Lower/Bridge.cpp +++ b/flang/lib/Lower/Bridge.cpp @@ -2854,13 +2854,20 @@ std::optional lhsType = assign.lhs.GetType(); assert(lhsType && "lhs cannot be typeless"); - - // Assignment to polymorphic allocatables may require changing the - // variable dynamic type (See Fortran 2018 10.2.1.3 p3). - if ((lhsType->IsPolymorphic() || - lhsType->IsUnlimitedPolymorphic()) && - Fortran::lower::isWholeAllocatable(assign.lhs)) { - mlir::Value lhs = genExprMutableBox(loc, assign.lhs).getAddr(); + std::optional rhsType = + assign.rhs.GetType(); + + // Assignment to/from polymorphic entities are done with the + // runtime. + if (lhsType->IsPolymorphic() || + lhsType->IsUnlimitedPolymorphic() || + rhsType->IsPolymorphic() || + rhsType->IsUnlimitedPolymorphic()) { + mlir::Value lhs; + if (Fortran::lower::isWholeAllocatable(assign.lhs)) + lhs = genExprMutableBox(loc, assign.lhs).getAddr(); + else + lhs = fir::getBase(genExprBox(loc, assign.lhs, stmtCtx)); mlir::Value rhs = fir::getBase(genExprBox(loc, assign.rhs, stmtCtx)); fir::runtime::genAssign(*builder, loc, lhs, rhs); diff --git a/flang/test/Lower/polymorphic.f90 b/flang/test/Lower/polymorphic.f90 --- a/flang/test/Lower/polymorphic.f90 +++ b/flang/test/Lower/polymorphic.f90 @@ -933,6 +933,24 @@ class(*), optional, intent(in) :: up end subroutine + function rhs() + class(p1), pointer :: rhs + end function + + subroutine test_rhs_assign(a) + type(p1) :: a + a = rhs() + end subroutine + +! CHECK-LABEL: func.func @_QMpolymorphic_testPtest_rhs_assign( +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref> {fir.bindc_name = "a"}) { +! CHECK: %[[RES:.*]] = fir.alloca !fir.class>> {bindc_name = ".result"} +! CHECK: %[[A:.*]] = fir.embox %[[ARG0]] : (!fir.ref>) -> !fir.box> +! CHECK: %[[LOAD_RES:.*]] = fir.load %[[RES]] : !fir.ref>>> +! CHECK: %[[A_NONE:.*]] = fir.convert %[[A]] : (!fir.box>) -> !fir.ref> +! CHECK: %[[RES_NONE:.*]] = fir.convert %[[LOAD_RES]] : (!fir.class>>) -> !fir.box +! CHECK: %{{.*}} = fir.call @_FortranAAssign(%[[A_NONE]], %[[RES_NONE]], %{{.*}}, %{{.*}}) {{.*}} : (!fir.ref>, !fir.box, !fir.ref, i32) -> none + end module program test