diff options
Diffstat (limited to 'flang/runtime/descriptor.cpp')
-rw-r--r-- | flang/runtime/descriptor.cpp | 43 |
1 files changed, 35 insertions, 8 deletions
diff --git a/flang/runtime/descriptor.cpp b/flang/runtime/descriptor.cpp index efcd61b50c4f..3a750255eb23 100644 --- a/flang/runtime/descriptor.cpp +++ b/flang/runtime/descriptor.cpp @@ -17,9 +17,7 @@ namespace Fortran::runtime { -Descriptor::Descriptor(const Descriptor &that) { - std::memcpy(this, &that, that.SizeInBytes()); -} +Descriptor::Descriptor(const Descriptor &that) { *this = that; } Descriptor::~Descriptor() { if (raw_.attribute != CFI_attribute_pointer) { @@ -27,13 +25,32 @@ Descriptor::~Descriptor() { } } +Descriptor &Descriptor::operator=(const Descriptor &that) { + std::memcpy(this, &that, that.SizeInBytes()); + return *this; +} + void Descriptor::Establish(TypeCode t, std::size_t elementBytes, void *p, int rank, const SubscriptValue *extent, ISO::CFI_attribute_t attribute, bool addendum) { Terminator terminator{__FILE__, __LINE__}; + // Subtle: the standard CFI_establish() function doesn't allow a zero + // elem_len argument in cases where elem_len is not ignored; and when it + // returns an error code (CFI_INVALID_ELEM_LEN in this case), it must not + // modify the descriptor. That design makes sense, maybe, for actual + // C interoperability, but we need to work around it here. A zero + // incoming element length is replaced by 4 so that it will be valid + // for all CHARACTER kinds. + std::size_t workaroundElemLen{elementBytes ? elementBytes : 4}; RUNTIME_CHECK(terminator, - ISO::CFI_establish(&raw_, p, attribute, t.raw(), elementBytes, rank, + ISO::CFI_establish(&raw_, p, attribute, t.raw(), workaroundElemLen, rank, extent) == CFI_SUCCESS); + if (elementBytes == 0) { + raw_.elem_len = 0; + for (int j{0}; j < rank; ++j) { + GetDimension(j).SetByteStride(0); + } + } raw_.f18Addendum = addendum; DescriptorAddendum *a{Addendum()}; RUNTIME_CHECK(terminator, addendum == (a != nullptr)); @@ -210,10 +227,9 @@ bool Descriptor::SubscriptsForZeroBasedElementNumber(SubscriptValue *subscript, for (int j{raw_.rank - 1}; j >= 0; --j) { int k{permutation ? permutation[j] : j}; const Dimension &dim{GetDimension(k)}; - std::size_t quotient{j ? elementNumber / dimCoefficient[j] : 0}; - subscript[k] = - dim.LowerBound() + elementNumber - dimCoefficient[j] * quotient; - elementNumber = quotient; + std::size_t quotient{elementNumber / dimCoefficient[j]}; + subscript[k] = quotient + dim.LowerBound(); + elementNumber -= quotient * dimCoefficient[j]; } return true; } @@ -244,6 +260,17 @@ void Descriptor::Dump(FILE *f) const { } } +DescriptorAddendum &DescriptorAddendum::operator=( + const DescriptorAddendum &that) { + derivedType_ = that.derivedType_; + flags_ = that.flags_; + auto lenParms{that.LenParameters()}; + for (std::size_t j{0}; j < lenParms; ++j) { + len_[j] = that.len_[j]; + } + return *this; +} + std::size_t DescriptorAddendum::SizeInBytes() const { return SizeInBytes(LenParameters()); } |