@@ -101,6 +101,9 @@ class DescriptorAddendum {
101101 explicit RT_API_ATTRS DescriptorAddendum (
102102 const typeInfo::DerivedType *dt = nullptr )
103103 : derivedType_{dt}, len_{0 } {}
104+ RT_API_ATTRS DescriptorAddendum (const DescriptorAddendum &that) {
105+ *this = that;
106+ }
104107 RT_API_ATTRS DescriptorAddendum &operator =(const DescriptorAddendum &);
105108
106109 RT_API_ATTRS const typeInfo::DerivedType *derivedType () const {
@@ -181,6 +184,9 @@ class Descriptor {
181184 const SubscriptValue *extent = nullptr ,
182185 ISO::CFI_attribute_t attribute = CFI_attribute_other);
183186
187+ RT_API_ATTRS void UncheckedScalarEstablish (
188+ const typeInfo::DerivedType &, void *);
189+
184190 // To create a descriptor for a derived type the caller
185191 // must provide non-null dt argument.
186192 // The addendum argument is only used for testing purposes,
@@ -433,7 +439,9 @@ class Descriptor {
433439 bool stridesAreContiguous{true };
434440 for (int j{0 }; j < leadingDimensions; ++j) {
435441 const Dimension &dim{GetDimension (j)};
436- stridesAreContiguous &= bytes == dim.ByteStride () || dim.Extent () == 1 ;
442+ if (bytes != dim.ByteStride () && dim.Extent () != 1 ) {
443+ stridesAreContiguous = false ;
444+ }
437445 bytes *= dim.Extent ();
438446 }
439447 // One and zero element arrays are contiguous even if the descriptor
@@ -448,28 +456,44 @@ class Descriptor {
448456
449457 // The result, if any, is a fixed stride value that can be used to
450458 // address all elements. It generalizes contiguity by also allowing
451- // the case of an array with extent 1 on all but one dimension.
459+ // the case of an array with extent 1 on all dimensions but one.
460+ // Returns 0 for an empty array, a byte stride if one is well-defined
461+ // for the array, or nullopt otherwise.
452462 RT_API_ATTRS common::optional<SubscriptValue> FixedStride () const {
453- auto rank{static_cast <std::size_t >(raw_.rank )};
454- common::optional<SubscriptValue> stride;
455- for (std::size_t j{0 }; j < rank; ++j) {
456- const Dimension &dim{GetDimension (j)};
457- auto extent{dim.Extent ()};
458- if (extent == 0 ) {
459- break ; // empty array
460- } else if (extent == 1 ) { // ok
461- } else if (stride) {
462- // Extent > 1 on multiple dimensions
463- if (IsContiguous ()) {
464- return ElementBytes ();
463+ int rank{raw_.rank };
464+ auto elementBytes{static_cast <SubscriptValue>(ElementBytes ())};
465+ if (rank == 0 ) {
466+ return elementBytes;
467+ } else if (rank == 1 ) {
468+ const Dimension &dim{GetDimension (0 )};
469+ return dim.Extent () == 0 ? 0 : dim.ByteStride ();
470+ } else {
471+ common::optional<SubscriptValue> stride;
472+ auto bytes{elementBytes};
473+ for (int j{0 }; j < rank; ++j) {
474+ const Dimension &dim{GetDimension (j)};
475+ auto extent{dim.Extent ()};
476+ if (extent == 0 ) {
477+ return 0 ; // empty array
478+ } else if (extent == 1 ) { // ok
465479 } else {
466- return common::nullopt ;
480+ if (stride) { // Extent > 1 on multiple dimensions
481+ if (bytes != dim.ByteStride ()) { // discontiguity
482+ while (++j < rank) {
483+ if (GetDimension (j).Extent () == 0 ) {
484+ return 0 ; // empty array
485+ }
486+ }
487+ return common::nullopt ; // nonempty, discontiguous
488+ }
489+ } else {
490+ stride = dim.ByteStride ();
491+ }
492+ bytes *= extent;
467493 }
468- } else {
469- stride = dim.ByteStride ();
470494 }
495+ return stride.value_or (elementBytes /* for singleton*/ );
471496 }
472- return stride.value_or (0 ); // 0 for scalars and empty arrays
473497 }
474498
475499 // Establishes a pointer to a section or element.
0 commit comments