#include "flang/Runtime/allocatable.h"
#include "derived.h"
#include "stat.h"
#include "terminator.h"
#include "type-info.h"
#include "flang/Runtime/assign.h"
namespace Fortran::runtime {
extern "C" {
void RTNAME(AllocatableInitIntrinsic)(Descriptor &descriptor,
TypeCategory category, int kind, int rank, int corank) {
INTERNAL_CHECK(corank == 0);
descriptor.Establish(TypeCode{category, kind},
Descriptor::BytesFor(category, kind), nullptr, rank, nullptr,
CFI_attribute_allocatable);
}
void RTNAME(AllocatableInitCharacter)(Descriptor &descriptor,
SubscriptValue length, int kind, int rank, int corank) {
INTERNAL_CHECK(corank == 0);
descriptor.Establish(
kind, length, nullptr, rank, nullptr, CFI_attribute_allocatable);
}
void RTNAME(AllocatableInitDerived)(Descriptor &descriptor,
const typeInfo::DerivedType &derivedType, int rank, int corank) {
INTERNAL_CHECK(corank == 0);
descriptor.Establish(
derivedType, nullptr, rank, nullptr, CFI_attribute_allocatable);
}
int RTNAME(MoveAlloc)(Descriptor &to, const Descriptor & ,
bool , const Descriptor * ,
const char * , int ) {
INTERNAL_CHECK(false);
return StatOk;
}
void RTNAME(AllocatableSetBounds)(Descriptor &descriptor, int zeroBasedDim,
SubscriptValue lower, SubscriptValue upper) {
INTERNAL_CHECK(zeroBasedDim >= 0 && zeroBasedDim < descriptor.rank());
descriptor.GetDimension(zeroBasedDim).SetBounds(lower, upper);
}
void RTNAME(AllocatableSetDerivedLength)(
Descriptor &descriptor, int which, SubscriptValue x) {
DescriptorAddendum *addendum{descriptor.Addendum()};
INTERNAL_CHECK(addendum != nullptr);
addendum->SetLenParameterValue(which, x);
}
void RTNAME(AllocatableApplyMold)(
Descriptor &descriptor, const Descriptor &mold) {
descriptor = mold;
descriptor.set_base_addr(nullptr);
descriptor.raw().attribute = CFI_attribute_allocatable;
}
int RTNAME(AllocatableAllocate)(Descriptor &descriptor, bool hasStat,
const Descriptor *errMsg, const char *sourceFile, int sourceLine) {
Terminator terminator{sourceFile, sourceLine};
if (!descriptor.IsAllocatable()) {
return ReturnError(terminator, StatInvalidDescriptor, errMsg, hasStat);
}
if (descriptor.IsAllocated()) {
return ReturnError(terminator, StatBaseNotNull, errMsg, hasStat);
}
int stat{ReturnError(terminator, descriptor.Allocate(), errMsg, hasStat)};
if (stat == StatOk) {
if (const DescriptorAddendum * addendum{descriptor.Addendum()}) {
if (const auto *derived{addendum->derivedType()}) {
if (!derived->noInitializationNeeded()) {
stat = Initialize(descriptor, *derived, terminator, hasStat, errMsg);
}
}
}
}
return stat;
}
int RTNAME(AllocatableDeallocate)(Descriptor &descriptor, bool hasStat,
const Descriptor *errMsg, const char *sourceFile, int sourceLine) {
Terminator terminator{sourceFile, sourceLine};
if (!descriptor.IsAllocatable()) {
return ReturnError(terminator, StatInvalidDescriptor, errMsg, hasStat);
}
if (!descriptor.IsAllocated()) {
return ReturnError(terminator, StatBaseNull, errMsg, hasStat);
}
return ReturnError(terminator, descriptor.Destroy(true), errMsg, hasStat);
}
void RTNAME(AllocatableDeallocateNoFinal)(
Descriptor &descriptor, const char *sourceFile, int sourceLine) {
Terminator terminator{sourceFile, sourceLine};
if (!descriptor.IsAllocatable()) {
ReturnError(terminator, StatInvalidDescriptor);
} else if (!descriptor.IsAllocated()) {
ReturnError(terminator, StatBaseNull);
} else {
ReturnError(terminator, descriptor.Destroy(false));
}
}
}
}