/// Return true iff `ty` is the type of an ALLOCATABLE entity or value.
bool isAllocatableType(mlir::Type ty);
+/// Return true iff `ty` is !fir.box<none>.
+bool isBoxNone(mlir::Type ty);
+
/// Return true iff `ty` is the type of a boxed record type.
/// e.g. !fir.box<!fir.type<derived>>
bool isBoxedRecordType(mlir::Type ty);
/// has the dummy attributes in BIND(C) contexts.
mlir::Value box = builder.createBox(
loc, fir::factory::genMutableBoxRead(builder, loc, mutableBox));
+
+ // NULL() passed as argument is passed as a !fir.box<none>. Since
+ // select op requires the same type for its two argument, convert
+ // !fir.box<none> to !fir.class<none> when the argument is
+ // polymorphic.
+ if (fir::isBoxNone(box.getType()) && fir::isPolymorphicType(argTy))
+ box = builder.createConvert(
+ loc,
+ fir::ClassType::get(mlir::NoneType::get(builder.getContext())),
+ box);
+
// Need the box types to be exactly similar for the selectOp.
mlir::Value convertedBox = builder.createConvert(loc, argTy, box);
caller.placeInput(arg, builder.create<mlir::arith::SelectOp>(
return false;
}
+bool isBoxNone(mlir::Type ty) {
+ if (auto box = ty.dyn_cast<fir::BoxType>())
+ return box.getEleTy().isa<mlir::NoneType>();
+ return false;
+}
+
bool isBoxedRecordType(mlir::Type ty) {
if (auto refTy = fir::dyn_cast_ptrEleTy(ty))
ty = refTy;
! CHECK: %[[REBOX:.*]] = fir.rebox %[[LOAD_P]](%{{.*}}) : (!fir.class<!fir.heap<!fir.array<?x?xnone>>>, !fir.shift<2>) -> !fir.box<!fir.ptr<!fir.array<?x?x!fir.type<_QMpolymorphic_testTnon_extensible{d:i32}>>>>
! CHECK: fir.store %[[REBOX]] to %[[T]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?x?x!fir.type<_QMpolymorphic_testTnon_extensible{d:i32}>>>>>
+ subroutine sub_with_poly_optional(a)
+ class(*), optional :: a
+ end subroutine
+
+ subroutine test_call_with_null()
+ call sub_with_poly_optional(null())
+ end subroutine
+
+! CHECK-LABEL: func.func @_QMpolymorphic_testPtest_call_with_null() {
+! CHECK: %[[NULL_LLVM_PTR:.*]] = fir.alloca !fir.llvm_ptr<none>
+! CHECK: %[[NULL_BOX_NONE:.*]] = fir.convert %[[NULL_LLVM_PTR]] : (!fir.ref<!fir.llvm_ptr<none>>) -> !fir.ref<!fir.box<none>>
+! CHECK: %[[BOX_NONE:.*]] = fir.load %[[NULL_BOX_NONE]] : !fir.ref<!fir.box<none>>
+! CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[BOX_NONE]] : (!fir.box<none>) -> !fir.ref<none>
+! CHECK: %[[BOX_ADDR_I64:.*]] = fir.convert %[[BOX_ADDR]] : (!fir.ref<none>) -> i64
+! CHECK: %[[C0:.*]] = arith.constant 0 : i64
+! CHECK: %[[IS_ALLOCATED_OR_ASSOCIATED:.*]] = arith.cmpi ne, %[[BOX_ADDR_I64]], %[[C0]] : i64
+! CHECK: %[[ABSENT:.*]] = fir.absent !fir.class<none>
+! CHECK: %[[BOX_NONE:.*]] = fir.load %[[NULL_BOX_NONE]] : !fir.ref<!fir.box<none>>
+! CHECK: %[[CLASS_NONE:.*]] = fir.convert %[[BOX_NONE]] : (!fir.box<none>) -> !fir.class<none>
+! CHECK: %[[ARG:.*]] = arith.select %[[IS_ALLOCATED_OR_ASSOCIATED]], %[[CLASS_NONE]], %[[ABSENT]] : !fir.class<none>
+! CHECK: fir.call @_QMpolymorphic_testPsub_with_poly_optional(%[[ARG]]) {{.*}} : (!fir.class<none>) -> ()
+
end module
program test