[flang] Replace module writer posix file handling with llvm file handling. (flang...
[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   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_; }
89
90   SemanticsContext &set_location(
91       const std::optional<parser::CharBlock> &location) {
92     location_ = location;
93     return *this;
94   }
95   SemanticsContext &set_searchDirectories(const std::vector<std::string> &x) {
96     searchDirectories_ = x;
97     return *this;
98   }
99   SemanticsContext &set_moduleDirectory(const std::string &x) {
100     moduleDirectory_ = x;
101     return *this;
102   }
103   SemanticsContext &set_moduleFileSuffix(const std::string &x) {
104     moduleFileSuffix_ = x;
105     return *this;
106   }
107   SemanticsContext &set_warnOnNonstandardUsage(bool x) {
108     warnOnNonstandardUsage_ = x;
109     return *this;
110   }
111   SemanticsContext &set_warningsAreErrors(bool x) {
112     warningsAreErrors_ = x;
113     return *this;
114   }
115
116   SemanticsContext &set_debugModuleWriter(bool x) {
117     debugModuleWriter_ = x;
118     return *this;
119   }
120
121   const DeclTypeSpec &MakeNumericType(TypeCategory, int kind = 0);
122   const DeclTypeSpec &MakeLogicalType(int kind = 0);
123
124   bool AnyFatalError() const;
125
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);
131
132   template<typename... A> parser::Message &Say(A &&... args) {
133     CHECK(location_);
134     return messages_.Say(*location_, std::forward<A>(args)...);
135   }
136   template<typename... A>
137   parser::Message &Say(parser::CharBlock at, A &&... args) {
138     return messages_.Say(at, std::forward<A>(args)...);
139   }
140   parser::Message &Say(parser::Message &&msg) {
141     return messages_.Say(std::move(msg));
142   }
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);
148   }
149
150   const Scope &FindScope(parser::CharBlock) const;
151   Scope &FindScope(parser::CharBlock);
152
153   const ConstructStack &constructStack() const { return constructStack_; }
154   template<typename N> void PushConstruct(const N &node) {
155     constructStack_.emplace_back(&node);
156   }
157   void PopConstruct();
158
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);
169
170 private:
171   void CheckIndexVarRedefine(
172       const parser::CharBlock &, const Symbol &, parser::MessageFixedText &&);
173   bool CheckError(bool);
174
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_;
186   Scope globalScope_;
187   parser::Messages messages_;
188   evaluate::FoldingContext foldingContext_;
189   ConstructStack constructStack_;
190   struct IndexVarInfo {
191     parser::CharBlock location;
192     IndexVarKind kind;
193   };
194   std::map<SymbolRef, const IndexVarInfo> activeIndexVars_;
195 };
196
197 class Semantics {
198 public:
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()});
204   }
205
206   SemanticsContext &context() const { return context_; }
207   bool Perform();
208   const Scope &FindScope(const parser::CharBlock &where) const {
209     return context_.FindScope(where);
210   }
211   bool AnyFatalError() const { return context_.AnyFatalError(); }
212   void EmitMessages(std::ostream &) const;
213   void DumpSymbols(std::ostream &);
214   void DumpSymbolsSources(std::ostream &) const;
215
216 private:
217   SemanticsContext &context_;
218   parser::Program &program_;
219   const parser::CookedSource &cooked_;
220 };
221
222 // Base class for semantics checkers.
223 struct BaseChecker {
224   template<typename N> void Enter(const N &) {}
225   template<typename N> void Leave(const N &) {}
226 };
227 }
228 #endif