156 lines · c
1//===-- lib/Semantics/check-io.h --------------------------------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef FORTRAN_SEMANTICS_CHECK_IO_H_10#define FORTRAN_SEMANTICS_CHECK_IO_H_11 12#include "flang/Common/enum-set.h"13#include "flang/Parser/parse-tree.h"14#include "flang/Semantics/semantics.h"15#include "flang/Semantics/tools.h"16 17namespace Fortran::semantics {18 19using common::IoSpecKind;20using common::IoStmtKind;21 22class IoChecker : public virtual BaseChecker {23public:24 explicit IoChecker(SemanticsContext &context) : context_{context} {}25 26 void Enter(const parser::BackspaceStmt &) { Init(IoStmtKind::Backspace); }27 void Enter(const parser::CloseStmt &) { Init(IoStmtKind::Close); }28 void Enter(const parser::EndfileStmt &) { Init(IoStmtKind::Endfile); }29 void Enter(const parser::FlushStmt &) { Init(IoStmtKind::Flush); }30 void Enter(const parser::InquireStmt &) { Init(IoStmtKind::Inquire); }31 void Enter(const parser::OpenStmt &) { Init(IoStmtKind::Open); }32 void Enter(const parser::PrintStmt &) { Init(IoStmtKind::Print); }33 void Enter(const parser::ReadStmt &) { Init(IoStmtKind::Read); }34 void Enter(const parser::RewindStmt &) { Init(IoStmtKind::Rewind); }35 void Enter(const parser::WaitStmt &) { Init(IoStmtKind::Wait); }36 void Enter(const parser::WriteStmt &) { Init(IoStmtKind::Write); }37 38 void Enter(39 const parser::Statement<common::Indirection<parser::FormatStmt>> &);40 41 void Enter(const parser::ConnectSpec &);42 void Enter(const parser::ConnectSpec::CharExpr &);43 void Enter(const parser::ConnectSpec::Newunit &);44 void Enter(const parser::ConnectSpec::Recl &);45 void Enter(const parser::EndLabel &);46 void Enter(const parser::EorLabel &);47 void Enter(const parser::ErrLabel &);48 void Enter(const parser::FileUnitNumber &);49 void Enter(const parser::Format &);50 void Enter(const parser::IdExpr &);51 void Enter(const parser::IdVariable &);52 void Enter(const parser::InputItem &);53 void Enter(const parser::InquireSpec &);54 void Enter(const parser::InquireSpec::CharVar &);55 void Enter(const parser::InquireSpec::IntVar &);56 void Enter(const parser::InquireSpec::LogVar &);57 void Enter(const parser::IoControlSpec &);58 void Enter(const parser::IoControlSpec::Asynchronous &);59 void Enter(const parser::IoControlSpec::CharExpr &);60 void Enter(const parser::IoControlSpec::Pos &);61 void Enter(const parser::IoControlSpec::Rec &);62 void Enter(const parser::IoControlSpec::Size &);63 void Enter(const parser::IoUnit &);64 void Enter(const parser::MsgVariable &);65 void Enter(const parser::OutputItem &);66 void Enter(const parser::StatusExpr &);67 void Enter(const parser::StatVariable &);68 69 void Leave(const parser::BackspaceStmt &);70 void Leave(const parser::CloseStmt &);71 void Leave(const parser::EndfileStmt &);72 void Leave(const parser::FlushStmt &);73 void Leave(const parser::InquireStmt &);74 void Leave(const parser::OpenStmt &);75 void Leave(const parser::PrintStmt &);76 void Leave(const parser::ReadStmt &);77 void Leave(const parser::RewindStmt &);78 void Leave(const parser::WaitStmt &);79 void Leave(const parser::WriteStmt &);80 81private:82 // Presence flag values.83 ENUM_CLASS(Flag, IoControlList, InternalUnit, NumberUnit, StarUnit, CharFmt,84 LabelFmt, StarFmt, AssignFmt, FmtOrNml, KnownAccess, AccessDirect,85 AccessStream, AdvanceYes, AsynchronousYes, KnownStatus, StatusNew,86 StatusReplace, StatusScratch, DataList)87 88 template <typename R, typename T> std::optional<R> GetConstExpr(const T &x) {89 using DefaultCharConstantType = evaluate::Ascii;90 if (const SomeExpr * expr{GetExpr(context_, x)}) {91 const auto foldExpr{92 evaluate::Fold(context_.foldingContext(), common::Clone(*expr))};93 if constexpr (std::is_same_v<R, std::string>) {94 return evaluate::GetScalarConstantValue<DefaultCharConstantType>(95 foldExpr);96 } else {97 static_assert(std::is_same_v<R, std::int64_t>, "unexpected type");98 return evaluate::ToInt64(foldExpr);99 }100 }101 return std::nullopt;102 }103 104 void LeaveReadWrite() const;105 106 void SetSpecifier(IoSpecKind);107 108 void CheckStringValue(109 IoSpecKind, const std::string &, const parser::CharBlock &) const;110 111 void CheckForRequiredSpecifier(IoSpecKind) const;112 void CheckForRequiredSpecifier(bool, const std::string &) const;113 void CheckForRequiredSpecifier(IoSpecKind, IoSpecKind) const;114 void CheckForRequiredSpecifier(IoSpecKind, bool, const std::string &) const;115 void CheckForRequiredSpecifier(bool, const std::string &, IoSpecKind) const;116 void CheckForRequiredSpecifier(117 bool, const std::string &, bool, const std::string &) const;118 119 void CheckForProhibitedSpecifier(IoSpecKind) const;120 void CheckForProhibitedSpecifier(IoSpecKind, IoSpecKind) const;121 void CheckForProhibitedSpecifier(IoSpecKind, bool, const std::string &) const;122 void CheckForProhibitedSpecifier(bool, const std::string &, IoSpecKind) const;123 124 template <typename A>125 void CheckForDefinableVariable(const A &var, const std::string &s) const;126 127 void CheckForPureSubprogram() const;128 void CheckForUselessIomsg() const;129 130 parser::Message *CheckForBadIoType(const evaluate::DynamicType &,131 common::DefinedIo, parser::CharBlock) const;132 void CheckForBadIoType(133 const SomeExpr &, common::DefinedIo, parser::CharBlock) const;134 parser::Message *CheckForBadIoType(135 const Symbol &, common::DefinedIo, parser::CharBlock) const;136 137 void CheckNamelist(138 const Symbol &, common::DefinedIo, parser::CharBlock) const;139 140 void Init(IoStmtKind s) {141 stmt_ = s;142 specifierSet_.reset();143 flags_.reset();144 }145 146 void Done() { stmt_ = IoStmtKind::None; }147 148 SemanticsContext &context_;149 IoStmtKind stmt_{IoStmtKind::None};150 common::EnumSet<IoSpecKind, common::IoSpecKind_enumSize> specifierSet_;151 common::EnumSet<Flag, Flag_enumSize> flags_;152};153 154} // namespace Fortran::semantics155#endif // FORTRAN_SEMANTICS_CHECK_IO_H_156