From: peter klausler Date: Fri, 30 Oct 2020 19:53:42 +0000 (-0700) Subject: [flang] Detect and rewrite ambiguous READ(CVAR)[,item-list] X-Git-Tag: llvmorg-13-init~7531 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=4acd8f7f0a7ef4009fe039297335b931ab9e62d0;p=platform%2Fupstream%2Fllvm.git [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 --- diff --git a/flang/lib/Parser/io-parsers.cpp b/flang/lib/Parser/io-parsers.cpp index 3615501..0aab883 100644 --- a/flang/lib/Parser/io-parsers.cpp +++ b/flang/lib/Parser/io-parsers.cpp @@ -139,6 +139,10 @@ TYPE_CONTEXT_PARSER("CLOSE statement"_en_US, // R1210 read-stmt -> // READ ( io-control-spec-list ) [input-item-list] | // READ format [, input-item-list] +// The ambiguous READ(CVAR) is parsed as if CVAR were the unit. +// As Fortran doesn't have internal unformatted I/O, it should +// be parsed as if (CVAR) were a format; this is corrected by +// rewriting in semantics when we know that CVAR is character. constexpr auto inputItemList{ extension( some("," >> inputItem)) || // legacy extension: leading comma diff --git a/flang/lib/Semantics/rewrite-parse-tree.cpp b/flang/lib/Semantics/rewrite-parse-tree.cpp index 42962c8..706e28c 100644 --- a/flang/lib/Semantics/rewrite-parse-tree.cpp +++ b/flang/lib/Semantics/rewrite-parse-tree.cpp @@ -146,7 +146,25 @@ void FixMisparsedUntaggedNamelistName(READ_OR_WRITE &x) { } } +// READ(CVAR) [, ...] will be misparsed as UNIT=CVAR; correct +// it to READ CVAR [,...] with CVAR as a format rather than as +// an internal I/O unit for unformatted I/O, which Fortran does +// not support. void RewriteMutator::Post(parser::ReadStmt &x) { + if (x.iounit && !x.format && x.controls.empty()) { + if (auto *var{std::get_if(&x.iounit->u)}) { + const parser::Name &last{parser::GetLastName(*var)}; + DeclTypeSpec *type{last.symbol ? last.symbol->GetType() : nullptr}; + if (type && type->category() == DeclTypeSpec::Character) { + x.format = std::visit( + [](auto &&indirection) { + return parser::Expr{std::move(indirection)}; + }, + std::move(var->u)); + x.iounit.reset(); + } + } + } FixMisparsedUntaggedNamelistName(x); } diff --git a/flang/test/Semantics/rewrite01.f90 b/flang/test/Semantics/rewrite01.f90 new file mode 100644 index 0000000..2219945 --- /dev/null +++ b/flang/test/Semantics/rewrite01.f90 @@ -0,0 +1,10 @@ +! RUN: %f18 -fparse-only -fdebug-dump-parse-tree %s 2>&1 | FileCheck %s +! Ensure that READ(CVAR) [, item-list] is corrected when CVAR is a +! character variable so as to be a formatted read from the default +! unit, not an unformatted read from an internal unit (which is not +! possible in Fortran). +character :: cvar +! CHECK-NOT: IoUnit -> Variable -> Designator -> DataRef -> Name = 'cvar' +! CHECK: Format -> Expr = 'cvar' +read(cvar) +end