Warning: This file is not a C or C++ file. It does not have highlighting.

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/Evaluate/target.h"
18#include "flang/Parser/message.h"
19#include "flang/Semantics/module-dependences.h"
20#include <iosfwd>
21#include <set>
22#include <string>
23#include <vector>
24
25namespace llvm {
26class raw_ostream;
27}
28
29namespace Fortran::common {
30class IntrinsicTypeDefaultKinds;
31}
32
33namespace Fortran::parser {
34struct Name;
35struct Program;
36class AllCookedSources;
37struct AssociateConstruct;
38struct BlockConstruct;
39struct CaseConstruct;
40struct DoConstruct;
41struct ChangeTeamConstruct;
42struct CriticalConstruct;
43struct ForallConstruct;
44struct IfConstruct;
45struct SelectRankConstruct;
46struct SelectTypeConstruct;
47struct Variable;
48struct WhereConstruct;
49} // namespace Fortran::parser
50
51namespace Fortran::semantics {
52
53class Symbol;
54class CommonBlockMap;
55using CommonBlockList = std::vector<std::pair<SymbolRef, std::size_t>>;
56
57using ConstructNode = std::variant<const parser::AssociateConstruct *,
58 const parser::BlockConstruct *, const parser::CaseConstruct *,
59 const parser::ChangeTeamConstruct *, const parser::CriticalConstruct *,
60 const parser::DoConstruct *, const parser::ForallConstruct *,
61 const parser::IfConstruct *, const parser::SelectRankConstruct *,
62 const parser::SelectTypeConstruct *, const parser::WhereConstruct *>;
63using ConstructStack = std::vector<ConstructNode>;
64
65class SemanticsContext {
66public:
67 SemanticsContext(const common::IntrinsicTypeDefaultKinds &,
68 const common::LanguageFeatureControl &, parser::AllCookedSources &);
69 ~SemanticsContext();
70
71 const common::IntrinsicTypeDefaultKinds &defaultKinds() const {
72 return defaultKinds_;
73 }
74 const common::LanguageFeatureControl &languageFeatures() const {
75 return languageFeatures_;
76 };
77 int GetDefaultKind(TypeCategory) const;
78 int doublePrecisionKind() const {
79 return defaultKinds_.doublePrecisionKind();
80 }
81 int quadPrecisionKind() const { return defaultKinds_.quadPrecisionKind(); }
82 bool IsEnabled(common::LanguageFeature feature) const {
83 return languageFeatures_.IsEnabled(feature);
84 }
85 template <typename A> bool ShouldWarn(A x) const {
86 return languageFeatures_.ShouldWarn(x);
87 }
88 const std::optional<parser::CharBlock> &location() const { return location_; }
89 const std::vector<std::string> &searchDirectories() const {
90 return searchDirectories_;
91 }
92 const std::vector<std::string> &intrinsicModuleDirectories() const {
93 return intrinsicModuleDirectories_;
94 }
95 const std::string &moduleDirectory() const { return moduleDirectory_; }
96 const std::string &moduleFileSuffix() const { return moduleFileSuffix_; }
97 bool underscoring() const { return underscoring_; }
98 bool warningsAreErrors() const { return warningsAreErrors_; }
99 bool debugModuleWriter() const { return debugModuleWriter_; }
100 const evaluate::IntrinsicProcTable &intrinsics() const { return intrinsics_; }
101 const evaluate::TargetCharacteristics &targetCharacteristics() const {
102 return targetCharacteristics_;
103 }
104 evaluate::TargetCharacteristics &targetCharacteristics() {
105 return targetCharacteristics_;
106 }
107 Scope &globalScope() { return globalScope_; }
108 Scope &intrinsicModulesScope() { return intrinsicModulesScope_; }
109 parser::Messages &messages() { return messages_; }
110 evaluate::FoldingContext &foldingContext() { return foldingContext_; }
111 parser::AllCookedSources &allCookedSources() { return allCookedSources_; }
112 ModuleDependences &moduleDependences() { return moduleDependences_; }
113
114 SemanticsContext &set_location(
115 const std::optional<parser::CharBlock> &location) {
116 location_ = location;
117 return *this;
118 }
119 SemanticsContext &set_searchDirectories(const std::vector<std::string> &x) {
120 searchDirectories_ = x;
121 return *this;
122 }
123 SemanticsContext &set_intrinsicModuleDirectories(
124 const std::vector<std::string> &x) {
125 intrinsicModuleDirectories_ = x;
126 return *this;
127 }
128 SemanticsContext &set_moduleDirectory(const std::string &x) {
129 moduleDirectory_ = x;
130 return *this;
131 }
132 SemanticsContext &set_moduleFileSuffix(const std::string &x) {
133 moduleFileSuffix_ = x;
134 return *this;
135 }
136 SemanticsContext &set_underscoring(bool x) {
137 underscoring_ = x;
138 return *this;
139 }
140 SemanticsContext &set_warnOnNonstandardUsage(bool x) {
141 warnOnNonstandardUsage_ = x;
142 return *this;
143 }
144 SemanticsContext &set_warningsAreErrors(bool x) {
145 warningsAreErrors_ = x;
146 return *this;
147 }
148
149 SemanticsContext &set_debugModuleWriter(bool x) {
150 debugModuleWriter_ = x;
151 return *this;
152 }
153
154 const DeclTypeSpec &MakeNumericType(TypeCategory, int kind = 0);
155 const DeclTypeSpec &MakeLogicalType(int kind = 0);
156
157 bool AnyFatalError() const;
158
159 // Test or set the Error flag on a Symbol
160 bool HasError(const Symbol &);
161 bool HasError(const Symbol *);
162 bool HasError(const parser::Name &);
163 void SetError(const Symbol &, bool = true);
164
165 template <typename... A> parser::Message &Say(A &&...args) {
166 CHECK(location_);
167 return messages_.Say(*location_, std::forward<A>(args)...);
168 }
169 template <typename... A>
170 parser::Message &Say(parser::CharBlock at, A &&...args) {
171 return messages_.Say(at, std::forward<A>(args)...);
172 }
173 parser::Message &Say(parser::Message &&msg) {
174 return messages_.Say(std::move(msg));
175 }
176 template <typename... A>
177 parser::Message &SayWithDecl(const Symbol &symbol,
178 const parser::CharBlock &at, parser::MessageFixedText &&msg,
179 A &&...args) {
180 auto &message{Say(at, std::move(msg), args...)};
181 evaluate::AttachDeclaration(&message, symbol);
182 return message;
183 }
184
185 const Scope &FindScope(parser::CharBlock) const;
186 Scope &FindScope(parser::CharBlock);
187 void UpdateScopeIndex(Scope &, parser::CharBlock);
188
189 bool IsInModuleFile(parser::CharBlock) const;
190
191 const ConstructStack &constructStack() const { return constructStack_; }
192 template <typename N> void PushConstruct(const N &node) {
193 constructStack_.emplace_back(&node);
194 }
195 void PopConstruct();
196
197 ENUM_CLASS(IndexVarKind, DO, FORALL)
198 // Check to see if a variable being redefined is a DO or FORALL index.
199 // If so, emit a message.
200 void WarnIndexVarRedefine(const parser::CharBlock &, const Symbol &);
201 void CheckIndexVarRedefine(const parser::CharBlock &, const Symbol &);
202 void CheckIndexVarRedefine(const parser::Variable &);
203 void CheckIndexVarRedefine(const parser::Name &);
204 void ActivateIndexVar(const parser::Name &, IndexVarKind);
205 void DeactivateIndexVar(const parser::Name &);
206 SymbolVector GetIndexVars(IndexVarKind);
207 SourceName SaveTempName(std::string &&);
208 SourceName GetTempName(const Scope &);
209 static bool IsTempName(const std::string &);
210
211 // Locate and process the contents of a built-in module on demand
212 Scope *GetBuiltinModule(const char *name);
213
214 // Defines builtinsScope_ from the __Fortran_builtins module
215 void UseFortranBuiltinsModule();
216 const Scope *GetBuiltinsScope() const { return builtinsScope_; }
217
218 void UsePPCBuiltinTypesModule();
219 const Scope &GetCUDABuiltinsScope();
220 void UsePPCBuiltinsModule();
221 Scope *GetPPCBuiltinTypesScope() { return ppcBuiltinTypesScope_; }
222 const Scope *GetPPCBuiltinsScope() const { return ppcBuiltinsScope_; }
223
224 // Saves a module file's parse tree so that it remains available
225 // during semantics.
226 parser::Program &SaveParseTree(parser::Program &&);
227
228 // Ensures a common block definition does not conflict with previous
229 // appearances in the program and consolidate information about
230 // common blocks at the program level for later checks and lowering.
231 // This can obviously not check any conflicts between different compilation
232 // units (in case such conflicts exist, the behavior will depend on the
233 // linker).
234 void MapCommonBlockAndCheckConflicts(const Symbol &);
235
236 // Get the list of common blocks appearing in the program. If a common block
237 // appears in several subprograms, only one of its appearance is returned in
238 // the list alongside the biggest byte size of all its appearances.
239 // If a common block is initialized in any of its appearances, the list will
240 // contain the appearance with the initialization, otherwise the appearance
241 // with the biggest size is returned. The extra byte size information allows
242 // handling the case where the common block initialization is not the
243 // appearance with the biggest size: the common block will have the biggest
244 // size with the first bytes initialized with the initial value. This is not
245 // standard, if the initialization and biggest size appearances are in
246 // different compilation units, the behavior will depend on the linker. The
247 // linker may have the behavior described before, but it may also keep the
248 // initialized common symbol without extending its size, or have some other
249 // behavior.
250 CommonBlockList GetCommonBlocks() const;
251
252private:
253 struct ScopeIndexComparator {
254 bool operator()(parser::CharBlock, parser::CharBlock) const;
255 };
256 using ScopeIndex =
257 std::multimap<parser::CharBlock, Scope &, ScopeIndexComparator>;
258 ScopeIndex::iterator SearchScopeIndex(parser::CharBlock);
259
260 void CheckIndexVarRedefine(
261 const parser::CharBlock &, const Symbol &, parser::MessageFixedText &&);
262 void CheckError(const Symbol &);
263
264 const common::IntrinsicTypeDefaultKinds &defaultKinds_;
265 const common::LanguageFeatureControl &languageFeatures_;
266 parser::AllCookedSources &allCookedSources_;
267 std::optional<parser::CharBlock> location_;
268 std::vector<std::string> searchDirectories_;
269 std::vector<std::string> intrinsicModuleDirectories_;
270 std::string moduleDirectory_{"."s};
271 std::string moduleFileSuffix_{".mod"};
272 bool underscoring_{true};
273 bool warnOnNonstandardUsage_{false};
274 bool warningsAreErrors_{false};
275 bool debugModuleWriter_{false};
276 const evaluate::IntrinsicProcTable intrinsics_;
277 evaluate::TargetCharacteristics targetCharacteristics_;
278 Scope globalScope_;
279 Scope &intrinsicModulesScope_;
280 ScopeIndex scopeIndex_;
281 parser::Messages messages_;
282 evaluate::FoldingContext foldingContext_;
283 ConstructStack constructStack_;
284 struct IndexVarInfo {
285 parser::CharBlock location;
286 IndexVarKind kind;
287 };
288 std::map<SymbolRef, const IndexVarInfo, SymbolAddressCompare>
289 activeIndexVars_;
290 UnorderedSymbolSet errorSymbols_;
291 std::set<std::string> tempNames_;
292 const Scope *builtinsScope_{nullptr}; // module __Fortran_builtins
293 Scope *ppcBuiltinTypesScope_{nullptr}; // module __Fortran_PPC_types
294 std::optional<const Scope *> cudaBuiltinsScope_; // module __CUDA_builtins
295 const Scope *ppcBuiltinsScope_{nullptr}; // module __ppc_intrinsics
296 std::list<parser::Program> modFileParseTrees_;
297 std::unique_ptr<CommonBlockMap> commonBlockMap_;
298 ModuleDependences moduleDependences_;
299};
300
301class Semantics {
302public:
303 explicit Semantics(SemanticsContext &context, parser::Program &program,
304 bool debugModuleWriter = false)
305 : context_{context}, program_{program} {
306 context.set_debugModuleWriter(debugModuleWriter);
307 }
308
309 SemanticsContext &context() const { return context_; }
310 bool Perform();
311 const Scope &FindScope(const parser::CharBlock &where) const {
312 return context_.FindScope(where);
313 }
314 bool AnyFatalError() const { return context_.AnyFatalError(); }
315 void EmitMessages(llvm::raw_ostream &) const;
316 void DumpSymbols(llvm::raw_ostream &);
317 void DumpSymbolsSources(llvm::raw_ostream &) const;
318
319private:
320 SemanticsContext &context_;
321 parser::Program &program_;
322};
323
324// Base class for semantics checkers.
325struct BaseChecker {
326 template <typename N> void Enter(const N &) {}
327 template <typename N> void Leave(const N &) {}
328};
329} // namespace Fortran::semantics
330#endif
331

Warning: This file is not a C or C++ file. It does not have highlighting.

source code of flang/include/flang/Semantics/semantics.h