Skip to content

Commit 4180b29

Browse files
committed
[flang][runtime] Support DT edit descriptor in result of READ(SIZE=)
When a formatted I/O READ statement processes a DT edit descriptor to call a user-defined I/O subroutine to read a derived type data item, all of the characters that that subroutine reads via child I/O count as charecters read by an edit descriptor and should accumulate in the result returned by a SIZE= item in the original READ statement's control list. Differential Revision: https://reviews.llvm.org/D144234
1 parent 7067aee commit 4180b29

File tree

6 files changed

+37
-6
lines changed

6 files changed

+37
-6
lines changed

flang/runtime/connection.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ struct ConnectionState : public ConnectionAttributes {
7474

7575
std::int64_t currentRecordNumber{1}; // 1 is first
7676

77-
// positionInRecord is the 0-based bytes offset in the current recurd
77+
// positionInRecord is the 0-based bytes offset in the current record
7878
// to/from which the next data transfer will occur. It can be past
7979
// furthestPositionInRecord if moved by an X or T or TR control edit
8080
// descriptor.

flang/runtime/descriptor-io.cpp

+10
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,13 @@ std::optional<bool> DefinedFormattedIo(IoStatementState &io,
5050
int unit{external->unitNumber()};
5151
int ioStat{IostatOk};
5252
char ioMsg[100];
53+
std::optional<std::int64_t> startPos;
54+
if (edit.descriptor == DataEdit::DefinedDerivedType &&
55+
special.which() == typeInfo::SpecialBinding::Which::ReadFormatted) {
56+
// DT is an edit descriptor so everything that the child
57+
// I/O subroutine reads counts towards READ(SIZE=).
58+
startPos = io.InquirePos();
59+
}
5360
if (special.IsArgDescriptor(0)) {
5461
auto *p{special.GetProc<void (*)(const Descriptor &, int &, char *,
5562
const Descriptor &, int &, char *, std::size_t, std::size_t)>()};
@@ -69,6 +76,9 @@ std::optional<bool> DefinedFormattedIo(IoStatementState &io,
6976
RUNTIME_CHECK(handler, external == closing);
7077
external->DestroyClosed();
7178
}
79+
if (startPos) {
80+
io.GotChar(io.InquirePos() - *startPos);
81+
}
7282
return handler.GetIoStat() == IostatOk;
7383
} else {
7484
// There's a user-defined I/O subroutine, but there's a FORMAT present and

flang/runtime/internal-unit.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,12 @@ void InternalDescriptorUnit<DIR>::BackspaceRecord(IoErrorHandler &handler) {
157157
BeginRecord();
158158
}
159159

160+
template <Direction DIR>
161+
std::int64_t InternalDescriptorUnit<DIR>::InquirePos() {
162+
return (currentRecordNumber - 1) * recordLength.value_or(0) +
163+
positionInRecord + 1;
164+
}
165+
160166
template class InternalDescriptorUnit<Direction::Output>;
161167
template class InternalDescriptorUnit<Direction::Input>;
162168
} // namespace Fortran::runtime::io

flang/runtime/internal-unit.h

+1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ template <Direction DIR> class InternalDescriptorUnit : public ConnectionState {
3434
std::size_t GetNextInputBytes(const char *&, IoErrorHandler &);
3535
bool AdvanceRecord(IoErrorHandler &);
3636
void BackspaceRecord(IoErrorHandler &);
37+
std::int64_t InquirePos();
3738

3839
private:
3940
Descriptor &descriptor() { return staticDescriptor_.descriptor(); }

flang/runtime/io-stmt.cpp

+15-4
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ bool IoStatementBase::Inquire(InquiryKeywordHash, std::int64_t &) {
7070
return false;
7171
}
7272

73+
std::int64_t IoStatementBase::InquirePos() { return 0; }
74+
7375
void IoStatementBase::BadInquiryKeywordHashCrash(InquiryKeywordHash inquiry) {
7476
char buffer[16];
7577
const char *decode{InquiryKeywordHashDecode(buffer, sizeof buffer, inquiry)};
@@ -137,6 +139,11 @@ void InternalIoStatementState<DIR>::HandleRelativePosition(std::int64_t n) {
137139
return unit_.HandleRelativePosition(n);
138140
}
139141

142+
template <Direction DIR>
143+
std::int64_t InternalIoStatementState<DIR>::InquirePos() {
144+
return unit_.InquirePos();
145+
}
146+
140147
template <Direction DIR, typename CHAR>
141148
InternalFormattedIoStatementState<DIR, CHAR>::InternalFormattedIoStatementState(
142149
Buffer buffer, std::size_t length, const CharType *format,
@@ -206,6 +213,10 @@ void ExternalIoStatementBase::SetAsynchronous() {
206213
asynchronousID_ = unit().GetAsynchronousId(*this);
207214
}
208215

216+
std::int64_t ExternalIoStatementBase::InquirePos() {
217+
return unit_.InquirePos();
218+
}
219+
209220
void OpenStatementState::set_path(const char *path, std::size_t length) {
210221
pathLength_ = TrimTrailingSpaces(path, length);
211222
path_ = SaveDefaultCharacter(path, pathLength_, *this);
@@ -635,6 +646,10 @@ bool IoStatementState::Inquire(InquiryKeywordHash inquiry, std::int64_t &n) {
635646
[&](auto &x) { return x.get().Inquire(inquiry, n); }, u_);
636647
}
637648

649+
std::int64_t IoStatementState::InquirePos() {
650+
return common::visit([&](auto &x) { return x.get().InquirePos(); }, u_);
651+
}
652+
638653
void IoStatementState::GotChar(int n) {
639654
if (auto *formattedIn{
640655
get_if<FormattedIoStatementState<Direction::Input>>()}) {
@@ -823,10 +838,6 @@ ExternalFileUnit *ChildIoStatementState<DIR>::GetExternalFileUnit() const {
823838
return child_.parent().GetExternalFileUnit();
824839
}
825840

826-
template <Direction DIR> void ChildIoStatementState<DIR>::CompleteOperation() {
827-
IoStatementBase::CompleteOperation();
828-
}
829-
830841
template <Direction DIR> int ChildIoStatementState<DIR>::EndIoStatement() {
831842
CompleteOperation();
832843
auto result{IoStatementBase::EndIoStatement()};

flang/runtime/io-stmt.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ class IoStatementState {
102102
bool Inquire(InquiryKeywordHash, bool &);
103103
bool Inquire(InquiryKeywordHash, std::int64_t, bool &); // PENDING=
104104
bool Inquire(InquiryKeywordHash, std::int64_t &);
105+
std::int64_t InquirePos();
105106
void GotChar(signed int = 1); // for READ(SIZE=); can be <0
106107

107108
MutableModes &mutableModes();
@@ -262,6 +263,7 @@ class IoStatementBase : public IoErrorHandler {
262263
bool Inquire(InquiryKeywordHash, bool &);
263264
bool Inquire(InquiryKeywordHash, std::int64_t, bool &);
264265
bool Inquire(InquiryKeywordHash, std::int64_t &);
266+
std::int64_t InquirePos();
265267

266268
void BadInquiryKeywordHashCrash(InquiryKeywordHash);
267269

@@ -343,6 +345,7 @@ class InternalIoStatementState : public IoStatementBase,
343345
MutableModes &mutableModes() { return unit_.modes; }
344346
void HandleRelativePosition(std::int64_t);
345347
void HandleAbsolutePosition(std::int64_t);
348+
std::int64_t InquirePos();
346349

347350
protected:
348351
bool free_{true};
@@ -406,6 +409,7 @@ class ExternalIoStatementBase : public IoStatementBase {
406409
int EndIoStatement();
407410
ExternalFileUnit *GetExternalFileUnit() const { return &unit_; }
408411
void SetAsynchronous();
412+
std::int64_t InquirePos();
409413

410414
private:
411415
ExternalFileUnit &unit_;
@@ -483,7 +487,6 @@ class ChildIoStatementState : public IoStatementBase,
483487
MutableModes &mutableModes();
484488
ConnectionState &GetConnectionState();
485489
ExternalFileUnit *GetExternalFileUnit() const;
486-
void CompleteOperation();
487490
int EndIoStatement();
488491
bool Emit(const char *, std::size_t bytes, std::size_t elementBytes = 0);
489492
std::size_t GetNextInputBytes(const char *&);

0 commit comments

Comments
 (0)