1 //===-- lib/Semantics/check-io.h --------------------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 #ifndef FORTRAN_SEMANTICS_CHECK_IO_H_
10 #define FORTRAN_SEMANTICS_CHECK_IO_H_
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"
17 namespace Fortran::semantics
{
19 using common::IoSpecKind
;
20 using common::IoStmtKind
;
22 class IoChecker
: public virtual BaseChecker
{
24 explicit IoChecker(SemanticsContext
&context
) : context_
{context
} {}
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
); }
39 const parser::Statement
<common::Indirection
<parser::FormatStmt
>> &);
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
&);
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
&);
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
)
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
)}) {
92 evaluate::Fold(context_
.foldingContext(), common::Clone(*expr
))};
93 if constexpr (std::is_same_v
<R
, std::string
>) {
94 return evaluate::GetScalarConstantValue
<DefaultCharConstantType
>(
97 static_assert(std::is_same_v
<R
, std::int64_t>, "unexpected type");
98 return evaluate::ToInt64(foldExpr
);
104 void LeaveReadWrite() const;
106 void SetSpecifier(IoSpecKind
);
108 void CheckStringValue(
109 IoSpecKind
, const std::string
&, const parser::CharBlock
&) const;
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;
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;
124 template <typename A
>
125 void CheckForDefinableVariable(const A
&var
, const std::string
&s
) const;
127 void CheckForPureSubprogram() const;
129 parser::Message
*CheckForBadIoType(const evaluate::DynamicType
&,
130 GenericKind::DefinedIo
, parser::CharBlock
) const;
131 void CheckForBadIoType(
132 const SomeExpr
&, GenericKind::DefinedIo
, parser::CharBlock
) const;
133 parser::Message
*CheckForBadIoType(
134 const Symbol
&, GenericKind::DefinedIo
, parser::CharBlock
) const;
137 const Symbol
&, GenericKind::DefinedIo
, parser::CharBlock
) const;
139 void Init(IoStmtKind s
) {
141 specifierSet_
.reset();
145 void Done() { stmt_
= IoStmtKind::None
; }
147 SemanticsContext
&context_
;
148 IoStmtKind stmt_
{IoStmtKind::None
};
149 common::EnumSet
<IoSpecKind
, common::IoSpecKind_enumSize
> specifierSet_
;
150 common::EnumSet
<Flag
, Flag_enumSize
> flags_
;
153 } // namespace Fortran::semantics
154 #endif // FORTRAN_SEMANTICS_CHECK_IO_H_