Skip to content

Commit 90e9fcb

Browse files
committed
[flang] Set declared type when NULLIFY a polymorphic pointer
Fortran standard 7.3.2.3 point 7 mentions that a diassociated pointer dynamic type is its declared type. in 9.7.2 note 1, when a NULLIFY statement is applied to a polymorphic pointer, its dynamic type becomes the same as its declared type. This patch enforce these standard points by calling the runtime function `PointerNullifyDerived` with the declared type descriptor. Reviewed By: jeanPerier Differential Revision: https://reviews.llvm.org/D136948
1 parent a2ab8fc commit 90e9fcb

File tree

7 files changed

+106
-3
lines changed

7 files changed

+106
-3
lines changed

flang/include/flang/Optimizer/Builder/MutableBox.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,8 @@ void associateMutableBoxWithRemap(fir::FirOpBuilder &builder,
7474
/// previously associated/allocated. The function generates code that sets the
7575
/// address field of the MutableBoxValue to zero.
7676
void disassociateMutableBox(fir::FirOpBuilder &builder, mlir::Location loc,
77-
const fir::MutableBoxValue &box);
77+
const fir::MutableBoxValue &box,
78+
bool polymorphicSetType = true);
7879

7980
/// Generate code to conditionally reallocate a MutableBoxValue with a new
8081
/// shape, lower bounds, and LEN parameters if it is unallocated or if its

flang/include/flang/Optimizer/Builder/Runtime/Derived.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ class Location;
1616

1717
namespace fir {
1818
class FirOpBuilder;
19+
class RecordType;
1920
}
2021

