[flang-commits] [flang] 01688ee - [flang] Accommodate unknowable CHARACTER length in evaluate::ArrayConstructor<>

Peter Klausler via flang-commits flang-commits at lists.llvm.org
Fri Dec 2 10:37:35 PST 2022


Author: Peter Klausler
Date: 2022-12-02T10:37:28-08:00
New Revision: 01688ee9df5ead4dcff3c460d7f038f307f1ee5d

URL: https://github.com/llvm/llvm-project/commit/01688ee9df5ead4dcff3c460d7f038f307f1ee5d
DIFF: https://github.com/llvm/llvm-project/commit/01688ee9df5ead4dcff3c460d7f038f307f1ee5d.diff

LOG: [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

Added: 
    

Modified: 
    flang/include/flang/Evaluate/expression.h
    flang/lib/Evaluate/expression.cpp
    flang/lib/Evaluate/fold-implementation.h
    flang/lib/Evaluate/formatting.cpp
    flang/lib/Semantics/expression.cpp

Removed: 
    


################################################################################
diff  --git a/flang/include/flang/Evaluate/expression.h b/flang/include/flang/Evaluate/expression.h
index 90309affbe25..642ddf511684 100644
--- a/flang/include/flang/Evaluate/expression.h
+++ b/flang/include/flang/Evaluate/expression.h
@@ -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 <>

diff  --git a/flang/lib/Evaluate/expression.cpp b/flang/lib/Evaluate/expression.cpp
index 3ea99c8962ea..5b0bc14dc3e1 100644
--- a/flang/lib/Evaluate/expression.cpp
+++ b/flang/lib/Evaluate/expression.cpp
@@ -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 {

diff  --git a/flang/lib/Evaluate/fold-implementation.h b/flang/lib/Evaluate/fold-implementation.h
index 5035e4630494..79bea7805f30 100644
--- a/flang/lib/Evaluate/fold-implementation.h
+++ b/flang/lib/Evaluate/fold-implementation.h
@@ -1171,10 +1171,12 @@ template <typename T> class ArrayConstructorFolder {
         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

diff  --git a/flang/lib/Evaluate/formatting.cpp b/flang/lib/Evaluate/formatting.cpp
index 646d4bc5b2f7..9b649e7cee55 100644
--- a/flang/lib/Evaluate/formatting.cpp
+++ b/flang/lib/Evaluate/formatting.cpp
@@ -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 << ']';
 }

diff  --git a/flang/lib/Semantics/expression.cpp b/flang/lib/Semantics/expression.cpp
index c59a5f543c60..95e4a7446516 100644
--- a/flang/lib/Semantics/expression.cpp
+++ b/flang/lib/Semantics/expression.cpp
@@ -1343,15 +1343,15 @@ class ArrayConstructorContext {
               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;


        


More information about the flang-commits mailing list