Skip to content

Commit 52e2397

Browse files
committed
[flang] Add AllocatableInit functions for use in allocate lowering
`AllocatableInitIntrinsic`, `AllocatableInitCharacter` and `AllocatableInitDerived` are meant to be used to initialize a descriptor when it is instantiated and not to be used multiple times in a scope. Add `AllocatableInitDerivedForAllocate`, `AllocatableInitCharacterForAllocate` and `AllocatableInitDerivedForAllocate` to be used for the allocation in allocate statement. These new functions are meant to be used on an initialized descriptor and will return directly if the descriptor is allocated so the error handling is done by the call to `AllocatableAllocate`. Reviewed By: PeteSteinfeld Differential Revision: https://reviews.llvm.org/D146290
1 parent 257f4fd commit 52e2397

File tree

3 files changed

+52
-0
lines changed

3 files changed

+52
-0
lines changed

flang/include/flang/Runtime/allocatable.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,17 @@ void RTNAME(AllocatableInitCharacter)(Descriptor &, SubscriptValue length = 0,
3333
void RTNAME(AllocatableInitDerived)(
3434
Descriptor &, const typeInfo::DerivedType &, int rank = 0, int corank = 0);
3535

36+
// Initializes the descriptor for an allocatable of intrinsic or derived type.
37+
// These functions are meant to be used in the allocate statement lowering. If
38+
// the descriptor is allocated, the initialization is skiped so the error
39+
// handling can be done by AllocatableAllocate.
40+
void RTNAME(AllocatableInitIntrinsicForAllocate)(
41+
Descriptor &, TypeCategory, int kind, int rank = 0, int corank = 0);
42+
void RTNAME(AllocatableInitCharacterForAllocate)(Descriptor &,
43+
SubscriptValue length = 0, int kind = 1, int rank = 0, int corank = 0);
44+
void RTNAME(AllocatableInitDerivedForAllocate)(
45+
Descriptor &, const typeInfo::DerivedType &, int rank = 0, int corank = 0);
46+
3647
// Checks that an allocatable is not already allocated in statements
3748
// with STAT=. Use this on a value descriptor before setting bounds or
3849
// type parameters. Not necessary on a freshly initialized descriptor.

flang/runtime/allocatable.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,30 @@ void RTNAME(AllocatableInitDerived)(Descriptor &descriptor,
4141
derivedType, nullptr, rank, nullptr, CFI_attribute_allocatable);
4242
}
4343

44+
void RTNAME(AllocatableInitIntrinsicForAllocate)(Descriptor &descriptor,
45+
TypeCategory category, int kind, int rank, int corank) {
46+
if (descriptor.IsAllocated()) {
47+
return;
48+
}
49+
RTNAME(AllocatableInitIntrinsic)(descriptor, category, kind, rank, corank);
50+
}
51+
52+
void RTNAME(AllocatableInitCharacterForAllocate)(Descriptor &descriptor,
53+
SubscriptValue length, int kind, int rank, int corank) {
54+
if (descriptor.IsAllocated()) {
55+
return;
56+
}
57+
RTNAME(AllocatableInitCharacter)(descriptor, length, kind, rank, corank);
58+
}
59+
60+
void RTNAME(AllocatableInitDerivedForAllocate)(Descriptor &descriptor,
61+
const typeInfo::DerivedType &derivedType, int rank, int corank) {
62+
if (descriptor.IsAllocated()) {
63+
return;
64+
}
65+
RTNAME(AllocatableInitDerived)(descriptor, derivedType, rank, corank);
66+
}
67+
4468
std::int32_t RTNAME(MoveAlloc)(Descriptor &to, Descriptor &from,
4569
const typeInfo::DerivedType *derivedType, bool hasStat,
4670
const Descriptor *errMsg, const char *sourceFile, int sourceLine) {

flang/unittests/Runtime/Allocatable.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,3 +94,20 @@ TEST(AllocatableTest, AllocateFromScalarSource) {
9494
EXPECT_EQ(*a->OffsetElement<float>(), 3.4F);
9595
a->Destroy();
9696
}
97+
98+
TEST(AllocatableTest, DoubleAllocation) {
99+
// CLASS(*), ALLOCATABLE :: r
100+
// ALLOCATE(REAL::r)
101+
auto r{createAllocatable(TypeCategory::Real, 4, 0)};
102+
EXPECT_FALSE(r->IsAllocated());
103+
EXPECT_TRUE(r->IsAllocatable());
104+
RTNAME(AllocatableAllocate)(*r);
105+
EXPECT_TRUE(r->IsAllocated());
106+
107+
// Make sure AllocatableInitIntrinsicForAllocate doesn't reset the decsriptor
108+
// if it is allocated.
109+
// ALLOCATE(INTEGER::r)
110+
RTNAME(AllocatableInitIntrinsicForAllocate)
111+
(*r, Fortran::common::TypeCategory::Integer, 4);
112+
EXPECT_TRUE(r->IsAllocated());
113+
}

0 commit comments

Comments
 (0)