[flang] Rewrite read-stmt/write-stmt parse trees for misparsed namelist group names

Original-commit: flang-compiler/f18@e0f1b1c469
Reviewed-on: https://github.com/flang-compiler/f18/pull/394
Tree-same-pre-rewrite: false
This commit is contained in:
peter klausler 2019-04-09 16:36:29 -07:00
parent 798e5544b0
commit 0e55f2463b
2 changed files with 40 additions and 2 deletions

View File

@ -2613,7 +2613,7 @@ struct ReadStmt {
std::optional<IoUnit> iounit; // if first in controls without UNIT=
std::optional<Format> format; // if second in controls without FMT=, or
// no (io-control-spec-list); might be
// an untagged namelist group name (TODO)
// an untagged namelist group name, too
std::list<IoControlSpec> controls;
std::list<InputItem> items;
};
@ -2633,7 +2633,7 @@ struct WriteStmt {
items(std::move(its)) {}
std::optional<IoUnit> iounit; // if first in controls without UNIT=
std::optional<Format> format; // if second in controls without FMT=;
// might be an untagged namelist group (TODO)
// might be an untagged namelist group, too
std::list<IoControlSpec> controls;
std::list<OutputItem> items;
};

View File

@ -26,6 +26,7 @@ namespace Fortran::semantics {
using namespace parser::literals;
/// Convert mis-identified statement functions to array element assignments.
/// Convert mis-identified format expressions to namelist group names.
class RewriteMutator {
public:
RewriteMutator(parser::Messages &messages) : messages_{messages} {}
@ -37,6 +38,8 @@ public:
void Post(parser::Name &);
void Post(parser::SpecificationPart &);
bool Pre(parser::ExecutionPart &);
void Post(parser::ReadStmt &);
void Post(parser::WriteStmt &);
// Name resolution yet implemented:
bool Pre(parser::EquivalenceStmt &) { return false; }
@ -101,6 +104,41 @@ bool RewriteMutator::Pre(parser::ExecutionPart &x) {
return true;
}
// When a namelist group name appears (without NML=) in a READ or WRITE
// statement in such a way that it can be misparsed as a format expression,
// rewrite the I/O statement's parse tree node as if the namelist group
// name had appeared with NML=.
template<typename READ_OR_WRITE>
void FixMisparsedUntaggedNamelistName(READ_OR_WRITE &x) {
if (x.format.has_value()) {
if (auto *charExpr{
std::get_if<parser::DefaultCharExpr>(&x.format.value().u)}) {
parser::Expr &expr{charExpr->thing.value()};
if (auto *designator{
std::get_if<common::Indirection<parser::Designator>>(&expr.u)}) {
parser::Name *name{
std::get_if<parser::ObjectName>(&designator->value().u)};
if (auto *dr{std::get_if<parser::DataRef>(&designator->value().u)}) {
name = std::get_if<parser::Name>(&dr->u);
}
if (name != nullptr && name->symbol != nullptr &&
name->symbol->has<NamelistDetails>()) {
x.controls.emplace_front(parser::IoControlSpec{std::move(*name)});
x.format.reset();
}
}
}
}
}
void RewriteMutator::Post(parser::ReadStmt &x) {
FixMisparsedUntaggedNamelistName(x);
}
void RewriteMutator::Post(parser::WriteStmt &x) {
FixMisparsedUntaggedNamelistName(x);
}
bool RewriteParseTree(SemanticsContext &context, parser::Program &program) {
RewriteMutator mutator{context.messages()};
parser::Walk(program, mutator);