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