[flang-commits] [flang] 10b990a - [flang] Diagnose known out-of-range subscripts in more circumstances

Peter Klausler via flang-commits flang-commits at lists.llvm.org
Sat Jan 28 15:27:28 PST 2023


Author: Peter Klausler
Date: 2023-01-28T15:27:17-08:00
New Revision: 10b990a03b1ede533b8443edffa3607aae4295c7

URL: https://github.com/llvm/llvm-project/commit/10b990a03b1ede533b8443edffa3607aae4295c7
DIFF: https://github.com/llvm/llvm-project/commit/10b990a03b1ede533b8443edffa3607aae4295c7.diff

LOG: [flang] Diagnose known out-of-range subscripts in more circumstances

Semantics can catch out-of-range subscript values already when they
appear in DATA statement objects and constant folding of name constant
array indexing; this patch fills the gap by checking known constant
subscript values in other contexts.

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

Added: 
    flang/test/Semantics/expr-errors06.f90

Modified: 
    flang/include/flang/Semantics/expression.h
    flang/lib/Semantics/data-to-inits.cpp
    flang/lib/Semantics/expression.cpp
    flang/lib/Semantics/type.cpp
    flang/test/Lower/OpenACC/acc-data-operands.f90
    flang/test/Lower/explicit-interface-results.f90
    flang/test/Semantics/allocate10.f90
    flang/test/Semantics/allocate11.f90
    flang/test/Semantics/data04.f90

Removed: 
    


