Skip to content

Commit 5a9497d

Browse files
committed
[flang] Allow large and erroneous ac-implied-do's
We sometimes unroll an ac-implied-do of an array constructor into a flat list of values. We then re-analyze the array constructor that contains the resulting list of expressions. Such a list may or may not contain errors. But when processing an array constructor with an unrolled ac-implied-do, the compiler was building an expression to represent the extent of the resulting array constructor containing the list of values. The number of operands in this extent expression was based on the number of elements in the unrolled list of values. For very large lists, this created an expression so large that it could not be evaluated by the compiler without overflowing the stack. I fixed this by continuously folding the extent expression as each operand is added to it. I added the test .../flang/test/Semantics/array-constr-big.f90 that will cause the compiler to seg fault without this change. Also, when the unrolled ac-implied-do expression contains errors, we were repeating the same error message referencing the same source line for every instance of the erroneous expression in the unrolled list. This potentially resulted in a very long list of messages for a single error in the source code. I fixed this by comparing the message being emitted to the previously emitted message. If they are the same, I do not emit the message. This change is also tested by the new test array-constr-big.f90. Several of the existing tests had duplicate error messages for the same source line, and this change caused differences in their output. So I adjusted the tests to match the new message emitting behavior. Differential Revision: https://reviews.llvm.org/D102210
1 parent cba508f commit 5a9497d

File tree

10 files changed

+62
-10
lines changed

10 files changed

+62
-10
lines changed

flang/include/flang/Evaluate/shape.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#define FORTRAN_EVALUATE_SHAPE_H_
1414

1515
#include "expression.h"
16+
#include "fold.h"
1617
#include "traverse.h"
1718
#include "variable.h"
1819
#include "flang/Common/indirection.h"
@@ -180,6 +181,11 @@ class GetShapeHelper
180181
for (const auto &value : values) {
181182
if (MaybeExtentExpr n{GetArrayConstructorValueExtent(value)}) {
182183
result = std::move(result) + std::move(*n);
184+
if (context_) {
185+
// Fold during expression creation to avoid creating an expression so
186+
// large we can't evalute it without overflowing the stack.
187+
result = Fold(*context_, std::move(result));
188+
}
183189
} else {
184190
return std::nullopt;
185191
}

flang/include/flang/Parser/message.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,10 +200,11 @@ class Message : public common::ReferenceCounted<Message> {
200200
return std::holds_alternative<MessageExpectedText>(text_);
201201
}
202202
bool Merge(const Message &);
203+
bool operator==(const Message &that) const;
204+
bool operator!=(const Message &that) const { return !(*this == that); }
203205

204206
private:
205207
bool AtSameLocation(const Message &) const;
206-
207208
std::variant<ProvenanceRange, CharBlock> location_;
208209
std::variant<MessageFixedText, MessageFormattedText, MessageExpectedText>
209210
text_;

flang/lib/Parser/message.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,26 @@ void Message::Emit(llvm::raw_ostream &o, const AllCookedSources &allCooked,
211211
}
212212
}
213213

