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