diff options
Diffstat (limited to 'flang/runtime/derived.cpp')
| -rw-r--r-- | flang/runtime/derived.cpp | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/flang/runtime/derived.cpp b/flang/runtime/derived.cpp index 659f54fa344b..7c164ff89045 100644 --- a/flang/runtime/derived.cpp +++ b/flang/runtime/derived.cpp @@ -122,6 +122,84 @@ RT_API_ATTRS int Initialize(const Descriptor &instance, return stat; } +RT_API_ATTRS int InitializeClone(const Descriptor &clone, + const Descriptor &orig, const typeInfo::DerivedType &derived, + Terminator &terminator, bool hasStat, const Descriptor *errMsg) { + const Descriptor &componentDesc{derived.component()}; + std::size_t elements{orig.Elements()}; + int stat{StatOk}; + + // Initialize each data component. + std::size_t components{componentDesc.Elements()}; + for (std::size_t i{0}; i < components; ++i) { + const typeInfo::Component &comp{ + *componentDesc.ZeroBasedIndexedElement<typeInfo::Component>(i)}; + SubscriptValue at[maxRank]; + orig.GetLowerBounds(at); + // Allocate allocatable components that are also allocated in the original + // object. + if (comp.genre() == typeInfo::Component::Genre::Allocatable) { + // Initialize each element. + for (std::size_t j{0}; j < elements; ++j, orig.IncrementSubscripts(at)) { + Descriptor &origDesc{ + *orig.ElementComponent<Descriptor>(at, comp.offset())}; + Descriptor &cloneDesc{ + *clone.ElementComponent<Descriptor>(at, comp.offset())}; + if (origDesc.IsAllocated()) { + cloneDesc.ApplyMold(origDesc, origDesc.rank()); + stat = ReturnError(terminator, cloneDesc.Allocate(), errMsg, hasStat); + if (stat == StatOk) { + if (const DescriptorAddendum * addendum{cloneDesc.Addendum()}) { + if (const typeInfo::DerivedType * + derived{addendum->derivedType()}) { + if (!derived->noInitializationNeeded()) { + // Perform default initialization for the allocated element. + stat = Initialize( + cloneDesc, *derived, terminator, hasStat, errMsg); + } + // Initialize derived type's allocatables. + if (stat == StatOk) { + stat = InitializeClone(cloneDesc, origDesc, *derived, + terminator, hasStat, errMsg); + } + } + } + } + } + if (stat != StatOk) { + break; + } + } + } else if (comp.genre() == typeInfo::Component::Genre::Data && + comp.derivedType()) { + // Handle nested derived types. + const typeInfo::DerivedType &compType{*comp.derivedType()}; + SubscriptValue extents[maxRank]; + GetComponentExtents(extents, comp, orig); + // Data components don't have descriptors, allocate them. + StaticDescriptor<maxRank, true, 0> origStaticDesc; + StaticDescriptor<maxRank, true, 0> cloneStaticDesc; + Descriptor &origDesc{origStaticDesc.descriptor()}; + Descriptor &cloneDesc{cloneStaticDesc.descriptor()}; + // Initialize each element. + for (std::size_t j{0}; j < elements; ++j, orig.IncrementSubscripts(at)) { + origDesc.Establish(compType, + orig.ElementComponent<char>(at, comp.offset()), comp.rank(), + extents); + cloneDesc.Establish(compType, + clone.ElementComponent<char>(at, comp.offset()), comp.rank(), + extents); + stat = InitializeClone( + cloneDesc, origDesc, compType, terminator, hasStat, errMsg); + if (stat != StatOk) { + break; + } + } + } + } + return stat; +} + static RT_API_ATTRS const typeInfo::SpecialBinding *FindFinal( const typeInfo::DerivedType &derived, int rank) { if (const auto *ranked{derived.FindSpecialBinding( |
