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 const evaluate::IntrinsicProcTable &intrinsics() const { return intrinsics_; }
84 Scope &globalScope() { return globalScope_; }
85 parser::Messages &messages() { return messages_; }
86 evaluate::FoldingContext &foldingContext() { return foldingContext_; }
87 parser::AllSources &allSources() { return allSources_; }
89 SemanticsContext &set_location(
90 const std::optional<parser::CharBlock> &location) {
94 SemanticsContext &set_searchDirectories(const std::vector<std::string> &x) {
95 searchDirectories_ = x;
98 SemanticsContext &set_moduleDirectory(const std::string &x) {
102 SemanticsContext &set_moduleFileSuffix(const std::string &x) {
103 moduleFileSuffix_ = x;
106 SemanticsContext &set_warnOnNonstandardUsage(bool x) {
107 warnOnNonstandardUsage_ = x;
110 SemanticsContext &set_warningsAreErrors(bool x) {
111 warningsAreErrors_ = x;
115 const DeclTypeSpec &MakeNumericType(TypeCategory, int kind = 0);
116 const DeclTypeSpec &MakeLogicalType(int kind = 0);
118 bool AnyFatalError() const;
120 // Test or set the Error flag on a Symbol
121 bool HasError(const Symbol &);
122 bool HasError(const Symbol *);
123 bool HasError(const parser::Name &);
124 void SetError(Symbol &, bool = true);
126 template<typename... A> parser::Message &Say(A &&... args) {
128 return messages_.Say(*location_, std::forward<A>(args)...);
130 template<typename... A>
131 parser::Message &Say(parser::CharBlock at, A &&... args) {
132 return messages_.Say(at, std::forward<A>(args)...);
134 parser::Message &Say(parser::Message &&msg) {
135 return messages_.Say(std::move(msg));
137 template<typename... A>
138 void SayWithDecl(const Symbol &symbol, const parser::CharBlock &at,
139 parser::MessageFixedText &&msg, A &&... args) {
140 auto &message{Say(at, std::move(msg), args...)};
141 evaluate::AttachDeclaration(&message, symbol);
144 const Scope &FindScope(parser::CharBlock) const;
145 Scope &FindScope(parser::CharBlock);
147 const ConstructStack &constructStack() const { return constructStack_; }
148 template<typename N> void PushConstruct(const N &node) {
149 constructStack_.emplace_back(&node);
153 ENUM_CLASS(IndexVarKind, DO, FORALL)
154 // Check to see if a variable being redefined is a DO or FORALL index.
155 // If so, emit a message.
156 void WarnIndexVarRedefine(const parser::CharBlock &, const Symbol &);
157 void CheckIndexVarRedefine(const parser::CharBlock &, const Symbol &);
158 void CheckIndexVarRedefine(const parser::Variable &);
159 void CheckIndexVarRedefine(const parser::Name &);
160 void ActivateIndexVar(const parser::Name &, IndexVarKind);
161 void DeactivateIndexVar(const parser::Name &);
162 SymbolVector GetIndexVars(IndexVarKind);
165 void CheckIndexVarRedefine(
166 const parser::CharBlock &, const Symbol &, parser::MessageFixedText &&);
167 bool CheckError(bool);
169 const common::IntrinsicTypeDefaultKinds &defaultKinds_;
170 const common::LanguageFeatureControl languageFeatures_;
171 parser::AllSources &allSources_;
172 std::optional<parser::CharBlock> location_;
173 std::vector<std::string> searchDirectories_;
174 std::string moduleDirectory_{"."s};
175 std::string moduleFileSuffix_{".mod"};
176 bool warnOnNonstandardUsage_{false};
177 bool warningsAreErrors_{false};
178 const evaluate::IntrinsicProcTable intrinsics_;
180 parser::Messages messages_;
181 evaluate::FoldingContext foldingContext_;
182 ConstructStack constructStack_;
183 struct IndexVarInfo {
184 parser::CharBlock location;
187 std::map<SymbolRef, const IndexVarInfo> activeIndexVars_;
192 explicit Semantics(SemanticsContext &context, parser::Program &program,
193 parser::CookedSource &cooked)
194 : context_{context}, program_{program}, cooked_{cooked} {
195 context.globalScope().AddSourceRange(parser::CharBlock{cooked.data()});
198 SemanticsContext &context() const { return context_; }
200 const Scope &FindScope(const parser::CharBlock &where) const {
201 return context_.FindScope(where);
203 bool AnyFatalError() const { return context_.AnyFatalError(); }
204 void EmitMessages(std::ostream &) const;
205 void DumpSymbols(std::ostream &);
206 void DumpSymbolsSources(std::ostream &) const;
209 SemanticsContext &context_;
210 parser::Program &program_;
211 const parser::CookedSource &cooked_;
214 // Base class for semantics checkers.
216 template<typename N> void Enter(const N &) {}
217 template<typename N> void Leave(const N &) {}