[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