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