diff --git a/flang/lib/Lower/ConvertExpr.cpp b/flang/lib/Lower/ConvertExpr.cpp --- a/flang/lib/Lower/ConvertExpr.cpp +++ b/flang/lib/Lower/ConvertExpr.cpp @@ -416,7 +416,8 @@ if (fir::unwrapRefType(fir::getBase(p).getType()) .isa()) return p; - return builder.create(loc, fir::getBase(p)); + mlir::Value load = builder.create(loc, fir::getBase(p)); + return fir::PolymorphicValue(load, p.getSourceBox()); }, [&](const fir::UnboxedValue &v) -> fir::ExtendedValue { if (fir::unwrapRefType(fir::getBase(v).getType()) @@ -429,9 +430,6 @@ fir::factory::genMutableBoxRead(builder, loc, box)); }, [&](const fir::BoxValue &box) -> fir::ExtendedValue { - if (box.isUnlimitedPolymorphic()) - fir::emitFatalError( - loc, "attempting to load an unlimited polymorphic entity"); return genLoad(builder, loc, fir::factory::readBoxValue(builder, loc, box)); }, diff --git a/flang/lib/Optimizer/Builder/FIRBuilder.cpp b/flang/lib/Optimizer/Builder/FIRBuilder.cpp --- a/flang/lib/Optimizer/Builder/FIRBuilder.cpp +++ b/flang/lib/Optimizer/Builder/FIRBuilder.cpp @@ -816,7 +816,7 @@ fir::ExtendedValue fir::factory::readBoxValue(fir::FirOpBuilder &builder, mlir::Location loc, const fir::BoxValue &box) { - assert(!box.isUnlimitedPolymorphic() && !box.hasAssumedRank() && + assert(!box.hasAssumedRank() && "cannot read unlimited polymorphic or assumed rank fir.box"); auto addr = builder.create(loc, box.getMemTy(), box.getAddr()); @@ -830,10 +830,15 @@ } if (box.isDerivedWithLenParameters()) TODO(loc, "read fir.box with length parameters"); + mlir::Value sourceBox; + if (box.isPolymorphic()) + sourceBox = box.getAddr(); + if (box.isPolymorphic() && box.rank() == 0) + return fir::PolymorphicValue(addr, sourceBox); if (box.rank() == 0) return addr; return fir::ArrayBoxValue(addr, fir::factory::readExtents(builder, loc, box), - box.getLBounds()); + box.getLBounds(), sourceBox); } llvm::SmallVector 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 @@ -53,6 +53,10 @@ class(p1), allocatable :: a(:) end type + type :: p5 + class(*), allocatable :: up + end type + contains elemental subroutine assign_p1_int(lhs, rhs) @@ -1138,6 +1142,28 @@ ! CHECK-SAME: %[[B:.*]]: !fir.class>> {fir.bindc_name = "b"}) { ! CHECK: %[[A:.*]] = fir.alloca !fir.class>>> + subroutine pass_up(up) + class(*), intent(in) :: up + end subroutine + + subroutine parenthesized_up(a) + type(p5) :: a + call pass_up((a%up)) + end subroutine + +! CHECK-LABEL: func.func @_QMpolymorphic_testPparenthesized_up( +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref>}>> {fir.bindc_name = "a"}) { +! CHECK: %[[ALLOCA:.*]] = fir.alloca +! CHECK: %[[FIELD_UP:.*]] = fir.field_index up, !fir.type<_QMpolymorphic_testTp5{up:!fir.class>}> +! CHECK: %[[COORD:.*]] = fir.coordinate_of %[[ARG0]], %[[FIELD_UP]] : (!fir.ref>}>>, !fir.field) -> !fir.ref>> +! CHECK: %[[LOAD:.*]] = fir.load %[[COORD]] : !fir.ref>> +! CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[LOAD]] : (!fir.class>) -> !fir.heap +! CHECK: %[[LOAD_ADDR:.*]] = fir.load %[[BOX_ADDR]] : !fir.heap +! CHECK: %[[NO_REASSOC:.*]] = fir.no_reassoc %[[LOAD_ADDR]] : none +! CHECK: fir.store %[[NO_REASSOC]] to %[[ALLOCA]] : !fir.ref +! CHECK: %[[EMBOX:.*]] = fir.embox %[[ALLOCA]] source_box %[[LOAD]] : (!fir.ref, !fir.class>) -> !fir.class +! CHECK: fir.call @_QMpolymorphic_testPpass_up(%[[EMBOX]]) fastmath : (!fir.class) -> () + end module program test