diff --git a/flang/include/flang/Evaluate/expression.h b/flang/include/flang/Evaluate/expression.h --- a/flang/include/flang/Evaluate/expression.h +++ b/flang/include/flang/Evaluate/expression.h @@ -473,20 +473,20 @@ public: using Result = Type; using Base = ArrayConstructorValues; - CLASS_BOILERPLATE(ArrayConstructor) - ArrayConstructor(Expr &&len, Base &&v) - : Base{std::move(v)}, length_{std::move(len)} {} - template - explicit ArrayConstructor(const A &prototype) - : length_{prototype.LEN().value()} {} + DEFAULT_CONSTRUCTORS_AND_ASSIGNMENTS(ArrayConstructor) + explicit ArrayConstructor(Base &&values) : Base{std::move(values)} {} + template explicit ArrayConstructor(const Expr &) {} + ArrayConstructor &set_LEN(Expr &&); bool operator==(const ArrayConstructor &) const; static constexpr Result result() { return Result{}; } static constexpr DynamicType GetType() { return Result::GetType(); } llvm::raw_ostream &AsFortran(llvm::raw_ostream &) const; - const Expr &LEN() const { return length_.value(); } + const Expr *LEN() const { + return length_ ? &length_->value() : nullptr; + } private: - common::CopyableIndirection> length_; + std::optional>> length_; }; template <> diff --git a/flang/lib/Evaluate/expression.cpp b/flang/lib/Evaluate/expression.cpp --- a/flang/lib/Evaluate/expression.cpp +++ b/flang/lib/Evaluate/expression.cpp @@ -35,7 +35,13 @@ [](const Constant &c) -> T { return AsExpr(Constant{c.LEN()}); }, - [](const ArrayConstructor &a) -> T { return a.LEN(); }, + [](const ArrayConstructor &a) -> T { + if (const auto *len{a.LEN()}) { + return T{*len}; + } else { + return std::nullopt; + } + }, [](const Parentheses &x) { return x.left().LEN(); }, [](const Convert &x) { return common::visit( @@ -142,6 +148,13 @@ return values_ == that.values_; } +template +auto ArrayConstructor>::set_LEN( + Expr &&len) -> ArrayConstructor & { + length_.emplace(std::move(len)); + return *this; +} + template bool ArrayConstructor>::operator==( const ArrayConstructor &that) const { diff --git a/flang/lib/Evaluate/fold-implementation.h b/flang/lib/Evaluate/fold-implementation.h --- a/flang/lib/Evaluate/fold-implementation.h +++ b/flang/lib/Evaluate/fold-implementation.h @@ -1171,10 +1171,12 @@ return Expr{Constant{array.GetType().GetDerivedTypeSpec(), std::move(elements_), ConstantSubscripts{n}}}; } else if constexpr (T::category == TypeCategory::Character) { - auto length{Fold(context_, common::Clone(array.LEN()))}; - if (std::optional lengthValue{ToInt64(length)}) { - return Expr{Constant{ - *lengthValue, std::move(elements_), ConstantSubscripts{n}}}; + if (const auto *len{array.LEN()}) { + auto length{Fold(context_, common::Clone(*len))}; + if (std::optional lengthValue{ToInt64(length)}) { + return Expr{Constant{ + *lengthValue, std::move(elements_), ConstantSubscripts{n}}}; + } } } else { return Expr{ @@ -1371,12 +1373,13 @@ template ArrayConstructor ArrayConstructorFromMold( const A &prototype, std::optional> &&length) { + ArrayConstructor result{prototype}; if constexpr (RESULT::category == TypeCategory::Character) { - return ArrayConstructor{ - std::move(length.value()), ArrayConstructorValues{}}; - } else { - return ArrayConstructor{prototype}; + if (length) { + result.set_LEN(std::move(*length)); + } } + return result; } // array * array case diff --git a/flang/lib/Evaluate/formatting.cpp b/flang/lib/Evaluate/formatting.cpp --- a/flang/lib/Evaluate/formatting.cpp +++ b/flang/lib/Evaluate/formatting.cpp @@ -421,7 +421,10 @@ llvm::raw_ostream & ArrayConstructor>::AsFortran( llvm::raw_ostream &o) const { - o << '[' << GetType().AsFortran(LEN().AsFortran()) << "::"; + o << '['; + if (const auto *len{LEN()}) { + o << GetType().AsFortran(len->AsFortran()) << "::"; + } EmitArray(o, *this); return o << ']'; } diff --git a/flang/lib/Semantics/expression.cpp b/flang/lib/Semantics/expression.cpp --- a/flang/lib/Semantics/expression.cpp +++ b/flang/lib/Semantics/expression.cpp @@ -1343,15 +1343,15 @@ MakeSpecific(std::move(values_))}); } } else if (type_->kind() == T::kind) { + ArrayConstructor result{MakeSpecific(std::move(values_))}; if constexpr (T::category == TypeCategory::Character) { if (auto len{type_->LEN()}) { - return AsMaybeExpr(ArrayConstructor{ - *std::move(len), MakeSpecific(std::move(values_))}); + if (IsConstantExpr(*len)) { + result.set_LEN(std::move(*len)); + } } - } else { - return AsMaybeExpr( - ArrayConstructor{MakeSpecific(std::move(values_))}); } + return AsMaybeExpr(std::move(result)); } } return std::nullopt;