################################################################################
diff  --git a/flang/include/flang/Semantics/expression.h b/flang/include/flang/Semantics/expression.h
index 0dc1216bbeece..1e56dded3547d 100644
--- a/flang/include/flang/Semantics/expression.h
+++ b/flang/include/flang/Semantics/expression.h
@@ -111,6 +111,8 @@ class ExpressionAnalyzer {
   semantics::SemanticsContext &context() const { return context_; }
   bool inWhereBody() const { return inWhereBody_; }
   void set_inWhereBody(bool yes = true) { inWhereBody_ = yes; }
+  bool inDataStmtObject() const { return inDataStmtObject_; }
+  void set_inDataStmtObject(bool yes = true) { inDataStmtObject_ = yes; }
 
   FoldingContext &GetFoldingContext() const { return foldingContext_; }
 
@@ -329,6 +331,7 @@ class ExpressionAnalyzer {
       DataRef &&, const Symbol &, const semantics::Scope &);
   MaybeExpr CompleteSubscripts(ArrayRef &&);
   MaybeExpr ApplySubscripts(DataRef &&, std::vector<Subscript> &&);
+  void CheckConstantSubscripts(ArrayRef &);
   bool CheckRanks(const DataRef &); // Return false if error exists.
   bool CheckPolymorphic(const DataRef &); // ditto
   bool CheckDataRef(const DataRef &); // ditto
@@ -385,6 +388,7 @@ class ExpressionAnalyzer {
   bool isNullPointerOk_{false};
   bool useSavedTypedExprs_{true};
   bool inWhereBody_{false};
+  bool inDataStmtObject_{false};
   bool inDataStmtConstant_{false};
   bool inStmtFunctionDefinition_{false};
   friend class ArgumentAnalyzer;
@@ -457,6 +461,8 @@ class ExprChecker {
     exprAnalyzer_.Analyze(x);
     return false;
   }
+  bool Pre(const parser::DataStmtObject &);
+  void Post(const parser::DataStmtObject &);
   bool Pre(const parser::DataImpliedDo &);
 
   bool Pre(const parser::CallStmt &x) {

diff  --git a/flang/lib/Semantics/data-to-inits.cpp b/flang/lib/Semantics/data-to-inits.cpp
index 77d6107a93d38..aaa118b32ffe2 100644
--- a/flang/lib/Semantics/data-to-inits.cpp
+++ b/flang/lib/Semantics/data-to-inits.cpp
@@ -160,7 +160,14 @@ bool DataInitializationCompiler<DSV>::Scan(const parser::Variable &var) {
 template <typename DSV>
 bool DataInitializationCompiler<DSV>::Scan(
     const parser::Designator &designator) {
-  if (auto expr{exprAnalyzer_.Analyze(designator)}) {
+  MaybeExpr expr;
+  { // The out-of-range subscript errors from the designator folder are a
+    // more specific than the default ones from expression semantics, so
+    // disable those to avoid piling on.
+    auto restorer{exprAnalyzer_.GetContextualMessages().DiscardMessages()};
+    expr = exprAnalyzer_.Analyze(designator);
+  }
+  if (expr) {
     parser::CharBlock at{parser::FindSourceLocation(designator)};
     exprAnalyzer_.GetFoldingContext().messages().SetLocation(at);
     scope_ = &exprAnalyzer_.context().FindScope(at);

diff  --git a/flang/lib/Semantics/expression.cpp b/flang/lib/Semantics/expression.cpp
index 9abb698d7d69d..6099ec419e415 100644
--- a/flang/lib/Semantics/expression.cpp
+++ b/flang/lib/Semantics/expression.cpp
@@ -276,6 +276,12 @@ MaybeExpr ExpressionAnalyzer::CompleteSubscripts(ArrayRef &&ref) {
     // SELECT TYPE/RANK or ASSOCIATE.
     CHECK(symbol.has<semantics::AssocEntityDetails>());
   }
+  if (!semantics::IsNamedConstant(symbol) && !inDataStmtObject_) {
+    // Subscripts of named constants are checked in folding.
+    // Subscripts of DATA statement objects are checked in data statement
+    // conversion to initializers.
+    CheckConstantSubscripts(ref);
+  }
   return Designate(DataRef{std::move(ref)});
 }
 
@@ -302,6 +308,111 @@ MaybeExpr ExpressionAnalyzer::ApplySubscripts(
       std::move(dataRef.u));
 }
 
+void ExpressionAnalyzer::CheckConstantSubscripts(ArrayRef &ref) {
+  // Fold subscript expressions and check for an empty triplet.
+  Shape lb{GetLBOUNDs(foldingContext_, ref.base())};
+  Shape ub{GetUBOUNDs(foldingContext_, ref.base())};
+  bool anyPossiblyEmptyDim{false};
+  int dim{0};
+  for (Subscript &ss : ref.subscript()) {
+    if (Triplet * triplet{std::get_if<Triplet>(&ss.u)}) {
+      auto expr{Fold(triplet->stride())};
+      auto stride{ToInt64(expr)};
+      triplet->set_stride(std::move(expr));
+      if (stride) {
+        if (*stride == 0) {
+          Say("Stride of triplet must not be zero"_err_en_US);
+          return;
+        }
+        std::optional<ConstantSubscript> lower, upper;
+        if (auto expr{triplet->lower()}) {
+          *expr = Fold(std::move(*expr));
+          lower = ToInt64(*expr);
+          triplet->set_lower(std::move(*expr));
+        } else {
+          lower = ToInt64(lb[dim]);
+        }
+        if (auto expr{triplet->upper()}) {
+          *expr = Fold(std::move(*expr));
+          upper = ToInt64(*expr);
+          triplet->set_upper(std::move(*expr));
+        } else {
+          upper = ToInt64(ub[dim]);
+        }
+        if (lower && upper) {
+          if (*stride > 0) {
+            anyPossiblyEmptyDim |= *lower > *upper;
+          } else {
+            anyPossiblyEmptyDim |= *lower < *upper;
+          }
+        } else {
+          anyPossiblyEmptyDim = true;
+        }
+      } else {
+        anyPossiblyEmptyDim = true;
+      }
+    } else { // not triplet
+      auto &expr{std::get<IndirectSubscriptIntegerExpr>(ss.u).value()};
+      expr = Fold(std::move(expr));
+      anyPossiblyEmptyDim |= expr.Rank() > 0; // vector subscript
+    }
+    ++dim;
+  }
+  if (anyPossiblyEmptyDim) {
+    return;
+  }
+  dim = 0;
+  for (Subscript &ss : ref.subscript()) {
+    auto dimLB{ToInt64(lb[dim])};
+    auto dimUB{ToInt64(ub[dim])};
+    std::optional<ConstantSubscript> val[2];
+    int vals{0};
+    if (auto *triplet{std::get_if<Triplet>(&ss.u)}) {
+      auto stride{ToInt64(triplet->stride())};
+      std::optional<ConstantSubscript> lower, upper;
+      if (const auto *lowerExpr{triplet->GetLower()}) {
+        lower = ToInt64(*lowerExpr);
+      } else if (lb[dim]) {
+        lower = ToInt64(*lb[dim]);
+      }
+      if (const auto *upperExpr{triplet->GetUpper()}) {
+        upper = ToInt64(*upperExpr);
+      } else if (ub[dim]) {
+        upper = ToInt64(*ub[dim]);
+      }
+      if (stride && *stride != 0 && lower && upper) {
+        // Normalize upper bound for non-unit stride
+        // 1:10:2 -> 1:9:2, 10:1:-2 -> 10:2:-2
+        *upper = *lower + *stride * ((*upper - *lower) / *stride);
+        val[vals++] = lower;
+        val[vals++] = upper;
+      }
+    } else {
+      val[vals++] =
+          ToInt64(std::get<IndirectSubscriptIntegerExpr>(ss.u).value());
+    }
+    for (int j{0}; j < vals; ++j) {
+      if (val[j]) {
+        if (dimLB && *val[j] < *dimLB) {
+          AttachDeclaration(
+              Say("Subscript %jd is less than lower bound %jd for dimension %d of array"_err_en_US,
+                  static_cast<std::intmax_t>(*val[j]),
+                  static_cast<std::intmax_t>(*dimLB), dim + 1),
+              ref.base().GetLastSymbol());
+        }
+        if (dimUB && *val[j] > *dimUB) {
+          AttachDeclaration(
+              Say("Subscript %jd is greater than upper bound %jd for dimension %d of array"_err_en_US,
+                  static_cast<std::intmax_t>(*val[j]),
+                  static_cast<std::intmax_t>(*dimUB), dim + 1),
+              ref.base().GetLastSymbol());
+        }
+      }
+    }
+    ++dim;
+  }
+}
+
 // C919a - only one part-ref of a data-ref may have rank > 0
 bool ExpressionAnalyzer::CheckRanks(const DataRef &dataRef) {
   return common::visit(
@@ -4098,6 +4209,15 @@ evaluate::Expr<evaluate::SubscriptInteger> AnalyzeKindSelector(
 
 ExprChecker::ExprChecker(SemanticsContext &context) : context_{context} {}
 
+bool ExprChecker::Pre(const parser::DataStmtObject &obj) {
+  exprAnalyzer_.set_inDataStmtObject(true);
+  return true;
+}
+
+void ExprChecker::Post(const parser::DataStmtObject &obj) {
+  exprAnalyzer_.set_inDataStmtObject(false);
+}
+
 bool ExprChecker::Pre(const parser::DataImpliedDo &ido) {
   parser::Walk(std::get<parser::DataImpliedDo::Bounds>(ido.t), *this);
   const auto &bounds{std::get<parser::DataImpliedDo::Bounds>(ido.t)};

diff  --git a/flang/lib/Semantics/type.cpp b/flang/lib/Semantics/type.cpp
index b8fc2a67d5776..04f1729e910c8 100644
--- a/flang/lib/Semantics/type.cpp
+++ b/flang/lib/Semantics/type.cpp
@@ -325,28 +325,33 @@ void DerivedTypeSpec::Instantiate(Scope &containingScope) {
     const SourceName &name{symbol.name()};
     if (typeScope.find(symbol.name()) != typeScope.end()) {
       // This type parameter belongs to the derived type itself, not to
-      // one of its ancestors.  Put the type parameter expression value
-      // into the new scope as the initialization value for the parameter.
+      // one of its ancestors.  Put the type parameter expression value,
+      // when there is one, into the new scope as the initialization value
+      // for the parameter.  And when there is no explicit value, add an
+      // uninitialized type parameter to forestall use of any default.
       if (ParamValue * paramValue{FindParameter(name)}) {
         const TypeParamDetails &details{symbol.get<TypeParamDetails>()};
         paramValue->set_attr(details.attr());
+        TypeParamDetails instanceDetails{details.attr()};
+        if (const DeclTypeSpec * type{details.type()}) {
+          instanceDetails.set_type(*type);
+        }
+        desc += sep;
+        desc += name.ToString();
+        desc += '=';
+        sep = ',';
         if (MaybeIntExpr expr{paramValue->GetExplicit()}) {
           if (auto folded{evaluate::NonPointerInitializationExpr(symbol,
                   SomeExpr{std::move(*expr)}, foldingContext, &newScope)}) {
-            desc += sep;
-            desc += name.ToString();
-            desc += '=';
             desc += folded->AsFortran();
-            sep = ',';
-            TypeParamDetails instanceDetails{details.attr()};
-            if (const DeclTypeSpec * type{details.type()}) {
-              instanceDetails.set_type(*type);
-            }
             instanceDetails.set_init(
                 std::move(DEREF(evaluate::UnwrapExpr<SomeIntExpr>(*folded))));
-            newScope.try_emplace(name, std::move(instanceDetails));
           }
         }
+        if (!instanceDetails.init()) {
+          desc += '*';
+        }
+        newScope.try_emplace(name, std::move(instanceDetails));
       }
     }
   }

diff  --git a/flang/test/Lower/OpenACC/acc-data-operands.f90 b/flang/test/Lower/OpenACC/acc-data-operands.f90
index 002c021e8f486..4081c993fda22 100644
--- a/flang/test/Lower/OpenACC/acc-data-operands.f90
+++ b/flang/test/Lower/OpenACC/acc-data-operands.f90
@@ -21,12 +21,11 @@ subroutine acc_operand_array_section()
 
   !CHECK: %[[ARR:.*]] = fir.alloca !fir.array<100xf32>
 
-  !CHECK: %[[C1:.*]] = fir.convert %c1_i32 : (i32) -> i64
+  !CHECK: %[[C1:.*]] = arith.constant 1 : i64
   !CHECK: %[[LB1:.*]] = fir.convert %[[C1]] : (i64) -> index
   !CHECK: %[[C1_I64:.*]] = arith.constant 1 : i64
   !CHECK: %[[STEP1:.*]] = fir.convert %[[C1_I64]] : (i64) -> index
-  !CHECK: %[[C50:.*]] = arith.constant 50 : i32
-  !CHECK: %[[C50_I64:.*]] = fir.convert %[[C50]] : (i32) -> i64
+  !CHECK: %[[C50_I64:.*]] = arith.constant 50 : i64
   !CHECK: %[[UB1:.*]] = fir.convert %[[C50_I64]] : (i64) -> index
   !CHECK: %[[SHAPE1:.*]] = fir.shape %{{.*}} : (index) -> !fir.shape<1>
   !CHECK: %[[SLICE1:.*]] = fir.slice %[[LB1]], %[[UB1]], %[[STEP1]] : (index, index, index) -> !fir.slice<1>
@@ -34,13 +33,11 @@ subroutine acc_operand_array_section()
   !CHECK: %[[MEM1:.*]] = fir.alloca !fir.box<!fir.array<50xf32>>
   !CHECK: fir.store %[[ARR_SECTION1]] to %[[MEM1]] : !fir.ref<!fir.box<!fir.array<50xf32>>>
 
-  !CHECK: %[[C51:.*]] = arith.constant 51 : i32
-  !CHECK: %[[C51_I64:.*]] = fir.convert %[[C51]] : (i32) -> i64
+  !CHECK: %[[C51_I64:.*]] = arith.constant 51 : i64
   !CHECK: %[[LB2:.*]] = fir.convert %[[C51_I64]] : (i64) -> index
   !CHECK: %[[C1_I64:.*]] = arith.constant 1 : i64
   !CHECK: %[[STEP2:.*]] = fir.convert %[[C1_I64]] : (i64) -> index
-  !CHECK: %[[C100:.*]] = arith.constant 100 : i32
-  !CHECK: %[[C100_I64:.*]] = fir.convert %[[C100]] : (i32) -> i64
+  !CHECK: %[[C100_I64:.*]] = arith.constant 100 : i64
   !CHECK: %[[UB2:.*]] = fir.convert %[[C100_I64]] : (i64) -> index
   !CHECK: %[[SHAPE2:.*]] = fir.shape %{{.*}} : (index) -> !fir.shape<1>
   !CHECK: %[[SLICE2:.*]] = fir.slice %[[LB2]], %[[UB2]], %[[STEP2]] : (index, index, index) -> !fir.slice<1>
@@ -64,13 +61,11 @@ subroutine acc_operand_array_section_component()
   !CHECK: %[[W:.*]] = fir.alloca !fir.type<_QMacc_data_operandTwrapper{data:!fir.array<100xf32>}>
   !CHECK: %[[FIELD_INDEX:.*]] = fir.field_index data, !fir.type<_QMacc_data_operandTwrapper{data:!fir.array<100xf32>}>
   !CHECK: %[[DATA_COORD:.*]] = fir.coordinate_of %[[W]], %[[FIELD_INDEX]] : (!fir.ref<!fir.type<_QMacc_data_operandTwrapper{data:!fir.array<100xf32>}>>, !fir.field) -> !fir.ref<!fir.array<100xf32>>
-  !CHECK: %[[C1:.*]] = arith.constant 1 : i32
-  !CHECK: %[[C1_I64:.*]] = fir.convert %[[C1]] : (i32) -> i64
-  !CHECK: %[[LB:.*]] = fir.convert %3 : (i64) -> index
-  !CHECK: %[[C1_I64:.*]] = arith.constant 1 : i64
-  !CHECK: %[[STEP:.*]] = fir.convert %[[C1_I64]] : (i64) -> index
-  !CHECK: %[[C20:.*]] = arith.constant 20 : i32
-  !CHECK: %[[C20_I64:.*]] = fir.convert %[[C20]] : (i32) -> i64
+  !CHECK: %[[C1_I64_1:.*]] = arith.constant 1 : i64
+  !CHECK: %[[LB:.*]] = fir.convert %[[C1_I64_1]] : (i64) -> index
+  !CHECK: %[[C1_I64_2:.*]] = arith.constant 1 : i64
+  !CHECK: %[[STEP:.*]] = fir.convert %[[C1_I64_2]] : (i64) -> index
+  !CHECK: %[[C20_I64:.*]] = arith.constant 20 : i64
   !CHECK: %[[UB:.*]] = fir.convert %[[C20_I64]] : (i64) -> index
   !CHECK: %[[SHAPE:.*]] = fir.shape %{{.*}} : (index) -> !fir.shape<1>
   !CHECK: %[[SLICE:.*]] = fir.slice %[[LB]], %[[UB]], %[[STEP]] : (index, index, index) -> !fir.slice<1>
@@ -105,7 +100,9 @@ subroutine acc_operand_array_derived_type_component()
 
   !CHECK-LABEL: func.func @_QMacc_data_operandPacc_operand_array_derived_type_component
   !CHECK: %[[W:.*]] = fir.alloca !fir.array<10x!fir.type<_QMacc_data_operandTwrapper{data:!fir.array<100xf32>}>>
-  !CHECK: %[[IDX:.*]] = arith.subi %{{.*}}, %c1_i64 : i64
+  !CHECK: %[[C1_I64_1:.*]] = arith.constant 1 : i64
+  !CHECK: %[[C1_I64_2:.*]] = arith.constant 1 : i64
+  !CHECK: %[[IDX:.*]] = arith.subi %[[C1_I64_1]], %[[C1_I64_2]] : i64
   !CHECK: %[[COORD1:.*]] = fir.coordinate_of %[[W]], %[[IDX]] : (!fir.ref<!fir.array<10x!fir.type<_QMacc_data_operandTwrapper{data:!fir.array<100xf32>}>>>, i64) -> !fir.ref<!fir.type<_QMacc_data_operandTwrapper{data:!fir.array<100xf32>}>>
   !CHECK: %[[COORD2:.*]] = fir.field_index data, !fir.type<_QMacc_data_operandTwrapper{data:!fir.array<100xf32>}>
   !CHECK: %[[COORD_OF:.*]] = fir.coordinate_of %[[COORD1]], %[[COORD2]] : (!fir.ref<!fir.type<_QMacc_data_operandTwrapper{data:!fir.array<100xf32>}>>, !fir.field) -> !fir.ref<!fir.array<100xf32>>
@@ -125,13 +122,11 @@ subroutine acc_operand_array_section_allocatable()
   !CHECK: %[[ARR_HEAP:.*]] = fir.alloca !fir.heap<!fir.array<?xf32>> {uniq_name = "_QMacc_data_operandFacc_operand_array_section_allocatableEa.addr"}
 
   !CHECK: %[[LOAD_ARR0:.*]] = fir.load %[[ARR_HEAP]] : !fir.ref<!fir.heap<!fir.array<?xf32>>>
-  !CHECK: %[[C1_I32:.*]] = arith.constant 1 : i32
-  !CHECK: %[[C1_I64:.*]] = fir.convert %[[C1_I32]] : (i32) -> i64
+  !CHECK: %[[C1_I64:.*]] = arith.constant 1 : i64
   !CHECK: %[[LB0:.*]] = fir.convert %[[C1_I64]] : (i64) -> index
   !CHECK: %[[C1_STEP:.*]] = arith.constant 1 : i64
   !CHECK: %[[STEP0:.*]] = fir.convert %[[C1_STEP]] : (i64) -> index
-  !CHECK: %[[C50_I32:.*]] = arith.constant 50 : i32
-  !CHECK: %[[C50_I64:.*]] = fir.convert %[[C50_I32]] : (i32) -> i64
+  !CHECK: %[[C50_I64:.*]] = arith.constant 50 : i64
   !CHECK: %[[UB0:.*]] = fir.convert %[[C50_I64]] : (i64) -> index
   !CHECK: %[[SHAPE_SHIFT0:.*]] = fir.shape_shift %{{.*}}, %{{.*}} : (index, index) -> !fir.shapeshift<1>
   !CHECK: %[[SLICE0:.*]] = fir.slice %[[LB0]], %[[UB0]], %[[STEP0]] : (index, index, index) -> !fir.slice<1>
@@ -140,13 +135,11 @@ subroutine acc_operand_array_section_allocatable()
   !CHECK: fir.store %[[ARR_SECTION0]] to %[[MEM0]] : !fir.ref<!fir.box<!fir.array<50xf32>>>
 
   !CHECK: %[[LOAD_ARR1:.*]] = fir.load %[[ARR_HEAP]] : !fir.ref<!fir.heap<!fir.array<?xf32>>>
-  !CHECK: %[[C51_I32:.*]] = arith.constant 51 : i32
-  !CHECK: %[[C51_I64:.*]] = fir.convert %[[C51_I32]] : (i32) -> i64
+  !CHECK: %[[C51_I64:.*]] = arith.constant 51 : i64
   !CHECK: %[[LB1:.*]] = fir.convert %[[C51_I64]] : (i64) -> index
   !CHECK: %[[C1_STEP:.*]] = arith.constant 1 : i64
   !CHECK: %[[STEP1:.*]] = fir.convert %[[C1_STEP]] : (i64) -> index
-  !CHECK: %[[C100_I32:.*]] = arith.constant 100 : i32
-  !CHECK: %[[C100_I64:.*]] = fir.convert %[[C100_I32]] : (i32) -> i64
+  !CHECK: %[[C100_I64:.*]] = arith.constant 100 : i64
   !CHECK: %[[UB1:.*]] = fir.convert %[[C100_I64]] : (i64) -> index
   !CHECK: %[[SHAPE_SHIFT1:.*]] = fir.shape_shift %{{.*}}, %{{.*}} : (index, index) -> !fir.shapeshift<1>
   !CHECK: %[[SLICE1:.*]] = fir.slice %[[LB1]], %[[UB1]], %[[STEP1]] : (index, index, index) -> !fir.slice<1>
@@ -179,13 +172,11 @@ subroutine acc_operand_array_section_pointer()
   !CHECK: %[[PTR_LOAD:.*]] = fir.load %[[PTR]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>
   !CHECK: %[[C0:.*]] = arith.constant 0 : index
   !CHECK: %[[BOX_DIMS:.*]]:3 = fir.box_dims %[[PTR_LOAD]], %[[C0]] : (!fir.box<!fir.ptr<!fir.array<?xf32>>>, index) -> (index, index, index)
-  !CHECK: %[[C1_I32:.*]] = arith.constant 1 : i32
-  !CHECK: %[[C1_I64:.*]] = fir.convert %[[C1_I32]] : (i32) -> i64
+  !CHECK: %[[C1_I64:.*]] = arith.constant 1 : i64
   !CHECK: %[[LB0:.*]] = fir.convert %[[C1_I64]] : (i64) -> index
   !CHECK: %[[C1_STEP:.*]] = arith.constant 1 : i64
   !CHECK: %[[STEP0:.*]] = fir.convert %[[C1_STEP]] : (i64) -> index
-  !CHECK: %[[C50_I32:.*]] = arith.constant 50 : i32
-  !CHECK: %[[C50_I64:.*]] = fir.convert %[[C50_I32]] : (i32) -> i64
+  !CHECK: %[[C50_I64:.*]] = arith.constant 50 : i64
   !CHECK: %[[UB0:.*]] = fir.convert %[[C50_I64]] : (i64) -> index
   !CHECK: %[[SHIFT0:.*]] = fir.shift %[[BOX_DIMS]]#0 : (index) -> !fir.shift<1>
   !CHECK: %[[SLICE0:.*]] = fir.slice %[[LB0]], %[[UB0]], %[[STEP0]] : (index, index, index) -> !fir.slice<1>

diff  --git a/flang/test/Lower/explicit-interface-results.f90 b/flang/test/Lower/explicit-interface-results.f90
index 7cec69fd62009..7821c4041b969 100644
--- a/flang/test/Lower/explicit-interface-results.f90
+++ b/flang/test/Lower/explicit-interface-results.f90
@@ -383,9 +383,9 @@ function test_recursion(n) result(res)
   ! CHECK: fir.alloca !fir.array<?xi32>, {{.*}}some_local
   ! CHECK-NOT: fir.alloca !fir.array<?xi32>
   integer :: some_local(n)
-  some_local(0) = n + 64
+  some_local(1) = n + 64
   if (n.eq.1) then
-    res = char(some_local(0))
+    res = char(some_local(1))
   ! CHECK: else
   else 
     ! CHECK-NOT: fir.alloca !fir.array<?xi32>
@@ -407,7 +407,7 @@ function test_recursion(n) result(res)
 
     ! CHECK-NOT: fir.alloca !fir.array<?xi32>
     ! CHECK: fir.call @_QPtest_recursion(%[[tmp]], {{.*}}
-    res = char(some_local(0)) // test_recursion(n-1)
+    res = char(some_local(1)) // test_recursion(n-1)
 
     ! Verify that symbol n was not remapped to the actual argument passed
     ! to n in the call (that the temporary mapping was cleaned-up).

diff  --git a/flang/test/Semantics/allocate10.f90 b/flang/test/Semantics/allocate10.f90
index 5f7a1e5e719bb..eaa17d391a690 100644
--- a/flang/test/Semantics/allocate10.f90
+++ b/flang/test/Semantics/allocate10.f90
@@ -96,7 +96,7 @@ subroutine C939_C942a_C945b(xsrc1a, xsrc1c, xsrc0, xsrc2a, xsrc2c, pos)
 
  ! Test the check is not influenced by SOURCE
  !ERROR: The number of shape specifications, when they appear, must match the rank of allocatable object
- allocate(a1%x(5, 4, 3), SOURCE=xsrc2a(1:5, 1:4, 1:3))
+ allocate(a1%x(5, 4, 3), SOURCE=xsrc2a(4:8, 1:4, 1:3))
  !ERROR: The number of shape specifications, when they appear, must match the rank of allocatable object
  allocate(x2(5), MOLD=xsrc1a(1:5))
  !ERROR: The number of shape specifications, when they appear, must match the rank of allocatable object

diff  --git a/flang/test/Semantics/allocate11.f90 b/flang/test/Semantics/allocate11.f90
index 960d45ffc7ee3..6440248b6f4a9 100644
--- a/flang/test/Semantics/allocate11.f90
+++ b/flang/test/Semantics/allocate11.f90
@@ -146,7 +146,7 @@ subroutine C938_C947(var2, ptr, ptr2, fptr, my_team, srca)
   !ERROR: SOURCE or MOLD expression type must not be C_PTR or C_FUNPTR from ISO_C_BINDING when an allocatable object is a coarray
   allocate(var[5:*], SOURCE=ptr)
   !ERROR: SOURCE or MOLD expression type must not be C_PTR or C_FUNPTR from ISO_C_BINDING when an allocatable object is a coarray
-  allocate(varok, var[5:*], MOLD=ptr2(1))
+  allocate(varok, var[5:*], MOLD=ptr2(2))
   !ERROR: SOURCE or MOLD expression type must not be C_PTR or C_FUNPTR from ISO_C_BINDING when an allocatable object is a coarray
   allocate(var[5:*], MOLD=fptr)
   !ERROR: SOURCE or MOLD expression type must not be TEAM_TYPE from ISO_FORTRAN_ENV when an allocatable object is a coarray

diff  --git a/flang/test/Semantics/data04.f90 b/flang/test/Semantics/data04.f90
index 79bec29f9807d..777ddbf2d6b29 100644
--- a/flang/test/Semantics/data04.f90
+++ b/flang/test/Semantics/data04.f90
@@ -36,7 +36,7 @@ function f(i)
       DATA a /1/
       !C876
       !ERROR: Automatic variable 'b' must not be initialized in a DATA statement
-      DATA b(0) /1/
+      DATA b(1) /1/
       !C876
       !Ok: As charPtr is a pointer, it is not an automatic object
       DATA charPtr / NULL() /

diff  --git a/flang/test/Semantics/expr-errors06.f90 b/flang/test/Semantics/expr-errors06.f90
new file mode 100644
index 0000000000000..ad5baf708f34c
--- /dev/null
+++ b/flang/test/Semantics/expr-errors06.f90
@@ -0,0 +1,29 @@
+! RUN: %python %S/test_errors.py %s %flang_fc1 -Werror
+! Check out-of-range subscripts
+real a(10)
+integer, parameter :: n(2) = [1, 2]
+!ERROR: DATA statement designator 'a(0_8)' is out of range
+!ERROR: DATA statement designator 'a(11_8)' is out of range
+data a(0)/0./, a(10+1)/0./
+!ERROR: Subscript 0 is less than lower bound 1 for dimension 1 of array
+print *, a(0)
+!ERROR: Subscript 0 is less than lower bound 1 for dimension 1 of array
+print *, a(1-1)
+!ERROR: Subscript 11 is greater than upper bound 10 for dimension 1 of array
+print *, a(11)
+!ERROR: Subscript 11 is greater than upper bound 10 for dimension 1 of array
+print *, a(10+1)
+!ERROR: Subscript value (0) is out of range on dimension 1 in reference to a constant array value
+print *, n(0)
+!ERROR: Subscript value (3) is out of range on dimension 1 in reference to a constant array value
+print *, n(4-1)
+print *, a(1:12:3) ! ok
+!ERROR: Subscript 13 is greater than upper bound 10 for dimension 1 of array
+print *, a(1:13:3)
+print *, a(10:-1:-3) ! ok
+!ERROR: Subscript -2 is less than lower bound 1 for dimension 1 of array
+print *, a(10:-2:-3)
+print *, a(-1:-2) ! empty section is ok
+print *, a(0:11:-1) ! empty section is ok
+end
+


        


More information about the flang-commits mailing list