Skip to content

Commit 4acd8f7

Browse files
committed
[flang] Detect and rewrite ambiguous READ(CVAR)[,item-list]
READ(CVAR)[,item-list] with a character variable CVAR could be parsed as an unformatted READ from an internal unit or as a formatted READ from the default external unit with a needlessly parenthesized variable format. We parse it as the former, but Fortran doesn't have unformatted internal I/O. Differential revision: https://reviews.llvm.org/D90493
1 parent 1cb0b56 commit 4acd8f7

File tree

3 files changed

+32
-0
lines changed

3 files changed

+32
-0
lines changed

flang/lib/Parser/io-parsers.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,10 @@ TYPE_CONTEXT_PARSER("CLOSE statement"_en_US,
139139
// R1210 read-stmt ->
140140
// READ ( io-control-spec-list ) [input-item-list] |
141141
// READ format [, input-item-list]
142+
// The ambiguous READ(CVAR) is parsed as if CVAR were the unit.
143+
// As Fortran doesn't have internal unformatted I/O, it should
144+
// be parsed as if (CVAR) were a format; this is corrected by
145+
// rewriting in semantics when we know that CVAR is character.
142146
constexpr auto inputItemList{
143147
extension<LanguageFeature::IOListLeadingComma>(
144148
some("," >> inputItem)) || // legacy extension: leading comma

flang/lib/Semantics/rewrite-parse-tree.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,25 @@ void FixMisparsedUntaggedNamelistName(READ_OR_WRITE &x) {
146146
}
147147
}
148148

149+
// READ(CVAR) [, ...] will be misparsed as UNIT=CVAR; correct
150+
// it to READ CVAR [,...] with CVAR as a format rather than as
151+
// an internal I/O unit for unformatted I/O, which Fortran does
152+
// not support.
149153
void RewriteMutator::Post(parser::ReadStmt &x) {
154+
if (x.iounit && !x.format && x.controls.empty()) {
155+
if (auto *var{std::get_if<parser::Variable>(&x.iounit->u)}) {
156+
const parser::Name &last{parser::GetLastName(*var)};
157+
DeclTypeSpec *type{last.symbol ? last.symbol->GetType() : nullptr};
158+
if (type && type->category() == DeclTypeSpec::Character) {
159+
x.format = std::visit(
160+
[](auto &&indirection) {
161+
return parser::Expr{std::move(indirection)};
162+
},
163+
std::move(var->u));
164+
x.iounit.reset();
165+
}
166+
}
167+
}
150168
FixMisparsedUntaggedNamelistName(x);
151169
}
152170

flang/test/Semantics/rewrite01.f90

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
! RUN: %f18 -fparse-only -fdebug-dump-parse-tree %s 2>&1 | FileCheck %s
2+
! Ensure that READ(CVAR) [, item-list] is corrected when CVAR is a
3+
! character variable so as to be a formatted read from the default
4+
! unit, not an unformatted read from an internal unit (which is not
5+
! possible in Fortran).
6+
character :: cvar
7+
! CHECK-NOT: IoUnit -> Variable -> Designator -> DataRef -> Name = 'cvar'
8+
! CHECK: Format -> Expr = 'cvar'
9+
read(cvar)
10+
end

0 commit comments

Comments
 (0)