diff --git a/flang/runtime/assign.cpp b/flang/runtime/assign.cpp index 237acb0c89fc2..879b413efe127 100644 --- a/flang/runtime/assign.cpp +++ b/flang/runtime/assign.cpp @@ -393,53 +393,45 @@ RT_API_ATTRS static void Assign( // Copy the data components (incl. the parent) first. const Descriptor &componentDesc{updatedToDerived->component()}; std::size_t numComponents{componentDesc.Elements()}; - for (std::size_t k{0}; k < numComponents; ++k) { - const auto &comp{ - *componentDesc.ZeroBasedIndexedElement( - k)}; // TODO: exploit contiguity here - // Use PolymorphicLHS for components so that the right things happen - // when the components are polymorphic; when they're not, they're both - // not, and their declared types will match. - int nestedFlags{MaybeReallocate | PolymorphicLHS}; - if (flags & ComponentCanBeDefinedAssignment) { - nestedFlags |= CanBeDefinedAssignment | ComponentCanBeDefinedAssignment; - } - switch (comp.genre()) { - case typeInfo::Component::Genre::Data: - if (comp.category() == TypeCategory::Derived) { - StaticDescriptor statDesc[2]; - Descriptor &toCompDesc{statDesc[0].descriptor()}; - Descriptor &fromCompDesc{statDesc[1].descriptor()}; - for (std::size_t j{0}; j < toElements; ++j, - to.IncrementSubscripts(toAt), from.IncrementSubscripts(fromAt)) { + for (std::size_t j{0}; j < toElements; + ++j, to.IncrementSubscripts(toAt), from.IncrementSubscripts(fromAt)) { + for (std::size_t k{0}; k < numComponents; ++k) { + const auto &comp{ + *componentDesc.ZeroBasedIndexedElement( + k)}; // TODO: exploit contiguity here + // Use PolymorphicLHS for components so that the right things happen + // when the components are polymorphic; when they're not, they're both + // not, and their declared types will match. + int nestedFlags{MaybeReallocate | PolymorphicLHS}; + if (flags & ComponentCanBeDefinedAssignment) { + nestedFlags |= + CanBeDefinedAssignment | ComponentCanBeDefinedAssignment; + } + switch (comp.genre()) { + case typeInfo::Component::Genre::Data: + if (comp.category() == TypeCategory::Derived) { + StaticDescriptor statDesc[2]; + Descriptor &toCompDesc{statDesc[0].descriptor()}; + Descriptor &fromCompDesc{statDesc[1].descriptor()}; comp.CreatePointerDescriptor(toCompDesc, to, terminator, toAt); comp.CreatePointerDescriptor( fromCompDesc, from, terminator, fromAt); Assign(toCompDesc, fromCompDesc, terminator, nestedFlags); - } - } else { // Component has intrinsic type; simply copy raw bytes - std::size_t componentByteSize{comp.SizeInBytes(to)}; - for (std::size_t j{0}; j < toElements; ++j, - to.IncrementSubscripts(toAt), from.IncrementSubscripts(fromAt)) { + } else { // Component has intrinsic type; simply copy raw bytes + std::size_t componentByteSize{comp.SizeInBytes(to)}; Fortran::runtime::memmove(to.Element(toAt) + comp.offset(), from.Element(fromAt) + comp.offset(), componentByteSize); } - } - break; - case typeInfo::Component::Genre::Pointer: { - std::size_t componentByteSize{comp.SizeInBytes(to)}; - for (std::size_t j{0}; j < toElements; ++j, - to.IncrementSubscripts(toAt), from.IncrementSubscripts(fromAt)) { + break; + case typeInfo::Component::Genre::Pointer: { + std::size_t componentByteSize{comp.SizeInBytes(to)}; Fortran::runtime::memmove(to.Element(toAt) + comp.offset(), from.Element(fromAt) + comp.offset(), componentByteSize); - } - } break; - case typeInfo::Component::Genre::Allocatable: - case typeInfo::Component::Genre::Automatic: - for (std::size_t j{0}; j < toElements; ++j, - to.IncrementSubscripts(toAt), from.IncrementSubscripts(fromAt)) { + } break; + case typeInfo::Component::Genre::Allocatable: + case typeInfo::Component::Genre::Automatic: { auto *toDesc{reinterpret_cast( to.Element(toAt) + comp.offset())}; const auto *fromDesc{reinterpret_cast( @@ -470,18 +462,16 @@ RT_API_ATTRS static void Assign( // The actual deallocation may be avoided, if the existing // location can be reoccupied. Assign(*toDesc, *fromDesc, terminator, nestedFlags | DeallocateLHS); + } break; } - break; } - } - // Copy procedure pointer components - const Descriptor &procPtrDesc{updatedToDerived->procPtr()}; - std::size_t numProcPtrs{procPtrDesc.Elements()}; - for (std::size_t k{0}; k < numProcPtrs; ++k) { - const auto &procPtr{ - *procPtrDesc.ZeroBasedIndexedElement(k)}; - for (std::size_t j{0}; j < toElements; ++j, to.IncrementSubscripts(toAt), - from.IncrementSubscripts(fromAt)) { + // Copy procedure pointer components + const Descriptor &procPtrDesc{updatedToDerived->procPtr()}; + std::size_t numProcPtrs{procPtrDesc.Elements()}; + for (std::size_t k{0}; k < numProcPtrs; ++k) { + const auto &procPtr{ + *procPtrDesc.ZeroBasedIndexedElement( + k)}; Fortran::runtime::memmove(to.Element(toAt) + procPtr.offset, from.Element(fromAt) + procPtr.offset, sizeof(typeInfo::ProcedurePointer));