-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[flang] Catch attempts to subscribe empty arrays #108246
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
An array that has one or more empty dimensions cannot have subscripts unless there's a possibility that they constitute an empty array section. We previously only checked that constant subscripts are in bounds.
@llvm/pr-subscribers-flang-semantics Author: Peter Klausler (klausler) ChangesAn array that has one or more empty dimensions cannot have subscripts unless there's a possibility that they constitute an empty array section. We previously only checked that constant subscripts are in bounds. Full diff: https://github.com/llvm/llvm-project/pull/108246.diff 3 Files Affected:
diff --git a/flang/include/flang/Semantics/expression.h b/flang/include/flang/Semantics/expression.h
index b1304d704232dc..c90c8c4b3cc70f 100644
--- a/flang/include/flang/Semantics/expression.h
+++ b/flang/include/flang/Semantics/expression.h
@@ -331,7 +331,7 @@ class ExpressionAnalyzer {
const semantics::Scope &, bool C919bAlreadyEnforced = false);
MaybeExpr CompleteSubscripts(ArrayRef &&);
MaybeExpr ApplySubscripts(DataRef &&, std::vector<Subscript> &&);
- void CheckConstantSubscripts(ArrayRef &);
+ void CheckSubscripts(ArrayRef &);
bool CheckRanks(const DataRef &); // Return false if error exists.
bool CheckPolymorphic(const DataRef &); // ditto
bool CheckDataRef(const DataRef &); // ditto
diff --git a/flang/lib/Semantics/expression.cpp b/flang/lib/Semantics/expression.cpp
index 943512f75d7eba..e9252a70868434 100644
--- a/flang/lib/Semantics/expression.cpp
+++ b/flang/lib/Semantics/expression.cpp
@@ -298,7 +298,7 @@ MaybeExpr ExpressionAnalyzer::CompleteSubscripts(ArrayRef &&ref) {
// Subscripts of named constants are checked in folding.
// Subscripts of DATA statement objects are checked in data statement
// conversion to initializers.
- CheckConstantSubscripts(ref);
+ CheckSubscripts(ref);
}
return Designate(DataRef{std::move(ref)});
}
@@ -326,7 +326,7 @@ MaybeExpr ExpressionAnalyzer::ApplySubscripts(
std::move(dataRef.u));
}
-void ExpressionAnalyzer::CheckConstantSubscripts(ArrayRef &ref) {
+void ExpressionAnalyzer::CheckSubscripts(ArrayRef &ref) {
// Fold subscript expressions and check for an empty triplet.
const Symbol &arraySymbol{ref.base().GetLastSymbol()};
Shape lb{GetLBOUNDs(foldingContext_, NamedEntity{arraySymbol})};
@@ -390,6 +390,13 @@ void ExpressionAnalyzer::CheckConstantSubscripts(ArrayRef &ref) {
for (Subscript &ss : ref.subscript()) {
auto dimLB{ToInt64(lb[dim])};
auto dimUB{ToInt64(ub[dim])};
+ if (dimUB && dimLB && *dimUB < *dimLB) {
+ AttachDeclaration(
+ Say("Empty array dimension %d cannot be subscripted as an element or non-empty array section"_err_en_US,
+ dim + 1),
+ arraySymbol);
+ break;
+ }
std::optional<ConstantSubscript> val[2];
int vals{0};
if (auto *triplet{std::get_if<Triplet>(&ss.u)}) {
diff --git a/flang/test/Semantics/expr-errors06.f90 b/flang/test/Semantics/expr-errors06.f90
index 84872c7fcdbc58..bdcb92cbe5e4df 100644
--- a/flang/test/Semantics/expr-errors06.f90
+++ b/flang/test/Semantics/expr-errors06.f90
@@ -1,7 +1,7 @@
! RUN: %python %S/test_errors.py %s %flang_fc1 -Werror
! Check out-of-range subscripts
subroutine subr(da)
- real a(10), da(2,1)
+ real a(10), da(2,1), empty(1:0,1)
integer, parameter :: n(2) = [1, 2]
integer unknown
!ERROR: DATA statement designator 'a(0_8)' is out of range
@@ -39,4 +39,10 @@ subroutine subr(da)
print *, da(1,0)
!WARNING: Subscript 2 is greater than upper bound 1 for dimension 2 of array
print *, da(1,2)
+ print *, empty([(j,j=1,0)],1) ! ok
+ print *, empty(1:0,1) ! ok
+ print *, empty(:,1) ! ok
+ print *, empty(i:j,k) ! ok
+ !ERROR: Empty array dimension 1 cannot be subscripted as an element or non-empty array section
+ print *, empty(i,1)
end
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All builds and tests correctly and looks good.
Sadly, we're observing a regression after this one. The following snippet compiles with classic flang and gfortran, while it fails on the new flang after this commit:
This is surprisingly common in large codebases. |
Ok, I'll downgrade this to an optional warning. |
An array that has one or more empty dimensions cannot have subscripts unless there's a possibility that they constitute an empty array section.
We previously only checked that constant subscripts are in bounds.