[flang] Accommodate unknowable CHARACTER length in evaluate::ArrayConstructor<>
The internal representation for array constructors in expressions during semantic analysis needs to be able to accommodate circumstances (e.g. TRIM(), substrings) in which the length of the elements in the array is either unknown or cannot be represented as a context-free integer expression. Differential Revision: https://reviews.llvm.org/D139041
This commit is contained in:
parent
4d6483e91b
commit
01688ee9df
|
@ -473,20 +473,20 @@ class ArrayConstructor<Type<TypeCategory::Character, KIND>>
|
|||
public:
|
||||
using Result = Type<TypeCategory::Character, KIND>;
|
||||
using Base = ArrayConstructorValues<Result>;
|
||||
CLASS_BOILERPLATE(ArrayConstructor)
|
||||
ArrayConstructor(Expr<SubscriptInteger> &&len, Base &&v)
|
||||
: Base{std::move(v)}, length_{std::move(len)} {}
|
||||
template <typename A>
|
||||
explicit ArrayConstructor(const A &prototype)
|
||||
: length_{prototype.LEN().value()} {}
|
||||
DEFAULT_CONSTRUCTORS_AND_ASSIGNMENTS(ArrayConstructor)
|
||||
explicit ArrayConstructor(Base &&values) : Base{std::move(values)} {}
|
||||
template <typename T> explicit ArrayConstructor(const Expr<T> &) {}
|
||||
ArrayConstructor &set_LEN(Expr<SubscriptInteger> &&);
|
||||
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<SubscriptInteger> &LEN() const { return length_.value(); }
|
||||
const Expr<SubscriptInteger> *LEN() const {
|
||||
return length_ ? &length_->value() : nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
common::CopyableIndirection<Expr<SubscriptInteger>> length_;
|
||||
std::optional<common::CopyableIndirection<Expr<SubscriptInteger>>> length_;
|
||||
};
|
||||
|
||||
template <>
|
||||
|
|
|
@ -35,7 +35,13 @@ Expr<Type<TypeCategory::Character, KIND>>::LEN() const {
|
|||
[](const Constant<Result> &c) -> T {
|
||||
return AsExpr(Constant<SubscriptInteger>{c.LEN()});
|
||||
},
|
||||
[](const ArrayConstructor<Result> &a) -> T { return a.LEN(); },
|
||||
[](const ArrayConstructor<Result> &a) -> T {
|
||||
if (const auto *len{a.LEN()}) {
|
||||
return T{*len};
|
||||
} else {
|
||||
return std::nullopt;
|
||||
}
|
||||
},
|
||||
[](const Parentheses<Result> &x) { return x.left().LEN(); },
|
||||
[](const Convert<Result> &x) {
|
||||
return common::visit(
|
||||
|
@ -142,6 +148,13 @@ bool ArrayConstructorValues<R>::operator==(
|
|||
return values_ == that.values_;
|
||||
}
|
||||
|
||||
template <int KIND>
|
||||
auto ArrayConstructor<Type<TypeCategory::Character, KIND>>::set_LEN(
|
||||
Expr<SubscriptInteger> &&len) -> ArrayConstructor & {
|
||||
length_.emplace(std::move(len));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <int KIND>
|
||||
bool ArrayConstructor<Type<TypeCategory::Character, KIND>>::operator==(
|
||||
const ArrayConstructor &that) const {
|
||||
|
|
|
@ -1171,10 +1171,12 @@ public:
|
|||
return Expr<T>{Constant<T>{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<ConstantSubscript> lengthValue{ToInt64(length)}) {
|
||||
return Expr<T>{Constant<T>{
|
||||
*lengthValue, std::move(elements_), ConstantSubscripts{n}}};
|
||||
if (const auto *len{array.LEN()}) {
|
||||
auto length{Fold(context_, common::Clone(*len))};
|
||||
if (std::optional<ConstantSubscript> lengthValue{ToInt64(length)}) {
|
||||
return Expr<T>{Constant<T>{
|
||||
*lengthValue, std::move(elements_), ConstantSubscripts{n}}};
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return Expr<T>{
|
||||
|
@ -1371,12 +1373,13 @@ std::optional<Expr<RESULT>> MapOperation(FoldingContext &context,
|
|||
template <typename RESULT, typename A>
|
||||
ArrayConstructor<RESULT> ArrayConstructorFromMold(
|
||||
const A &prototype, std::optional<Expr<SubscriptInteger>> &&length) {
|
||||
ArrayConstructor<RESULT> result{prototype};
|
||||
if constexpr (RESULT::category == TypeCategory::Character) {
|
||||
return ArrayConstructor<RESULT>{
|
||||
std::move(length.value()), ArrayConstructorValues<RESULT>{}};
|
||||
} else {
|
||||
return ArrayConstructor<RESULT>{prototype};
|
||||
if (length) {
|
||||
result.set_LEN(std::move(*length));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// array * array case
|
||||
|
|
|
@ -421,7 +421,10 @@ template <int KIND>
|
|||
llvm::raw_ostream &
|
||||
ArrayConstructor<Type<TypeCategory::Character, KIND>>::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 << ']';
|
||||
}
|
||||
|
|
|
@ -1343,15 +1343,15 @@ public:
|
|||
MakeSpecific<T>(std::move(values_))});
|
||||
}
|
||||
} else if (type_->kind() == T::kind) {
|
||||
ArrayConstructor<T> result{MakeSpecific<T>(std::move(values_))};
|
||||
if constexpr (T::category == TypeCategory::Character) {
|
||||
if (auto len{type_->LEN()}) {
|
||||
return AsMaybeExpr(ArrayConstructor<T>{
|
||||
*std::move(len), MakeSpecific<T>(std::move(values_))});
|
||||
if (IsConstantExpr(*len)) {
|
||||
result.set_LEN(std::move(*len));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return AsMaybeExpr(
|
||||
ArrayConstructor<T>{MakeSpecific<T>(std::move(values_))});
|
||||
}
|
||||
return AsMaybeExpr(std::move(result));
|
||||
}
|
||||
}
|
||||
return std::nullopt;
|
||||
|
|
Loading…
Reference in New Issue