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 // Specification expressions from the bounds of a zero-size explicit-shape
473 // bounds array (F2023). The entity is scalar, so these bounds are not
474 // part of shape(), but they are still specification expressions that must be
475 // validated during declaration checking, when the scope is fully resolved.
476 void add_droppedBoundToCheck(Bound &&bound) {
477 droppedBoundsToCheck_.emplace_back(std::move(bound));
478 }
479 const std::vector<Bound> &droppedBoundsToCheck() const {
480 return droppedBoundsToCheck_;
481 }
482
483private:
484 MaybeExpr init_;
485 const parser::Expr *unanalyzedPDTComponentInit_{nullptr};
486 ArraySpec shape_;
487 ArraySpec coshape_;
488 std::vector<Bound> droppedBoundsToCheck_;
489 common::IgnoreTKRSet ignoreTKR_;
490 const Symbol *commonBlock_{nullptr}; // common block this object is in
491 std::optional<common::CUDADataAttr> cudaDataAttr_;
492 friend llvm::raw_ostream &operator<<(
493 llvm::raw_ostream &, const ObjectEntityDetails &);
494};
495
496// Mixin for details with passed-object dummy argument.
497// If a procedure pointer component or type-bound procedure does not have
498// the NOPASS attribute on its symbol, then PASS is assumed; the name
499// is optional; if it is missing, the first dummy argument of the procedure's
500// interface is the passed-object dummy argument.
502public:
503 std::optional<SourceName> passName() const { return passName_; }
504 void set_passName(const SourceName &passName) { passName_ = passName; }
505
506private:
507 std::optional<SourceName> passName_;
508};
509
510// A procedure pointer (other than one defined with POINTER and an
511// INTERFACE block), a dummy procedure (without an INTERFACE but with
512// EXTERNAL or use in a procedure reference), or external procedure.
513class ProcEntityDetails : public EntityDetails,
514 public WithPassArg,
515 public WithOmpDeclarative {
516public:
517 ProcEntityDetails() = default;
518 explicit ProcEntityDetails(EntityDetails &&);
519 ProcEntityDetails(const ProcEntityDetails &) = default;
520 ProcEntityDetails(ProcEntityDetails &&) = default;
521 ProcEntityDetails &operator=(const ProcEntityDetails &) = default;
522
523 const Symbol *rawProcInterface() const { return rawProcInterface_; }
524 const Symbol *procInterface() const { return procInterface_; }
525 void set_procInterfaces(const Symbol &raw, const Symbol &resolved) {
526 rawProcInterface_ = &raw;
527 procInterface_ = &resolved;
528 }
529 inline bool HasExplicitInterface() const;
530
531 // Be advised: !init().has_value() => uninitialized pointer,
532 // while *init() == nullptr => explicit NULL() initialization.
533 std::optional<const Symbol *> init() const { return init_; }
534 void set_init(const Symbol &symbol) { init_ = &symbol; }
535 void set_init(std::nullptr_t) { init_ = nullptr; }
536 bool isCUDAKernel() const { return isCUDAKernel_; }
537 void set_isCUDAKernel(bool yes = true) { isCUDAKernel_ = yes; }
538 std::optional<SourceName> usedAsProcedureHere() const {
539 return usedAsProcedureHere_;
540 }
541 void set_usedAsProcedureHere(SourceName here) { usedAsProcedureHere_ = here; }
542 const std::vector<OpenACCRoutineInfo> &openACCRoutineInfos() const {
543 return openACCRoutineInfos_;
544 }
545 void add_openACCRoutineInfo(OpenACCRoutineInfo info) {
546 openACCRoutineInfos_.push_back(info);
547 }
548
549private:
550 const Symbol *rawProcInterface_{nullptr};
551 const Symbol *procInterface_{nullptr};
552 std::optional<const Symbol *> init_;
553 bool isCUDAKernel_{false};
554 std::optional<SourceName> usedAsProcedureHere_;
555 std::vector<OpenACCRoutineInfo> openACCRoutineInfos_;
556 friend llvm::raw_ostream &operator<<(
557 llvm::raw_ostream &, const ProcEntityDetails &);
558};
559
560// These derived type details represent the characteristics of a derived
561// type definition that are shared by all instantiations of that type.
562// The DerivedTypeSpec instances whose type symbols share these details
563// each own a scope into which the components' symbols have been cloned
564// and specialized for each distinct set of type parameter values.
566public:
567 const SymbolVector &paramNameOrder() const { return paramNameOrder_; }
568 const SymbolVector &paramDeclOrder() const { return paramDeclOrder_; }
569 bool sequence() const { return sequence_; }
570 bool isDECStructure() const { return isDECStructure_; }
571 bool isEnumerationType() const { return isEnumerationType_; }
572 void set_isEnumerationType(bool x = true) { isEnumerationType_ = x; }
573 // Name of the hidden component created for an enumeration type to hold
574 // the 1-based enumerator ordinal.
575 static constexpr char ordinalComponentName[]{"__ordinal"};
576 int enumeratorCount() const { return enumeratorCount_; }
577 void set_enumeratorCount(int n) { enumeratorCount_ = n; }
578 std::map<SourceName, SymbolRef> &finals() { return finals_; }
579 const std::map<SourceName, SymbolRef> &finals() const { return finals_; }
580 bool isForwardReferenced() const { return isForwardReferenced_; }
581 void add_paramNameOrder(const Symbol &symbol) {
582 paramNameOrder_.push_back(symbol);
583 }
584 void add_paramDeclOrder(const Symbol &symbol) {
585 paramDeclOrder_.push_back(symbol);
586 }
587 void add_component(const Symbol &);
588 void set_sequence(bool x = true) { sequence_ = x; }
589 void set_isDECStructure(bool x = true) { isDECStructure_ = x; }
590 void set_isForwardReferenced(bool value) { isForwardReferenced_ = value; }
591 const std::list<SourceName> &componentNames() const {
592 return componentNames_;
593 }
594 const std::map<SourceName, const parser::Expr *> &
595 originalKindParameterMap() const {
596 return originalKindParameterMap_;
597 }
598 void add_originalKindParameter(SourceName, const parser::Expr *);
599
600 // If this derived type extends another, locate the parent component's symbol.
601 const Symbol *GetParentComponent(const Scope &) const;
602
603 std::optional<SourceName> GetParentComponentName() const {
604 if (componentNames_.empty()) {
605 return std::nullopt;
606 } else {
607 return componentNames_.front();
608 }
609 }
610
611 const Symbol *GetFinalForRank(int) const;
612
613private:
614 // These are (1) the symbols of the derived type parameters in the order
615 // in which they appear on the type definition statement(s), and (2) the
616 // symbols that correspond to those names in the order in which their
617 // declarations appear in the derived type definition(s).
618 SymbolVector paramNameOrder_;
619 SymbolVector paramDeclOrder_;
620 // These are the names of the derived type's components in component
621 // order. A parent component, if any, appears first in this list.
622 std::list<SourceName> componentNames_;
623 std::map<SourceName, SymbolRef> finals_; // FINAL :: subr
624 bool sequence_{false};
625 bool isDECStructure_{false};
626 bool isForwardReferenced_{false};
627 std::map<SourceName, const parser::Expr *> originalKindParameterMap_;
628
629 // These fields are only used if the derived type is an enumeration type.
630 bool isEnumerationType_{false};
631 int enumeratorCount_{0};
632
633 friend llvm::raw_ostream &operator<<(
634 llvm::raw_ostream &, const DerivedTypeDetails &);
635};
636
637class ProcBindingDetails : public WithPassArg {
638public:
639 explicit ProcBindingDetails(const Symbol &symbol) : symbol_{symbol} {}
640 const Symbol &symbol() const { return symbol_; }
641 void ReplaceSymbol(const Symbol &symbol) { symbol_ = symbol; }
642 int numPrivatesNotOverridden() const { return numPrivatesNotOverridden_; }
643 void set_numPrivatesNotOverridden(int n) { numPrivatesNotOverridden_ = n; }
644
645private:
646 SymbolRef symbol_; // procedure bound to; may be forward
647 // Homonymous private bindings in ancestor types from other modules
648 int numPrivatesNotOverridden_{0};
649};
650
652public:
653 const SymbolVector &objects() const { return objects_; }
654 void add_object(const Symbol &object) { objects_.push_back(object); }
655 void add_objects(const SymbolVector &objects) {
656 objects_.insert(objects_.end(), objects.begin(), objects.end());
657 }
658
659private:
660 SymbolVector objects_;
661};
662
663class CommonBlockDetails : public WithBindName, public WithOmpDeclarative {
664public:
665 explicit CommonBlockDetails(SourceName location)
666 : sourceLocation_{location} {}
667 SourceName sourceLocation() const { return sourceLocation_; }
668 MutableSymbolVector &objects() { return objects_; }
669 const MutableSymbolVector &objects() const { return objects_; }
670 void add_object(Symbol &object) { objects_.emplace_back(object); }
671 void replace_object(Symbol &object, unsigned index) {
672 CHECK(index < objects_.size());
673 objects_[index] = object;
674 }
675 std::size_t alignment() const { return alignment_; }
676 void set_alignment(std::size_t alignment) { alignment_ = alignment; }
677
678private:
679 SourceName sourceLocation_;
680 MutableSymbolVector objects_;
681 std::size_t alignment_{0}; // required alignment in bytes
682};
683
684class MiscDetails {
685public:
686 ENUM_CLASS(Kind, None, ConstructName, ScopeName, PassName, ComplexPartRe,
687 ComplexPartIm, KindParamInquiry, LenParamInquiry, SelectRankAssociateName,
688 SelectTypeAssociateName, TypeBoundDefinedOp);
689 MiscDetails(Kind kind) : kind_{kind} {}
690 Kind kind() const { return kind_; }
691
692private:
693 Kind kind_;
694};
695
696class TypeParamDetails {
697public:
698 TypeParamDetails() = default;
699 TypeParamDetails(const TypeParamDetails &) = default;
700 TypeParamDetails &operator=(const TypeParamDetails &) = default;
701 std::optional<common::TypeParamAttr> attr() const { return attr_; }
702 TypeParamDetails &set_attr(common::TypeParamAttr);
703 MaybeIntExpr &init() { return init_; }
704 const MaybeIntExpr &init() const { return init_; }
705 void set_init(MaybeIntExpr &&expr) { init_ = std::move(expr); }
706 const DeclTypeSpec *type() const { return type_; }
707 TypeParamDetails &set_type(const DeclTypeSpec &);
708 void ReplaceType(const DeclTypeSpec &);
709
710private:
711 std::optional<common::TypeParamAttr> attr_;
712 MaybeIntExpr init_;
713 const DeclTypeSpec *type_{nullptr};
714};
715
716// Record the USE of a symbol: location is where (USE statement or renaming);
717// symbol is in the USEd module.
718class UseDetails {
719public:
720 UseDetails(const SourceName &location, const Symbol &symbol)
721 : location_{location}, symbol_{symbol} {}
722 const SourceName &location() const { return location_; }
723 const Symbol &symbol() const { return symbol_; }
724
725private:
726 SourceName location_;
727 SymbolRef symbol_;
728};
729
730// A symbol with ambiguous use-associations. Record where they were so
731// we can report the error if it is used.
732class UseErrorDetails {
733public:
734 UseErrorDetails(const UseDetails &);
735 UseErrorDetails &add_occurrence(const SourceName &, const Symbol &);
736 using ListType = std::list<std::pair<SourceName, const Symbol *>>;
737 const ListType occurrences() const { return occurrences_; };
738
739private:
740 ListType occurrences_;
741};
742
743// A symbol host-associated from an enclosing scope.
744class HostAssocDetails {
745public:
746 HostAssocDetails(const Symbol &symbol) : symbol_{symbol} {}
747 const Symbol &symbol() const { return symbol_; }
748 bool implicitOrSpecExprError{false};
749 bool implicitOrExplicitTypeError{false};
750
751private:
752 SymbolRef symbol_;
753};
754
755// A GenericKind is one of: generic name, defined operator,
756// defined assignment, intrinsic operator, or defined I/O.
757struct GenericKind {
758 ENUM_CLASS(OtherKind, Name, DefinedOp, Assignment, Concat)
759 GenericKind() : u{OtherKind::Name} {}
760 template <typename T> GenericKind(const T &x) { u = x; }
761 bool IsName() const { return Is(OtherKind::Name); }
762 bool IsAssignment() const { return Is(OtherKind::Assignment); }
763 bool IsDefinedOperator() const { return Is(OtherKind::DefinedOp); }
764 bool IsIntrinsicOperator() const;
765 bool IsOperator() const;
766 std::string ToString() const;
767 static SourceName AsFortran(common::DefinedIo);
768 std::variant<OtherKind, common::NumericOperator, common::LogicalOperator,
769 common::RelationalOperator, common::DefinedIo>
770 u;
771
772private:
773 template <typename T> bool Has() const {
774 return std::holds_alternative<T>(u);
775 }
776 bool Is(OtherKind) const;
777};
778
779// A generic interface or type-bound generic.
780class GenericDetails {
781public:
782 GenericDetails() {}
783
784 GenericKind kind() const { return kind_; }
785 void set_kind(GenericKind kind) { kind_ = kind; }
786
787 const SymbolVector &specificProcs() const { return specificProcs_; }
788 const std::vector<SourceName> &bindingNames() const { return bindingNames_; }
789 void AddSpecificProc(const Symbol &, SourceName bindingName);
790 const SymbolVector &uses() const { return uses_; }
791
792 // specific and derivedType indicate a specific procedure or derived type
793 // with the same name as this generic. Only one of them may be set in
794 // a scope that declares them, but both can be set during USE association
795 // when generics are combined.
796 Symbol *specific() { return specific_; }
797 const Symbol *specific() const { return specific_; }
798 void set_specific(Symbol &specific);
799 void clear_specific();
800 Symbol *derivedType() { return derivedType_; }
801 const Symbol *derivedType() const { return derivedType_; }
802 void set_derivedType(Symbol &derivedType);
803 void clear_derivedType();
804 void AddUse(const Symbol &);
805
806 // Copy in specificProcs, specific, and derivedType from another generic
807 void CopyFrom(const GenericDetails &);
808
809 // Check that specific is one of the specificProcs. If not, return the
810 // specific as a raw pointer.
811 const Symbol *CheckSpecific() const;
812 Symbol *CheckSpecific();
813
814private:
815 GenericKind kind_;
816 // all of the specific procedures for this generic
817 SymbolVector specificProcs_;
818 std::vector<SourceName> bindingNames_;
819 // Symbols used from other modules merged into this one
820 SymbolVector uses_;
821 // a specific procedure with the same name as this generic, if any
822 Symbol *specific_{nullptr};
823 // a derived type with the same name as this generic, if any
824 Symbol *derivedType_{nullptr};
825};
826llvm::raw_ostream &operator<<(llvm::raw_ostream &, const GenericDetails &);
827
828// Used for OpenMP DECLARE REDUCTION, it holds the information
829// needed to resolve which declaration (there could be multiple
830// with the same name) to use for a given type.
831class UserReductionDetails {
832public:
833 using TypeVector = std::vector<const DeclTypeSpec *>;
834 using DeclVector = std::vector<const parser::OpenMPDeclarativeConstruct *>;
835
836 UserReductionDetails() = default;
837
838 void AddType(const DeclTypeSpec &type) { typeList_.push_back(&type); }
839 const TypeVector &GetTypeList() const { return typeList_; }
840
841 bool SupportsType(const DeclTypeSpec &type) const {
842 // We have to compare the actual type, not the pointer, as some
843 // types are not guaranteed to be the same object.
844 for (auto t : typeList_) {
845 if (*t == type) {
846 return true;
847 }
848 }
849 // For derived and class-derived types, match on the type symbol pointer.
850 if (type.category() == DeclTypeSpec::TypeDerived ||
851 type.category() == DeclTypeSpec::ClassDerived) {
852 const auto &rhs = type.derivedTypeSpec();
853 const auto &rhsSym = rhs.typeSymbol();
854 for (auto t : typeList_) {
855 if (t->category() == DeclTypeSpec::TypeDerived ||
856 t->category() == DeclTypeSpec::ClassDerived) {
857 const auto &lhs = t->derivedTypeSpec();
858 const auto &lhsSym = lhs.typeSymbol();
859 if (&lhsSym == &rhsSym) {
860 return true;
861 }
862 }
863 }
864 }
865 return false;
866 }
867
868 void AddDecl(const parser::OpenMPDeclarativeConstruct *decl) {
869 declList_.emplace_back(decl);
870 }
871 const DeclVector &GetDeclList() const { return declList_; }
872
873private:
874 TypeVector typeList_;
875 DeclVector declList_;
876};
877
878// Used for OpenMP DECLARE MAPPER, it holds the declaration constructs
879// so they can be serialized into module files and later re-parsed when
880// USE-associated.
881class MapperDetails {
882public:
883 using DeclVector = std::vector<const parser::OpenMPDeclarativeConstruct *>;
884
885 MapperDetails() = default;
886
887 void AddDecl(const parser::OpenMPDeclarativeConstruct *decl) {
888 declList_.emplace_back(decl);
889 }
890 const DeclVector &GetDeclList() const { return declList_; }
891
892private:
893 DeclVector declList_;
894};
895
897
898using Details = std::variant<UnknownDetails, MainProgramDetails, ModuleDetails,
904llvm::raw_ostream &operator<<(llvm::raw_ostream &, const Details &);
905std::string DetailsToString(const Details &);
906
907class Symbol {
908public:
909 ENUM_CLASS(Flag,
910 Function, // symbol is a function or statement function
911 Subroutine, // symbol is a subroutine
912 StmtFunction, // symbol is a statement function or result
913 Implicit, // symbol is implicitly typed
914 ImplicitOrError, // symbol must be implicitly typed or it's an error
915 ModFile, // symbol came from .mod file
916 ParentComp, // symbol is the "parent component" of an extended type
917 CrayPointer, CrayPointee,
918 LocalityLocal, // named in LOCAL locality-spec
919 LocalityLocalInit, // named in LOCAL_INIT locality-spec
920 LocalityReduce, // named in REDUCE locality-spec
921 LocalityShared, // named in SHARED locality-spec
922 InDataStmt, // initialized in a DATA statement, =>object, or /init/
923 InNamelist, // in a Namelist group
924 InCommonBlock, // referenced in a common block
925 EntryDummyArgument,
926 CompilerCreated, // A compiler created symbol
927 // For compiler created symbols that are constant but cannot legally have
928 // the PARAMETER attribute.
929 ReadOnly,
930 // OpenACC data-sharing attribute
931 AccPrivate, AccFirstPrivate, AccShared,
932 // OpenACC data-mapping attribute
933 AccCopy, AccCopyIn, AccCopyInReadOnly, AccCopyOut, AccCreate, AccDelete,
934 AccPresent, AccLink, AccDeviceResident, AccDevicePtr, AccUseDevice,
935 // OpenACC declare
936 AccDeclare,
937 // OpenACC declare on allocatable/pointer needs cross-TU action recipes
938 AccDeclareAction,
939 // OpenACC data-movement attribute
940 AccDevice, AccHost, AccSelf,
941 // OpenACC miscellaneous flags
942 AccCommonBlock, AccThreadPrivate, AccReduction, AccNone, AccPreDetermined,
943 // OpenMP data-sharing attribute
944 OmpShared, OmpPrivate, OmpLinear, OmpFirstPrivate, OmpLastPrivate,
945 OmpGroupPrivate,
946 // OpenMP data-mapping attribute
947 OmpMapTo, OmpMapFrom, OmpMapToFrom, OmpMapStorage, OmpMapDelete,
948 OmpUseDevicePtr, OmpUseDeviceAddr, OmpIsDevicePtr, OmpHasDeviceAddr,
949 // OpenMP data-copying attribute
950 OmpCopyIn, OmpCopyPrivate,
951 // OpenMP special variables
952 OmpInVar, OmpOrigVar, OmpOutVar, OmpPrivVar,
953 // OpenMP miscellaneous flags
954 OmpReserved, OmpCommonBlock, OmpReduction, OmpInReduction, OmpAligned,
955 OmpNontemporal, OmpAllocate, OmpDeclarativeAllocateDirective,
956 OmpExecutableAllocateDirective, OmpDeclareSimd, OmpDeclareTarget,
957 OmpThreadprivate, OmpDeclareReduction, OmpFlushed, OmpCriticalLock,
958 OmpIfSpecified, OmpNone, OmpPreDetermined, OmpExplicit, OmpImplicit,
959 OmpDependObject, OmpInclusiveScan, OmpExclusiveScan, OmpInScanReduction,
960 OmpUniform);
962
963 const Scope &owner() const { return *owner_; }
964 const SourceName &name() const { return name_; }
965 Attrs &attrs() { return attrs_; }
966 const Attrs &attrs() const { return attrs_; }
967 Attrs &implicitAttrs() { return implicitAttrs_; }
968 const Attrs &implicitAttrs() const { return implicitAttrs_; }
969 Flags &flags() { return flags_; }
970 const Flags &flags() const { return flags_; }
971 bool test(Flag flag) const { return flags_.test(flag); }
972 void set(Flag flag, bool value = true) { flags_.set(flag, value); }
973 // The Scope introduced by this symbol, if any.
974 Scope *scope() { return scope_; }
975 const Scope *scope() const { return scope_; }
976 void set_scope(Scope *scope) { scope_ = scope; }
977 std::size_t size() const { return size_; }
978 void set_size(std::size_t size) { size_ = size; }
979 std::size_t offset() const { return offset_; }
980 void set_offset(std::size_t offset) { offset_ = offset; }
981 // Give the symbol a name with a different source location but same chars.
982 void ReplaceName(const SourceName &);
983 static std::string OmpFlagToClauseName(Flag ompFlag);
984
985 // Does symbol have this type of details?
986 template <typename D> bool has() const {
987 return std::holds_alternative<D>(details_);
988 }
989
990 // Return a non-owning pointer to details if it is type D, else nullptr.
991 template <typename D> D *detailsIf() { return std::get_if<D>(&details_); }
992 template <typename D> const D *detailsIf() const {
993 return std::get_if<D>(&details_);
994 }
995
996 // Return a reference to the details which must be of type D.
997 template <typename D> D &get() {
998 return const_cast<D &>(const_cast<const Symbol *>(this)->get<D>());
999 }
1000 template <typename D> const D &get() const {
1001 const auto *p{detailsIf<D>()};
1002 CHECK(p);
1003 return *p;
1004 }
1005
1006 Details &details() { return details_; }
1007 const Details &details() const { return details_; }
1008 // Assign the details of the symbol from one of the variants.
1009 // Only allowed in certain cases.
1010 void set_details(Details &&);
1011
1012 // Can the details of this symbol be replaced with the given details?
1013 bool CanReplaceDetails(const Details &details) const;
1014
1015 // Follow use-associations and host-associations to get the ultimate entity.
1016 inline Symbol &GetUltimate();
1017 inline const Symbol &GetUltimate() const;
1018
1019 inline DeclTypeSpec *GetType();
1020 inline const DeclTypeSpec *GetType() const;
1021 void SetType(const DeclTypeSpec &);
1022
1023 const std::string *GetBindName() const;
1024 void SetBindName(std::string &&);
1025 bool GetIsExplicitBindName() const;
1026 void SetIsExplicitBindName(bool);
1027 void SetIsCDefined(bool);
1028 bool IsFuncResult() const;
1029 bool IsObjectArray() const;
1030 const ArraySpec *GetShape() const;
1031 bool IsSubprogram() const;
1032 bool IsFromModFile() const;
1033 bool HasExplicitInterface() const {
1034 return common::visit(
1036 [](const SubprogramDetails &) { return true; },
1037 [](const SubprogramNameDetails &) { return true; },
1038 [&](const ProcEntityDetails &x) {
1039 return attrs_.test(Attr::INTRINSIC) || x.HasExplicitInterface();
1040 },
1041 [](const ProcBindingDetails &x) {
1042 return x.symbol().HasExplicitInterface();
1043 },
1044 [](const UseDetails &x) {
1045 return x.symbol().HasExplicitInterface();
1046 },
1047 [](const HostAssocDetails &x) {
1048 return x.symbol().HasExplicitInterface();
1049 },
1050 [](const GenericDetails &x) {
1051 return x.specific() && x.specific()->HasExplicitInterface();
1052 },
1053 [](const auto &) { return false; },
1054 },
1055 details_);
1056 }
1057 bool HasLocalLocality() const {
1058 return test(Flag::LocalityLocal) || test(Flag::LocalityLocalInit);
1059 }
1060
1061 bool operator==(const Symbol &that) const { return this == &that; }
1062 bool operator!=(const Symbol &that) const { return !(*this == that); }
1063
1064 int Rank() const { return RankImpl(); }
1065 int Corank() const { return CorankImpl(); }
1066
1067 // If there is a parent component, return a pointer to its derived type spec.
1068 // The Scope * argument defaults to this->scope_ but should be overridden
1069 // for a parameterized derived type instantiation with the instance's scope.
1070 const DerivedTypeSpec *GetParentTypeSpec(const Scope * = nullptr) const;
1071
1072 // If a derived type's symbol refers to an extended derived type,
1073 // return the parent component's symbol. The scope of the derived type
1074 // can be overridden.
1075 const Symbol *GetParentComponent(const Scope * = nullptr) const;
1076
1077 SemanticsContext &GetSemanticsContext() const;
1078#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1079 LLVM_DUMP_METHOD void dump() const;
1080#endif
1081
1082private:
1083 const Scope *owner_;
1084 SourceName name_;
1085 Attrs attrs_;
1086 Attrs implicitAttrs_; // subset of attrs_ that were not explicit
1087 Flags flags_;
1088 Scope *scope_{nullptr};
1089 std::size_t size_{0}; // size in bytes
1090 std::size_t offset_{0}; // byte offset in scope or common block
1091 Details details_;
1092
1093 Symbol() {} // only created in class Symbols
1094 std::string GetDetailsName() const;
1095 friend llvm::raw_ostream &operator<<(llvm::raw_ostream &, const Symbol &);
1096 friend llvm::raw_ostream &DumpForUnparse(
1097 llvm::raw_ostream &, const Symbol &, bool);
1098
1099 static constexpr int startRecursionDepth{100};
1100
1101 inline const DeclTypeSpec *GetTypeImpl(int depth = startRecursionDepth) const;
1102 inline int RankImpl(int depth = startRecursionDepth) const {
1103 if (depth-- == 0) {
1104 return 0;
1105 }
1106 return common::visit(
1108 [&](const SubprogramDetails &sd) {
1109 return sd.isFunction() ? sd.result().RankImpl(depth) : 0;
1110 },
1111 [](const GenericDetails &) {
1112 return 0; /*TODO*/
1113 },
1114 [&](const ProcBindingDetails &x) {
1115 return x.symbol().RankImpl(depth);
1116 },
1117 [&](const UseDetails &x) { return x.symbol().RankImpl(depth); },
1118 [&](const HostAssocDetails &x) {
1119 return x.symbol().RankImpl(depth);
1120 },
1121 [](const ObjectEntityDetails &oed) { return oed.shape().Rank(); },
1122 [&](const ProcEntityDetails &ped) {
1123 const Symbol *iface{ped.procInterface()};
1124 return iface ? iface->RankImpl(depth) : 0;
1125 },
1126 [](const AssocEntityDetails &aed) {
1127 if (auto assocRank{aed.rank()}) {
1128 // RANK(n) & RANK(*)
1129 return *assocRank;
1130 } else if (aed.IsAssumedRank()) {
1131 // RANK DEFAULT
1132 return 0;
1133 } else if (const auto &expr{aed.expr()}) {
1134 return expr->Rank();
1135 } else {
1136 return 0;
1137 }
1138 },
1139 [](const auto &) { return 0; },
1140 },
1141 details_);
1142 }
1143 inline int CorankImpl(int depth = startRecursionDepth) const {
1144 if (depth-- == 0) {
1145 return 0;
1146 }
1147 return common::visit(
1149 [&](const SubprogramDetails &sd) {
1150 return sd.isFunction() ? sd.result().CorankImpl(depth) : 0;
1151 },
1152 [](const GenericDetails &) { return 0; },
1153 [&](const ProcEntityDetails &ped) {
1154 const Symbol *iface{ped.procInterface()};
1155 return iface ? iface->CorankImpl(depth) : 0;
1156 },
1157 [&](const UseDetails &x) { return x.symbol().CorankImpl(depth); },
1158 [&](const HostAssocDetails &x) {
1159 return x.symbol().CorankImpl(depth);
1160 },
1161 [](const ObjectEntityDetails &oed) { return oed.coshape().Rank(); },
1162 [](const AssocEntityDetails &aed) {
1163 return aed.expr() ? aed.expr()->Corank() : 0;
1164 },
1165 [](const auto &) { return 0; },
1166 },
1167 details_);
1168 }
1169 template <std::size_t> friend class Symbols;
1170 template <class, std::size_t> friend class std::array;
1171};
1172
1173llvm::raw_ostream &operator<<(llvm::raw_ostream &, Symbol::Flag);
1174
1175// Manage memory for all symbols. BLOCK_SIZE symbols at a time are allocated.
1176// Make() returns a reference to the next available one. They are never
1177// deleted.
1178template <std::size_t BLOCK_SIZE> class Symbols {
1179public:
1180 Symbol &Make(const Scope &owner, const SourceName &name, const Attrs &attrs,
1181 Details &&details) {
1182 Symbol &symbol = Get();
1183 symbol.owner_ = &owner;
1184 symbol.name_ = name;
1185 symbol.attrs_ = attrs;
1186 symbol.details_ = std::move(details);
1187 return symbol;
1188 }
1189
1190private:
1191 using blockType = std::array<Symbol, BLOCK_SIZE>;
1192 std::list<blockType *> blocks_;
1193 std::size_t nextIndex_{0};
1194 blockType *currBlock_{nullptr};
1195
1196 Symbol &Get() {
1197 if (nextIndex_ == 0) {
1198 blocks_.push_back(new blockType());
1199 currBlock_ = blocks_.back();
1200 }
1201 Symbol &result = (*currBlock_)[nextIndex_];
1202 if (++nextIndex_ >= BLOCK_SIZE) {
1203 nextIndex_ = 0; // allocate a new block next time
1204 }
1205 return result;
1206 }
1207};
1208
1209// Define a few member functions here in the header so that they
1210// can be used by lib/Evaluate without inducing a dependence cycle
1211// between the two shared libraries.
1212
1213inline bool ProcEntityDetails::HasExplicitInterface() const {
1214 return procInterface_ && procInterface_->HasExplicitInterface();
1215}
1216
1217inline Symbol &Symbol::GetUltimate() {
1218 return const_cast<Symbol &>(const_cast<const Symbol *>(this)->GetUltimate());
1219}
1220inline const Symbol &Symbol::GetUltimate() const {
1221 if (const auto *details{detailsIf<UseDetails>()}) {
1222 return details->symbol().GetUltimate();
1223 } else if (const auto *details{detailsIf<HostAssocDetails>()}) {
1224 return details->symbol().GetUltimate();
1225 } else {
1226 return *this;
1227 }
1228}
1229
1230inline DeclTypeSpec *Symbol::GetType() {
1231 return const_cast<DeclTypeSpec *>(
1232 const_cast<const Symbol *>(this)->GetType());
1233}
1234
1235inline const DeclTypeSpec *Symbol::GetTypeImpl(int depth) const {
1236 if (depth-- == 0) {
1237 return nullptr;
1238 }
1239 return common::visit(
1240 common::visitors{
1241 [](const EntityDetails &x) { return x.type(); },
1242 [](const ObjectEntityDetails &x) { return x.type(); },
1243 [](const AssocEntityDetails &x) { return x.type(); },
1244 [&](const SubprogramDetails &x) {
1245 return x.isFunction() ? x.result().GetTypeImpl(depth) : nullptr;
1246 },
1247 [&](const ProcEntityDetails &x) {
1248 const Symbol *symbol{x.procInterface()};
1249 return symbol ? symbol->GetTypeImpl(depth) : x.type();
1250 },
1251 [&](const ProcBindingDetails &x) {
1252 return x.symbol().GetTypeImpl(depth);
1253 },
1254 [](const TypeParamDetails &x) { return x.type(); },
1255 [&](const UseDetails &x) { return x.symbol().GetTypeImpl(depth); },
1256 [&](const HostAssocDetails &x) {
1257 return x.symbol().GetTypeImpl(depth);
1258 },
1259 [&](const GenericDetails &x) {
1260 return x.specific() ? x.specific()->GetTypeImpl(depth) : nullptr;
1261 },
1262 [](const auto &) -> const DeclTypeSpec * { return nullptr; },
1263 },
1264 details_);
1265}
1266
1267inline const DeclTypeSpec *Symbol::GetType() const { return GetTypeImpl(); }
1268
1269// Defined here, where Symbol is a complete type, so that it can be inlined
1270// into FortranEvaluate without that library needing to link FortranSemantics.
1271inline const Scope *DerivedTypeSpec::GetScope() const {
1272 return scope_ ? scope_ : typeSymbol_.scope();
1273}
1274
1275// Sets and maps keyed by Symbols
1276
1278 bool operator()(const SymbolRef &x, const SymbolRef &y) const {
1279 return &*x < &*y;
1280 }
1281 bool operator()(const MutableSymbolRef &x, const MutableSymbolRef &y) const {
1282 return &*x < &*y;
1283 }
1284};
1285
1286// Symbol comparison is usually based on the order of cooked source
1287// stream creation and, when both are from the same cooked source,
1288// their positions in that cooked source stream.
1289// Don't use this comparator or SourceOrderedSymbolSet to hold
1290// Symbols that might be subject to ReplaceName().
1292 // These functions are implemented in Evaluate/tools.cpp to
1293 // satisfy complicated shared library interdependency.
1294 bool operator()(const SymbolRef &, const SymbolRef &) const;
1295 bool operator()(const MutableSymbolRef &, const MutableSymbolRef &) const;
1296};
1297
1299 bool operator()(const SymbolRef &, const SymbolRef &) const;
1300 bool operator()(const MutableSymbolRef &, const MutableSymbolRef &) const;
1301};
1302
1303using UnorderedSymbolSet = std::set<SymbolRef, SymbolAddressCompare>;
1304using SourceOrderedSymbolSet = std::set<SymbolRef, SymbolSourcePositionCompare>;
1305
1306template <typename A>
1307SourceOrderedSymbolSet OrderBySourcePosition(const A &container) {
1308 SourceOrderedSymbolSet result;
1309 for (SymbolRef x : container) {
1310 result.emplace(x);
1311 }
1312 return result;
1313}
1314
1315} // namespace Fortran::semantics
1316
1317// Define required info so that SymbolRef can be used inside llvm::DenseMap.
1318namespace llvm {
1319template <> struct DenseMapInfo<Fortran::semantics::SymbolRef> {
1320 static unsigned getHashValue(const Fortran::semantics::SymbolRef &sym) {
1321 return DenseMapInfo<const Fortran::semantics::Symbol *>::getHashValue(
1322 &sym.get());
1323 }
1324
1325 static bool isEqual(const Fortran::semantics::SymbolRef &LHS,
1326 const Fortran::semantics::SymbolRef &RHS) {
1327 return LHS == RHS;
1328 }
1329};
1330} // namespace llvm
1331#endif // FORTRAN_SEMANTICS_SYMBOL_H_
Definition enum-set.h:28
Definition reference.h:18
Definition char-block.h:26
Definition type.h:63
Definition symbol.h:367
Definition symbol.h:780
Definition symbol.h:881
Definition symbol.h:684
Definition symbol.h:128
Definition program-tree.h:31
Definition scope.h:68
Definition symbol.h:907
Definition symbol.h:1178
Definition symbol.h:896
Definition symbol.h:718
Definition symbol.h:158
Definition symbol.h:501
Definition check-expression.h:19
Definition bit-population-count.h:20
Definition idioms.h:60
Definition parse-tree.h:1737
Definition type.h:239
Definition symbol.h:757
Definition omp-declare-variant.h:25