diff --git a/flang-rt/include/flang-rt/runtime/format-implementation.h b/flang-rt/include/flang-rt/runtime/format-implementation.h index 8f4eb1161dd1..85dc922bc31b 100644 --- a/flang-rt/include/flang-rt/runtime/format-implementation.h +++ b/flang-rt/include/flang-rt/runtime/format-implementation.h @@ -427,7 +427,11 @@ RT_API_ATTRS int FormatControl::CueUpNextDataEdit( } else { --chars; } - EmitAscii(context, format_ + start, chars); + if constexpr (std::is_base_of_v) { + context.HandleRelativePosition(chars); + } else { + EmitAscii(context, format_ + start, chars); + } } else if (ch == 'H') { // 9HHOLLERITH if (!repeat || *repeat < 1 || offset_ + *repeat > formatLength_) { @@ -435,7 +439,12 @@ RT_API_ATTRS int FormatControl::CueUpNextDataEdit( maybeReversionPoint); return 0; } - EmitAscii(context, format_ + offset_, static_cast(*repeat)); + if constexpr (std::is_base_of_v) { + context.HandleRelativePosition(static_cast(*repeat)); + } else { + EmitAscii( + context, format_ + offset_, static_cast(*repeat)); + } offset_ += *repeat; } else if (ch >= 'A' && ch <= 'Z') { int start{offset_ - 1}; diff --git a/flang-rt/unittests/Runtime/NumericalFormatTest.cpp b/flang-rt/unittests/Runtime/NumericalFormatTest.cpp index a752f9d6c723..f1492d0e39fe 100644 --- a/flang-rt/unittests/Runtime/NumericalFormatTest.cpp +++ b/flang-rt/unittests/Runtime/NumericalFormatTest.cpp @@ -882,6 +882,7 @@ TEST(IOApiTests, EditDoubleInputValues) { {"(F18.1)", " 125", 0x4029000000000000, 0}, {"(F18.2)", " 125", 0x3ff4000000000000, 0}, {"(F18.3)", " 125", 0x3fc0000000000000, 0}, + {"('str',F3.0)", "xxx125", 0x405f400000000000, 0}, {"(-1P,F18.0)", " 125", 0x4093880000000000, 0}, // 1250 {"(1P,F18.0)", " 125", 0x4029000000000000, 0}, // 12.5 {"(BZ,F18.0)", " 125 ", 0x4093880000000000, 0}, // 1250 diff --git a/flang/docs/Extensions.md b/flang/docs/Extensions.md index 00a7e2bac84e..1cc4881438cc 100644 --- a/flang/docs/Extensions.md +++ b/flang/docs/Extensions.md @@ -424,6 +424,10 @@ end * A zero field width is allowed for logical formatted output (`L0`). * `OPEN(..., FORM='BINARY')` is accepted as a legacy synonym for the standard `OPEN(..., FORM='UNFORMATTED', ACCESS='STREAM')`. +* A character string edit descriptor is allowed in an input format + with an optional compilation-time warning. When executed, it + is treated as an 'nX' positioning control descriptor that skips + over the same number of characters, without comparison. ### Extensions supported when enabled by options diff --git a/flang/include/flang/Common/format.h b/flang/include/flang/Common/format.h index da416506ffb5..1650f56140b4 100644 --- a/flang/include/flang/Common/format.h +++ b/flang/include/flang/Common/format.h @@ -430,11 +430,11 @@ template void FormatValidator::NextToken() { } } SetLength(); - if (stmt_ == IoStmtKind::Read && - previousToken_.kind() != TokenKind::DT) { // 13.3.2p6 - ReportError("String edit descriptor in READ format expression"); - } else if (token_.kind() != TokenKind::String) { + if (token_.kind() != TokenKind::String) { ReportError("Unterminated string"); + } else if (stmt_ == IoStmtKind::Read && + previousToken_.kind() != TokenKind::DT) { // 13.3.2p6 + ReportWarning("String edit descriptor in READ format expression"); } break; default: diff --git a/flang/test/Semantics/io09.f90 b/flang/test/Semantics/io09.f90 index 495cbf059005..7fc9d8ffe7b4 100644 --- a/flang/test/Semantics/io09.f90 +++ b/flang/test/Semantics/io09.f90 @@ -1,8 +1,8 @@ -! RUN: %python %S/test_errors.py %s %flang_fc1 - !ERROR: String edit descriptor in READ format expression +! RUN: %python %S/test_errors.py %s %flang_fc1 -pedantic + !WARNING: String edit descriptor in READ format expression read(*,'("abc")') - !ERROR: String edit descriptor in READ format expression + !ERROR: Unterminated string !ERROR: Unterminated format expression read(*,'("abc)')