FLANG
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 "module-dependences.h"
13#include "program-tree.h"
14#include "scope.h"
15#include "symbol.h"
16#include "flang/Evaluate/common.h"
17#include "flang/Evaluate/intrinsics.h"
18#include "flang/Evaluate/target.h"
19#include "flang/Parser/message.h"
20#include "flang/Support/Fortran-features.h"
21#include "flang/Support/LangOptions.h"
22#include <iosfwd>
23#include <set>
24#include <string>
25#include <vector>
26
27namespace llvm {
28class raw_ostream;
29}
30
31namespace Fortran::common {
33}
34
35namespace Fortran::parser {
36struct Name;
37struct Program;
40struct BlockConstruct;
41struct CaseConstruct;
42struct DoConstruct;
45struct ForallConstruct;
46struct IfConstruct;
49struct Variable;
50struct WhereConstruct;
51} // namespace Fortran::parser
52
53namespace Fortran::semantics {
54
55class Symbol;
56class CommonBlockMap;
57using CommonBlockList = std::vector<std::pair<SymbolRef, std::size_t>>;
58
59using ConstructNode = std::variant<const parser::AssociateConstruct *,
60 const parser::BlockConstruct *, const parser::CaseConstruct *,
61 const parser::ChangeTeamConstruct *, const parser::CriticalConstruct *,
62 const parser::DoConstruct *, const parser::ForallConstruct *,
63 const parser::IfConstruct *, const parser::SelectRankConstruct *,
64 const parser::SelectTypeConstruct *, const parser::WhereConstruct *>;
65using ConstructStack = std::vector<ConstructNode>;
66
67class SemanticsContext {
68public:
69 SemanticsContext(const common::IntrinsicTypeDefaultKinds &,
72 ~SemanticsContext();
73
74 const common::IntrinsicTypeDefaultKinds &defaultKinds() const {
75 return defaultKinds_;
76 }
77 const common::LanguageFeatureControl &languageFeatures() const {
78 return languageFeatures_;
79 }
80 const common::LangOptions &langOptions() const { return langOpts_; }
81 int GetDefaultKind(TypeCategory) const;
82 int doublePrecisionKind() const {
83 return defaultKinds_.doublePrecisionKind();
84 }
85 int quadPrecisionKind() const { return defaultKinds_.quadPrecisionKind(); }
86 bool IsEnabled(common::LanguageFeature feature) const {
87 return languageFeatures_.IsEnabled(feature);
88 }
89 template <typename A> bool ShouldWarn(A x) const {
90 return languageFeatures_.ShouldWarn(x);
91 }
92 const std::optional<parser::CharBlock> &location() const { return location_; }
93 const std::vector<std::string> &searchDirectories() const {
94 return searchDirectories_;
95 }
96 const std::vector<std::string> &intrinsicModuleDirectories() const {
97 return intrinsicModuleDirectories_;
98 }
99 const std::string &moduleDirectory() const { return moduleDirectory_; }
100 const std::string &moduleFileSuffix() const { return moduleFileSuffix_; }
101 bool underscoring() const { return underscoring_; }
102 bool warningsAreErrors() const { return warningsAreErrors_; }
103 bool debugModuleWriter() const { return debugModuleWriter_; }
104 const evaluate::IntrinsicProcTable &intrinsics() const { return intrinsics_; }
105 const evaluate::TargetCharacteristics &targetCharacteristics() const {
106 return targetCharacteristics_;
107 }
108 evaluate::TargetCharacteristics &targetCharacteristics() {
109 return targetCharacteristics_;
110 }
111 Scope &globalScope() { return globalScope_; }
112 Scope &intrinsicModulesScope() { return intrinsicModulesScope_; }
113 Scope *currentHermeticModuleFileScope() {
114 return currentHermeticModuleFileScope_;
115 }
116 void set_currentHermeticModuleFileScope(Scope *scope) {
117 currentHermeticModuleFileScope_ = scope;
118 }
119 parser::Messages &messages() { return messages_; }
120 evaluate::FoldingContext &foldingContext() { return foldingContext_; }
121 parser::AllCookedSources &allCookedSources() { return allCookedSources_; }
122 ModuleDependences &moduleDependences() { return moduleDependences_; }
123 std::map<const Symbol *, SourceName> &moduleFileOutputRenamings() {
124 return moduleFileOutputRenamings_;
125 }
126
127 SemanticsContext &set_location(
128 const std::optional<parser::CharBlock> &location) {
129 location_ = location;
130 return *this;
131 }
132 SemanticsContext &set_searchDirectories(const std::vector<std::string> &x) {
133 searchDirectories_ = x;
134 return *this;
135 }
136 SemanticsContext &set_intrinsicModuleDirectories(
137 const std::vector<std::string> &x) {
138 intrinsicModuleDirectories_ = x;
139 return *this;
140 }
141 SemanticsContext &set_moduleDirectory(const std::string &x) {
142 moduleDirectory_ = x;
143 return *this;
144 }
145 SemanticsContext &set_moduleFileSuffix(const std::string &x) {
146 moduleFileSuffix_ = x;
147 return *this;
148 }
149 SemanticsContext &set_underscoring(bool x) {
150 underscoring_ = x;
151 return *this;
152 }
153 SemanticsContext &set_warnOnNonstandardUsage(bool x) {
154 warnOnNonstandardUsage_ = x;
155 return *this;
156 }
157 SemanticsContext &set_maxErrors(size_t x) {
158 maxErrors_ = x;
159 return *this;
160 }
161 SemanticsContext &set_warningsAreErrors(bool x) {
162 warningsAreErrors_ = x;
163 return *this;
164 }
165 SemanticsContext &set_debugModuleWriter(bool x) {
166 debugModuleWriter_ = x;
167 return *this;
168 }
169
170 const DeclTypeSpec &MakeNumericType(TypeCategory, int kind = 0);
171 const DeclTypeSpec &MakeLogicalType(int kind = 0);
172
173 std::size_t maxErrors() const { return maxErrors_; }
174
175 bool AnyFatalError() const;
176
177 // Test or set the Error flag on a Symbol
178 bool HasError(const Symbol &);
179 bool HasError(const Symbol *);
180 bool HasError(const parser::Name &);
181 void SetError(const Symbol &, bool = true);
182
183 template <typename... A> parser::Message &Say(A &&...args) {
184 CHECK(location_);
185 return messages_.Say(*location_, std::forward<A>(args)...);
186 }
187 template <typename... A>
188 parser::Message &Say(parser::CharBlock at, A &&...args) {
189 return messages_.Say(at, std::forward<A>(args)...);
190 }
191 parser::Message &Say(parser::Message &&msg) {
192 return messages_.Say(std::move(msg));
193 }
194 template <typename... A>
195 parser::Message &SayWithDecl(const Symbol &symbol,
197 A &&...args) {
198 auto &message{Say(at, std::move(msg), args...)};
199 evaluate::AttachDeclaration(&message, symbol);
200 return message;
201 }
202
203 template <typename... A>
204 parser::Message *Warn(parser::Messages &messages,
205 common::LanguageFeature feature, parser::CharBlock at, A &&...args) {
206 return messages.Warn(IsInModuleFile(at), languageFeatures_, feature, at,
207 std::forward<A>(args)...);
208 }
209 template <typename... A>
210 parser::Message *Warn(parser::Messages &messages,
211 common::UsageWarning warning, parser::CharBlock at, A &&...args) {
212 return messages.Warn(IsInModuleFile(at), languageFeatures_, warning, at,
213 std::forward<A>(args)...);
214 }
215 template <typename... A>
217 common::LanguageFeature feature, parser::CharBlock at, A &&...args) {
218 return messages.Warn(IsInModuleFile(at), languageFeatures_, feature, at,
219 std::forward<A>(args)...);
220 }
221 template <typename... A>
223 common::UsageWarning warning, parser::CharBlock at, A &&...args) {
224 return messages.Warn(IsInModuleFile(at), languageFeatures_, warning, at,
225 std::forward<A>(args)...);
226 }
227 template <typename... A>
229 common::LanguageFeature feature, A &&...args) {
230 return messages.Warn(IsInModuleFile(messages.at()), languageFeatures_,
231 feature, messages.at(), std::forward<A>(args)...);
232 }
233 template <typename... A>
235 common::UsageWarning warning, A &&...args) {
236 return messages.Warn(IsInModuleFile(messages.at()), languageFeatures_,
237 warning, messages.at(), std::forward<A>(args)...);
238 }
239 template <typename... A>
240 parser::Message *Warn(
241 common::LanguageFeature feature, parser::CharBlock at, A &&...args) {
242 return Warn(messages_, feature, at, std::forward<A>(args)...);
243 }
244 template <typename... A>
245 parser::Message *Warn(
246 common::UsageWarning warning, parser::CharBlock at, A &&...args) {
247 return Warn(messages_, warning, at, std::forward<A>(args)...);
248 }
249 template <typename... A>
250 parser::Message *Warn(common::LanguageFeature feature, A &&...args) {
251 CHECK(location_);
252 return Warn(feature, *location_, std::forward<A>(args)...);
253 }
254 template <typename... A>
255 parser::Message *Warn(common::UsageWarning warning, A &&...args) {
256 CHECK(location_);
257 return Warn(warning, *location_, std::forward<A>(args)...);
258 }
259
260 void EmitMessages(llvm::raw_ostream &);
261
262 const Scope &FindScope(parser::CharBlock) const;
263 Scope &FindScope(parser::CharBlock);
264 void UpdateScopeIndex(Scope &, parser::CharBlock);
265 void DumpScopeIndex(llvm::raw_ostream &) const;
266
267 bool IsInModuleFile(parser::CharBlock) const;
268
269 const ConstructStack &constructStack() const { return constructStack_; }
270 template <typename N> void PushConstruct(const N &node) {
271 constructStack_.emplace_back(&node);
272 }
273 void PopConstruct();
274
275 ENUM_CLASS(IndexVarKind, DO, FORALL)
276 // Check to see if a variable being redefined is a DO or FORALL index.
277 // If so, emit a message.
278 void WarnIndexVarRedefine(const parser::CharBlock &, const Symbol &);
279 void CheckIndexVarRedefine(const parser::CharBlock &, const Symbol &);
280 void CheckIndexVarRedefine(const parser::Variable &);
281 void CheckIndexVarRedefine(const parser::Name &);
282 void ActivateIndexVar(const parser::Name &, IndexVarKind);
283 void DeactivateIndexVar(const parser::Name &);
284 SymbolVector GetIndexVars(IndexVarKind);
285 SourceName SaveTempName(std::string &&);
286 SourceName GetTempName(const Scope &);
287 static bool IsTempName(const std::string &);
288
289 // Locate and process the contents of a built-in module on demand
290 Scope *GetBuiltinModule(const char *name);
291
292 // Defines builtinsScope_ from the __Fortran_builtins module
293 void UseFortranBuiltinsModule();
294 const Scope *GetBuiltinsScope() const { return builtinsScope_; }
295
296 const Scope &GetCUDABuiltinsScope();
297 const Scope &GetCUDADeviceScope();
298
299 void UsePPCBuiltinTypesModule();
300 void UsePPCBuiltinsModule();
301 Scope *GetPPCBuiltinTypesScope() { return ppcBuiltinTypesScope_; }
302 const Scope *GetPPCBuiltinsScope() const { return ppcBuiltinsScope_; }
303
304 // Saves a module file's parse tree so that it remains available
305 // during semantics.
306 parser::Program &SaveParseTree(parser::Program &&);
307
308 // Ensures a common block definition does not conflict with previous
309 // appearances in the program and consolidate information about
310 // common blocks at the program level for later checks and lowering.
311 // This can obviously not check any conflicts between different compilation
312 // units (in case such conflicts exist, the behavior will depend on the
313 // linker).
314 void MapCommonBlockAndCheckConflicts(const Symbol &);
315
316 // Get the list of common blocks appearing in the program. If a common block
317 // appears in several subprograms, only one of its appearance is returned in
318 // the list alongside the biggest byte size of all its appearances.
319 // If a common block is initialized in any of its appearances, the list will
320 // contain the appearance with the initialization, otherwise the appearance
321 // with the biggest size is returned. The extra byte size information allows
322 // handling the case where the common block initialization is not the
323 // appearance with the biggest size: the common block will have the biggest
324 // size with the first bytes initialized with the initial value. This is not
325 // standard, if the initialization and biggest size appearances are in
326 // different compilation units, the behavior will depend on the linker. The
327 // linker may have the behavior described before, but it may also keep the
328 // initialized common symbol without extending its size, or have some other
329 // behavior.
330 CommonBlockList GetCommonBlocks() const;
331
332 void NoteDefinedSymbol(const Symbol &);
333 bool IsSymbolDefined(const Symbol &) const;
334
335 void DumpSymbols(llvm::raw_ostream &);
336
337 // Top-level ProgramTrees are owned by the SemanticsContext for persistence.
338 ProgramTree &SaveProgramTree(ProgramTree &&);
339
340private:
341 struct ScopeIndexComparator {
342 bool operator()(parser::CharBlock, parser::CharBlock) const;
343 };
344 using ScopeIndex =
345 std::multimap<parser::CharBlock, Scope &, ScopeIndexComparator>;
346 ScopeIndex::iterator SearchScopeIndex(parser::CharBlock);
347
348 parser::Message *CheckIndexVarRedefine(
350 void CheckError(const Symbol &);
351
352 const common::IntrinsicTypeDefaultKinds &defaultKinds_;
353 const common::LanguageFeatureControl &languageFeatures_;
354 const common::LangOptions &langOpts_;
355 parser::AllCookedSources &allCookedSources_;
356 std::optional<parser::CharBlock> location_;
357 std::vector<std::string> searchDirectories_;
358 std::vector<std::string> intrinsicModuleDirectories_;
359 std::string moduleDirectory_{"."s};
360 std::string moduleFileSuffix_{".mod"};
361 bool underscoring_{true};
362 bool warnOnNonstandardUsage_{false};
363 bool warningsAreErrors_{false};
364 bool debugModuleWriter_{false};
365 const evaluate::IntrinsicProcTable intrinsics_;
366 evaluate::TargetCharacteristics targetCharacteristics_;
367 Scope globalScope_;
368 Scope &intrinsicModulesScope_;
369 Scope *currentHermeticModuleFileScope_{nullptr};
370 ScopeIndex scopeIndex_;
371 parser::Messages messages_;
372 std::size_t maxErrors_{0};
373 evaluate::FoldingContext foldingContext_;
374 ConstructStack constructStack_;
375 struct IndexVarInfo {
376 parser::CharBlock location;
377 IndexVarKind kind;
378 };
379 std::map<SymbolRef, const IndexVarInfo, SymbolAddressCompare>
380 activeIndexVars_;
381 UnorderedSymbolSet errorSymbols_;
382 std::set<std::string> tempNames_;
383 const Scope *builtinsScope_{nullptr}; // module __Fortran_builtins
384 Scope *ppcBuiltinTypesScope_{nullptr}; // module __Fortran_PPC_types
385 std::optional<const Scope *> cudaBuiltinsScope_; // module __CUDA_builtins
386 std::optional<const Scope *> cudaDeviceScope_; // module cudadevice
387 const Scope *ppcBuiltinsScope_{nullptr}; // module __ppc_intrinsics
388 std::list<parser::Program> modFileParseTrees_;
389 std::unique_ptr<CommonBlockMap> commonBlockMap_;
390 ModuleDependences moduleDependences_;
391 std::map<const Symbol *, SourceName> moduleFileOutputRenamings_;
392 UnorderedSymbolSet isDefined_;
393 std::list<ProgramTree> programTrees_;
394};
395
396class Semantics {
397public:
398 explicit Semantics(SemanticsContext &context, parser::Program &program)
399 : context_{context}, program_{program} {}
400 Semantics &set_hermeticModuleFileOutput(bool yes = true) {
401 hermeticModuleFileOutput_ = yes;
402 return *this;
403 }
404
405 SemanticsContext &context() const { return context_; }
406 bool Perform();
407 const Scope &FindScope(const parser::CharBlock &where) const {
408 return context_.FindScope(where);
409 }
410 bool AnyFatalError() const { return context_.AnyFatalError(); }
411 void EmitMessages(llvm::raw_ostream &);
412 void DumpSymbols(llvm::raw_ostream &);
413 void DumpSymbolsSources(llvm::raw_ostream &) const;
414
415private:
416 SemanticsContext &context_;
417 parser::Program &program_;
418 bool hermeticModuleFileOutput_{false};
419};
420
421// Base class for semantics checkers.
423 template <typename N> void Enter(const N &) {}
424 template <typename N> void Leave(const N &) {}
425};
426} // namespace Fortran::semantics
427#endif
Definition default-kinds.h:26
Definition LangOptions.h:58
Definition Fortran-features.h:90
Definition common.h:216
Definition provenance.h:281
Definition char-block.h:28
Definition message.h:386
Definition message.h:46
Definition message.h:190
Definition message.h:322
Definition semantics.cpp:240
Definition module-dependences.h:21
Definition program-tree.h:31
Definition scope.h:58
Definition semantics.h:67
Definition symbol.h:791
Definition bit-population-count.h:20
Definition check-expression.h:19
Definition parse-tree.h:2179
Definition parse-tree.h:2201
Definition parse-tree.h:2443
Definition parse-tree.h:2232
Definition parse-tree.h:2248
Definition parse-tree.h:2344
Definition parse-tree.h:2149
Definition parse-tree.h:2378
Definition parse-tree.h:583
Definition parse-tree.h:2478
Definition parse-tree.h:2512
Definition parse-tree.h:1871
Definition parse-tree.h:2096
Definition semantics.h:422