FLANG

semantics.h
1 //===-- include/flang/Semantics/semantics.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_SEMANTICS_H_
10 #define FORTRAN_SEMANTICS_SEMANTICS_H_
11
12 #include "scope.h"
13 #include "symbol.h"
14 #include "flang/Common/Fortran-features.h"
15 #include "flang/Evaluate/common.h"
16 #include "flang/Evaluate/intrinsics.h"
17 #include "flang/Parser/message.h"
18 #include <iosfwd>
19 #include <string>
20 #include <vector>
21
22 namespace llvm {
23 class raw_ostream;
24 }
25
26 namespace Fortran::common {
27 class IntrinsicTypeDefaultKinds;
28 }
29
30 namespace Fortran::parser {
31 struct Name;
32 struct Program;
33 class CookedSource;
34 struct AssociateConstruct;
35 struct BlockConstruct;
36 struct CaseConstruct;
37 struct DoConstruct;
38 struct ChangeTeamConstruct;
39 struct CriticalConstruct;
40 struct ForallConstruct;
41 struct IfConstruct;
42 struct SelectRankConstruct;
43 struct SelectTypeConstruct;
44 struct Variable;
45 struct WhereConstruct;
46 } // namespace Fortran::parser
47
48 namespace Fortran::semantics {
49
50 class Symbol;
51
52 using ConstructNode = std::variant<const parser::AssociateConstruct *,
53 const parser::BlockConstruct *, const parser::CaseConstruct *,
54 const parser::ChangeTeamConstruct *, const parser::CriticalConstruct *,
55 const parser::DoConstruct *, const parser::ForallConstruct *,
56 const parser::IfConstruct *, const parser::SelectRankConstruct *,
57 const parser::SelectTypeConstruct *, const parser::WhereConstruct *>;
58 using ConstructStack = std::vector<ConstructNode>;
59
60 class SemanticsContext {
61 public:
62 SemanticsContext(const common::IntrinsicTypeDefaultKinds &,
63 const common::LanguageFeatureControl &, parser::AllSources &);
64 ~SemanticsContext();
65
66 const common::IntrinsicTypeDefaultKinds &defaultKinds() const {
67 return defaultKinds_;
68 }
69 const common::LanguageFeatureControl &languageFeatures() const {
70 return languageFeatures_;
71 };
72 int GetDefaultKind(TypeCategory) const;
73 int doublePrecisionKind() const {
74 return defaultKinds_.doublePrecisionKind();
75 }
76 int quadPrecisionKind() const { return defaultKinds_.quadPrecisionKind(); }
77 bool IsEnabled(common::LanguageFeature) const;
78 bool ShouldWarn(common::LanguageFeature) const;
79 const std::optional<parser::CharBlock> &location() const { return location_; }
80 const std::vector<std::string> &searchDirectories() const {
81 return searchDirectories_;
82 }
83 const std::string &moduleDirectory() const { return moduleDirectory_; }
84 const std::string &moduleFileSuffix() const { return moduleFileSuffix_; }
85 bool warnOnNonstandardUsage() const { return warnOnNonstandardUsage_; }
86 bool warningsAreErrors() const { return warningsAreErrors_; }
87 bool debugModuleWriter() const { return debugModuleWriter_; }
88 const evaluate::IntrinsicProcTable &intrinsics() const { return intrinsics_; }
89 Scope &globalScope() { return globalScope_; }
90 parser::Messages &messages() { return messages_; }
91 evaluate::FoldingContext &foldingContext() { return foldingContext_; }
92 parser::AllSources &allSources() { return allSources_; }
93
94 SemanticsContext &set_location(
95 const std::optional<parser::CharBlock> &location) {
96 location_ = location;
97 return *this;
98 }
99 SemanticsContext &set_searchDirectories(const std::vector<std::string> &x) {
100 searchDirectories_ = x;
101 return *this;
102 }
103 SemanticsContext &set_moduleDirectory(const std::string &x) {
104 moduleDirectory_ = x;
105 return *this;
106 }
107 SemanticsContext &set_moduleFileSuffix(const std::string &x) {
108 moduleFileSuffix_ = x;
109 return *this;
110 }
111 SemanticsContext &set_warnOnNonstandardUsage(bool x) {
112 warnOnNonstandardUsage_ = x;
113 return *this;
114 }
115 SemanticsContext &set_warningsAreErrors(bool x) {
116 warningsAreErrors_ = x;
117 return *this;
118 }
119
120 SemanticsContext &set_debugModuleWriter(bool x) {
121 debugModuleWriter_ = x;
122 return *this;
123 }
124
125 const DeclTypeSpec &MakeNumericType(TypeCategory, int kind = 0);
126 const DeclTypeSpec &MakeLogicalType(int kind = 0);
127
128 bool AnyFatalError() const;
129
130 // Test or set the Error flag on a Symbol
131 bool HasError(const Symbol &);
132 bool HasError(const Symbol *);
133 bool HasError(const parser::Name &);
134 void SetError(Symbol &, bool = true);
135
136 template <typename... A> parser::Message &Say(A &&... args) {
137 CHECK(location_);
138 return messages_.Say(*location_, std::forward<A>(args)...);
139 }
140 template <typename... A>
141 parser::Message &Say(parser::CharBlock at, A &&... args) {
142 return messages_.Say(at, std::forward<A>(args)...);
143 }
144 parser::Message &Say(parser::Message &&msg) {
145 return messages_.Say(std::move(msg));
146 }
147 template <typename... A>
148 void SayWithDecl(const Symbol &symbol, const parser::CharBlock &at,
149 parser::MessageFixedText &&msg, A &&... args) {
150 auto &message{Say(at, std::move(msg), args...)};
151 evaluate::AttachDeclaration(&message, symbol);
152 }
153
154 const Scope &FindScope(parser::CharBlock) const;
155 Scope &FindScope(parser::CharBlock);
156
157 const ConstructStack &constructStack() const { return constructStack_; }
158 template <typename N> void PushConstruct(const N &node) {
159 constructStack_.emplace_back(&node);
160 }
161 void PopConstruct();
162
163 ENUM_CLASS(IndexVarKind, DO, FORALL)
164 // Check to see if a variable being redefined is a DO or FORALL index.
165 // If so, emit a message.
166 void WarnIndexVarRedefine(const parser::CharBlock &, const Symbol &);
167 void CheckIndexVarRedefine(const parser::CharBlock &, const Symbol &);
168 void CheckIndexVarRedefine(const parser::Variable &);
169 void CheckIndexVarRedefine(const parser::Name &);
170 void ActivateIndexVar(const parser::Name &, IndexVarKind);
171 void DeactivateIndexVar(const parser::Name &);
172 SymbolVector GetIndexVars(IndexVarKind);
173
174 private:
175 void CheckIndexVarRedefine(
176 const parser::CharBlock &, const Symbol &, parser::MessageFixedText &&);
177 bool CheckError(bool);
178
179 const common::IntrinsicTypeDefaultKinds &defaultKinds_;
180 const common::LanguageFeatureControl languageFeatures_;
181 parser::AllSources &allSources_;
182 std::optional<parser::CharBlock> location_;
183 std::vector<std::string> searchDirectories_;
184 std::string moduleDirectory_{"."s};
185 std::string moduleFileSuffix_{".mod"};
186 bool warnOnNonstandardUsage_{false};
187 bool warningsAreErrors_{false};
188 bool debugModuleWriter_{false};
189 const evaluate::IntrinsicProcTable intrinsics_;
190 Scope globalScope_;
191 parser::Messages messages_;
192 evaluate::FoldingContext foldingContext_;
193 ConstructStack constructStack_;
194 struct IndexVarInfo {
195 parser::CharBlock location;
196 IndexVarKind kind;
197 };
198 std::map<SymbolRef, const IndexVarInfo> activeIndexVars_;
199 };
200
201 class Semantics {
202 public:
203 explicit Semantics(SemanticsContext &context, parser::Program &program,
204 parser::CookedSource &cooked, bool debugModuleWriter = false)
205 : context_{context}, program_{program}, cooked_{cooked} {
206 context.set_debugModuleWriter(debugModuleWriter);
207 context.globalScope().AddSourceRange(parser::CharBlock{cooked.data()});
208 }
209
210 SemanticsContext &context() const { return context_; }
211 bool Perform();
212 const Scope &FindScope(const parser::CharBlock &where) const {
213 return context_.FindScope(where);
214 }
215 bool AnyFatalError() const { return context_.AnyFatalError(); }
216 void EmitMessages(llvm::raw_ostream &) const;
217 void DumpSymbols(llvm::raw_ostream &);
218 void DumpSymbolsSources(llvm::raw_ostream &) const;
219
220 private:
221 SemanticsContext &context_;
222 parser::Program &program_;
223 const parser::CookedSource &cooked_;
224 };
225
226 // Base class for semantics checkers.
227 struct BaseChecker {
228 template <typename N> void Enter(const N &) {}
229 template <typename N> void Leave(const N &) {}
230 };
231 } // namespace Fortran::semantics
232 #endif
Fortran::parser::AllSources
Definition: provenance.h:137
Fortran::semantics::SemanticsContext
Definition: semantics.h:60
Fortran::parser::CookedSource
Definition: provenance.h:216
Fortran::semantics::DeclTypeSpec
Definition: type.h:302
Fortran::common::LanguageFeatureControl
Definition: Fortran-features.h:35
Fortran::semantics::Symbol
Definition: symbol.h:479
Fortran::parser::Messages
Definition: message.h:213
Fortran::common::IntrinsicTypeDefaultKinds
Definition: default-kinds.h:26
Fortran::evaluate::FoldingContext
Definition: common.h:209
Fortran::parser::Message
Definition: message.h:141
Fortran::parser::Variable
Definition: parse-tree.h:1780
Fortran::parser::Name
Definition: parse-tree.h:555
Fortran::parser::MessageFixedText
Definition: message.h:33
Fortran::semantics::BaseChecker
Definition: semantics.h:227
Fortran::parser::CharBlock
Definition: char-block.h:28
Fortran::semantics::Scope
Definition: scope.h:56
Fortran::semantics::Semantics
Definition: semantics.h:201
Fortran::parser
Definition: check-expression.h:19