1 //===-- include/flang/Semantics/semantics.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_SEMANTICS_H_
10 #define FORTRAN_SEMANTICS_SEMANTICS_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"
22 namespace Fortran::common {
23 class IntrinsicTypeDefaultKinds;
26 namespace Fortran::parser {
30 struct AssociateConstruct;
31 struct BlockConstruct;
34 struct ChangeTeamConstruct;
35 struct CriticalConstruct;
36 struct ForallConstruct;
38 struct SelectRankConstruct;
39 struct SelectTypeConstruct;
41 struct WhereConstruct;
44 namespace Fortran::semantics {
48 using ConstructNode = std::variant<const parser::AssociateConstruct *,
49 const parser::BlockConstruct *, const parser::CaseConstruct *,
50 const parser::ChangeTeamConstruct *, const parser::CriticalConstruct *,
51 const parser::DoConstruct *, const parser::ForallConstruct *,
52 const parser::IfConstruct *, const parser::SelectRankConstruct *,
53 const parser::SelectTypeConstruct *, const parser::WhereConstruct *>;
54 using ConstructStack = std::vector<ConstructNode>;
56 class SemanticsContext {
58 SemanticsContext(const common::IntrinsicTypeDefaultKinds &,
59 const common::LanguageFeatureControl &, parser::AllSources &);
62 const common::IntrinsicTypeDefaultKinds &defaultKinds() const {
65 const common::LanguageFeatureControl &languageFeatures() const {
66 return languageFeatures_;
68 int GetDefaultKind(TypeCategory) const;
69 int doublePrecisionKind() const {
70 return defaultKinds_.doublePrecisionKind();
72 int quadPrecisionKind() const { return defaultKinds_.quadPrecisionKind(); }
73 bool IsEnabled(common::LanguageFeature) const;
74 bool ShouldWarn(common::LanguageFeature) const;
75 const std::optional<parser::CharBlock> &location() const { return location_; }
76 const std::vector<std::string> &searchDirectories() const {
77 return searchDirectories_;
79 const std::string &moduleDirectory() const { return moduleDirectory_; }
80 const std::string &moduleFileSuffix() const { return moduleFileSuffix_; }
81 bool warnOnNonstandardUsage() const { return warnOnNonstandardUsage_; }
82 bool warningsAreErrors() const { return warningsAreErrors_; }
83 bool debugModuleWriter() const { return debugModuleWriter_; }
84 const evaluate::IntrinsicProcTable &intrinsics() const { return intrinsics_; }
85 Scope &globalScope() { return globalScope_; }
86 parser::Messages &messages() { return messages_; }
87 evaluate::FoldingContext &foldingContext() { return foldingContext_; }
88 parser::AllSources &allSources() { return allSources_; }
90 SemanticsContext &set_location(
91 const std::optional<parser::CharBlock> &location) {
95 SemanticsContext &set_searchDirectories(const std::vector<std::string> &x) {
96 searchDirectories_ = x;
99 SemanticsContext &set_moduleDirectory(const std::string &x) {
100 moduleDirectory_ = x;
103 SemanticsContext &set_moduleFileSuffix(const std::string &x) {
104 moduleFileSuffix_ = x;
107 SemanticsContext &set_warnOnNonstandardUsage(bool x) {
108 warnOnNonstandardUsage_ = x;
111 SemanticsContext &set_warningsAreErrors(bool x) {
112 warningsAreErrors_ = x;
116 SemanticsContext &set_debugModuleWriter(bool x) {
117 debugModuleWriter_ = x;
121 const DeclTypeSpec &MakeNumericType(TypeCategory, int kind = 0);
122 const DeclTypeSpec &MakeLogicalType(int kind = 0);
124 bool AnyFatalError() const;
126 // Test or set the Error flag on a Symbol
127 bool HasError(const Symbol &);
128 bool HasError(const Symbol *);
129 bool HasError(const parser::Name &);
130 void SetError(Symbol &, bool = true);
132 template<typename... A> parser::Message &Say(A &&... args) {
134 return messages_.Say(*location_, std::forward<A>(args)...);
136 template<typename... A>
137 parser::Message &Say(parser::CharBlock at, A &&... args) {
138 return messages_.Say(at, std::forward<A>(args)...);
140 parser::Message &Say(parser::Message &&msg) {
141 return messages_.Say(std::move(msg));
143 template<typename... A>
144 void SayWithDecl(const Symbol &symbol, const parser::CharBlock &at,
145 parser::MessageFixedText &&msg, A &&... args) {
146 auto &message{Say(at, std::move(msg), args...)};
147 evaluate::AttachDeclaration(&message, symbol);
150 const Scope &FindScope(parser::CharBlock) const;
151 Scope &FindScope(parser::CharBlock);
153 const ConstructStack &constructStack() const { return constructStack_; }
154 template<typename N> void PushConstruct(const N &node) {
155 constructStack_.emplace_back(&node);
159 ENUM_CLASS(IndexVarKind, DO, FORALL)
160 // Check to see if a variable being redefined is a DO or FORALL index.
161 // If so, emit a message.
162 void WarnIndexVarRedefine(const parser::CharBlock &, const Symbol &);
163 void CheckIndexVarRedefine(const parser::CharBlock &, const Symbol &);
164 void CheckIndexVarRedefine(const parser::Variable &);
165 void CheckIndexVarRedefine(const parser::Name &);
166 void ActivateIndexVar(const parser::Name &, IndexVarKind);
167 void DeactivateIndexVar(const parser::Name &);
168 SymbolVector GetIndexVars(IndexVarKind);
171 void CheckIndexVarRedefine(
172 const parser::CharBlock &, const Symbol &, parser::MessageFixedText &&);
173 bool CheckError(bool);
175 const common::IntrinsicTypeDefaultKinds &defaultKinds_;
176 const common::LanguageFeatureControl languageFeatures_;
177 parser::AllSources &allSources_;
178 std::optional<parser::CharBlock> location_;
179 std::vector<std::string> searchDirectories_;
180 std::string moduleDirectory_{"."s};
181 std::string moduleFileSuffix_{".mod"};
182 bool warnOnNonstandardUsage_{false};
183 bool warningsAreErrors_{false};
184 bool debugModuleWriter_{false};
185 const evaluate::IntrinsicProcTable intrinsics_;
187 parser::Messages messages_;
188 evaluate::FoldingContext foldingContext_;
189 ConstructStack constructStack_;
190 struct IndexVarInfo {
191 parser::CharBlock location;
194 std::map<SymbolRef, const IndexVarInfo> activeIndexVars_;
199 explicit Semantics(SemanticsContext &context, parser::Program &program,
200 parser::CookedSource &cooked, bool debugModuleWriter = false)
201 : context_{context}, program_{program}, cooked_{cooked} {
202 context.set_debugModuleWriter(debugModuleWriter);
203 context.globalScope().AddSourceRange(parser::CharBlock{cooked.data()});
206 SemanticsContext &context() const { return context_; }
208 const Scope &FindScope(const parser::CharBlock &where) const {
209 return context_.FindScope(where);
211 bool AnyFatalError() const { return context_.AnyFatalError(); }
212 void EmitMessages(std::ostream &) const;
213 void DumpSymbols(std::ostream &);
214 void DumpSymbolsSources(std::ostream &) const;
217 SemanticsContext &context_;
218 parser::Program &program_;
219 const parser::CookedSource &cooked_;
222 // Base class for semantics checkers.
224 template<typename N> void Enter(const N &) {}
225 template<typename N> void Leave(const N &) {}