[flang-commits] [flang] 7995fa2 - [flang] Catch case of character array constructor with indeterminable length

Peter Klausler via flang-commits flang-commits at lists.llvm.org
Fri Jul 21 13:26:42 PDT 2023


Author: Peter Klausler
Date: 2023-07-21T13:26:34-07:00
New Revision: 7995fa2fd6c0663e71dece3600d2e842d9c31d62

URL: https://github.com/llvm/llvm-project/commit/7995fa2fd6c0663e71dece3600d2e842d9c31d62
DIFF: https://github.com/llvm/llvm-project/commit/7995fa2fd6c0663e71dece3600d2e842d9c31d62.diff

LOG: [flang] Catch case of character array constructor with indeterminable length

F'2023 7.8 para 5 requires that an implied DO loop with no iterations
in a character array constructor should have items whose lengths are
constant expressions independent of the value of the implied DO loop
index.

Differential Revision: https://reviews.llvm.org/D155968

Added: 
    flang/test/Semantics/array-constr-len.f90

Modified: 
    flang/lib/Semantics/expression.cpp

Removed: 
    


################################################################################
diff  --git a/flang/lib/Semantics/expression.cpp b/flang/lib/Semantics/expression.cpp
index be67ae822d9b72..777ef3b20b2324 100644
--- a/flang/lib/Semantics/expression.cpp
+++ b/flang/lib/Semantics/expression.cpp
@@ -1474,7 +1474,7 @@ class ArrayConstructorContext {
       } 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()}) {
+          if (auto len{LengthIfGood()}) {
             // The ac-do-variables may be treated as constant expressions,
             // if some conditions on ac-implied-do-control hold (10.1.12 (12)).
             // At the same time, they may be treated as constant expressions
@@ -1488,9 +1488,7 @@ class ArrayConstructorContext {
             // with a dangling reference to the ac-do-variable.
             // Prevent this by checking for the ac-do-variable references
             // in the 'len' expression.
-            if (!ContainsAnyImpliedDoIndex(*len) && IsConstantExpr(*len)) {
-              result.set_LEN(std::move(*len));
-            }
+            result.set_LEN(std::move(*len));
           }
         }
         return AsMaybeExpr(std::move(result));
@@ -1502,6 +1500,19 @@ class ArrayConstructorContext {
 private:
   using ImpliedDoIntType = ResultType<ImpliedDoIndex>;
 
+  std::optional<Expr<SubscriptInteger>> LengthIfGood() const {
+    if (type_) {
+      auto len{type_->LEN()};
+      if (len && IsConstantExpr(*len) && !ContainsAnyImpliedDoIndex(*len)) {
+        return len;
+      }
+    }
+    return std::nullopt;
+  }
+  bool NeedLength() const {
+    return !explicitType_ && type_ &&
+        type_->category() == TypeCategory::Character && !LengthIfGood();
+  }
   void Push(MaybeExpr &&);
   void Add(const parser::AcValue::Triplet &);
   void Add(const parser::Expr &);
@@ -1611,7 +1622,8 @@ void ArrayConstructorContext::Push(MaybeExpr &&x) {
   } else if (!explicitType_) {
     if (type_->IsTkCompatibleWith(xType) && xType.IsTkCompatibleWith(*type_)) {
       values_.Push(std::move(*x));
-      if (auto thisLen{ToInt64(xType.LEN())}) {
+      auto xLen{xType.LEN()};
+      if (auto thisLen{ToInt64(xLen)}) {
         if (constantLength_) {
           if (exprAnalyzer_.context().ShouldWarn(
                   common::LanguageFeature::DistinctArrayConstructorLengths) &&
@@ -1628,12 +1640,14 @@ void ArrayConstructorContext::Push(MaybeExpr &&x) {
             // length of the array constructor's character elements, not the
             // first, when there is no explicit type.
             *constantLength_ = *thisLen;
-            type_->length = xType.LEN();
+            type_->length = std::move(xLen);
           }
         } else {
           constantLength_ = *thisLen;
-          type_->length = xType.LEN();
+          type_->length = std::move(xLen);
         }
+      } else if (xLen && NeedLength()) {
+        type_->length = std::move(xLen);
       }
     } else {
       if (!(messageDisplayedSet_ & 2)) {
@@ -1735,6 +1749,7 @@ void ArrayConstructorContext::Add(const parser::AcImpliedDo &impliedDo) {
       bool isNonemptyConstant{isConstant &&
           ((*cStride > 0 && *cLower <= *cUpper) ||
               (*cStride < 0 && *cLower >= *cUpper))};
+      bool isEmpty{isConstant && !isNonemptyConstant};
       bool unrollConstantLoop{false};
       parser::Messages buffer;
       auto saveMessagesDisplayed{messageDisplayedSet_};
@@ -1754,6 +1769,12 @@ void ArrayConstructorContext::Add(const parser::AcImpliedDo &impliedDo) {
               std::move(*upper), std::move(*stride), std::move(v)});
         }
       }
+      // F'2023 7.8 p5
+      if (!(messageDisplayedSet_ & 0x100) && isEmpty && NeedLength()) {
+        exprAnalyzer_.SayAt(name,
+            "Array constructor implied DO loop has no iterations and indeterminate character length"_err_en_US);
+        messageDisplayedSet_ |= 0x100;
+      }
       if (unrollConstantLoop) {
         messageDisplayedSet_ = saveMessagesDisplayed;
         UnrollConstantImpliedDo(impliedDo, name, *cLower, *cUpper, *cStride);

diff  --git a/flang/test/Semantics/array-constr-len.f90 b/flang/test/Semantics/array-constr-len.f90
new file mode 100644
index 00000000000000..11460a0244ca26
--- /dev/null
+++ b/flang/test/Semantics/array-constr-len.f90
@@ -0,0 +1,14 @@
+! RUN: %python %S/test_errors.py %s %flang_fc1
+! Confirm enforcement of F'2023 7.8 p5
+subroutine subr(s,n)
+  character*(*) s
+  !ERROR: Array constructor implied DO loop has no iterations and indeterminate character length
+  print *, [(s(1:n),j=1,0)]
+  !ERROR: Array constructor implied DO loop has no iterations and indeterminate character length
+  print *, [(s(1:n),j=0,1,-1)]
+  !ERROR: Array constructor implied DO loop has no iterations and indeterminate character length
+  print *, [(s(1:j),j=1,0)]
+  print *, [(s(1:1),j=1,0)] ! ok
+  print *, [character(2)::(s(1:n),j=1,0)] ! ok
+  print *, [character(n)::(s(1:n),j=1,0)] ! ok
+end


        


More information about the flang-commits mailing list