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