214+
// Messages are equal if they're for the same location and text, and the user
215+
// visible aspects of their attachments are the same
216+
bool Message::operator==(const Message &that) const {
217+
if (!AtSameLocation(that) || ToString() != that.ToString()) {
218+
return false;
219+
}
220+
const Message *thatAttachment{that.attachment_.get()};
221+
for (const Message *attachment{attachment_.get()}; attachment;
222+
attachment = attachment->attachment_.get()) {
223+
if (!thatAttachment ||
224+
attachment->attachmentIsContext_ !=
225+
thatAttachment->attachmentIsContext_ ||
226+
*attachment != *thatAttachment) {
227+
return false;
228+
}
229+
thatAttachment = thatAttachment->attachment_.get();
230+
}
231+
return true;
232+
}
233+
214234
bool Message::Merge(const Message &that) {
215235
return AtSameLocation(that) &&
216236
(!that.attachment_.get() ||
@@ -305,8 +325,14 @@ void Messages::Emit(llvm::raw_ostream &o, const AllCookedSources &allCooked,
305325
}
306326
std::stable_sort(sorted.begin(), sorted.end(),
307327
[](const Message *x, const Message *y) { return x->SortBefore(*y); });
328+
const Message *lastMsg{nullptr};
308329
for (const Message *msg : sorted) {
330+
if (lastMsg && *msg == *lastMsg) {
331+
// Don't emit two identical messages for the same location
332+
continue;
333+
}
309334
msg->Emit(o, allCooked, echoSourceLines);
335+
lastMsg = msg;
310336
}
311337
}
312338

flang/test/Semantics/allocate02.f90

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,5 @@ subroutine C943_C944(src, src2)
4444
!ERROR: At most one of source-expr and type-spec may appear in a ALLOCATE statement
4545
allocate(y3, source=src, stat=stat, errmsg=msg, mold=mld)
4646
!ERROR: At most one of source-expr and type-spec may appear in a ALLOCATE statement
47-
!ERROR: At most one of source-expr and type-spec may appear in a ALLOCATE statement
4847
allocate(real:: y4, source=src, stat=stat, errmsg=msg, mold=mld)
4948
end subroutine
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
! RUN: %S/test_errors.sh %s %t %flang_fc1
2+
! Ensure that evaluating a very large array constructor does not crash the
3+
! compiler
4+
program BigArray
5+
integer, parameter :: limit = 30
6+
!ERROR: Must be a constant value
7+
integer(foo),parameter :: jval4(limit,limit,limit) = &
8+
!ERROR: Must be a constant value
9+
reshape( (/ &
10+
( &
11+
( &
12+
(0,ii=1,limit), &
13+
jj=-limit,kk &
14+
), &
15+
( &
16+
i4,jj=-kk,kk &
17+
), &
18+
( &
19+
( &
20+
!ERROR: Must be a constant value
21+
0_foo,ii=1,limit &
22+
),
23+
jj=kk,limit &
24+
), &
25+
kk=1,limit &
26+
) /), &
27+
(/ limit /) )
28+
end

flang/test/Semantics/io06.f90

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@
3535
!ERROR: REWIND statement must have a UNIT number specifier
3636
rewind(iostat=stat2)
3737

38-
!ERROR: Duplicate ERR specifier
3938
!ERROR: Duplicate ERR specifier
4039
flush(err=9, unit=10, &
4140
err=9, &

flang/test/Semantics/omp-atomic.f90

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
a = a + 1
2828
!$omp end atomic
2929

30-
!ERROR: expected end of line
3130
!ERROR: expected end of line
3231
!$omp atomic read write
3332
a = a + 1
@@ -41,7 +40,6 @@
4140
!$omp atomic num_threads(4)
4241
a = a + 1
4342

44-
!ERROR: expected end of line
4543
!ERROR: expected end of line
4644
!$omp atomic capture num_threads(4)
4745
a = a + 1

flang/test/Semantics/omp-clause-validity01.f90

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,6 @@
215215
a = 3.14
216216
enddo
217217

218-
!ERROR: Clause LINEAR is not allowed if clause ORDERED appears on the DO directive
219218
!ERROR: Clause LINEAR is not allowed if clause ORDERED appears on the DO directive
220219
!ERROR: The parameter of the ORDERED clause must be a constant positive integer expression
221220
!$omp do ordered(1-1) private(b) linear(b) linear(a)

flang/test/Semantics/omp-flush01.f90

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,13 @@
2222
array = (/1, 2, 3, 4, 5, 6, 7, 8, 9, 10/)
2323
!$omp flush acquire
2424

25-
!ERROR: expected end of line
2625
!ERROR: expected end of line
2726
!$omp flush private(array)
2827
!ERROR: expected end of line
29-
!ERROR: expected end of line
3028
!$omp flush num_threads(4)
3129

3230
! Mix allowed and not allowed clauses.
3331
!ERROR: expected end of line
34-
!ERROR: expected end of line
3532
!$omp flush num_threads(4) acquire
3633
end if
3734
!$omp end parallel

flang/test/Semantics/resolve70.f90

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ subroutine s()
2424

2525
! ac-spec for an array constructor
2626
!ERROR: ABSTRACT derived type may not be used here
27-
!ERROR: ABSTRACT derived type may not be used here
2827
type (abstractType), parameter :: abstractArray(*) = (/ abstractType :: /)
2928

3029
class(*), allocatable :: selector

0 commit comments

Comments
 (0)