Skip to content

Commit 5242018

Browse files
authored
[flang] Catch attempts to subscribe empty arrays (llvm#108246)
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.
1 parent 1595ca4 commit 5242018

File tree

3 files changed

+17
-4
lines changed

3 files changed

+17
-4
lines changed

flang/include/flang/Semantics/expression.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,7 @@ class ExpressionAnalyzer {
331331
const semantics::Scope &, bool C919bAlreadyEnforced = false);
332332
MaybeExpr CompleteSubscripts(ArrayRef &&);
333333
MaybeExpr ApplySubscripts(DataRef &&, std::vector<Subscript> &&);
334-
void CheckConstantSubscripts(ArrayRef &);
334+
void CheckSubscripts(ArrayRef &);
335335
bool CheckRanks(const DataRef &); // Return false if error exists.
336336
bool CheckPolymorphic(const DataRef &); // ditto
337337
bool CheckDataRef(const DataRef &); // ditto

flang/lib/Semantics/expression.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,7 @@ MaybeExpr ExpressionAnalyzer::CompleteSubscripts(ArrayRef &&ref) {
298298
// Subscripts of named constants are checked in folding.
299299
// Subscripts of DATA statement objects are checked in data statement
300300
// conversion to initializers.
301-
CheckConstantSubscripts(ref);
301+
CheckSubscripts(ref);
302302
}
303303
return Designate(DataRef{std::move(ref)});
304304
}
@@ -326,7 +326,7 @@ MaybeExpr ExpressionAnalyzer::ApplySubscripts(
326326
std::move(dataRef.u));
327327
}
328328

329-
void ExpressionAnalyzer::CheckConstantSubscripts(ArrayRef &ref) {
329+
void ExpressionAnalyzer::CheckSubscripts(ArrayRef &ref) {
330330
// Fold subscript expressions and check for an empty triplet.
331331
const Symbol &arraySymbol{ref.base().GetLastSymbol()};
332332
Shape lb{GetLBOUNDs(foldingContext_, NamedEntity{arraySymbol})};
@@ -390,6 +390,13 @@ void ExpressionAnalyzer::CheckConstantSubscripts(ArrayRef &ref) {
390390
for (Subscript &ss : ref.subscript()) {
391391
auto dimLB{ToInt64(lb[dim])};
392392
auto dimUB{ToInt64(ub[dim])};
393+
if (dimUB && dimLB && *dimUB < *dimLB) {
394+
AttachDeclaration(
395+
Say("Empty array dimension %d cannot be subscripted as an element or non-empty array section"_err_en_US,
396+
dim + 1),
397+
arraySymbol);
398+
break;
399+
}
393400
std::optional<ConstantSubscript> val[2];
394401
int vals{0};
395402
if (auto *triplet{std::get_if<Triplet>(&ss.u)}) {

flang/test/Semantics/expr-errors06.f90

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
! RUN: %python %S/test_errors.py %s %flang_fc1 -Werror
22
! Check out-of-range subscripts
33
subroutine subr(da)
4-
real a(10), da(2,1)
4+
real a(10), da(2,1), empty(1:0,1)
55
integer, parameter :: n(2) = [1, 2]
66
integer unknown
77
!ERROR: DATA statement designator 'a(0_8)' is out of range
@@ -39,4 +39,10 @@ subroutine subr(da)
3939
print *, da(1,0)
4040
!WARNING: Subscript 2 is greater than upper bound 1 for dimension 2 of array
4141
print *, da(1,2)
42+
print *, empty([(j,j=1,0)],1) ! ok
43+
print *, empty(1:0,1) ! ok
44+
print *, empty(:,1) ! ok
45+
print *, empty(i:j,k) ! ok
46+
!ERROR: Empty array dimension 1 cannot be subscripted as an element or non-empty array section
47+
print *, empty(i,1)
4248
end

0 commit comments

Comments
 (0)