[flang-commits] [flang] c6cb726 - [flang] Replay a FORMAT at the right position
peter klausler via flang-commits
flang-commits at lists.llvm.org
Tue Jul 21 19:00:35 PDT 2020
Author: peter klausler
Date: 2020-07-21T18:59:49-07:00
New Revision: c6cb726a8c60d97908016fe7fb76cdc88b543db2
URL: https://github.com/llvm/llvm-project/commit/c6cb726a8c60d97908016fe7fb76cdc88b543db2
DIFF: https://github.com/llvm/llvm-project/commit/c6cb726a8c60d97908016fe7fb76cdc88b543db2.diff
LOG: [flang] Replay a FORMAT at the right position
When FORMAT control reaches the final parenthesis and data items
remain, we advance a record and revert to the beginning of the
FORMAT for further items. But when the FORMAT contains any
nested parenthesized group of editing descriptors, possibly
repeated, reversion must be to the beginning of the last such
top-level parenthesized group, including its repetition count.
Reviewed By: sscalpone, PeteSteinfeld
Differential Revision: https://reviews.llvm.org/D84281
Added:
Modified:
flang/runtime/format-implementation.h
flang/unittests/Runtime/hello.cpp
Removed:
################################################################################
diff --git a/flang/runtime/format-implementation.h b/flang/runtime/format-implementation.h
index ce0e08b99005..a4453cd172ea 100644
--- a/flang/runtime/format-implementation.h
+++ b/flang/runtime/format-implementation.h
@@ -225,6 +225,7 @@ int FormatControl<CONTEXT>::CueUpNextDataEdit(Context &context, bool stop) {
while (true) {
std::optional<int> repeat;
bool unlimited{false};
+ auto maybeReversionPoint{offset_};
CharType ch{GetNextChar(context)};
while (ch == ',' || ch == ':') {
// Skip commas, and don't complain if they're missing; the format
@@ -254,6 +255,7 @@ int FormatControl<CONTEXT>::CueUpNextDataEdit(Context &context, bool stop) {
return 0;
}
stack_[height_].start = offset_ - 1; // the '('
+ RUNTIME_CHECK(context, format_[stack_[height_].start] == '(');
if (unlimited || height_ == 0) {
stack_[height_].remaining = Iteration::unlimited;
unlimitedLoopCheck = offset_ - 1;
@@ -265,6 +267,12 @@ int FormatControl<CONTEXT>::CueUpNextDataEdit(Context &context, bool stop) {
} else {
stack_[height_].remaining = 0;
}
+ if (height_ == 1) {
+ // Subtle point (F'2018 13.4 para 9): tha last parenthesized group
+ // at height 1 becomes the restart point after control reaches the
+ // end of the format, including its repeat count.
+ stack_[0].start = maybeReversionPoint - 1;
+ }
++height_;
} else if (height_ == 0) {
context.SignalError(IostatErrorInFormat, "FORMAT lacks initial '('");
@@ -276,14 +284,15 @@ int FormatControl<CONTEXT>::CueUpNextDataEdit(Context &context, bool stop) {
}
context.AdvanceRecord(); // implied / before rightmost )
}
+ auto restart{stack_[height_ - 1].start + 1};
if (stack_[height_ - 1].remaining == Iteration::unlimited) {
- offset_ = stack_[height_ - 1].start + 1;
+ offset_ = restart;
if (offset_ == unlimitedLoopCheck) {
context.SignalError(IostatErrorInFormat,
"Unlimited repetition in FORMAT lacks data edit descriptors");
}
} else if (stack_[height_ - 1].remaining-- > 0) {
- offset_ = stack_[height_ - 1].start + 1;
+ offset_ = restart;
} else {
--height_;
}
@@ -396,7 +405,7 @@ DataEdit FormatControl<CONTEXT>::GetNextDataEdit(
++height_;
}
edit.repeat = 1;
- if (height_ > 1) {
+ if (height_ > 1) { // Subtle: stack_[0].start doesn't necessarily point to '('
int start{stack_[height_ - 1].start};
if (format_[start] != '(') {
if (stack_[height_ - 1].remaining > maxRepeat) {
diff --git a/flang/unittests/Runtime/hello.cpp b/flang/unittests/Runtime/hello.cpp
index 71d49437bfcc..0543571bbb57 100644
--- a/flang/unittests/Runtime/hello.cpp
+++ b/flang/unittests/Runtime/hello.cpp
@@ -38,16 +38,16 @@ static void hello() {
}
static void multiline() {
- char buffer[4][32];
+ char buffer[5][32];
StaticDescriptor<1> staticDescriptor[2];
Descriptor &whole{staticDescriptor[0].descriptor()};
- SubscriptValue extent[]{4};
+ SubscriptValue extent[]{5};
whole.Establish(TypeCode{CFI_type_char}, sizeof buffer[0], &buffer, 1, extent,
CFI_attribute_pointer);
whole.Dump();
whole.Check();
Descriptor §ion{staticDescriptor[1].descriptor()};
- SubscriptValue lowers[]{0}, uppers[]{3}, strides[]{1};
+ SubscriptValue lowers[]{0}, uppers[]{4}, strides[]{1};
section.Establish(whole.type(), whole.ElementBytes(), nullptr, 1, extent,
CFI_attribute_pointer);
if (auto error{
@@ -57,12 +57,16 @@ static void multiline() {
}
section.Dump();
section.Check();
- const char *format{"('?abcde,',T1,'>',T9,A,TL12,A,TR25,'<'//G0,25X,'done')"};
+ const char *format{
+ "('?abcde,',T1,'>',T9,A,TL12,A,TR25,'<'//G0,17X,'abcd',1(2I4))"};
auto cookie{IONAME(BeginInternalArrayFormattedOutput)(
section, format, std::strlen(format))};
IONAME(OutputAscii)(cookie, "WORLD", 5);
IONAME(OutputAscii)(cookie, "HELLO", 5);
IONAME(OutputInteger64)(cookie, 789);
+ for (int j{666}; j <= 999; j += 111) {
+ IONAME(OutputInteger64)(cookie, j);
+ }
if (auto status{IONAME(EndIoStatement)(cookie)}) {
Fail() << "multiline: '" << format << "' failed, status "
<< static_cast<int>(status) << '\n';
@@ -70,7 +74,8 @@ static void multiline() {
test(format,
">HELLO, WORLD <"
" "
- "789 done"
+ "789 abcd 666 777"
+ " 888 999 "
" ",
std::string{buffer[0], sizeof buffer});
}
More information about the flang-commits
mailing list