2122
namespace fir::runtime {
@@ -30,5 +31,11 @@ void genDerivedTypeInitialize(fir::FirOpBuilder &builder, mlir::Location loc,
3031
void genDerivedTypeDestroy(fir::FirOpBuilder &builder, mlir::Location loc,
3132
mlir::Value box);
3233

34+
/// Generate call to `PointerNullifyDerived` runtime function to nullify
35+
/// and set the correct dynamic type to a boxed derived type.
36+
void genNullifyDerivedType(fir::FirOpBuilder &builder, mlir::Location loc,
37+
mlir::Value box, fir::RecordType derivedType,
38+
unsigned rank = 0);
39+
3340
} // namespace fir::runtime
3441
#endif // FORTRAN_OPTIMIZER_BUILDER_RUNTIME_DERIVED_H

flang/lib/Lower/Allocatable.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -720,7 +720,8 @@ fir::MutableBoxValue Fortran::lower::createMutableBox(
720720
fir::MutableBoxValue box(boxAddr, nonDeferredParams, mutableProperties);
721721
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
722722
if (!var.isGlobal() && !Fortran::semantics::IsDummy(var.getSymbol()))
723-
fir::factory::disassociateMutableBox(builder, loc, box);
723+
fir::factory::disassociateMutableBox(builder, loc, box,
724+
/*polymorphicSetType=*/false);
724725
return box;
725726
}
726727

flang/lib/Lower/Bridge.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include "flang/Optimizer/Builder/Character.h"
3333
#include "flang/Optimizer/Builder/FIRBuilder.h"
3434
#include "flang/Optimizer/Builder/Runtime/Character.h"
35+
#include "flang/Optimizer/Builder/Runtime/Derived.h"
3536
#include "flang/Optimizer/Builder/Runtime/EnvironmentDefaults.h"
3637
#include "flang/Optimizer/Builder/Runtime/Ragged.h"
3738
#include "flang/Optimizer/Builder/Todo.h"

flang/lib/Optimizer/Builder/MutableBox.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -646,7 +646,18 @@ void fir::factory::associateMutableBoxWithRemap(
646646

647647
void fir::factory::disassociateMutableBox(fir::FirOpBuilder &builder,
648648
mlir::Location loc,
649-
const fir::MutableBoxValue &box) {
649+
const fir::MutableBoxValue &box,
650+
bool polymorphicSetType) {
651+
if (box.isPolymorphic() && polymorphicSetType) {
652+
// 7.3.2.3 point 7. The dynamic type of a disassociated pointer is the
653+
// same as its declared type.
654+
auto boxTy = box.getBoxTy().dyn_cast<fir::BaseBoxType>();
655+
auto eleTy = fir::dyn_cast_ptrOrBoxEleTy(boxTy.getEleTy());
656+
if (auto recTy = eleTy.dyn_cast<fir::RecordType>())
657+
fir::runtime::genNullifyDerivedType(builder, loc, box.getAddr(), recTy,
658+
box.rank());
659+
return;
660+
}
650661
MutablePropertyWriter{builder, loc, box}.setUnallocatedStatus();
651662
}
652663

flang/lib/Optimizer/Builder/Runtime/Derived.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@
99
#include "flang/Optimizer/Builder/Runtime/Derived.h"
1010
#include "flang/Optimizer/Builder/FIRBuilder.h"
1111
#include "flang/Optimizer/Builder/Runtime/RTBuilder.h"
12+
#include "flang/Optimizer/Support/FatalError.h"
13+
#include "flang/Optimizer/Support/InternalNames.h"
1214
#include "flang/Runtime/derived-api.h"
15+
#include "flang/Runtime/pointer.h"
1316

1417
using namespace Fortran::runtime;
1518

@@ -33,3 +36,29 @@ void fir::runtime::genDerivedTypeDestroy(fir::FirOpBuilder &builder,
3336
auto args = fir::runtime::createArguments(builder, loc, fTy, box);
3437
builder.create<fir::CallOp>(loc, func, args);
3538
}
39+
40+
void fir::runtime::genNullifyDerivedType(fir::FirOpBuilder &builder,
41+
mlir::Location loc, mlir::Value box,
42+
fir::RecordType derivedType,
43+
unsigned rank) {
44+
std::string typeDescName =
45+
fir::NameUniquer::getTypeDescriptorName(derivedType.getName());
46+
fir::GlobalOp typeDescGlobal = builder.getNamedGlobal(typeDescName);
47+
if (!typeDescGlobal)
48+
fir::emitFatalError(loc, "no type descriptor found for NULLIFY");
49+
auto typeDescAddr = builder.create<fir::AddrOfOp>(
50+
loc, fir::ReferenceType::get(typeDescGlobal.getType()),
51+
typeDescGlobal.getSymbol());
52+
mlir::func::FuncOp callee =
53+
fir::runtime::getRuntimeFunc<mkRTKey(PointerNullifyDerived)>(loc,
54+
builder);
55+
llvm::ArrayRef<mlir::Type> inputTypes = callee.getFunctionType().getInputs();
56+
llvm::SmallVector<mlir::Value> args;
57+
args.push_back(builder.createConvert(loc, inputTypes[0], box));
58+
args.push_back(builder.createConvert(loc, inputTypes[1], typeDescAddr));
59+
mlir::Value rankCst = builder.createIntegerConstant(loc, inputTypes[2], rank);
60+
mlir::Value c0 = builder.createIntegerConstant(loc, inputTypes[3], 0);
61+
args.push_back(rankCst);
62+
args.push_back(c0);
63+
builder.create<fir::CallOp>(loc, callee, args);
64+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
! RUN: bbc -polymorphic-type -emit-fir %s -o - | FileCheck %s
2+
3+
module poly
4+
type p1
5+
integer :: a
6+
integer :: b
7+
contains
8+
procedure, nopass :: proc1 => proc1_p1
9+
end type
10+
11+
type, extends(p1) :: p2
12+
integer :: c
13+
contains
14+
procedure, nopass :: proc1 => proc1_p2
15+
end type
16+
17+
contains
18+
19+
subroutine proc1_p1()
20+
print*, 'call proc1_p1'
21+
end subroutine
22+
23+
subroutine proc1_p2()
24+
print*, 'call proc1_p2'
25+
end subroutine
26+
27+
subroutine test_nullify()
28+
class(p1), pointer :: c
29+
30+
allocate(p2::c)
31+
call c%proc1()
32+
33+
nullify(c) ! c dynamic type must be reset to p1
34+
35+
call c%proc1()
36+
end subroutine
37+
end module
38+
39+
program test
40+
use poly
41+
call test_nullify()
42+
end
43+
44+
! CHECK-LABEL: func.func @_QMpolyPtest_nullify()
45+
! CHECK: %[[C_DESC:.*]] = fir.alloca !fir.class<!fir.ptr<!fir.type<_QMpolyTp1{a:i32,b:i32}>>> {bindc_name = "c", uniq_name = "_QMpolyFtest_nullifyEc"}
46+
! CHECK: %[[C_ADDR:.*]] = fir.alloca !fir.ptr<!fir.type<_QMpolyTp1{a:i32,b:i32}>> {uniq_name = "_QMpolyFtest_nullifyEc.addr"}
47+
! CHECK: %{{.*}} = fir.call @_FortranAPointerAllocate(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}) : (!fir.ref<!fir.box<none>>, i1, !fir.box<none>, !fir.ref<i8>, i32) -> i32
48+
! CHECK: %[[DECLARED_TYPE:.*]] = fir.address_of(@_QMpolyE.dt.p1) : !fir.ref<!fir.type<{{.*}}>>
49+
! CHECK: %[[C_DESC_CAST:.*]] = fir.convert %[[C_DESC]] : (!fir.ref<!fir.class<!fir.ptr<!fir.type<_QMpolyTp1{a:i32,b:i32}>>>>) -> !fir.ref<!fir.box<none>>
50+
! CHECK: %[[TYPE_DESC_CAST:.*]] = fir.convert %[[DECLARED_TYPE]] : (!fir.ref<!fir.type<{{.*}}>>) -> !fir.ref<none>
51+
! CHECK: %[[RANK:.*]] = arith.constant 0 : i32
52+
! CHECK: %[[CORANK:.*]] = arith.constant 0 : i32
53+
! CHECK: %{{.*}} = fir.call @_FortranAPointerNullifyDerived(%[[C_DESC_CAST]], %[[TYPE_DESC_CAST]], %[[RANK]], %[[CORANK]]) : (!fir.ref<!fir.box<none>>, !fir.ref<none>, i32, i32) -> none

0 commit comments

Comments
 (0)