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