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