• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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-exception
6 //
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 
17 namespace Fortran::semantics {
18 
19 using common::IoSpecKind;
20 using common::IoStmtKind;
21 
22 class IoChecker : public virtual BaseChecker {
23 public:
IoChecker(SemanticsContext & context)24   explicit IoChecker(SemanticsContext &context) : context_{context} {}
25 
Enter(const parser::BackspaceStmt &)26   void Enter(const parser::BackspaceStmt &) { Init(IoStmtKind::Backspace); }
Enter(const parser::CloseStmt &)27   void Enter(const parser::CloseStmt &) { Init(IoStmtKind::Close); }
Enter(const parser::EndfileStmt &)28   void Enter(const parser::EndfileStmt &) { Init(IoStmtKind::Endfile); }
Enter(const parser::FlushStmt &)29   void Enter(const parser::FlushStmt &) { Init(IoStmtKind::Flush); }
Enter(const parser::InquireStmt &)30   void Enter(const parser::InquireStmt &) { Init(IoStmtKind::Inquire); }
Enter(const parser::OpenStmt &)31   void Enter(const parser::OpenStmt &) { Init(IoStmtKind::Open); }
Enter(const parser::PrintStmt &)32   void Enter(const parser::PrintStmt &) { Init(IoStmtKind::Print); }
Enter(const parser::ReadStmt &)33   void Enter(const parser::ReadStmt &) { Init(IoStmtKind::Read); }
Enter(const parser::RewindStmt &)34   void Enter(const parser::RewindStmt &) { Init(IoStmtKind::Rewind); }
Enter(const parser::WaitStmt &)35   void Enter(const parser::WaitStmt &) { Init(IoStmtKind::Wait); }
Enter(const parser::WriteStmt &)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 
81 private:
82   // Presence flag values.
ENUM_CLASS(Flag,IoControlList,InternalUnit,NumberUnit,StarUnit,CharFmt,LabelFmt,StarFmt,AssignFmt,FmtOrNml,KnownAccess,AccessDirect,AccessStream,AdvanceYes,AsynchronousYes,KnownStatus,StatusNew,StatusReplace,StatusScratch,DataList)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 =
90         evaluate::Type<common::TypeCategory::Character, 1>;
91     if (const SomeExpr * expr{GetExpr(x)}) {
92       const auto foldExpr{
93           evaluate::Fold(context_.foldingContext(), common::Clone(*expr))};
94       if constexpr (std::is_same_v<R, std::string>) {
95         return evaluate::GetScalarConstantValue<DefaultCharConstantType>(
96             foldExpr);
97       } else {
98         static_assert(std::is_same_v<R, std::int64_t>, "unexpected type");
99         return evaluate::ToInt64(foldExpr);
100       }
101     }
102     return std::nullopt;
103   }
104 
105   void LeaveReadWrite() const;
106 
107   void SetSpecifier(IoSpecKind);
108 
109   void CheckStringValue(
110       IoSpecKind, const std::string &, const parser::CharBlock &) const;
111 
112   void CheckForRequiredSpecifier(IoSpecKind) const;
113   void CheckForRequiredSpecifier(bool, const std::string &) const;
114   void CheckForRequiredSpecifier(IoSpecKind, IoSpecKind) const;
115   void CheckForRequiredSpecifier(IoSpecKind, bool, const std::string &) const;
116   void CheckForRequiredSpecifier(bool, const std::string &, IoSpecKind) const;
117   void CheckForRequiredSpecifier(
118       bool, const std::string &, bool, const std::string &) const;
119 
120   void CheckForProhibitedSpecifier(IoSpecKind) const;
121   void CheckForProhibitedSpecifier(IoSpecKind, IoSpecKind) const;
122   void CheckForProhibitedSpecifier(IoSpecKind, bool, const std::string &) const;
123   void CheckForProhibitedSpecifier(bool, const std::string &, IoSpecKind) const;
124 
125   template <typename A>
126   void CheckForDefinableVariable(const A &var, const std::string &s) const;
127 
128   void CheckForPureSubprogram() const;
129 
Init(IoStmtKind s)130   void Init(IoStmtKind s) {
131     stmt_ = s;
132     specifierSet_.reset();
133     flags_.reset();
134   }
135 
Done()136   void Done() { stmt_ = IoStmtKind::None; }
137 
138   SemanticsContext &context_;
139   IoStmtKind stmt_{IoStmtKind::None};
140   common::EnumSet<IoSpecKind, common::IoSpecKind_enumSize> specifierSet_;
141   common::EnumSet<Flag, Flag_enumSize> flags_;
142 };
143 
144 } // namespace Fortran::semantics
145 #endif // FORTRAN_SEMANTICS_CHECK_IO_H_
146