Skip to content

Commit 4998587

Browse files
authored
[Flang] Support for passing procedure pointer, reference to a function that returns a procedure pointer to structure constructor. (#86533)
This PR fixes `not yet implemented: procedure pointer component in structure constructor` as shown in the following test case. ``` MODULE M TYPE :: DT PROCEDURE(Fun), POINTER, NOPASS :: pp1 END TYPE CONTAINS INTEGER FUNCTION Fun(Arg) INTEGER :: Arg Fun = Arg END FUNCTION END MODULE PROGRAM MAIN USE M IMPLICIT NONE TYPE (DT) :: v2 PROCEDURE(FUN), POINTER :: pp2 v2 = DT(pp2) v2 = DT(bar()) CONTAINS FUNCTION BAR() RESULT(res) PROCEDURE(FUN), POINTER :: res END END ```
1 parent 87519a2 commit 4998587

File tree

3 files changed

+46
-7
lines changed

3 files changed

+46
-7
lines changed

flang/lib/Lower/Bridge.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -3490,7 +3490,8 @@ class FirConverter : public Fortran::lower::AbstractConverter {
34903490
if (Fortran::evaluate::UnwrapExpr<Fortran::evaluate::NullPointer>(
34913491
assign.rhs)) {
34923492
// rhs is null(). rhs being null(pptr) is handled in genNull.
3493-
auto boxTy{Fortran::lower::getUntypedBoxProcType(&getMLIRContext())};
3493+
auto boxTy{
3494+
Fortran::lower::getUntypedBoxProcType(builder->getContext())};
34943495
hlfir::Entity rhs(
34953496
fir::factory::createNullBoxProc(*builder, loc, boxTy));
34963497
builder->createStoreWithConvert(loc, rhs, lhs);

flang/lib/Lower/ConvertExprToHLFIR.cpp

+18-3
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,8 @@ class HlfirDesignatorBuilder {
130130
// shape is deferred and should not be loaded now to preserve
131131
// pointer/allocatable aspects.
132132
if (componentSym.Rank() == 0 ||
133-
Fortran::semantics::IsAllocatableOrObjectPointer(&componentSym))
133+
Fortran::semantics::IsAllocatableOrObjectPointer(&componentSym) ||
134+
Fortran::semantics::IsProcedurePointer(&componentSym))
134135
return mlir::Value{};
135136

136137
fir::FirOpBuilder &builder = getBuilder();
@@ -1767,8 +1768,22 @@ class HlfirBuilder {
17671768

17681769
if (attrs && bitEnumContainsAny(attrs.getFlags(),
17691770
fir::FortranVariableFlagsEnum::pointer)) {
1770-
if (Fortran::semantics::IsProcedure(sym))
1771-
TODO(loc, "procedure pointer component in structure constructor");
1771+
if (Fortran::semantics::IsProcedure(sym)) {
1772+
// Procedure pointer components.
1773+
if (Fortran::evaluate::UnwrapExpr<Fortran::evaluate::NullPointer>(
1774+
expr)) {
1775+
auto boxTy{
1776+
Fortran::lower::getUntypedBoxProcType(builder.getContext())};
1777+
hlfir::Entity rhs(
1778+
fir::factory::createNullBoxProc(builder, loc, boxTy));
1779+
builder.createStoreWithConvert(loc, rhs, lhs);
1780+
continue;
1781+
}
1782+
hlfir::Entity rhs(getBase(Fortran::lower::convertExprToAddress(
1783+
loc, converter, expr, symMap, stmtCtx)));
1784+
builder.createStoreWithConvert(loc, rhs, lhs);
1785+
continue;
1786+
}
17721787
// Pointer component construction is just a copy of the box contents.
17731788
fir::ExtendedValue lhsExv =
17741789
hlfir::translateToExtendedValue(loc, builder, lhs);

flang/test/Lower/HLFIR/procedure-pointer-component-structure-constructor.f90

+26-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
! Test passing
22
! 1. NULL(),
33
! 2. procedure,
4-
! 3. procedure pointer, (pending)
5-
! 4. reference to a function that returns a procedure pointer (pending)
4+
! 3. procedure pointer,
5+
! 4. reference to a function that returns a procedure pointer.
66
! to a derived type structure constructor.
77
! RUN: bbc -emit-hlfir -o - %s | FileCheck %s
88

@@ -25,10 +25,33 @@ PROGRAM MAIN
2525
IMPLICIT NONE
2626
TYPE (DT), PARAMETER :: v1 = DT(NULL())
2727
TYPE (DT) :: v2
28+
PROCEDURE(FUN), POINTER :: pp2
2829
v2 = DT(fun)
30+
v2 = DT(pp2)
31+
v2 = DT(bar())
32+
CONTAINS
33+
FUNCTION BAR() RESULT(res)
34+
PROCEDURE(FUN), POINTER :: res
35+
END
2936
END
3037

31-
! CDHECK-LABEL: fir.global internal @_QFECv1 constant : !fir.type<_QMmTdt{pp1:!fir.boxproc<(!fir.ref<i32>) -> i32>}> {
38+
! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "main"} {
39+
! CHECK: %[[VAL_0:.*]] = fir.alloca !fir.type<_QMmTdt{pp1:!fir.boxproc<(!fir.ref<i32>) -> i32>}>
40+
! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.type<_QMmTdt{pp1:!fir.boxproc<(!fir.ref<i32>) -> i32>}>
41+
! CHECK: %[[VAL_2:.*]] = fir.alloca !fir.boxproc<(!fir.ref<i32>) -> i32> {bindc_name = "pp2", uniq_name = "_QFEpp2"}
42+
! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_2]] {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFEpp2"} : (!fir.ref<!fir.boxproc<(!fir.ref<i32>) -> i32>>) -> (!fir.ref<!fir.boxproc<(!fir.ref<i32>) -> i32>>, !fir.ref<!fir.boxproc<(!fir.ref<i32>) -> i32>>)
43+
! CHECK: %[[VAL_17:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "ctor.temp"} : (!fir.ref<!fir.type<_QMmTdt{pp1:!fir.boxproc<(!fir.ref<i32>) -> i32>}>>) -> (!fir.ref<!fir.type<_QMmTdt{pp1:!fir.boxproc<(!fir.ref<i32>) -> i32>}>>, !fir.ref<!fir.type<_QMmTdt{pp1:!fir.boxproc<(!fir.ref<i32>) -> i32>}>>)
44+
! CHECK: %[[VAL_23:.*]] = hlfir.designate %[[VAL_17]]#0{"pp1"} {fortran_attrs = #fir.var_attrs<pointer>} : (!fir.ref<!fir.type<_QMmTdt{pp1:!fir.boxproc<(!fir.ref<i32>) -> i32>}>>) -> !fir.ref<!fir.boxproc<(!fir.ref<i32>) -> i32>>
45+
! CHECK: %[[VAL_24:.*]] = fir.load %[[VAL_5]]#0 : !fir.ref<!fir.boxproc<(!fir.ref<i32>) -> i32>>
46+
! CHECK: fir.store %[[VAL_24]] to %[[VAL_23]] : !fir.ref<!fir.boxproc<(!fir.ref<i32>) -> i32>>
47+
! CHECK: %[[VAL_25:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "ctor.temp"} : (!fir.ref<!fir.type<_QMmTdt{pp1:!fir.boxproc<(!fir.ref<i32>) -> i32>}>>) -> (!fir.ref<!fir.type<_QMmTdt{pp1:!fir.boxproc<(!fir.ref<i32>) -> i32>}>>, !fir.ref<!fir.type<_QMmTdt{pp1:!fir.boxproc<(!fir.ref<i32>) -> i32>}>>)
48+
! CHECK: %[[VAL_31:.*]] = hlfir.designate %[[VAL_25]]#0{"pp1"} {fortran_attrs = #fir.var_attrs<pointer>} : (!fir.ref<!fir.type<_QMmTdt{pp1:!fir.boxproc<(!fir.ref<i32>) -> i32>}>>) -> !fir.ref<!fir.boxproc<(!fir.ref<i32>) -> i32>>
49+
! CHECK: %[[VAL_32:.*]] = fir.call @_QFPbar() fastmath<contract> : () -> !fir.boxproc<(!fir.ref<i32>) -> i32>
50+
! CHECK: fir.store %[[VAL_32]] to %[[VAL_31]] : !fir.ref<!fir.boxproc<(!fir.ref<i32>) -> i32>>
51+
! CHECK: return
52+
! CHECK: }
53+
54+
! CHECK-LABEL: fir.global internal @_QFECv1 constant : !fir.type<_QMmTdt{pp1:!fir.boxproc<(!fir.ref<i32>) -> i32>}> {
3255
! CHECK: %[[VAL_0:.*]] = fir.undefined !fir.type<_QMmTdt{pp1:!fir.boxproc<(!fir.ref<i32>) -> i32>}>
3356
! CHECK: %[[VAL_1:.*]] = fir.field_index pp1, !fir.type<_QMmTdt{pp1:!fir.boxproc<(!fir.ref<i32>) -> i32>}>
3457
! CHECK: %[[VAL_2:.*]] = fir.zero_bits (!fir.ref<i32>) -> i32

0 commit comments

Comments
 (0)