FLANG
symbol.h
1//===-- include/flang/Semantics/symbol.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_SYMBOL_H_
10#define FORTRAN_SEMANTICS_SYMBOL_H_
11
12#include "type.h"
13#include "flang/Common/enum-set.h"
14#include "flang/Common/reference.h"
15#include "flang/Common/visit.h"
16#include "flang/Semantics/module-dependences.h"
17#include "flang/Semantics/omp-declare-variant.h"
18#include "flang/Support/Fortran.h"
19#include "llvm/ADT/DenseMapInfo.h"
20#include "llvm/Frontend/OpenMP/OMP.h"
21
22#include <array>
23#include <functional>
24#include <list>
25#include <optional>
26#include <set>
27#include <variant>
28#include <vector>
29
30namespace llvm {
31class raw_ostream;
32}
33namespace Fortran::parser {
34struct Expr;
36} // namespace Fortran::parser
37
38namespace Fortran::semantics {
39
43
44class Scope;
45class Symbol;
46class ProgramTree;
47
48using SymbolRef = common::Reference<const Symbol>;
49using SymbolVector = std::vector<SymbolRef>;
50using MutableSymbolRef = common::Reference<Symbol>;
51using MutableSymbolVector = std::vector<MutableSymbolRef>;
52
53// Mixin for details with OpenMP declarative constructs.
55public:
56 const llvm::omp::ClauseSet &ompRequires() const { return ompRequires_; }
57 void set_ompRequires(llvm::omp::ClauseSet clauses) { ompRequires_ = clauses; }
58
59 const std::optional<common::OmpMemoryOrderType> &
60 ompAtomicDefaultMemOrder() const {
61 return ompAtomicDefaultMemOrder_;
62 }
63 void set_ompAtomicDefaultMemOrder(common::OmpMemoryOrderType flags) {
64 ompAtomicDefaultMemOrder_ = flags;
65 }
66
67 const llvm::omp::ClauseSet &ompDeclTarget() const { return ompDeclTarget_; }
68 void set_ompDeclTarget(llvm::omp::ClauseSet clauses) {
69 ompDeclTarget_ = clauses;
70 }
71
72 const std::optional<common::OmpDeviceType> &ompDeclTargetDeviceType() const {
73 return ompDeclTargetDeviceType_;
74 }
75 void set_ompDeclTarget(common::OmpDeviceType device) {
76 ompDeclTargetDeviceType_ = device;
77 }
78
79 const llvm::omp::ClauseSet &ompGroupprivate() const {
80 return ompGroupprivate_;
81 }
82 void set_ompGroupprivate(llvm::omp::ClauseSet clauses) {
83 ompGroupprivate_ = clauses;
84 }
85
86 const std::optional<common::OmpDeviceType> &
87 ompGroupprivateDeviceType() const {
88 return ompGroupprivateDeviceType_;
89 }
90 void set_ompGroupprivate(common::OmpDeviceType device) {
91 ompGroupprivateDeviceType_ = device;
92 }
93
94 // \p dir indicates to which declarative directive the given clauses
95 // belong to.
96 void printClauseSet(llvm::raw_ostream &os,
97 const llvm::omp::ClauseSet &clauses, llvm::omp::Directive dir,
99 friend llvm::raw_ostream &operator<<(
100 llvm::raw_ostream &, const WithOmpDeclarative &);
101
102 void set_version(unsigned version) { version_ = version; }
103
104private:
105 unsigned version_;
106 // The set of clauses from a REQUIRES directive. Only applicable
107 // to program unit symbols (i.e. scopes of the REQUIRES directive).
108 // The set of requirements for any program unit include requirements
109 // from any module used in the program unit.
110 llvm::omp::ClauseSet ompRequires_;
111 // The argument to ATOMIC_DEFAULT_MEM_ORDER. Only needed when the ADMO
112 // clause is present in the ompRequires_ set.
113 std::optional<common::OmpMemoryOrderType> ompAtomicDefaultMemOrder_;
114 // The set of clauses on DECLARE_TARGET directive that apply to this
115 // symbol.
116 llvm::omp::ClauseSet ompDeclTarget_;
117 // The argument to DEVICE_TYPE clause. Only needed when the clause is
118 // present in the ompDeclTarget_ set.
119 std::optional<common::OmpDeviceType> ompDeclTargetDeviceType_;
120 // The set of clauses on a GROUPPRIVATE directive declaring this symbol.
121 llvm::omp::ClauseSet ompGroupprivate_;
122 // The argument to a DEVICE_TYPE clause on a GROUPPRIVATE directive declaring
123 // this symbol. Only needed when the clause is present in ompGroupprivate_.
124 std::optional<common::OmpDeviceType> ompGroupprivateDeviceType_;
125};
126
127// A module or submodule.
128class ModuleDetails : public WithOmpDeclarative {
129public:
130 ModuleDetails(bool isSubmodule = false) : isSubmodule_{isSubmodule} {}
131 bool isSubmodule() const { return isSubmodule_; }
132 const Scope *scope() const { return scope_; }
133 const Scope *ancestor() const; // for submodule; nullptr for module
134 const Scope *parent() const; // for submodule; nullptr for module
135 void set_scope(const Scope *);
136 bool isDefaultPrivate() const { return isDefaultPrivate_; }
137 void set_isDefaultPrivate(bool yes = true) { isDefaultPrivate_ = yes; }
138 std::optional<ModuleCheckSumType> moduleFileHash() const {
139 return moduleFileHash_;
140 }
141 void set_moduleFileHash(ModuleCheckSumType x) { moduleFileHash_ = x; }
142 const Symbol *previous() const { return previous_; }
143 void set_previous(const Symbol *p) { previous_ = p; }
144
145private:
146 bool isSubmodule_;
147 bool isDefaultPrivate_{false};
148 const Scope *scope_{nullptr};
149 std::optional<ModuleCheckSumType> moduleFileHash_;
150 const Symbol *previous_{nullptr}; // same name, different module file hash
151};
152
154public:
155private:
156};
157
159public:
160 const std::string *bindName() const {
161 return bindName_ ? &*bindName_ : nullptr;
162 }
163 bool isExplicitBindName() const { return isExplicitBindName_; }
164 void set_bindName(std::string &&name) { bindName_ = std::move(name); }
165 void set_isExplicitBindName(bool yes) { isExplicitBindName_ = yes; }
166 bool isCDefined() const { return isCDefined_; }
167 void set_isCDefined(bool yes) { isCDefined_ = yes; }
168
169private:
170 std::optional<std::string> bindName_;
171 bool isExplicitBindName_{false};
172 bool isCDefined_{false};
173};
174
175// Device type specific OpenACC routine information
176class OpenACCRoutineDeviceTypeInfo {
177public:
178 explicit OpenACCRoutineDeviceTypeInfo(
179 Fortran::common::OpenACCDeviceType dType)
180 : deviceType_{dType} {}
181 bool isSeq() const { return isSeq_; }
182 void set_isSeq(bool value = true) { isSeq_ = value; }
183 bool isVector() const { return isVector_; }
184 void set_isVector(bool value = true) { isVector_ = value; }
185 bool isWorker() const { return isWorker_; }
186 void set_isWorker(bool value = true) { isWorker_ = value; }
187 bool isGang() const { return isGang_; }
188 void set_isGang(bool value = true) { isGang_ = value; }
189 unsigned gangDim() const { return gangDim_; }
190 void set_gangDim(unsigned value) { gangDim_ = value; }
191 const std::variant<std::string, SymbolRef> *bindName() const {
192 return bindName_.has_value() ? &*bindName_ : nullptr;
193 }
194 const std::optional<std::variant<std::string, SymbolRef>> &
195 bindNameOpt() const {
196 return bindName_;
197 }
198 void set_bindName(std::string &&name) { bindName_.emplace(std::move(name)); }
199 void set_bindName(SymbolRef symbol) { bindName_.emplace(symbol); }
200
201 Fortran::common::OpenACCDeviceType dType() const { return deviceType_; }
202
203 friend llvm::raw_ostream &operator<<(
204 llvm::raw_ostream &, const OpenACCRoutineDeviceTypeInfo &);
205
206private:
207 bool isSeq_{false};
208 bool isVector_{false};
209 bool isWorker_{false};
210 bool isGang_{false};
211 unsigned gangDim_{0};
212 // bind("name") -> std::string
213 // bind(sym) -> SymbolRef (requires namemangling in lowering)
214 std::optional<std::variant<std::string, SymbolRef>> bindName_;
215 Fortran::common::OpenACCDeviceType deviceType_{
216 Fortran::common::OpenACCDeviceType::None};
217};
218
219// OpenACC routine information. Device independent info are stored on the
220// OpenACCRoutineInfo instance while device dependent info are stored
221// in as objects in the OpenACCRoutineDeviceTypeInfo list.
222class OpenACCRoutineInfo : public OpenACCRoutineDeviceTypeInfo {
223public:
224 OpenACCRoutineInfo()
225 : OpenACCRoutineDeviceTypeInfo(Fortran::common::OpenACCDeviceType::None) {
226 }
227 bool isNohost() const { return isNohost_; }
228 void set_isNohost(bool value = true) { isNohost_ = value; }
229 const std::list<OpenACCRoutineDeviceTypeInfo> &deviceTypeInfos() const {
230 return deviceTypeInfos_;
231 }
232
233 OpenACCRoutineDeviceTypeInfo &add_deviceTypeInfo(
234 Fortran::common::OpenACCDeviceType type) {
235 return add_deviceTypeInfo(OpenACCRoutineDeviceTypeInfo(type));
236 }
237
238 OpenACCRoutineDeviceTypeInfo &add_deviceTypeInfo(
239 OpenACCRoutineDeviceTypeInfo &&info) {
240 deviceTypeInfos_.push_back(std::move(info));
241 return deviceTypeInfos_.back();
242 }
243
244 friend llvm::raw_ostream &operator<<(
245 llvm::raw_ostream &, const OpenACCRoutineInfo &);
246
247private:
248 std::list<OpenACCRoutineDeviceTypeInfo> deviceTypeInfos_;
249 bool isNohost_{false};
250};
251
252// A subroutine or function definition, or a subprogram interface defined
253// in an INTERFACE block as part of the definition of a dummy procedure
254// or a procedure pointer (with just POINTER).
256public:
257 bool isFunction() const { return result_ != nullptr; }
258 bool isInterface() const { return isInterface_; }
259 void set_isInterface(bool value = true) { isInterface_ = value; }
260 bool isDummy() const { return isDummy_; }
261 void set_isDummy(bool value = true) { isDummy_ = value; }
262 Scope *entryScope() { return entryScope_; }
263 const Scope *entryScope() const { return entryScope_; }
264 void set_entryScope(Scope &scope) { entryScope_ = &scope; }
265 const Symbol &result() const {
266 CHECK(isFunction());
267 return *result_;
268 }
269 void set_result(Symbol &result) {
270 CHECK(!result_);
271 result_ = &result;
272 }
273 const std::vector<Symbol *> &dummyArgs() const { return dummyArgs_; }
274 void add_dummyArg(Symbol &symbol) { dummyArgs_.push_back(&symbol); }
275 void add_alternateReturn() { dummyArgs_.push_back(nullptr); }
276 const MaybeExpr &stmtFunction() const { return stmtFunction_; }
277 void set_stmtFunction(SomeExpr &&expr) { stmtFunction_ = std::move(expr); }
278 Symbol *moduleInterface() { return moduleInterface_; }
279 const Symbol *moduleInterface() const { return moduleInterface_; }
280 void set_moduleInterface(Symbol &);
281 void ReplaceResult(Symbol &result) {
282 CHECK(result_ != nullptr);
283 result_ = &result;
284 }
285 bool defaultIgnoreTKR() const { return defaultIgnoreTKR_; }
286 void set_defaultIgnoreTKR(bool yes) { defaultIgnoreTKR_ = yes; }
287 std::optional<common::CUDASubprogramAttrs> cudaSubprogramAttrs() const {
288 return cudaSubprogramAttrs_;
289 }
290 void set_cudaSubprogramAttrs(common::CUDASubprogramAttrs csas) {
291 cudaSubprogramAttrs_ = csas;
292 }
293 std::vector<std::int64_t> &cudaLaunchBounds() { return cudaLaunchBounds_; }
294 const std::vector<std::int64_t> &cudaLaunchBounds() const {
295 return cudaLaunchBounds_;
296 }
297 void set_cudaLaunchBounds(std::vector<std::int64_t> &&x) {
298 cudaLaunchBounds_ = std::move(x);
299 }
300 std::vector<std::int64_t> &cudaClusterDims() { return cudaClusterDims_; }
301 const std::vector<std::int64_t> &cudaClusterDims() const {
302 return cudaClusterDims_;
303 }
304 void set_cudaClusterDims(std::vector<std::int64_t> &&x) {
305 cudaClusterDims_ = std::move(x);
306 }
307 const std::vector<OpenACCRoutineInfo> &openACCRoutineInfos() const {
308 return openACCRoutineInfos_;
309 }
310 void add_openACCRoutineInfo(OpenACCRoutineInfo info) {
311 openACCRoutineInfos_.push_back(info);
312 }
313
314 const std::vector<OmpDeclareVariantEntry> &ompDeclareVariants() const {
315 return ompDeclareVariants_;
316 }
317 void addOmpDeclareVariant(OmpDeclareVariantEntry &&entry) {
318 ompDeclareVariants_.push_back(std::move(entry));
319 }
320
321private:
322 bool isInterface_{false}; // true if this represents an interface-body
323 bool isDummy_{false}; // true when interface of dummy procedure
324 std::vector<Symbol *> dummyArgs_; // nullptr -> alternate return indicator
325 Symbol *result_{nullptr};
326 Scope *entryScope_{nullptr}; // if ENTRY, points to subprogram's scope
327 MaybeExpr stmtFunction_;
328 // For MODULE FUNCTION or SUBROUTINE, this is the symbol of its declared
329 // interface. For MODULE PROCEDURE, this is the declared interface if it
330 // appeared in an ancestor (sub)module.
331 Symbol *moduleInterface_{nullptr};
332 bool defaultIgnoreTKR_{false};
333 // CUDA ATTRIBUTES(...) from subroutine/function prefix
334 std::optional<common::CUDASubprogramAttrs> cudaSubprogramAttrs_;
335 // CUDA LAUNCH_BOUNDS(...) & CLUSTER_DIMS(...) from prefix
336 std::vector<std::int64_t> cudaLaunchBounds_, cudaClusterDims_;
337 // OpenACC routine information
338 std::vector<OpenACCRoutineInfo> openACCRoutineInfos_;
339 std::vector<OmpDeclareVariantEntry> ompDeclareVariants_;
340
341 friend llvm::raw_ostream &operator<<(
342 llvm::raw_ostream &, const SubprogramDetails &);
343};
344
345// For SubprogramNameDetails, the kind indicates whether it is the name
346// of a module subprogram or an internal subprogram or ENTRY.
347ENUM_CLASS(SubprogramKind, Module, Internal)
348
349// Symbol with SubprogramNameDetails is created when we scan for module and
350// internal procedure names, to record that there is a subprogram with this
351// name. Later they are replaced by SubprogramDetails with dummy and result
352// type information.
353class SubprogramNameDetails {
354public:
355 SubprogramNameDetails(SubprogramKind kind, ProgramTree &node)
356 : kind_{kind}, node_{node} {}
357 SubprogramNameDetails() = delete;
358 SubprogramKind kind() const { return kind_; }
359 ProgramTree &node() const { return *node_; }
360
361private:
362 SubprogramKind kind_;
364};
365
366// A name from an entity-decl -- could be object or function.
367class EntityDetails : public WithBindName {
368public:
369 explicit EntityDetails(bool isDummy = false) : isDummy_{isDummy} {}
370 const DeclTypeSpec *type() const { return type_; }
371 void set_type(const DeclTypeSpec &);
372 void ReplaceType(const DeclTypeSpec &);
373 bool isDummy() const { return isDummy_; }
374 void set_isDummy(bool value = true) { isDummy_ = value; }
375 bool isFuncResult() const { return isFuncResult_; }
376 void set_funcResult(bool x) { isFuncResult_ = x; }
377
378private:
379 bool isDummy_{false};
380 bool isFuncResult_{false};
381 const DeclTypeSpec *type_{nullptr};
382 friend llvm::raw_ostream &operator<<(
383 llvm::raw_ostream &, const EntityDetails &);
384};
385
386// Symbol is associated with a name or expression in an ASSOCIATE,
387// SELECT TYPE, or SELECT RANK construct.
388class AssocEntityDetails : public EntityDetails {
389public:
390 AssocEntityDetails() {}
391 explicit AssocEntityDetails(SomeExpr &&expr) : expr_{std::move(expr)} {}
392 AssocEntityDetails(const AssocEntityDetails &) = default;
393 AssocEntityDetails(AssocEntityDetails &&) = default;
394 AssocEntityDetails &operator=(const AssocEntityDetails &) = default;
395 AssocEntityDetails &operator=(AssocEntityDetails &&) = default;
396 const MaybeExpr &expr() const { return expr_; }
397
398 // SELECT RANK's rank cases will return a populated result for
399 // RANK(n) and RANK(*), and IsAssumedRank() will be true for
400 // RANK DEFAULT.
401 std::optional<int> rank() const {
402 int r{rank_.value_or(0)};
403 if (r == isAssumedSize) {
404 return 1; // RANK(*)
405 } else if (r == isAssumedRank) {
406 return std::nullopt; // RANK DEFAULT
407 } else {
408 return rank_;
409 }
410 }
411 bool IsAssumedSize() const { return rank_.value_or(0) == isAssumedSize; }
412 bool IsAssumedRank() const { return rank_.value_or(0) == isAssumedRank; }
413 bool isTypeGuard() const { return isTypeGuard_; }
414 void set_rank(int rank);
415 void set_IsAssumedSize();
416 void set_IsAssumedRank();
417 void set_isTypeGuard(bool yes = true);
418
419private:
420 MaybeExpr expr_;
421 // Populated for SELECT RANK with rank (n>=0) for RANK(n),
422 // isAssumedSize for RANK(*), or isAssumedRank for RANK DEFAULT.
423 static constexpr int isAssumedSize{-1}; // RANK(*)
424 static constexpr int isAssumedRank{-2}; // RANK DEFAULT
425 std::optional<int> rank_;
426 bool isTypeGuard_{false}; // TYPE IS or CLASS IS, but not CLASS(DEFAULT)
427};
428llvm::raw_ostream &operator<<(llvm::raw_ostream &, const AssocEntityDetails &);
429
430// An entity known to be an object.
431class ObjectEntityDetails : public EntityDetails, public WithOmpDeclarative {
432public:
433 explicit ObjectEntityDetails(EntityDetails &&);
434 ObjectEntityDetails(const ObjectEntityDetails &) = default;
435 ObjectEntityDetails(ObjectEntityDetails &&) = default;
436 ObjectEntityDetails &operator=(const ObjectEntityDetails &) = default;
437 ObjectEntityDetails(bool isDummy = false) : EntityDetails(isDummy) {}
438 MaybeExpr &init() { return init_; }
439 const MaybeExpr &init() const { return init_; }
440 void set_init(MaybeExpr &&expr) { init_ = std::move(expr); }
441 const parser::Expr *unanalyzedPDTComponentInit() const {
442 return unanalyzedPDTComponentInit_;
443 }
444 void set_unanalyzedPDTComponentInit(const parser::Expr *expr) {
445 unanalyzedPDTComponentInit_ = expr;
446 }
447 ArraySpec &shape() { return shape_; }
448 const ArraySpec &shape() const { return shape_; }
449 ArraySpec &coshape() { return coshape_; }
450 const ArraySpec &coshape() const { return coshape_; }
451 void set_shape(const ArraySpec &);
452 void set_coshape(const ArraySpec &);
453 const Symbol *commonBlock() const { return commonBlock_; }
454 void set_commonBlock(const Symbol &commonBlock) {
455 commonBlock_ = &commonBlock;
456 }
457 common::IgnoreTKRSet ignoreTKR() const { return ignoreTKR_; }
458 void set_ignoreTKR(common::IgnoreTKRSet set) { ignoreTKR_ = set; }
459 bool IsArray() const { return !shape_.empty(); }
460 bool IsCoarray() const { return !coshape_.empty(); }
461 bool IsAssumedShape() const {
462 return isDummy() && shape_.CanBeAssumedShape();
463 }
464 bool CanBeDeferredShape() const { return shape_.CanBeDeferredShape(); }
465 bool IsAssumedRank() const { return isDummy() && shape_.IsAssumedRank(); }
466 std::optional<common::CUDADataAttr> cudaDataAttr() const {
467 return cudaDataAttr_;
468 }
469 void set_cudaDataAttr(std::optional<common::CUDADataAttr> attr) {
470 cudaDataAttr_ = attr;
471 }
472
473private:
474 MaybeExpr init_;
475 const parser::Expr *unanalyzedPDTComponentInit_{nullptr};
476 ArraySpec shape_;
477 ArraySpec coshape_;
478 common::IgnoreTKRSet ignoreTKR_;
479 const Symbol *commonBlock_{nullptr}; // common block this object is in
480 std::optional<common::CUDADataAttr> cudaDataAttr_;
481 friend llvm::raw_ostream &operator<<(
482 llvm::raw_ostream &, const ObjectEntityDetails &);
483};
484
485// Mixin for details with passed-object dummy argument.
486// If a procedure pointer component or type-bound procedure does not have
487// the NOPASS attribute on its symbol, then PASS is assumed; the name
488// is optional; if it is missing, the first dummy argument of the procedure's
489// interface is the passed-object dummy argument.
491public:
492 std::optional<SourceName> passName() const { return passName_; }
493 void set_passName(const SourceName &passName) { passName_ = passName; }
494
495private:
496 std::optional<SourceName> passName_;
497};
498
499// A procedure pointer (other than one defined with POINTER and an
500// INTERFACE block), a dummy procedure (without an INTERFACE but with
501// EXTERNAL or use in a procedure reference), or external procedure.
502class ProcEntityDetails : public EntityDetails,
503 public WithPassArg,
504 public WithOmpDeclarative {
505public:
506 ProcEntityDetails() = default;
507 explicit ProcEntityDetails(EntityDetails &&);
508 ProcEntityDetails(const ProcEntityDetails &) = default;
509 ProcEntityDetails(ProcEntityDetails &&) = default;
510 ProcEntityDetails &operator=(const ProcEntityDetails &) = default;
511
512 const Symbol *rawProcInterface() const { return rawProcInterface_; }
513 const Symbol *procInterface() const { return procInterface_; }
514 void set_procInterfaces(const Symbol &raw, const Symbol &resolved) {
515 rawProcInterface_ = &raw;
516 procInterface_ = &resolved;
517 }
518 inline bool HasExplicitInterface() const;
519
520 // Be advised: !init().has_value() => uninitialized pointer,
521 // while *init() == nullptr => explicit NULL() initialization.
522 std::optional<const Symbol *> init() const { return init_; }
523 void set_init(const Symbol &symbol) { init_ = &symbol; }
524 void set_init(std::nullptr_t) { init_ = nullptr; }
525 bool isCUDAKernel() const { return isCUDAKernel_; }
526 void set_isCUDAKernel(bool yes = true) { isCUDAKernel_ = yes; }
527 std::optional<SourceName> usedAsProcedureHere() const {
528 return usedAsProcedureHere_;
529 }
530 void set_usedAsProcedureHere(SourceName here) { usedAsProcedureHere_ = here; }
531 const std::vector<OpenACCRoutineInfo> &openACCRoutineInfos() const {
532 return openACCRoutineInfos_;
533 }
534 void add_openACCRoutineInfo(OpenACCRoutineInfo info) {
535 openACCRoutineInfos_.push_back(info);
536 }
537
538private:
539 const Symbol *rawProcInterface_{nullptr};
540 const Symbol *procInterface_{nullptr};
541 std::optional<const Symbol *> init_;
542 bool isCUDAKernel_{false};
543 std::optional<SourceName> usedAsProcedureHere_;
544 std::vector<OpenACCRoutineInfo> openACCRoutineInfos_;
545 friend llvm::raw_ostream &operator<<(
546 llvm::raw_ostream &, const ProcEntityDetails &);
547};
548
549// These derived type details represent the characteristics of a derived
550// type definition that are shared by all instantiations of that type.
551// The DerivedTypeSpec instances whose type symbols share these details
552// each own a scope into which the components' symbols have been cloned
553// and specialized for each distinct set of type parameter values.
555public:
556 const SymbolVector &paramNameOrder() const { return paramNameOrder_; }
557 const SymbolVector &paramDeclOrder() const { return paramDeclOrder_; }
558 bool sequence() const { return sequence_; }
559 bool isDECStructure() const { return isDECStructure_; }
560 bool isEnumerationType() const { return isEnumerationType_; }
561 void set_isEnumerationType(bool x = true) { isEnumerationType_ = x; }
562 // Name of the hidden component created for an enumeration type to hold
563 // the 1-based enumerator ordinal.
564 static constexpr char ordinalComponentName[]{"__ordinal"};
565 int enumeratorCount() const { return enumeratorCount_; }
566 void set_enumeratorCount(int n) { enumeratorCount_ = n; }
567 std::map<SourceName, SymbolRef> &finals() { return finals_; }
568 const std::map<SourceName, SymbolRef> &finals() const { return finals_; }
569 bool isForwardReferenced() const { return isForwardReferenced_; }
570 void add_paramNameOrder(const Symbol &symbol) {
571 paramNameOrder_.push_back(symbol);
572 }
573 void add_paramDeclOrder(const Symbol &symbol) {
574 paramDeclOrder_.push_back(symbol);
575 }
576 void add_component(const Symbol &);
577 void set_sequence(bool x = true) { sequence_ = x; }
578 void set_isDECStructure(bool x = true) { isDECStructure_ = x; }
579 void set_isForwardReferenced(bool value) { isForwardReferenced_ = value; }
580 const std::list<SourceName> &componentNames() const {
581 return componentNames_;
582 }
583 const std::map<SourceName, const parser::Expr *> &
584 originalKindParameterMap() const {
585 return originalKindParameterMap_;
586 }
587 void add_originalKindParameter(SourceName, const parser::Expr *);
588
589 // If this derived type extends another, locate the parent component's symbol.
590 const Symbol *GetParentComponent(const Scope &) const;
591
592 std::optional<SourceName> GetParentComponentName() const {
593 if (componentNames_.empty()) {
594 return std::nullopt;
595 } else {
596 return componentNames_.front();
597 }
598 }
599
600 const Symbol *GetFinalForRank(int) const;
601
602private:
603 // These are (1) the symbols of the derived type parameters in the order
604 // in which they appear on the type definition statement(s), and (2) the
605 // symbols that correspond to those names in the order in which their
606 // declarations appear in the derived type definition(s).
607 SymbolVector paramNameOrder_;
608 SymbolVector paramDeclOrder_;
609 // These are the names of the derived type's components in component
610 // order. A parent component, if any, appears first in this list.
611 std::list<SourceName> componentNames_;
612 std::map<SourceName, SymbolRef> finals_; // FINAL :: subr
613 bool sequence_{false};
614 bool isDECStructure_{false};
615 bool isForwardReferenced_{false};
616 std::map<SourceName, const parser::Expr *> originalKindParameterMap_;
617
618 // These fields are only used if the derived type is an enumeration type.
619 bool isEnumerationType_{false};
620 int enumeratorCount_{0};
621
622 friend llvm::raw_ostream &operator<<(
623 llvm::raw_ostream &, const DerivedTypeDetails &);
624};
625
626class ProcBindingDetails : public WithPassArg {
627public:
628 explicit ProcBindingDetails(const Symbol &symbol) : symbol_{symbol} {}
629 const Symbol &symbol() const { return symbol_; }
630 void ReplaceSymbol(const Symbol &symbol) { symbol_ = symbol; }
631 int numPrivatesNotOverridden() const { return numPrivatesNotOverridden_; }
632 void set_numPrivatesNotOverridden(int n) { numPrivatesNotOverridden_ = n; }
633
634private:
635 SymbolRef symbol_; // procedure bound to; may be forward
636 // Homonymous private bindings in ancestor types from other modules
637 int numPrivatesNotOverridden_{0};
638};
639
641public:
642 const SymbolVector &objects() const { return objects_; }
643 void add_object(const Symbol &object) { objects_.push_back(object); }
644 void add_objects(const SymbolVector &objects) {
645 objects_.insert(objects_.end(), objects.begin(), objects.end());
646 }
647
648private:
649 SymbolVector objects_;
650};
651
652class CommonBlockDetails : public WithBindName, public WithOmpDeclarative {
653public:
654 explicit CommonBlockDetails(SourceName location)
655 : sourceLocation_{location} {}
656 SourceName sourceLocation() const { return sourceLocation_; }
657 MutableSymbolVector &objects() { return objects_; }
658 const MutableSymbolVector &objects() const { return objects_; }
659 void add_object(Symbol &object) { objects_.emplace_back(object); }
660 void replace_object(Symbol &object, unsigned index) {
661 CHECK(index < objects_.size());
662 objects_[index] = object;
663 }
664 std::size_t alignment() const { return alignment_; }
665 void set_alignment(std::size_t alignment) { alignment_ = alignment; }
666
667private:
668 SourceName sourceLocation_;
669 MutableSymbolVector objects_;
670 std::size_t alignment_{0}; // required alignment in bytes
671};
672
673class MiscDetails {
674public:
675 ENUM_CLASS(Kind, None, ConstructName, ScopeName, PassName, ComplexPartRe,
676 ComplexPartIm, KindParamInquiry, LenParamInquiry, SelectRankAssociateName,
677 SelectTypeAssociateName, TypeBoundDefinedOp);
678 MiscDetails(Kind kind) : kind_{kind} {}
679 Kind kind() const { return kind_; }
680
681private:
682 Kind kind_;
683};
684
685class TypeParamDetails {
686public:
687 TypeParamDetails() = default;
688 TypeParamDetails(const TypeParamDetails &) = default;
689 TypeParamDetails &operator=(const TypeParamDetails &) = default;
690 std::optional<common::TypeParamAttr> attr() const { return attr_; }
691 TypeParamDetails &set_attr(common::TypeParamAttr);
692 MaybeIntExpr &init() { return init_; }
693 const MaybeIntExpr &init() const { return init_; }
694 void set_init(MaybeIntExpr &&expr) { init_ = std::move(expr); }
695 const DeclTypeSpec *type() const { return type_; }
696 TypeParamDetails &set_type(const DeclTypeSpec &);
697 void ReplaceType(const DeclTypeSpec &);
698
699private:
700 std::optional<common::TypeParamAttr> attr_;
701 MaybeIntExpr init_;
702 const DeclTypeSpec *type_{nullptr};
703};
704
705// Record the USE of a symbol: location is where (USE statement or renaming);
706// symbol is in the USEd module.
707class UseDetails {
708public:
709 UseDetails(const SourceName &location, const Symbol &symbol)
710 : location_{location}, symbol_{symbol} {}
711 const SourceName &location() const { return location_; }
712 const Symbol &symbol() const { return symbol_; }
713
714private:
715 SourceName location_;
716 SymbolRef symbol_;
717};
718
719// A symbol with ambiguous use-associations. Record where they were so
720// we can report the error if it is used.
721class UseErrorDetails {
722public:
723 UseErrorDetails(const UseDetails &);
724 UseErrorDetails &add_occurrence(const SourceName &, const Symbol &);
725 using ListType = std::list<std::pair<SourceName, const Symbol *>>;
726 const ListType occurrences() const { return occurrences_; };
727
728private:
729 ListType occurrences_;
730};
731
732// A symbol host-associated from an enclosing scope.
733class HostAssocDetails {
734public:
735 HostAssocDetails(const Symbol &symbol) : symbol_{symbol} {}
736 const Symbol &symbol() const { return symbol_; }
737 bool implicitOrSpecExprError{false};
738 bool implicitOrExplicitTypeError{false};
739
740private:
741 SymbolRef symbol_;
742};
743
744// A GenericKind is one of: generic name, defined operator,
745// defined assignment, intrinsic operator, or defined I/O.
746struct GenericKind {
747 ENUM_CLASS(OtherKind, Name, DefinedOp, Assignment, Concat)
748 GenericKind() : u{OtherKind::Name} {}
749 template <typename T> GenericKind(const T &x) { u = x; }
750 bool IsName() const { return Is(OtherKind::Name); }
751 bool IsAssignment() const { return Is(OtherKind::Assignment); }
752 bool IsDefinedOperator() const { return Is(OtherKind::DefinedOp); }
753 bool IsIntrinsicOperator() const;
754 bool IsOperator() const;
755 std::string ToString() const;
756 static SourceName AsFortran(common::DefinedIo);
757 std::variant<OtherKind, common::NumericOperator, common::LogicalOperator,
758 common::RelationalOperator, common::DefinedIo>
759 u;
760
761private:
762 template <typename T> bool Has() const {
763 return std::holds_alternative<T>(u);
764 }
765 bool Is(OtherKind) const;
766};
767
768// A generic interface or type-bound generic.
769class GenericDetails {
770public:
771 GenericDetails() {}
772
773 GenericKind kind() const { return kind_; }
774 void set_kind(GenericKind kind) { kind_ = kind; }
775
776 const SymbolVector &specificProcs() const { return specificProcs_; }
777 const std::vector<SourceName> &bindingNames() const { return bindingNames_; }
778 void AddSpecificProc(const Symbol &, SourceName bindingName);
779 const SymbolVector &uses() const { return uses_; }
780
781 // specific and derivedType indicate a specific procedure or derived type
782 // with the same name as this generic. Only one of them may be set in
783 // a scope that declares them, but both can be set during USE association
784 // when generics are combined.
785 Symbol *specific() { return specific_; }
786 const Symbol *specific() const { return specific_; }
787 void set_specific(Symbol &specific);
788 void clear_specific();
789 Symbol *derivedType() { return derivedType_; }
790 const Symbol *derivedType() const { return derivedType_; }
791 void set_derivedType(Symbol &derivedType);
792 void clear_derivedType();
793 void AddUse(const Symbol &);
794
795 // Copy in specificProcs, specific, and derivedType from another generic
796 void CopyFrom(const GenericDetails &);
797
798 // Check that specific is one of the specificProcs. If not, return the
799 // specific as a raw pointer.
800 const Symbol *CheckSpecific() const;
801 Symbol *CheckSpecific();
802
803private:
804 GenericKind kind_;
805 // all of the specific procedures for this generic
806 SymbolVector specificProcs_;
807 std::vector<SourceName> bindingNames_;
808 // Symbols used from other modules merged into this one
809 SymbolVector uses_;
810 // a specific procedure with the same name as this generic, if any
811 Symbol *specific_{nullptr};
812 // a derived type with the same name as this generic, if any
813 Symbol *derivedType_{nullptr};
814};
815llvm::raw_ostream &operator<<(llvm::raw_ostream &, const GenericDetails &);
816
817// Used for OpenMP DECLARE REDUCTION, it holds the information
818// needed to resolve which declaration (there could be multiple
819// with the same name) to use for a given type.
820class UserReductionDetails {
821public:
822 using TypeVector = std::vector<const DeclTypeSpec *>;
823 using DeclVector = std::vector<const parser::OpenMPDeclarativeConstruct *>;
824
825 UserReductionDetails() = default;
826
827 void AddType(const DeclTypeSpec &type) { typeList_.push_back(&type); }
828 const TypeVector &GetTypeList() const { return typeList_; }
829
830 bool SupportsType(const DeclTypeSpec &type) const {
831 // We have to compare the actual type, not the pointer, as some
832 // types are not guaranteed to be the same object.
833 for (auto t : typeList_) {
834 if (*t == type) {
835 return true;
836 }
837 }
838 // For derived and class-derived types, match on the type symbol pointer.
839 if (type.category() == DeclTypeSpec::TypeDerived ||
840 type.category() == DeclTypeSpec::ClassDerived) {
841 const auto &rhs = type.derivedTypeSpec();
842 const auto &rhsSym = rhs.typeSymbol();
843 for (auto t : typeList_) {
844 if (t->category() == DeclTypeSpec::TypeDerived ||
845 t->category() == DeclTypeSpec::ClassDerived) {
846 const auto &lhs = t->derivedTypeSpec();
847 const auto &lhsSym = lhs.typeSymbol();
848 if (&lhsSym == &rhsSym) {
849 return true;
850 }
851 }
852 }
853 }
854 return false;
855 }
856
857 void AddDecl(const parser::OpenMPDeclarativeConstruct *decl) {
858 declList_.emplace_back(decl);
859 }
860 const DeclVector &GetDeclList() const { return declList_; }
861
862private:
863 TypeVector typeList_;
864 DeclVector declList_;
865};
866
867// Used for OpenMP DECLARE MAPPER, it holds the declaration constructs
868// so they can be serialized into module files and later re-parsed when
869// USE-associated.
870class MapperDetails {
871public:
872 using DeclVector = std::vector<const parser::OpenMPDeclarativeConstruct *>;
873
874 MapperDetails() = default;
875
876 void AddDecl(const parser::OpenMPDeclarativeConstruct *decl) {
877 declList_.emplace_back(decl);
878 }
879 const DeclVector &GetDeclList() const { return declList_; }
880
881private:
882 DeclVector declList_;
883};
884
886
887using Details = std::variant<UnknownDetails, MainProgramDetails, ModuleDetails,
893llvm::raw_ostream &operator<<(llvm::raw_ostream &, const Details &);
894std::string DetailsToString(const Details &);
895
896class Symbol {
897public:
898 ENUM_CLASS(Flag,
899 Function, // symbol is a function or statement function
900 Subroutine, // symbol is a subroutine
901 StmtFunction, // symbol is a statement function or result
902 Implicit, // symbol is implicitly typed
903 ImplicitOrError, // symbol must be implicitly typed or it's an error
904 ModFile, // symbol came from .mod file
905 ParentComp, // symbol is the "parent component" of an extended type
906 CrayPointer, CrayPointee,
907 LocalityLocal, // named in LOCAL locality-spec
908 LocalityLocalInit, // named in LOCAL_INIT locality-spec
909 LocalityReduce, // named in REDUCE locality-spec
910 LocalityShared, // named in SHARED locality-spec
911 InDataStmt, // initialized in a DATA statement, =>object, or /init/
912 InNamelist, // in a Namelist group
913 InCommonBlock, // referenced in a common block
914 EntryDummyArgument,
915 CompilerCreated, // A compiler created symbol
916 // For compiler created symbols that are constant but cannot legally have
917 // the PARAMETER attribute.
918 ReadOnly,
919 // OpenACC data-sharing attribute
920 AccPrivate, AccFirstPrivate, AccShared,
921 // OpenACC data-mapping attribute
922 AccCopy, AccCopyIn, AccCopyInReadOnly, AccCopyOut, AccCreate, AccDelete,
923 AccPresent, AccLink, AccDeviceResident, AccDevicePtr, AccUseDevice,
924 // OpenACC declare
925 AccDeclare,
926 // OpenACC declare on allocatable/pointer needs cross-TU action recipes
927 AccDeclareAction,
928 // OpenACC data-movement attribute
929 AccDevice, AccHost, AccSelf,
930 // OpenACC miscellaneous flags
931 AccCommonBlock, AccThreadPrivate, AccReduction, AccNone, AccPreDetermined,
932 // OpenMP data-sharing attribute
933 OmpShared, OmpPrivate, OmpLinear, OmpFirstPrivate, OmpLastPrivate,
934 OmpGroupPrivate,
935 // OpenMP data-mapping attribute
936 OmpMapTo, OmpMapFrom, OmpMapToFrom, OmpMapStorage, OmpMapDelete,
937 OmpUseDevicePtr, OmpUseDeviceAddr, OmpIsDevicePtr, OmpHasDeviceAddr,
938 // OpenMP data-copying attribute
939 OmpCopyIn, OmpCopyPrivate,
940 // OpenMP special variables
941 OmpInVar, OmpOrigVar, OmpOutVar, OmpPrivVar,
942 // OpenMP miscellaneous flags
943 OmpReserved, OmpCommonBlock, OmpReduction, OmpInReduction, OmpAligned,
944 OmpNontemporal, OmpAllocate, OmpDeclarativeAllocateDirective,
945 OmpExecutableAllocateDirective, OmpDeclareSimd, OmpDeclareTarget,
946 OmpThreadprivate, OmpDeclareReduction, OmpFlushed, OmpCriticalLock,
947 OmpIfSpecified, OmpNone, OmpPreDetermined, OmpExplicit, OmpImplicit,
948 OmpDependObject, OmpInclusiveScan, OmpExclusiveScan, OmpInScanReduction,
949 OmpUniform);
951
952 const Scope &owner() const { return *owner_; }
953 const SourceName &name() const { return name_; }
954 Attrs &attrs() { return attrs_; }
955 const Attrs &attrs() const { return attrs_; }
956 Attrs &implicitAttrs() { return implicitAttrs_; }
957 const Attrs &implicitAttrs() const { return implicitAttrs_; }
958 Flags &flags() { return flags_; }
959 const Flags &flags() const { return flags_; }
960 bool test(Flag flag) const { return flags_.test(flag); }
961 void set(Flag flag, bool value = true) { flags_.set(flag, value); }
962 // The Scope introduced by this symbol, if any.
963 Scope *scope() { return scope_; }
964 const Scope *scope() const { return scope_; }
965 void set_scope(Scope *scope) { scope_ = scope; }
966 std::size_t size() const { return size_; }
967 void set_size(std::size_t size) { size_ = size; }
968 std::size_t offset() const { return offset_; }
969 void set_offset(std::size_t offset) { offset_ = offset; }
970 // Give the symbol a name with a different source location but same chars.
971 void ReplaceName(const SourceName &);
972 static std::string OmpFlagToClauseName(Flag ompFlag);
973
974 // Does symbol have this type of details?
975 template <typename D> bool has() const {
976 return std::holds_alternative<D>(details_);
977 }
978
979 // Return a non-owning pointer to details if it is type D, else nullptr.
980 template <typename D> D *detailsIf() { return std::get_if<D>(&details_); }
981 template <typename D> const D *detailsIf() const {
982 return std::get_if<D>(&details_);
983 }
984
985 // Return a reference to the details which must be of type D.
986 template <typename D> D &get() {
987 return const_cast<D &>(const_cast<const Symbol *>(this)->get<D>());
988 }
989 template <typename D> const D &get() const {
990 const auto *p{detailsIf<D>()};
991 CHECK(p);
992 return *p;
993 }
994
995 Details &details() { return details_; }
996 const Details &details() const { return details_; }
997 // Assign the details of the symbol from one of the variants.
998 // Only allowed in certain cases.
999 void set_details(Details &&);
1000
1001 // Can the details of this symbol be replaced with the given details?
1002 bool CanReplaceDetails(const Details &details) const;
1003
1004 // Follow use-associations and host-associations to get the ultimate entity.
1005 inline Symbol &GetUltimate();
1006 inline const Symbol &GetUltimate() const;
1007
1008 inline DeclTypeSpec *GetType();
1009 inline const DeclTypeSpec *GetType() const;
1010 void SetType(const DeclTypeSpec &);
1011
1012 const std::string *GetBindName() const;
1013 void SetBindName(std::string &&);
1014 bool GetIsExplicitBindName() const;
1015 void SetIsExplicitBindName(bool);
1016 void SetIsCDefined(bool);
1017 bool IsFuncResult() const;
1018 bool IsObjectArray() const;
1019 const ArraySpec *GetShape() const;
1020 bool IsSubprogram() const;
1021 bool IsFromModFile() const;
1022 bool HasExplicitInterface() const {
1023 return common::visit(
1025 [](const SubprogramDetails &) { return true; },
1026 [](const SubprogramNameDetails &) { return true; },
1027 [&](const ProcEntityDetails &x) {
1028 return attrs_.test(Attr::INTRINSIC) || x.HasExplicitInterface();
1029 },
1030 [](const ProcBindingDetails &x) {
1031 return x.symbol().HasExplicitInterface();
1032 },
1033 [](const UseDetails &x) {
1034 return x.symbol().HasExplicitInterface();
1035 },
1036 [](const HostAssocDetails &x) {
1037 return x.symbol().HasExplicitInterface();
1038 },
1039 [](const GenericDetails &x) {
1040 return x.specific() && x.specific()->HasExplicitInterface();
1041 },
1042 [](const auto &) { return false; },
1043 },
1044 details_);
1045 }
1046 bool HasLocalLocality() const {
1047 return test(Flag::LocalityLocal) || test(Flag::LocalityLocalInit);
1048 }
1049
1050 bool operator==(const Symbol &that) const { return this == &that; }
1051 bool operator!=(const Symbol &that) const { return !(*this == that); }
1052
1053 int Rank() const { return RankImpl(); }
1054 int Corank() const { return CorankImpl(); }
1055
1056 // If there is a parent component, return a pointer to its derived type spec.
1057 // The Scope * argument defaults to this->scope_ but should be overridden
1058 // for a parameterized derived type instantiation with the instance's scope.
1059 const DerivedTypeSpec *GetParentTypeSpec(const Scope * = nullptr) const;
1060
1061 // If a derived type's symbol refers to an extended derived type,
1062 // return the parent component's symbol. The scope of the derived type
1063 // can be overridden.
1064 const Symbol *GetParentComponent(const Scope * = nullptr) const;
1065
1066 SemanticsContext &GetSemanticsContext() const;
1067#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1068 LLVM_DUMP_METHOD void dump() const;
1069#endif
1070
1071private:
1072 const Scope *owner_;
1073 SourceName name_;
1074 Attrs attrs_;
1075 Attrs implicitAttrs_; // subset of attrs_ that were not explicit
1076 Flags flags_;
1077 Scope *scope_{nullptr};
1078 std::size_t size_{0}; // size in bytes
1079 std::size_t offset_{0}; // byte offset in scope or common block
1080 Details details_;
1081
1082 Symbol() {} // only created in class Symbols
1083 std::string GetDetailsName() const;
1084 friend llvm::raw_ostream &operator<<(llvm::raw_ostream &, const Symbol &);
1085 friend llvm::raw_ostream &DumpForUnparse(
1086 llvm::raw_ostream &, const Symbol &, bool);
1087
1088 static constexpr int startRecursionDepth{100};
1089
1090 inline const DeclTypeSpec *GetTypeImpl(int depth = startRecursionDepth) const;
1091 inline int RankImpl(int depth = startRecursionDepth) const {
1092 if (depth-- == 0) {
1093 return 0;
1094 }
1095 return common::visit(
1097 [&](const SubprogramDetails &sd) {
1098 return sd.isFunction() ? sd.result().RankImpl(depth) : 0;
1099 },
1100 [](const GenericDetails &) {
1101 return 0; /*TODO*/
1102 },
1103 [&](const ProcBindingDetails &x) {
1104 return x.symbol().RankImpl(depth);
1105 },
1106 [&](const UseDetails &x) { return x.symbol().RankImpl(depth); },
1107 [&](const HostAssocDetails &x) {
1108 return x.symbol().RankImpl(depth);
1109 },
1110 [](const ObjectEntityDetails &oed) { return oed.shape().Rank(); },
1111 [&](const ProcEntityDetails &ped) {
1112 const Symbol *iface{ped.procInterface()};
1113 return iface ? iface->RankImpl(depth) : 0;
1114 },
1115 [](const AssocEntityDetails &aed) {
1116 if (auto assocRank{aed.rank()}) {
1117 // RANK(n) & RANK(*)
1118 return *assocRank;
1119 } else if (aed.IsAssumedRank()) {
1120 // RANK DEFAULT
1121 return 0;
1122 } else if (const auto &expr{aed.expr()}) {
1123 return expr->Rank();
1124 } else {
1125 return 0;
1126 }
1127 },
1128 [](const auto &) { return 0; },
1129 },
1130 details_);
1131 }
1132 inline int CorankImpl(int depth = startRecursionDepth) const {
1133 if (depth-- == 0) {
1134 return 0;
1135 }
1136 return common::visit(
1138 [&](const SubprogramDetails &sd) {
1139 return sd.isFunction() ? sd.result().CorankImpl(depth) : 0;
1140 },
1141 [](const GenericDetails &) { return 0; },
1142 [&](const ProcEntityDetails &ped) {
1143 const Symbol *iface{ped.procInterface()};
1144 return iface ? iface->CorankImpl(depth) : 0;
1145 },
1146 [&](const UseDetails &x) { return x.symbol().CorankImpl(depth); },
1147 [&](const HostAssocDetails &x) {
1148 return x.symbol().CorankImpl(depth);
1149 },
1150 [](const ObjectEntityDetails &oed) { return oed.coshape().Rank(); },
1151 [](const AssocEntityDetails &aed) {
1152 return aed.expr() ? aed.expr()->Corank() : 0;
1153 },
1154 [](const auto &) { return 0; },
1155 },
1156 details_);
1157 }
1158 template <std::size_t> friend class Symbols;
1159 template <class, std::size_t> friend class std::array;
1160};
1161
1162llvm::raw_ostream &operator<<(llvm::raw_ostream &, Symbol::Flag);
1163
1164// Manage memory for all symbols. BLOCK_SIZE symbols at a time are allocated.
1165// Make() returns a reference to the next available one. They are never
1166// deleted.
1167template <std::size_t BLOCK_SIZE> class Symbols {
1168public:
1169 Symbol &Make(const Scope &owner, const SourceName &name, const Attrs &attrs,
1170 Details &&details) {
1171 Symbol &symbol = Get();
1172 symbol.owner_ = &owner;
1173 symbol.name_ = name;
1174 symbol.attrs_ = attrs;
1175 symbol.details_ = std::move(details);
1176 return symbol;
1177 }
1178
1179private:
1180 using blockType = std::array<Symbol, BLOCK_SIZE>;
1181 std::list<blockType *> blocks_;
1182 std::size_t nextIndex_{0};
1183 blockType *currBlock_{nullptr};
1184
1185 Symbol &Get() {
1186 if (nextIndex_ == 0) {
1187 blocks_.push_back(new blockType());
1188 currBlock_ = blocks_.back();
1189 }
1190 Symbol &result = (*currBlock_)[nextIndex_];
1191 if (++nextIndex_ >= BLOCK_SIZE) {
1192 nextIndex_ = 0; // allocate a new block next time
1193 }
1194 return result;
1195 }
1196};
1197
1198// Define a few member functions here in the header so that they
1199// can be used by lib/Evaluate without inducing a dependence cycle
1200// between the two shared libraries.
1201
1202inline bool ProcEntityDetails::HasExplicitInterface() const {
1203 return procInterface_ && procInterface_->HasExplicitInterface();
1204}
1205
1206inline Symbol &Symbol::GetUltimate() {
1207 return const_cast<Symbol &>(const_cast<const Symbol *>(this)->GetUltimate());
1208}
1209inline const Symbol &Symbol::GetUltimate() const {
1210 if (const auto *details{detailsIf<UseDetails>()}) {
1211 return details->symbol().GetUltimate();
1212 } else if (const auto *details{detailsIf<HostAssocDetails>()}) {
1213 return details->symbol().GetUltimate();
1214 } else {
1215 return *this;
1216 }
1217}
1218
1219inline DeclTypeSpec *Symbol::GetType() {
1220 return const_cast<DeclTypeSpec *>(
1221 const_cast<const Symbol *>(this)->GetType());
1222}
1223
1224inline const DeclTypeSpec *Symbol::GetTypeImpl(int depth) const {
1225 if (depth-- == 0) {
1226 return nullptr;
1227 }
1228 return common::visit(
1229 common::visitors{
1230 [](const EntityDetails &x) { return x.type(); },
1231 [](const ObjectEntityDetails &x) { return x.type(); },
1232 [](const AssocEntityDetails &x) { return x.type(); },
1233 [&](const SubprogramDetails &x) {
1234 return x.isFunction() ? x.result().GetTypeImpl(depth) : nullptr;
1235 },
1236 [&](const ProcEntityDetails &x) {
1237 const Symbol *symbol{x.procInterface()};
1238 return symbol ? symbol->GetTypeImpl(depth) : x.type();
1239 },
1240 [&](const ProcBindingDetails &x) {
1241 return x.symbol().GetTypeImpl(depth);
1242 },
1243 [](const TypeParamDetails &x) { return x.type(); },
1244 [&](const UseDetails &x) { return x.symbol().GetTypeImpl(depth); },
1245 [&](const HostAssocDetails &x) {
1246 return x.symbol().GetTypeImpl(depth);
1247 },
1248 [&](const GenericDetails &x) {
1249 return x.specific() ? x.specific()->GetTypeImpl(depth) : nullptr;
1250 },
1251 [](const auto &) -> const DeclTypeSpec * { return nullptr; },
1252 },
1253 details_);
1254}
1255
1256inline const DeclTypeSpec *Symbol::GetType() const { return GetTypeImpl(); }
1257
1258// Defined here, where Symbol is a complete type, so that it can be inlined
1259// into FortranEvaluate without that library needing to link FortranSemantics.
1260inline const Scope *DerivedTypeSpec::GetScope() const {
1261 return scope_ ? scope_ : typeSymbol_.scope();
1262}
1263
1264// Sets and maps keyed by Symbols
1265
1267 bool operator()(const SymbolRef &x, const SymbolRef &y) const {
1268 return &*x < &*y;
1269 }
1270 bool operator()(const MutableSymbolRef &x, const MutableSymbolRef &y) const {
1271 return &*x < &*y;
1272 }
1273};
1274
1275// Symbol comparison is usually based on the order of cooked source
1276// stream creation and, when both are from the same cooked source,
1277// their positions in that cooked source stream.
1278// Don't use this comparator or SourceOrderedSymbolSet to hold
1279// Symbols that might be subject to ReplaceName().
1281 // These functions are implemented in Evaluate/tools.cpp to
1282 // satisfy complicated shared library interdependency.
1283 bool operator()(const SymbolRef &, const SymbolRef &) const;
1284 bool operator()(const MutableSymbolRef &, const MutableSymbolRef &) const;
1285};
1286
1288 bool operator()(const SymbolRef &, const SymbolRef &) const;
1289 bool operator()(const MutableSymbolRef &, const MutableSymbolRef &) const;
1290};
1291
1292using UnorderedSymbolSet = std::set<SymbolRef, SymbolAddressCompare>;
1293using SourceOrderedSymbolSet = std::set<SymbolRef, SymbolSourcePositionCompare>;
1294
1295template <typename A>
1296SourceOrderedSymbolSet OrderBySourcePosition(const A &container) {
1297 SourceOrderedSymbolSet result;
1298 for (SymbolRef x : container) {
1299 result.emplace(x);
1300 }
1301 return result;
1302}
1303
1304} // namespace Fortran::semantics
1305
1306// Define required info so that SymbolRef can be used inside llvm::DenseMap.
1307namespace llvm {
1308template <> struct DenseMapInfo<Fortran::semantics::SymbolRef> {
1309 static unsigned getHashValue(const Fortran::semantics::SymbolRef &sym) {
1310 return DenseMapInfo<const Fortran::semantics::Symbol *>::getHashValue(
1311 &sym.get());
1312 }
1313
1314 static bool isEqual(const Fortran::semantics::SymbolRef &LHS,
1315 const Fortran::semantics::SymbolRef &RHS) {
1316 return LHS == RHS;
1317 }
1318};
1319} // namespace llvm
1320#endif // FORTRAN_SEMANTICS_SYMBOL_H_
Definition enum-set.h:28
Definition reference.h:18
Definition char-block.h:26
Definition symbol.h:367
Definition symbol.h:769
Definition symbol.h:870
Definition symbol.h:673
Definition symbol.h:128
Definition program-tree.h:31
Definition scope.h:68
Definition symbol.h:896
Definition symbol.h:1167
Definition symbol.h:885
Definition symbol.h:707
Definition symbol.h:158
Definition symbol.h:490
Definition check-expression.h:19
Definition bit-population-count.h:20
Definition idioms.h:60
Definition parse-tree.h:1735
Definition type.h:239
Definition symbol.h:746
Definition omp-declare-variant.h:25