diff --git a/flang/include/flang/Optimizer/Dialect/FIRType.h b/flang/include/flang/Optimizer/Dialect/FIRType.h index b4f9528f6e6a1..6820e9b15ea30 100644 --- a/flang/include/flang/Optimizer/Dialect/FIRType.h +++ b/flang/include/flang/Optimizer/Dialect/FIRType.h @@ -276,6 +276,9 @@ bool isPointerType(mlir::Type ty); /// 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. +bool isBoxNone(mlir::Type ty); + /// Return true iff `ty` is the type of a boxed record type. /// e.g. !fir.box> bool isBoxedRecordType(mlir::Type ty); diff --git a/flang/lib/Lower/ConvertExpr.cpp b/flang/lib/Lower/ConvertExpr.cpp index e852e8b007f29..d64b28cf7873d 100644 --- a/flang/lib/Lower/ConvertExpr.cpp +++ b/flang/lib/Lower/ConvertExpr.cpp @@ -2704,6 +2704,17 @@ class ScalarExprLowering { /// 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. Since + // select op requires the same type for its two argument, convert + // !fir.box to !fir.class 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( diff --git a/flang/lib/Optimizer/Dialect/FIRType.cpp b/flang/lib/Optimizer/Dialect/FIRType.cpp index 8c73fc24741f6..dac0e6557538f 100644 --- a/flang/lib/Optimizer/Dialect/FIRType.cpp +++ b/flang/lib/Optimizer/Dialect/FIRType.cpp @@ -272,6 +272,12 @@ bool isAllocatableType(mlir::Type ty) { return false; } +bool isBoxNone(mlir::Type ty) { + if (auto box = ty.dyn_cast()) + return box.getEleTy().isa(); + return false; +} + bool isBoxedRecordType(mlir::Type ty) { if (auto refTy = fir::dyn_cast_ptrEleTy(ty)) ty = refTy; diff --git a/flang/test/Lower/polymorphic.f90 b/flang/test/Lower/polymorphic.f90 index da843a2ca59ac..ac6ae85bfdf23 100644 --- a/flang/test/Lower/polymorphic.f90 +++ b/flang/test/Lower/polymorphic.f90 @@ -767,6 +767,28 @@ subroutine rebox_up_to_record_type(p) ! CHECK: %[[REBOX:.*]] = fir.rebox %[[LOAD_P]](%{{.*}}) : (!fir.class>>, !fir.shift<2>) -> !fir.box>>> ! CHECK: fir.store %[[REBOX]] to %[[T]] : !fir.ref>>>> + 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 +! CHECK: %[[NULL_BOX_NONE:.*]] = fir.convert %[[NULL_LLVM_PTR]] : (!fir.ref>) -> !fir.ref> +! CHECK: %[[BOX_NONE:.*]] = fir.load %[[NULL_BOX_NONE]] : !fir.ref> +! CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[BOX_NONE]] : (!fir.box) -> !fir.ref +! CHECK: %[[BOX_ADDR_I64:.*]] = fir.convert %[[BOX_ADDR]] : (!fir.ref) -> 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 +! CHECK: %[[BOX_NONE:.*]] = fir.load %[[NULL_BOX_NONE]] : !fir.ref> +! CHECK: %[[CLASS_NONE:.*]] = fir.convert %[[BOX_NONE]] : (!fir.box) -> !fir.class +! CHECK: %[[ARG:.*]] = arith.select %[[IS_ALLOCATED_OR_ASSOCIATED]], %[[CLASS_NONE]], %[[ABSENT]] : !fir.class +! CHECK: fir.call @_QMpolymorphic_testPsub_with_poly_optional(%[[ARG]]) {{.*}} : (!fir.class) -> () + end module program test