dd384583e5493a8f3138fb0143f8d55c6244f84d
[platform/upstream/llvm.git] / flang / include / flang / Semantics / 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 Fortran::common {
23 class IntrinsicTypeDefaultKinds;
24 }
25
26 namespace Fortran::parser {
27 struct Name;
28 struct Program;
29 class CookedSource;
30 struct AssociateConstruct;
31 struct BlockConstruct;
32 struct CaseConstruct;
33 struct DoConstruct;
34 struct ChangeTeamConstruct;
35 struct CriticalConstruct;
36 struct ForallConstruct;
37 struct IfConstruct;
38 struct SelectRankConstruct;
39 struct SelectTypeConstruct;
40 struct Variable;
41 struct WhereConstruct;
42 }
43
44 namespace Fortran::semantics {
45
46 class Symbol;
47
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>;
55
56 class SemanticsContext {
57 public:
58   SemanticsContext(const common::IntrinsicTypeDefaultKinds &,
59       const common::LanguageFeatureControl &, parser::AllSources &);
60   ~SemanticsContext();
61
62   const common::IntrinsicTypeDefaultKinds &defaultKinds() const {
63     return defaultKinds_;
64   }
65   const common::LanguageFeatureControl &languageFeatures() const {
66     return languageFeatures_;
67   };
68   int GetDefaultKind(TypeCategory) const;
69   int doublePrecisionKind() const {
70     return defaultKinds_.doublePrecisionKind();
71   }
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_;
78   }
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_; }
88
89   SemanticsContext &set_location(
90       const std::optional<parser::CharBlock> &location) {
91     location_ = location;
92     return *this;
93   }
94   SemanticsContext &set_searchDirectories(const std::vector<std::string> &x) {
95     searchDirectories_ = x;
96     return *this;
97   }
98   SemanticsContext &set_moduleDirectory(const std::string &x) {
99     moduleDirectory_ = x;
100     return *this;
101   }
102   SemanticsContext &set_moduleFileSuffix(const std::string &x) {
103     moduleFileSuffix_ = x;
104     return *this;
105   }
106   SemanticsContext &set_warnOnNonstandardUsage(bool x) {
107     warnOnNonstandardUsage_ = x;
108     return *this;
109   }
110   SemanticsContext &set_warningsAreErrors(bool x) {
111     warningsAreErrors_ = x;
112     return *this;
113   }
114
115   const DeclTypeSpec &MakeNumericType(TypeCategory, int kind = 0);
116   const DeclTypeSpec &MakeLogicalType(int kind = 0);
117
118   bool AnyFatalError() const;
119
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);
125
126   template<typename... A> parser::Message &Say(A &&... args) {
127     CHECK(location_);
128     return messages_.Say(*location_, std::forward<A>(args)...);
129   }
130   template<typename... A>
131   parser::Message &Say(parser::CharBlock at, A &&... args) {
132     return messages_.Say(at, std::forward<A>(args)...);
133   }
134   parser::Message &Say(parser::Message &&msg) {
135     return messages_.Say(std::move(msg));
136   }
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);
142   }
143
144   const Scope &FindScope(parser::CharBlock) const;
145   Scope &FindScope(parser::CharBlock);
146
147   const ConstructStack &constructStack() const { return constructStack_; }
148   template<typename N> void PushConstruct(const N &node) {
149     constructStack_.emplace_back(&node);
150   }
151   void PopConstruct();
152
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);
163
164 private:
165   void CheckIndexVarRedefine(
166       const parser::CharBlock &, const Symbol &, parser::MessageFixedText &&);
167   bool CheckError(bool);
168
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_;
179   Scope globalScope_;
180   parser::Messages messages_;
181   evaluate::FoldingContext foldingContext_;
182   ConstructStack constructStack_;
183   struct IndexVarInfo {
184     parser::CharBlock location;
185     IndexVarKind kind;
186   };
187   std::map<SymbolRef, const IndexVarInfo> activeIndexVars_;
188 };
189
190 class Semantics {
191 public:
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()});
196   }
197
198   SemanticsContext &context() const { return context_; }
199   bool Perform();
200   const Scope &FindScope(const parser::CharBlock &where) const {
201     return context_.FindScope(where);
202   }
203   bool AnyFatalError() const { return context_.AnyFatalError(); }
204   void EmitMessages(std::ostream &) const;
205   void DumpSymbols(std::ostream &);
206   void DumpSymbolsSources(std::ostream &) const;
207
208 private:
209   SemanticsContext &context_;
210   parser::Program &program_;
211   const parser::CookedSource &cooked_;
212 };
213
214 // Base class for semantics checkers.
215 struct BaseChecker {
216   template<typename N> void Enter(const N &) {}
217   template<typename N> void Leave(const N &) {}
218 };
219 }
220 #endif