diff --git a/flang/include/flang/Evaluate/characteristics.h b/flang/include/flang/Evaluate/characteristics.h --- a/flang/include/flang/Evaluate/characteristics.h +++ b/flang/include/flang/Evaluate/characteristics.h @@ -146,6 +146,8 @@ const char *thisIs = "pointer", const char *thatIs = "target", bool isElemental = false, bool thisIsDeferredShape = false, bool thatIsDeferredShape = false) const; + std::optional> MeasureElementSizeInBytes( + FoldingContext &, bool align) const; std::optional> MeasureSizeInBytes( FoldingContext &) const; diff --git a/flang/lib/Evaluate/characteristics.cpp b/flang/lib/Evaluate/characteristics.cpp --- a/flang/lib/Evaluate/characteristics.cpp +++ b/flang/lib/Evaluate/characteristics.cpp @@ -168,19 +168,26 @@ thatIsDeferredShape); } +std::optional> TypeAndShape::MeasureElementSizeInBytes( + FoldingContext &foldingContext, bool align) const { + if (LEN_) { + CHECK(type_.category() == TypeCategory::Character); + return Fold(foldingContext, + Expr{type_.kind()} * Expr{*LEN_}); + } + if (auto elementBytes{type_.MeasureSizeInBytes(foldingContext, align)}) { + return Fold(foldingContext, std::move(*elementBytes)); + } + return std::nullopt; +} + std::optional> TypeAndShape::MeasureSizeInBytes( FoldingContext &foldingContext) const { if (auto elements{GetSize(Shape{shape_})}) { // Sizes of arrays (even with single elements) are multiples of // their alignments. - if (LEN_) { - CHECK(type_.category() == TypeCategory::Character); - return Fold(foldingContext, - std::move(*elements) * Expr{type_.kind()} * - Expr{*LEN_}); - } if (auto elementBytes{ - type_.MeasureSizeInBytes(foldingContext, GetRank(shape_) > 0)}) { + MeasureElementSizeInBytes(foldingContext, GetRank(shape_) > 0)}) { return Fold( foldingContext, std::move(*elements) * std::move(*elementBytes)); } diff --git a/flang/lib/Evaluate/fold-integer.cpp b/flang/lib/Evaluate/fold-integer.cpp --- a/flang/lib/Evaluate/fold-integer.cpp +++ b/flang/lib/Evaluate/fold-integer.cpp @@ -598,12 +598,11 @@ } } } else if (name == "storage_size") { // in bits - if (const auto *expr{UnwrapExpr>(args[0])}) { - if (auto type{expr->GetType()}) { - if (auto bytes{type->MeasureSizeInBytes(context, true)}) { - return Expr{ - Fold(context, Expr{8} * ConvertToType(std::move(*bytes)))}; - } + if (auto info{ + characteristics::TypeAndShape::Characterize(args[0], context)}) { + if (auto bytes{info->MeasureElementSizeInBytes(context, true)}) { + return Expr{ + Fold(context, Expr{8} * ConvertToType(std::move(*bytes)))}; } } } else if (name == "ubound") { diff --git a/flang/lib/Evaluate/shape.cpp b/flang/lib/Evaluate/shape.cpp --- a/flang/lib/Evaluate/shape.cpp +++ b/flang/lib/Evaluate/shape.cpp @@ -724,7 +724,7 @@ auto sourceBytes{ sourceTypeAndShape->MeasureSizeInBytes(*context_)}; auto moldElementBytes{ - moldTypeAndShape->type().MeasureSizeInBytes(*context_, true)}; + moldTypeAndShape->MeasureElementSizeInBytes(*context_, true)}; if (sourceBytes && moldElementBytes) { ExtentExpr extent{Fold(*context_, (std::move(*sourceBytes) + diff --git a/flang/lib/Semantics/compute-offsets.cpp b/flang/lib/Semantics/compute-offsets.cpp --- a/flang/lib/Semantics/compute-offsets.cpp +++ b/flang/lib/Semantics/compute-offsets.cpp @@ -323,7 +323,7 @@ chars->type().GetAlignment(foldingContext)}; } } else { // element size only - if (auto size{ToInt64(chars->type().MeasureSizeInBytes( + if (auto size{ToInt64(chars->MeasureElementSizeInBytes( foldingContext, true /*aligned*/))}) { return {static_cast(*size), chars->type().GetAlignment(foldingContext)};