/// e.g. !fir.box<!fir.type<derived>>
bool isBoxedRecordType(mlir::Type ty);
+/// Return the nested RecordType if one if found. Return ty otherwise.
+mlir::Type getDerivedType(mlir::Type ty);
+
/// Return true iff `ty` is the type of an polymorphic entity or
/// value.
bool isPolymorphicType(mlir::Type ty);
// same as its declared type.
auto boxTy = box.getBoxTy().dyn_cast<fir::BaseBoxType>();
auto eleTy = fir::dyn_cast_ptrOrBoxEleTy(boxTy.getEleTy());
- if (auto recTy = eleTy.dyn_cast<fir::RecordType>())
+ mlir::Type derivedType = fir::getDerivedType(eleTy);
+ if (auto recTy = derivedType.dyn_cast<fir::RecordType>())
fir::runtime::genNullifyDerivedType(builder, loc, box.getAddr(), recTy,
box.rank());
return;
return emitError(loc) << "no binding tables found";
// Get derived type information.
- auto declaredType =
- llvm::TypeSwitch<mlir::Type, mlir::Type>(
- dispatch.getObject().getType().getEleTy())
- .Case<fir::PointerType, fir::HeapType, fir::SequenceType>(
- [](auto p) {
- if (auto seq =
- p.getEleTy().template dyn_cast<fir::SequenceType>())
- return seq.getEleTy();
- return p.getEleTy();
- })
- .Default([](mlir::Type t) { return t; });
+ mlir::Type declaredType =
+ fir::getDerivedType(dispatch.getObject().getType().getEleTy());
assert(declaredType.isa<fir::RecordType>() && "expecting fir.type");
auto recordType = declaredType.dyn_cast<fir::RecordType>();
return isa_fir_type(t) || isa_std_type(t);
}
+mlir::Type getDerivedType(mlir::Type ty) {
+ return llvm::TypeSwitch<mlir::Type, mlir::Type>(ty)
+ .Case<fir::PointerType, fir::HeapType, fir::SequenceType>([](auto p) {
+ if (auto seq = p.getEleTy().template dyn_cast<fir::SequenceType>())
+ return seq.getEleTy();
+ return p.getEleTy();
+ })
+ .Default([](mlir::Type t) { return t; });
+}
+
mlir::Type dyn_cast_ptrEleTy(mlir::Type t) {
return llvm::TypeSwitch<mlir::Type, mlir::Type>(t)
.Case<fir::ReferenceType, fir::PointerType, fir::HeapType,
! CHECK: %[[CONVERT:.*]] = fir.convert %3 : (!fir.ref<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>>) -> !fir.ptr<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>>
! CHECK: fir.store %[[CONVERT]] to %[[PTR]] : !fir.ref<!fir.ptr<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>>>
+ subroutine nullify_pointer_array(a)
+ type(p3) :: a
+ nullify(a%p)
+ end subroutine
+
+! CHECK-LABEL: func.func @_QMpolymorphic_testPnullify_pointer_array(
+! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.type<_QMpolymorphic_testTp3{p:!fir.class<!fir.ptr<!fir.array<?x!fir.type<_QMpolymorphic_testTp3>>>>}>> {fir.bindc_name = "a"}) {
+! CHECK: %[[FIELD_P:.*]] = fir.field_index p, !fir.type<_QMpolymorphic_testTp3{p:!fir.class<!fir.ptr<!fir.array<?x!fir.type<_QMpolymorphic_testTp3>>>>}>
+! CHECK: %[[COORD_P:.*]] = fir.coordinate_of %[[ARG0]], %[[FIELD_P]] : (!fir.ref<!fir.type<_QMpolymorphic_testTp3{p:!fir.class<!fir.ptr<!fir.array<?x!fir.type<_QMpolymorphic_testTp3>>>>}>>, !fir.field) -> !fir.ref<!fir.class<!fir.ptr<!fir.array<?x!fir.type<_QMpolymorphic_testTp3{p:!fir.class<!fir.ptr<!fir.array<?x!fir.type<_QMpolymorphic_testTp3>>>>}>>>>>
+! CHECK: %[[TYPE_DESC_ADDR:.*]] = fir.address_of(@_QMpolymorphic_testE.dt.p3) : !fir.ref<!fir.type<{{.*}}>>
+! CHECK: %[[CONV_P:.*]] = fir.convert %[[COORD_P]] : (!fir.ref<!fir.class<!fir.ptr<!fir.array<?x!fir.type<_QMpolymorphic_testTp3{p:!fir.class<!fir.ptr<!fir.array<?x!fir.type<_QMpolymorphic_testTp3>>>>}>>>>>) -> !fir.ref<!fir.box<none>>
+! CHECK: %[[CONV_TDESC:.*]] = fir.convert %[[TYPE_DESC_ADDR]] : (!fir.ref<!fir.type<{{.*}}>>) -> !fir.ref<none>
+! CHECK: %[[C1:.*]] = arith.constant 1 : i32
+! CHECK: %[[C0:.*]] = arith.constant 0 : i32
+! CHECK: %{{.*}} = fir.call @_FortranAPointerNullifyDerived(%[[CONV_P]], %[[CONV_TDESC]], %[[C1]], %[[C0]]) {{.*}} : (!fir.ref<!fir.box<none>>, !fir.ref<none>, i32, i32) -> none
+
end module