After an ENDFILE statement, a WRITE is an error without
a prior BACKSPACE. Also fix the return value for the case
of formatted integer input with no input digits to be false
(exposed by new test).
Differential Revision: https://reviews.llvm.org/D117346
RECL= is required for direct access I/O, but is permitted
as well for sequential I/O, where it is defined by the
standard to specify a maximum record (line) length.
The standard does not say what should happen when an
sequential formatted input record appears whose length is
unequal to RECL= when it is specified.
Precedents from other compilers are unclear: one raises an error,
some honor RECL= as an effective truncation, and a few ignore the
situation. On output, all other compilers tested raised an
error when an attempt is made to emit a record longer than RECL=.
This patch treats RECL= as effective truncation on input and
as a hard limit with error on output, and also ensures that
RECL= can be set *longer* than the actual input record lengths.
Differential Revision: https://reviews.llvm.org/D115102
INQUIRE(POSITION=)'s results need to reflect the POSITION=
specifier used for the OPEN statement until the unit has been
repositioned. Preserve the POSITION= from OPEN and used it
for INQUIRE(POSITION=) until is becomes obsolete.
INQUIRE(PAD=) is implemented here in the case of an unconnected unit
with Fortran 2018 semantics; i.e., "UNDEFINED", rather than Fortran 90's
"YES"/"NO" (see 4.3.6 para 2). Apparent failures with F'90-only tests
will persist with INQUIRE(PAD=); these discrepancies don't seem to warrant
an option or environment variable.
To make the implementation of INQUIRE more closely match the language
in the standard, rename IsOpen() to IsConnected(), and use it explicitly
for the various INQUIRE specifiers.
Differential Revision: https://reviews.llvm.org/D114755
This is a near-universal language extension; external unit 0
is preconnected to the standard error output.
Differential Revision: https://reviews.llvm.org/D114298
The predefined units were not being initialized with FORM='FORMATTED',
so INQUIRE(PAD=) was failing if no I/O had already been done.
INQUIRE(POSITION=) was returning 'REWIND' on stdin/stdout (which
is somewhat defensible from the definition, and is what Intel Fortran
does), but most implementations return 'ASIS'. Change the runtime
to return 'REWIND' only for positionable external files, but 'ASIS'
for terminals, sockets, &c.
Differential Revision: https://reviews.llvm.org/D114028
1. To avoid overwriting the part of the record read in the non advancing read,
the furtherPositionInRecord field must be set to the max of the
furtherPositionInRecord and the positionInRecord at the beginning of the
IO write.
2. To allow any further read to succeed after the write, the unit
beganReadingRecord_ must be set to false when resetting the recordLength
during the write, otherwise, recordLength will not be computed in further
read and an assert is hit (at unit.cpp(398)).
The added unit test exercises both of these scenarios.
Differential Revision: https://reviews.llvm.org/D113740
Profiling a basic internal real input read benchmark shows some
hot spots in the code used to prepare input for decimal-to-binary
conversion, which is of course where the time should be spent.
The library that implements decimal to/from binary conversions has
been optimized, but not the code in the Fortran runtime that calls it,
and there are some obvious light changes worth making here.
Move some member functions from *.cpp files into the class definitions
of Descriptor and IoStatementState to enable inlining and specialization.
Make GetNextInputBytes() the new basic input API within the
runtime, replacing GetCurrentChar() -- which is rewritten in terms of
GetNextInputBytes -- so that input routines can have the
ability to acquire more than one input character at a time
and amortize overhead.
These changes speed up the time to read 1M random reals
using internal I/O from a character array from 1.29s to 0.54s
on my machine, which on par with Intel Fortran and much faster than
GNU Fortran.
Differential Revision: https://reviews.llvm.org/D113697
When processing the devious NAMELIST input
&group logarray = t t t
= 666 /
for LOGICAL::logarray(3) and INTEGER::t, the runtime library
needs to do some look-ahead on the input stream to make sure
that the last "t" on the first line is a truth value rather than
an item name -- which in this case it is. This look-ahead
was implemented in a previous patch but only worked for internal
input cases; this patch implements look-ahead capabilities for
input from an external file, too (and also adjusts repeated
list-directed input items to use this infrastructure, too).
Differential Revision: https://reviews.llvm.org/D113311
A recent change caused some variable-length sequential formatted
output statements with record positioning at the end of a FORMAT
(e.g., FORMAT('hi',10X) to append blanks at the end of the completed
record when emitting it.
Differential Revision: https://reviews.llvm.org/D112742
The runtime library was emitting unformatted record headers and
footers when an external unit had no fixed RECL=. This is wrong
for sequential files, which should have headers & footers even
with RECL. Change to omit headers & footers from unformatted
I/O only for direct access files.
Differential Revision: https://reviews.llvm.org/D112243
Count input characters corresponding to formatted edit descriptors
for READ(SIZE=); count output bytes for INQUIRE(IOLENGTH=).
The I/O APIs GetSize() and GetLength() were adjusted to return
std::size_t as function results.
Basic unit tests were added (and others fixed).
Differential Revision: https://reviews.llvm.org/D110291
When an end of record is met in non advancing IO:
- Set IOSTAT if present according to 12.11.4 (5).
- Position the file to the next record (12.11.4 (4)).
The previous code was only signaling EOR for fixed record length IO.
Reading at 12.11.4, I do not find the rational for this condition, so I
removed it.
It also does not seem the presence of padding should prevent
the EOR signaling.
The positionning to the next record was block when EOR is signaling
in FinishReadingRecord because ErrorHandler.isError() is true in this
case.
EOR in input is not an error, but I am not confident to modify
ErrorHandler.isError() to cover that. However, In FinishReadingRecord,
the code should not bail if the error is simply an end of record.
I did not check the SIZE requirements here because GetSize runtime is
not yet implemented.
Differential Revision: https://reviews.llvm.org/D109505
BACKSPACE leaves "recordLength" set, which is fine for a later READ,
but it causes a later WRITE to fail due to a misinterpretation of the
knowledge of the record length as indication of a fixed-length record
file (RECL=). Fix.
Differential Revision: https://reviews.llvm.org/D108594
A recent runtime I/O change[1] was meant to improve the handling of
input from external files missing a terminal newline on their last
records; the change was "triggered" by the wrong circumstances and
causing reads that should have pulled more data into the buffer to be
treated as EOFs. So fix that, and also don't retain input data
in the buffer once an input record has been finished unless it's
known that list-directed or NAMELIST input of a repeated input item
may need to backspace a non-positionable external unit to return
to the beginning of the repeated item.
[1] 6578893a0453384346f149479f8574dfff977ace
Differential Revision: https://reviews.llvm.org/D108164
Fix the external-io unittest under Windows.
In particular, fixes the following issues:
1. When creating a temporary file, open it with read+write permissions
using the _O_RDWR flag. _S_IREAD and _S_IWRITE are for the file
permissions of the created file.
2. _chsize returns 0 on success (just like ftruncate).
3. To set a std::optional, use its assign-operator overload instead of
getting a reference to its value and overwrite that. The latter is
invalid if the std::optional has no value, and is caught by
msvc's debug STL.
The non-GTest unittest is currently not executed under Windows because
of the added .exe extension to the output file: external-io.text.exe.
llvm-lit skips the file because .exe is not in the lists of test
suffixes (.test is). D105315 is going to change that by converting it
to a GTest-test.
Reviewed By: awarzynski
Differential Revision: https://reviews.llvm.org/D106726
When a WRITE overwrites an endfile record, we need to forget
that there was an endfile record. When doing a BACKSPACE
after an explicit ENDFILE statement, the position afterwards
must be upon the endfile record.
Attempts to join list-directed delimited character input across
record boundaries was due to a bad reading of the standard
and has been deleted, now that the requirements are better understood.
This problem would cause a read attempt past EOF if a delimited
character input value was at the end of a record.
It turns out that delimited list-directed (and NAMELIST) character
output is required to emit contiguous doubled instances of the
delimiter character when it appears in the output value. When
fixed-size records are being emitted, as is the case with internal
output, this is not possible when the problematic character falls
on the last position of a record. No two other Fortran compilers
do the same thing in this situation so there is no good precedent
to follow.
Because it seems least wrong, with this patch we now emit one copy
of the delimiter as the last character of the current record and
another as the first character of the next record. (The
second-least-wrong alternative might be to flag a runtime error,
but that seems harsh since it's not an explicit error in the standard,
and the output may not have to be usable later as input anyway.)
Consequently, the output is not suitable for use as list-directed or
NAMELIST input.
If a later standard were to clarify this case, this behavior will of
course change as needed to conform.
Differential Revision: https://reviews.llvm.org/D106695
F18 was sigalling an end-of-file error condition when reading an
unformatted sequential input file without an ultimate newline
(or CR-LF). Other Fortran implementations can handle it, so change
the runtime to support it.
Differential Revision: https://reviews.llvm.org/D106321
Non-advancing I/O was failing; ExternalFileUnit was losing
track of what writes had been committed to the file. Fixed.
Also, support the common extension of $ and \ in a FORMAT
as being equivalent to ADVANCE=NO.
Differential Revision: https://reviews.llvm.org/D105046
With derived type description tables now available to the
runtime library, it is possible to implement the concept
of "child" I/O statements in the runtime and use them to
convert instances of derived type I/O data transfers into
calls to user-defined subroutines when they have been specified
for a type. (See Fortran 2018, subclauses 12.6.4.8 & 13.7.6).
- Support formatted, list-directed, and NAMELIST
transfers to internal parent units; support these, and unformatted
transfers, for external parent units.
- Support nested child defined derived type I/O.
- Parse DT'foo'(v-list) FORMAT data edit descriptors and passes
their strings &/or v-list values as arguments to the defined
formatted I/O routines.
- Fix problems with this feature encountered in semantics and
FORMAT valiation during development and end-to-end testing.
- Convert typeInfo::SpecialBinding from a struct to a class
after adding a member function.
Differential Revision: https://reviews.llvm.org/D104930
Add InputNamelist and OutputNamelist as I/O data transfer APIs
to be used with internal & external list-directed I/O; delete the
needless original namelist-specific Begin... calls.
Implement NAMELIST output and input; add basic tests.
Differential Revision: https://reviews.llvm.org/D101931
The code that initializes the default units 5 & 6 had
a race condition that would allow threads access to the
unit map before it had been populated.
Also add some missing calls to va_end() that will never
be called (they're in program abort situations) but might
elicit warnings if absent.
Differential Revision: https://reviews.llvm.org/D101928
What the Fortran standard calls "preconnected" external I/O units
might not be known to be connected to unformatted or formatted files
until the first I/O data transfer statement is executed.
Support this deferred determination by representing the flag as
a tri-state Boolean and adapting its points of use.
Differential Revision: https://reviews.llvm.org/D101929
Debug the input path for READ statements with END= labels;
don't emit errors when the program can handle them.
BeginReadingRecord() member functions have been made
"bool" for more convenient handling of error cases,
and some code in IoErrorHandler has been cleaned up.
Differential Revision: https://reviews.llvm.org/D100421
An OPEN statement that affects an already connected unit
without changing its external file is required to have
STATUS="OLD" or default STATUS=. The code was eliciting
spurious runtime errors in situations where an OPEN statement
pertained to an existing unit number but did not need to have
STATUS="OLD'.
Differential Revision: https://reviews.llvm.org/D100352
It turns out that unformatted fixed-size output records
do need to be padded out if short, in order to avoid a
spurious EOF crash on a short record at the end of the file.
While here in AdvanceRecord(), move the unformatted
variable-length record header/footer writing code to here
from EndIoStatement().
Differential revision: https://reviews.llvm.org/D88685
A WRITE to an unformatted sequential variable-length unit after
a BACKSPACE needs to forget its previous knowledge of the length
of the record that's about to be overwritten, and a BACKSPACE
after an ENDFILE or at the start of the file needs to be a no-op.
Differential revision: https://reviews.llvm.org/D88675
Add checking to I/O statement APIs to catch cases where the formatted
I/O data item transfer routines like OutputInteger64 are being
incorrectly used for unformatted I/O, which should use the
unformatted block or descriptor-based data item interfaces.
Differential revision: https://reviews.llvm.org/D88672
The '/' control edit descriptor causes a runtime crash for an
external formatted sequential READ because the AdvanceRecord()
member function for external units implemented only the tasks
to finish reading the current record. Split those out into
a new FinishReadingRecord() member function, call that instead
from EndIoStatement(), and change AdvanceRecord() to both
finish reading the current record and to begin reading the next
one.
Differential revision: https://reviews.llvm.org/D88607
Add SetConvert() to the OPEN statement's runtime API.
Add ByteswapOption() to the main program's runtime API.
Check a $FORT_CONVERT environment variable, too, for
a swapping specifier.
Reviewed By: sscalpone
Differential Revision: https://reviews.llvm.org/D84284
Anonymous Fortran unit files (e.g., "./fort.7") need to be created
O_RDWR so that they can be written, rewound, and read. Other
files opened with no ACTION= specifier need to set read/write
permissions based on the file, if it exists.
Reviewed By: sscalpone
Differential Revision: https://reviews.llvm.org/D84063
I/O from/to an unopened unit number needs to open &/or create
a "fort.$UNIT" file.
Fixes FCVS test fm401.f.
Reviewed By: tskeith
Differential Revision: https://reviews.llvm.org/D83809
Rework initial implementation of external I/O unit operations to
fix problems exposed in unit tests (in a later patch). Add flushing.
Reviewed By: sscalpone
Differential Revision: https://reviews.llvm.org/D83147
New<A> used to return an A&; now it returns an OwningPtr<A>
to force better ownership tracking of allocations. Its API
has also been split into New<A> and SizedNew<A> to allow
allocations with a size override.
Reviewed By: tskeith
Differential Revision: https://reviews.llvm.org/D83108
Scan FORMAT strings locally to avoid C++ binary runtime dependence when computing deepest parenthesis nesting
Remove a dependency on ostream from runtime
Remove remaining direct external references from runtime to C++ library binaries
Remove runtime dependences on lib/common
SetPos() and SetRec()
Instantiate templates for input
Begin input; rearrange locking, deal with CLOSE races
View()
Update error message in test to agree with compiler change
First cut at real input
More robust I/O runtime error handling
Debugging of REAL input
Add iostat.{h,cpp}
Rename runtime/numeric-* to runtime/edit-*
Move templates around, templatize integer output editing
Move LOGICAL and CHARACTER output from io-api.cpp to edit-output.cpp
Change pointer argument to reference
More list-directed input
Complex list-directed input
Use enum class Direction rather than bool for templates
Catch up with changes to master
Undo reformatting of Lower code
Use record number instead of subscripts for internal unit
Unformatted sequential backspace
Testing and debugging
Dodge bogus GCC warning
Add <cstddef> for std::size_t to fix CI build
Address review comments
Original-commit: flang-compiler/f18@50406b3496
Reviewed-on: https://github.com/flang-compiler/f18/pull/1053
Use internal units for internal I/O state
Replace use of virtual functions
reference_wrapper
Internal formatted output to array descriptor
Delete dead code
Begin list-directed internal output
Refactorings and renamings for clarity
List-directed external I/O (character)
COMPLEX list-directed output
Control list items
First cut at unformatted I/O
More OPEN statement work; rename class to ExternalFileUnit
Complete OPEN (exc. for POSITION=), add CLOSE()
OPEN(POSITION=)
Flush buffers on crash and for terminal output; clean up
Documentation
Fix backquote in documentation
Fix typo in comment
Begin implementation of input
Refactor binary floating-point properties to a new header, simplify numeric output editing
Dodge spurious GCC 7.2 build warning
Address review comments
Original-commit: flang-compiler/f18@9c4bba11cf
Reviewed-on: https://github.com/flang-compiler/f18/pull/982
Address review comments
Integer output data editing (I,B,O,Z)
Full integer output formatting
Stub out some work in progress
Progress on E output data editing
E, D, EN, and ES output editing done
Fw.d output editing
Real G output editing
G output editing for reals
Make environment a distinct module
CHARACTER and LOGICAL output editing
Minimal decimal representations for E0, F0, G0 editing
Move real output editing code into its own file
Fix/dodge some GCC build problems
Prep work for external I/O statement state
External HELLO, WORLD
Fix build problem with GCC
Add virtual destructors where needed
Add new test
Original-commit: flang-compiler/f18@c3f1774f8e
Reviewed-on: https://github.com/flang-compiler/f18/pull/950