diff --git a/flang/include/flang/Optimizer/Dialect/FIROps.td b/flang/include/flang/Optimizer/Dialect/FIROps.td --- a/flang/include/flang/Optimizer/Dialect/FIROps.td +++ b/flang/include/flang/Optimizer/Dialect/FIROps.td @@ -824,12 +824,12 @@ }]; let arguments = (ins - fir_BoxType:$box, + BoxOrClassType:$box, Optional:$shape, Optional:$slice ); - let results = (outs fir_BoxType); + let results = (outs BoxOrClassType); let assemblyFormat = [{ $box (`(` $shape^ `)`)? (`[` $slice^ `]`)? attr-dict `:` functional-type(operands, results) 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 @@ -325,6 +325,11 @@ return create(loc, toTy, val); } + if (fir::isPolymorphicType(fromTy) && fir::isPolymorphicType(toTy)) { + return create(loc, toTy, val, mlir::Value{}, + /*slice=*/mlir::Value{}); + } + return createConvert(loc, toTy, val); } diff --git a/flang/test/Fir/invalid.fir b/flang/test/Fir/invalid.fir --- a/flang/test/Fir/invalid.fir +++ b/flang/test/Fir/invalid.fir @@ -20,7 +20,7 @@ func.func @bad_rebox_1(%arg0: !fir.ref>) { %c10 = arith.constant 10 : index %0 = fir.shape %c10 : (index) -> !fir.shape<1> - // expected-error@+1{{op operand #0 must be The type of a Fortran descriptor, but got '!fir.ref>'}} + // expected-error@+1{{op operand #0 must be box or class, but got '!fir.ref>'}} %1 = fir.rebox %arg0(%0) : (!fir.ref>, !fir.shape<1>) -> !fir.box> return } @@ -30,7 +30,7 @@ func.func @bad_rebox_2(%arg0: !fir.box>) { %c10 = arith.constant 10 : index %0 = fir.shape %c10 : (index) -> !fir.shape<1> - // expected-error@+1{{op result #0 must be The type of a Fortran descriptor, but got '!fir.ref>'}} + // expected-error@+1{{op result #0 must be box or class, but got '!fir.ref>'}} %1 = fir.rebox %arg0(%0) : (!fir.box>, !fir.shape<1>) -> !fir.ref> return } diff --git a/flang/test/Lower/dispatch.f90 b/flang/test/Lower/dispatch.f90 --- a/flang/test/Lower/dispatch.f90 +++ b/flang/test/Lower/dispatch.f90 @@ -130,6 +130,28 @@ ! CHECK: %{{.*}} = fir.dispatch "p1_fct3_arg0"(%[[P]] : !fir.class>) (%[[P]] : !fir.class>) -> f32 {pass_arg_pos = 0 : i32} ! CHECK: %{{.*}} = fir.dispatch "p1_fct4_arg1"(%[[P]] : !fir.class>) (%{{.*}}, %[[P]] : !fir.ref, !fir.class>) -> f32 {pass_arg_pos = 1 : i32} + subroutine check_dispatch_scalar_allocatable(p) + class(p1), allocatable :: p + call p%tbp_pass() + end subroutine + +! CHECK-LABEL: func.func @_QMcall_dispatchPcheck_dispatch_scalar_allocatable( +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref>>> {fir.bindc_name = "p"}) { +! CHECK: %[[LOAD:.*]] = fir.load %[[ARG0]] : !fir.ref>>> +! CHECK: %[[REBOX:.*]] = fir.rebox %[[LOAD]] : (!fir.class>>) -> !fir.class> +! CHECK: fir.dispatch "tbp_pass"(%[[REBOX]] : !fir.class>) (%1 : !fir.class>) {pass_arg_pos = 0 : i32} + + subroutine check_dispatch_scalar_pointer(p) + class(p1), pointer :: p + call p%tbp_pass() + end subroutine + +! CHECK-LABEL: func.func @_QMcall_dispatchPcheck_dispatch_scalar_pointer( +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref>>> {fir.bindc_name = "p"}) { +! CHECK: %[[LOAD:.*]] = fir.load %[[ARG0]] : !fir.ref>>> +! CHECK: %[[REBOX:.*]] = fir.rebox %[[LOAD]] : (!fir.class>>) -> !fir.class> +! CHECK: fir.dispatch "tbp_pass"(%[[REBOX]] : !fir.class>) (%1 : !fir.class>) {pass_arg_pos = 0 : i32} + ! ------------------------------------------------------------------------------ ! Test that direct call is emitted when the type is known ! ------------------------------------------------------------------------------