Index: flang/include/flang/Runtime/io-api.h =================================================================== --- flang/include/flang/Runtime/io-api.h +++ flang/include/flang/Runtime/io-api.h @@ -86,13 +86,15 @@ void **scratchArea = nullptr, std::size_t scratchBytes = 0, const char *sourceFile = nullptr, int sourceLine = 0); Cookie IONAME(BeginInternalArrayFormattedOutput)(const Descriptor &, - const char *format, std::size_t formatLength, void **scratchArea = nullptr, + const char *format, std::size_t formatLength, + const Descriptor *formatDescriptor = nullptr, void **scratchArea = nullptr, std::size_t scratchBytes = 0, const char *sourceFile = nullptr, - int sourceLine = 0, const Descriptor *formatDescriptor = nullptr); + int sourceLine = 0); Cookie IONAME(BeginInternalArrayFormattedInput)(const Descriptor &, - const char *format, std::size_t formatLength, void **scratchArea = nullptr, + const char *format, std::size_t formatLength, + const Descriptor *formatDescriptor = nullptr, void **scratchArea = nullptr, std::size_t scratchBytes = 0, const char *sourceFile = nullptr, - int sourceLine = 0, const Descriptor *formatDescriptor = nullptr); + int sourceLine = 0); // Internal I/O to/from a default-kind character scalar can avoid a // descriptor. @@ -106,14 +108,14 @@ int sourceLine = 0); Cookie IONAME(BeginInternalFormattedOutput)(char *internal, std::size_t internalLength, const char *format, std::size_t formatLength, - void **scratchArea = nullptr, std::size_t scratchBytes = 0, - const char *sourceFile = nullptr, int sourceLine = 0, - const Descriptor *formatDescriptor = nullptr); + const Descriptor *formatDescriptor = nullptr, void **scratchArea = nullptr, + std::size_t scratchBytes = 0, const char *sourceFile = nullptr, + int sourceLine = 0); Cookie IONAME(BeginInternalFormattedInput)(const char *internal, std::size_t internalLength, const char *format, std::size_t formatLength, - void **scratchArea = nullptr, std::size_t scratchBytes = 0, - const char *sourceFile = nullptr, int sourceLine = 0, - const Descriptor *formatDescriptor = nullptr); + const Descriptor *formatDescriptor = nullptr, void **scratchArea = nullptr, + std::size_t scratchBytes = 0, const char *sourceFile = nullptr, + int sourceLine = 0); // External unit numbers must fit in default integers. When the integer // provided as UNIT is of a wider type than the default integer, it could @@ -137,11 +139,11 @@ Cookie IONAME(BeginExternalListInput)(ExternalUnit = DefaultUnit, const char *sourceFile = nullptr, int sourceLine = 0); Cookie IONAME(BeginExternalFormattedOutput)(const char *format, std::size_t, - ExternalUnit = DefaultUnit, const char *sourceFile = nullptr, - int sourceLine = 0, const Descriptor *formatDescriptor = nullptr); + const Descriptor *formatDescriptor = nullptr, ExternalUnit = DefaultUnit, + const char *sourceFile = nullptr, int sourceLine = 0); Cookie IONAME(BeginExternalFormattedInput)(const char *format, std::size_t, - ExternalUnit = DefaultUnit, const char *sourceFile = nullptr, - int sourceLine = 0, const Descriptor *formatDescriptor = nullptr); + const Descriptor *formatDescriptor = nullptr, ExternalUnit = DefaultUnit, + const char *sourceFile = nullptr, int sourceLine = 0); Cookie IONAME(BeginUnformattedOutput)(ExternalUnit = DefaultUnit, const char *sourceFile = nullptr, int sourceLine = 0); Cookie IONAME(BeginUnformattedInput)(ExternalUnit = DefaultUnit, Index: flang/lib/Lower/IO.cpp =================================================================== --- flang/lib/Lower/IO.cpp +++ flang/lib/Lower/IO.cpp @@ -1487,9 +1487,15 @@ assert(pExpr && "missing format expression"); auto e = Fortran::semantics::GetExpr(*pExpr); if (Fortran::semantics::ExprHasTypeCategory( - *e, Fortran::common::TypeCategory::Character)) + *e, Fortran::common::TypeCategory::Character)) { // character expression + if (e->Rank()) + // Array: return address(descriptor) and no length (and no kind value). + return {fir::getBase(converter.genExprBox(loc, *e, stmtCtx)), + mlir::Value{}, mlir::Value{}}; + // Scalar: return address(format) and format length (and no kind value). return lowerStringLit(converter, loc, stmtCtx, *pExpr, strTy, lenTy); + } if (Fortran::semantics::ExprHasTypeCategory( *e, Fortran::common::TypeCategory::Integer) && @@ -1855,11 +1861,26 @@ auto maybeGetFormatArgs = [&]() { if (!isFormatted || isListOrNml) return; - auto pair = + std::tuple triple = getFormat(converter, loc, stmt, ioFuncTy.getInput(ioArgs.size()), ioFuncTy.getInput(ioArgs.size() + 1), stmtCtx); - ioArgs.push_back(std::get<0>(pair)); // format character string - ioArgs.push_back(std::get<1>(pair)); // format length + mlir::Value address = std::get<0>(triple); + mlir::Value length = std::get<1>(triple); + if (length) { + // Scalar format: string arg + length arg; no format descriptor arg + ioArgs.push_back(address); // format string + ioArgs.push_back(length); // format length + ioArgs.push_back( + builder.createNullConstant(loc, ioFuncTy.getInput(ioArgs.size()))); + return; + } + // Array format: no string arg, no length arg; format descriptor arg + ioArgs.push_back( + builder.createNullConstant(loc, ioFuncTy.getInput(ioArgs.size()))); + ioArgs.push_back( + builder.createNullConstant(loc, ioFuncTy.getInput(ioArgs.size()))); + ioArgs.push_back( // format descriptor + builder.createConvert(loc, ioFuncTy.getInput(ioArgs.size()), address)); }; if constexpr (hasIOCtrl) { // READ or WRITE if (isInternal) { @@ -1894,15 +1915,11 @@ loc, builder.getIntegerAttr(ioFuncTy.getInput(ioArgs.size()), Fortran::runtime::io::DefaultUnit))); } - // File name and line number. + // File name and line number are always the last two arguments. ioArgs.push_back( locToFilename(converter, loc, ioFuncTy.getInput(ioArgs.size()))); ioArgs.push_back( locToLineNo(converter, loc, ioFuncTy.getInput(ioArgs.size()))); - // Placeholder for format passed as a descriptor. - if (isFormatted && !isListOrNml) - ioArgs.push_back( - builder.createNullConstant(loc, ioFuncTy.getInput(ioArgs.size()))); } template Index: flang/runtime/format-implementation.h =================================================================== --- flang/runtime/format-implementation.h +++ flang/runtime/format-implementation.h @@ -33,21 +33,22 @@ RUNTIME_CHECK(terminator, maxHeight == maxHeight_); if (!format && formatDescriptor) { // The format is a character array passed via a descriptor. - formatLength = formatDescriptor->SizeInBytes() / sizeof(CharType); + std::size_t elements{formatDescriptor->Elements()}; + std::size_t elementBytes{formatDescriptor->ElementBytes()}; + formatLength = elements * elementBytes / sizeof(CharType); formatLength_ = static_cast(formatLength); if (formatDescriptor->IsContiguous()) { // Treat the contiguous array as a single character value. - format = const_cast( + format_ = const_cast( reinterpret_cast(formatDescriptor->raw().base_addr)); } else { // Concatenate its elements into a temporary array. char *p{reinterpret_cast( AllocateMemoryOrCrash(terminator, formatLength * sizeof(CharType)))}; - format = p; + format_ = p; SubscriptValue at[maxRank]; formatDescriptor->GetLowerBounds(at); - auto elementBytes{formatDescriptor->ElementBytes()}; - for (std::size_t j{0}; j < formatLength; ++j) { + for (std::size_t j{0}; j < elements; ++j) { std::memcpy(p, formatDescriptor->Element(at), elementBytes); p += elementBytes; formatDescriptor->IncrementSubscripts(at); Index: flang/runtime/io-api.cpp =================================================================== --- flang/runtime/io-api.cpp +++ flang/runtime/io-api.cpp @@ -69,32 +69,32 @@ template Cookie BeginInternalArrayFormattedIO(const Descriptor &descriptor, - const char *format, std::size_t formatLength, void ** /*scratchArea*/, - std::size_t /*scratchBytes*/, const char *sourceFile, int sourceLine, - const Descriptor *formatDescriptor) { + const char *format, std::size_t formatLength, + const Descriptor *formatDescriptor, void ** /*scratchArea*/, + std::size_t /*scratchBytes*/, const char *sourceFile, int sourceLine) { Terminator oom{sourceFile, sourceLine}; return &New>{oom}(descriptor, format, - formatLength, sourceFile, sourceLine, formatDescriptor) + formatLength, formatDescriptor, sourceFile, sourceLine) .release() ->ioStatementState(); } Cookie IONAME(BeginInternalArrayFormattedOutput)(const Descriptor &descriptor, - const char *format, std::size_t formatLength, void **scratchArea, - std::size_t scratchBytes, const char *sourceFile, int sourceLine, - const Descriptor *formatDescriptor) { + const char *format, std::size_t formatLength, + const Descriptor *formatDescriptor, void **scratchArea, + std::size_t scratchBytes, const char *sourceFile, int sourceLine) { return BeginInternalArrayFormattedIO(descriptor, format, - formatLength, scratchArea, scratchBytes, sourceFile, sourceLine, - formatDescriptor); + formatLength, formatDescriptor, scratchArea, scratchBytes, sourceFile, + sourceLine); } Cookie IONAME(BeginInternalArrayFormattedInput)(const Descriptor &descriptor, - const char *format, std::size_t formatLength, void **scratchArea, - std::size_t scratchBytes, const char *sourceFile, int sourceLine, - const Descriptor *formatDescriptor) { + const char *format, std::size_t formatLength, + const Descriptor *formatDescriptor, void **scratchArea, + std::size_t scratchBytes, const char *sourceFile, int sourceLine) { return BeginInternalArrayFormattedIO(descriptor, format, - formatLength, scratchArea, scratchBytes, sourceFile, sourceLine, - formatDescriptor); + formatLength, formatDescriptor, scratchArea, scratchBytes, sourceFile, + sourceLine); } template @@ -127,33 +127,32 @@ Cookie BeginInternalFormattedIO( std::conditional_t *internal, std::size_t internalLength, const char *format, std::size_t formatLength, - void ** /*scratchArea*/, std::size_t /*scratchBytes*/, - const char *sourceFile, int sourceLine, - const Descriptor *formatDescriptor) { + const Descriptor *formatDescriptor, void ** /*scratchArea*/, + std::size_t /*scratchBytes*/, const char *sourceFile, int sourceLine) { Terminator oom{sourceFile, sourceLine}; return &New>{oom}(internal, - internalLength, format, formatLength, sourceFile, sourceLine, - formatDescriptor) + internalLength, format, formatLength, formatDescriptor, sourceFile, + sourceLine) .release() ->ioStatementState(); } Cookie IONAME(BeginInternalFormattedOutput)(char *internal, std::size_t internalLength, const char *format, std::size_t formatLength, - void **scratchArea, std::size_t scratchBytes, const char *sourceFile, - int sourceLine, const Descriptor *formatDescriptor) { + const Descriptor *formatDescriptor, void **scratchArea, + std::size_t scratchBytes, const char *sourceFile, int sourceLine) { return BeginInternalFormattedIO(internal, internalLength, - format, formatLength, scratchArea, scratchBytes, sourceFile, sourceLine, - formatDescriptor); + format, formatLength, formatDescriptor, scratchArea, scratchBytes, + sourceFile, sourceLine); } Cookie IONAME(BeginInternalFormattedInput)(const char *internal, std::size_t internalLength, const char *format, std::size_t formatLength, - void **scratchArea, std::size_t scratchBytes, const char *sourceFile, - int sourceLine, const Descriptor *formatDescriptor) { + const Descriptor *formatDescriptor, void **scratchArea, + std::size_t scratchBytes, const char *sourceFile, int sourceLine) { return BeginInternalFormattedIO(internal, internalLength, - format, formatLength, scratchArea, scratchBytes, sourceFile, sourceLine, - formatDescriptor); + format, formatLength, formatDescriptor, scratchArea, scratchBytes, + sourceFile, sourceLine); } static Cookie NoopUnit(const Terminator &terminator, int unitNumber, @@ -244,8 +243,8 @@ template Cookie BeginExternalFormattedIO(const char *format, std::size_t formatLength, - ExternalUnit unitNumber, const char *sourceFile, int sourceLine, - const Descriptor *formatDescriptor) { + const Descriptor *formatDescriptor, ExternalUnit unitNumber, + const char *sourceFile, int sourceLine) { Terminator terminator{sourceFile, sourceLine}; if (unitNumber == DefaultUnit) { unitNumber = DIR == Direction::Input ? 5 : 6; @@ -269,8 +268,8 @@ } if (iostat == IostatOk) { return &child->BeginIoStatement>( - *child, format, formatLength, sourceFile, sourceLine, - formatDescriptor); + *child, format, formatLength, formatDescriptor, sourceFile, + sourceLine); } else { return &child->BeginIoStatement( iostat, nullptr /* no unit */, sourceFile, sourceLine); @@ -281,8 +280,8 @@ } if (iostat == IostatOk) { return &unit->BeginIoStatement>( - terminator, *unit, format, formatLength, sourceFile, sourceLine, - formatDescriptor); + terminator, *unit, format, formatLength, formatDescriptor, sourceFile, + sourceLine); } else { return &unit->BeginIoStatement( terminator, iostat, unit, sourceFile, sourceLine); @@ -291,17 +290,17 @@ } Cookie IONAME(BeginExternalFormattedOutput)(const char *format, - std::size_t formatLength, ExternalUnit unitNumber, const char *sourceFile, - int sourceLine, const Descriptor *formatDescriptor) { + std::size_t formatLength, const Descriptor *formatDescriptor, + ExternalUnit unitNumber, const char *sourceFile, int sourceLine) { return BeginExternalFormattedIO(format, formatLength, - unitNumber, sourceFile, sourceLine, formatDescriptor); + formatDescriptor, unitNumber, sourceFile, sourceLine); } Cookie IONAME(BeginExternalFormattedInput)(const char *format, - std::size_t formatLength, ExternalUnit unitNumber, const char *sourceFile, - int sourceLine, const Descriptor *formatDescriptor) { + std::size_t formatLength, const Descriptor *formatDescriptor, + ExternalUnit unitNumber, const char *sourceFile, int sourceLine) { return BeginExternalFormattedIO(format, formatLength, - unitNumber, sourceFile, sourceLine, formatDescriptor); + formatDescriptor, unitNumber, sourceFile, sourceLine); } template Index: flang/runtime/io-stmt.h =================================================================== --- flang/runtime/io-stmt.h +++ flang/runtime/io-stmt.h @@ -358,11 +358,11 @@ using typename InternalIoStatementState::Buffer; InternalFormattedIoStatementState(Buffer internal, std::size_t internalLength, const CharType *format, std::size_t formatLength, - const char *sourceFile = nullptr, int sourceLine = 0, - const Descriptor *formatDescriptor = nullptr); + const Descriptor *formatDescriptor = nullptr, + const char *sourceFile = nullptr, int sourceLine = 0); InternalFormattedIoStatementState(const Descriptor &, const CharType *format, - std::size_t formatLength, const char *sourceFile = nullptr, - int sourceLine = 0, const Descriptor *formatDescriptor = nullptr); + std::size_t formatLength, const Descriptor *formatDescriptor = nullptr, + const char *sourceFile = nullptr, int sourceLine = 0); IoStatementState &ioStatementState() { return ioStatementState_; } void CompleteOperation(); int EndIoStatement(); @@ -444,8 +444,8 @@ public: using CharType = CHAR; ExternalFormattedIoStatementState(ExternalFileUnit &, const CharType *format, - std::size_t formatLength, const char *sourceFile = nullptr, - int sourceLine = 0, const Descriptor *formatDescriptor = nullptr); + std::size_t formatLength, const Descriptor *formatDescriptor = nullptr, + const char *sourceFile = nullptr, int sourceLine = 0); void CompleteOperation(); int EndIoStatement(); std::optional GetNextDataEdit( @@ -500,8 +500,8 @@ public: using CharType = CHAR; ChildFormattedIoStatementState(ChildIo &, const CharType *format, - std::size_t formatLength, const char *sourceFile = nullptr, - int sourceLine = 0, const Descriptor *formatDescriptor = nullptr); + std::size_t formatLength, const Descriptor *formatDescriptor = nullptr, + const char *sourceFile = nullptr, int sourceLine = 0); MutableModes &mutableModes() { return mutableModes_; } void CompleteOperation(); int EndIoStatement(); Index: flang/runtime/io-stmt.cpp =================================================================== --- flang/runtime/io-stmt.cpp +++ flang/runtime/io-stmt.cpp @@ -140,8 +140,8 @@ template InternalFormattedIoStatementState::InternalFormattedIoStatementState( Buffer buffer, std::size_t length, const CharType *format, - std::size_t formatLength, const char *sourceFile, int sourceLine, - const Descriptor *formatDescriptor) + std::size_t formatLength, const Descriptor *formatDescriptor, + const char *sourceFile, int sourceLine) : InternalIoStatementState{buffer, length, sourceFile, sourceLine}, ioStatementState_{*this}, format_{*this, format, formatLength, formatDescriptor} {} @@ -149,7 +149,7 @@ template InternalFormattedIoStatementState::InternalFormattedIoStatementState( const Descriptor &d, const CharType *format, std::size_t formatLength, - const char *sourceFile, int sourceLine, const Descriptor *formatDescriptor) + const Descriptor *formatDescriptor, const char *sourceFile, int sourceLine) : InternalIoStatementState{d, sourceFile, sourceLine}, ioStatementState_{*this}, format_{*this, format, formatLength, formatDescriptor} {} @@ -398,7 +398,7 @@ template ExternalFormattedIoStatementState::ExternalFormattedIoStatementState( ExternalFileUnit &unit, const CHAR *format, std::size_t formatLength, - const char *sourceFile, int sourceLine, const Descriptor *formatDescriptor) + const Descriptor *formatDescriptor, const char *sourceFile, int sourceLine) : ExternalIoStatementState{unit, sourceFile, sourceLine}, format_{*this, format, formatLength, formatDescriptor} {} @@ -853,7 +853,7 @@ template ChildFormattedIoStatementState::ChildFormattedIoStatementState( ChildIo &child, const CHAR *format, std::size_t formatLength, - const char *sourceFile, int sourceLine, const Descriptor *formatDescriptor) + const Descriptor *formatDescriptor, const char *sourceFile, int sourceLine) : ChildIoStatementState{child, sourceFile, sourceLine}, mutableModes_{child.parent().mutableModes()}, format_{*this, format, formatLength, Index: flang/test/Lower/read-write-buffer.f90 =================================================================== --- flang/test/Lower/read-write-buffer.f90 +++ flang/test/Lower/read-write-buffer.f90 @@ -10,11 +10,12 @@ character(10) :: array(2) array(1) ="(15HThis i" array(2) ="s a test.)" - ! CHECK-DAG: %[[fmtLen:.*]] = arith.muli %[[c10]], %[[c2]] : index - ! CHECK-DAG: %[[scalarFmt:.*]] = fir.convert %[[mem]] : (!fir.ref>>) -> !fir.ref> - ! CHECK-DAG: %[[fmtArg:.*]] = fir.convert %[[scalarFmt]] : (!fir.ref>) -> !fir.ref - ! CHECK-DAG: %[[fmtLenArg:.*]] = fir.convert %[[fmtLen]] : (index) -> i64 - ! CHECK: fir.call @_FortranAioBeginExternalFormattedOutput(%[[fmtArg]], %[[fmtLenArg]], {{.*}}) + ! CHECK: %[[shape:.*]] = fir.shape %c2{{.*}} (index) -> !fir.shape<1> + ! CHECK: %[[fmtBox:.*]] = fir.embox %[[mem]](%[[shape]]) : (!fir.ref>>, !fir.shape<1>) -> !fir.box>> + ! CHECK: %[[fmtArg:.*]] = fir.zero_bits !fir.ref + ! CHECK: %[[fmtLenArg:.*]] = fir.zero_bits i64 + ! CHECK: %[[fmtDesc:.*]] = fir.convert %[[fmtBox]] : (!fir.box>>) -> !fir.box + ! CHECK: fir.call @_FortranAioBeginExternalFormattedOutput(%[[fmtArg]], %[[fmtLenArg]], %[[fmtDesc]], {{.*}}) write(*, array) end subroutine Index: flang/unittests/Runtime/ExternalIOTest.cpp =================================================================== --- flang/unittests/Runtime/ExternalIOTest.cpp +++ flang/unittests/Runtime/ExternalIOTest.cpp @@ -357,7 +357,7 @@ for (int j{1}; j <= records; ++j) { // WRITE(UNIT=unit,FMT=fmt,REC=j) j io = IONAME(BeginExternalFormattedOutput)( - fmt, sizeof fmt - 1, unit, __FILE__, __LINE__); + fmt, sizeof fmt - 1, nullptr, unit, __FILE__, __LINE__); ASSERT_TRUE(IONAME(SetRec)(io, j)) << "SetRec(" << j << ')'; ASSERT_TRUE(IONAME(OutputInteger64)(io, j)) << "OutputInteger64()"; ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) @@ -367,7 +367,7 @@ for (int j{records}; j >= 1; --j) { // READ(UNIT=unit,FMT=fmt,REC=j) n io = IONAME(BeginExternalFormattedInput)( - fmt, sizeof fmt - 1, unit, __FILE__, __LINE__); + fmt, sizeof fmt - 1, nullptr, unit, __FILE__, __LINE__); ASSERT_TRUE(IONAME(SetRec)(io, j)) << "SetRec(" << j << ')'; std::int64_t buffer; ASSERT_TRUE(IONAME(InputInteger)(io, buffer)) << "InputInteger()"; @@ -412,7 +412,7 @@ std::snprintf(fmt, sizeof fmt, "(%dI4)", j); // DO J=1,RECORDS; WRITE(UNIT=unit,FMT=fmt) BUFFER(0:j); END DO io = IONAME(BeginExternalFormattedOutput)( - fmt, std::strlen(fmt), unit, __FILE__, __LINE__); + fmt, std::strlen(fmt), nullptr, unit, __FILE__, __LINE__); for (int k{0}; k < j; ++k) { ASSERT_TRUE(IONAME(OutputInteger64)(io, buffer[k])) << "OutputInteger64()"; @@ -430,7 +430,7 @@ std::snprintf(fmt, sizeof fmt, "(%dI4)", j); // DO J=1,RECORDS; READ(UNIT=unit,FMT=fmt) n; check n; END DO io = IONAME(BeginExternalFormattedInput)( - fmt, std::strlen(fmt), unit, __FILE__, __LINE__); + fmt, std::strlen(fmt), nullptr, unit, __FILE__, __LINE__); std::int64_t check[records]; for (int k{0}; k < j; ++k) { @@ -456,7 +456,7 @@ std::snprintf(fmt, sizeof fmt, "(%dI4)", j); // READ(UNIT=unit,FMT=fmt,SIZE=chars) n; check io = IONAME(BeginExternalFormattedInput)( - fmt, std::strlen(fmt), unit, __FILE__, __LINE__); + fmt, std::strlen(fmt), nullptr, unit, __FILE__, __LINE__); std::int64_t check[records]; for (int k{0}; k < j; ++k) { @@ -510,7 +510,7 @@ for (const auto &record : records) { // WRITE(UNIT=unit,FMT=fmt) record io = IONAME(BeginExternalFormattedOutput)( - fmt.data(), fmt.length(), unit, __FILE__, __LINE__); + fmt.data(), fmt.length(), nullptr, unit, __FILE__, __LINE__); ASSERT_TRUE(IONAME(OutputAscii)(io, record.data(), record.length())) << "OutputAscii()"; ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) @@ -541,7 +541,7 @@ for (auto &inputItem : inputItems) { // READ(UNIT=unit, FMT=fmt, ADVANCE='NO', IOSTAT=iostat) inputItem io = IONAME(BeginExternalFormattedInput)( - fmt.data(), fmt.length(), unit, __FILE__, __LINE__); + fmt.data(), fmt.length(), nullptr, unit, __FILE__, __LINE__); IONAME(EnableHandlers)(io, true, false, false, false, false); ASSERT_TRUE(IONAME(SetAdvance)(io, "NO", 2)) << "SetAdvance(NO)" << j; bool result{ @@ -581,7 +581,7 @@ for (const auto &record : records) { // WRITE(UNIT=unit,FMT=fmt) record io = IONAME(BeginExternalFormattedOutput)( - fmt.data(), fmt.length(), unit, __FILE__, __LINE__); + fmt.data(), fmt.length(), nullptr, unit, __FILE__, __LINE__); ASSERT_TRUE(IONAME(OutputAscii)(io, record.data(), record.length())) << "OutputAscii()"; ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) @@ -608,7 +608,7 @@ for (auto &inputItem : inputItems) { // READ(UNIT=unit, FMT=fmt, ADVANCE='NO', IOSTAT=iostat) inputItem io = IONAME(BeginExternalFormattedInput)( - fmt.data(), fmt.length(), unit, __FILE__, __LINE__); + fmt.data(), fmt.length(), nullptr, unit, __FILE__, __LINE__); IONAME(EnableHandlers)(io, true, false, false, false, false); ASSERT_TRUE(IONAME(SetAdvance)(io, "NO", 2)) << "SetAdvance(NO)" << j; ASSERT_TRUE( @@ -625,7 +625,7 @@ static constexpr std::string_view outputItem{"XYZ"}; // WRITE(UNIT=unit,FMT=fmt) record io = IONAME(BeginExternalFormattedOutput)( - fmt.data(), fmt.length(), unit, __FILE__, __LINE__); + fmt.data(), fmt.length(), nullptr, unit, __FILE__, __LINE__); ASSERT_TRUE(IONAME(OutputAscii)(io, outputItem.data(), outputItem.length())) << "OutputAscii()"; ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) @@ -643,7 +643,7 @@ std::string expectedRecord{"ABCDEFGHXYZ "}; // READ(UNIT=unit, FMT=fmt, IOSTAT=iostat) result io = IONAME(BeginExternalFormattedInput)( - fmt.data(), fmt.length(), unit, __FILE__, __LINE__); + fmt.data(), fmt.length(), nullptr, unit, __FILE__, __LINE__); IONAME(EnableHandlers)(io, true, false, false, false, false); ASSERT_TRUE( IONAME(InputAscii)(io, resultRecord.data(), resultRecord.length())) @@ -674,7 +674,7 @@ // WRITE(unit,"(I8)") 1234 static constexpr std::string_view format{"(I8)"}; io = IONAME(BeginExternalFormattedOutput)( - format.data(), format.length(), unit, __FILE__, __LINE__); + format.data(), format.length(), nullptr, unit, __FILE__, __LINE__); ASSERT_TRUE(IONAME(OutputInteger64)(io, 1234)) << "OutputInteger64()"; ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) << "EndIoStatement for WRITE before ENDFILE"; @@ -684,7 +684,7 @@ << "EndIoStatement for ENDFILE"; // WRITE(unit,"(I8)",iostat=iostat) 5678 io = IONAME(BeginExternalFormattedOutput)( - format.data(), format.length(), unit, __FILE__, __LINE__); + format.data(), format.length(), nullptr, unit, __FILE__, __LINE__); IONAME(EnableHandlers)(io, true /*IOSTAT=*/); ASSERT_FALSE(IONAME(OutputInteger64)(io, 5678)) << "OutputInteger64()"; ASSERT_EQ(IONAME(EndIoStatement)(io), IostatWriteAfterEndfile) @@ -695,7 +695,7 @@ << "EndIoStatement for BACKSPACE"; // WRITE(unit,"(I8)") 3456 io = IONAME(BeginExternalFormattedOutput)( - format.data(), format.length(), unit, __FILE__, __LINE__); + format.data(), format.length(), nullptr, unit, __FILE__, __LINE__); ASSERT_TRUE(IONAME(OutputInteger64)(io, 3456)) << "OutputInteger64()"; ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) << "EndIoStatement for WRITE after BACKSPACE"; @@ -706,7 +706,7 @@ // READ(unit,"(I8)",END=) j, k std::int64_t j{-1}, k{-1}, eof{-1}; io = IONAME(BeginExternalFormattedInput)( - format.data(), format.length(), unit, __FILE__, __LINE__); + format.data(), format.length(), nullptr, unit, __FILE__, __LINE__); IONAME(EnableHandlers)(io, false, false, true /*END=*/); ASSERT_TRUE(IONAME(InputInteger)(io, j)) << "InputInteger(j)"; ASSERT_EQ(j, 1234) << "READ(j)";