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
781
782using Details = std::variant<UnknownDetails, MainProgramDetails, ModuleDetails,
788llvm::raw_ostream &operator<<(llvm::raw_ostream &, const Details &);
789std::string DetailsToString(const Details &);
790
791class Symbol {
792public:
793 ENUM_CLASS(Flag,
794 Function, // symbol is a function or statement function
795 Subroutine, // symbol is a subroutine
796 StmtFunction, // symbol is a statement function or result
797 Implicit, // symbol is implicitly typed
798 ImplicitOrError, // symbol must be implicitly typed or it's an error
799 ModFile, // symbol came from .mod file
800 ParentComp, // symbol is the "parent component" of an extended type
801 CrayPointer, CrayPointee,
802 LocalityLocal, // named in LOCAL locality-spec
803 LocalityLocalInit, // named in LOCAL_INIT locality-spec
804 LocalityReduce, // named in REDUCE locality-spec
805 LocalityShared, // named in SHARED locality-spec
806 InDataStmt, // initialized in a DATA statement, =>object, or /init/
807 InNamelist, // in a Namelist group
808 InCommonBlock, // referenced in a common block
809 EntryDummyArgument,
810 CompilerCreated, // A compiler created symbol
811 // For compiler created symbols that are constant but cannot legally have
812 // the PARAMETER attribute.
813 ReadOnly,
814 // OpenACC data-sharing attribute
815 AccPrivate, AccFirstPrivate, AccShared,
816 // OpenACC data-mapping attribute
817 AccCopy, AccCopyIn, AccCopyInReadOnly, AccCopyOut, AccCreate, AccDelete,
818 AccPresent, AccLink, AccDeviceResident, AccDevicePtr, AccUseDevice,
819 // OpenACC declare
820 AccDeclare,
821 // OpenACC data-movement attribute
822 AccDevice, AccHost, AccSelf,
823 // OpenACC miscellaneous flags
824 AccCommonBlock, AccThreadPrivate, AccReduction, AccNone, AccPreDetermined,
825 // OpenMP data-sharing attribute
826 OmpShared, OmpPrivate, OmpLinear, OmpFirstPrivate, OmpLastPrivate,
827 OmpGroupPrivate,
828 // OpenMP data-mapping attribute
829 OmpMapTo, OmpMapFrom, OmpMapToFrom, OmpMapStorage, OmpMapDelete,
830 OmpUseDevicePtr, OmpUseDeviceAddr, OmpIsDevicePtr, OmpHasDeviceAddr,
831 // OpenMP data-copying attribute
832 OmpCopyIn, OmpCopyPrivate,
833 // OpenMP miscellaneous flags
834 OmpCommonBlock, OmpReduction, OmpInReduction, OmpAligned, OmpNontemporal,
835 OmpAllocate, OmpDeclarativeAllocateDirective,
836 OmpExecutableAllocateDirective, OmpDeclareSimd, OmpDeclareTarget,
837 OmpThreadprivate, OmpDeclareReduction, OmpFlushed, OmpCriticalLock,
838 OmpIfSpecified, OmpNone, OmpPreDetermined, OmpExplicit, OmpImplicit,
839 OmpDependObject, OmpInclusiveScan, OmpExclusiveScan, OmpInScanReduction,
840 OmpUniform);
842
843 const Scope &owner() const { return *owner_; }
844 const SourceName &name() const { return name_; }
845 Attrs &attrs() { return attrs_; }
846 const Attrs &attrs() const { return attrs_; }
847 Attrs &implicitAttrs() { return implicitAttrs_; }
848 const Attrs &implicitAttrs() const { return implicitAttrs_; }
849 Flags &flags() { return flags_; }
850 const Flags &flags() const { return flags_; }
851 bool test(Flag flag) const { return flags_.test(flag); }
852 void set(Flag flag, bool value = true) { flags_.set(flag, value); }
853 // The Scope introduced by this symbol, if any.
854 Scope *scope() { return scope_; }
855 const Scope *scope() const { return scope_; }
856 void set_scope(Scope *scope) { scope_ = scope; }
857 std::size_t size() const { return size_; }
858 void set_size(std::size_t size) { size_ = size; }
859 std::size_t offset() const { return offset_; }
860 void set_offset(std::size_t offset) { offset_ = offset; }
861 // Give the symbol a name with a different source location but same chars.
862 void ReplaceName(const SourceName &);
863 static std::string OmpFlagToClauseName(Flag ompFlag);
864
865 // Does symbol have this type of details?
866 template <typename D> bool has() const {
867 return std::holds_alternative<D>(details_);
868 }
869
870 // Return a non-owning pointer to details if it is type D, else nullptr.
871 template <typename D> D *detailsIf() { return std::get_if<D>(&details_); }
872 template <typename D> const D *detailsIf() const {
873 return std::get_if<D>(&details_);
874 }
875
876 // Return a reference to the details which must be of type D.
877 template <typename D> D &get() {
878 return const_cast<D &>(const_cast<const Symbol *>(this)->get<D>());
879 }
880 template <typename D> const D &get() const {
881 const auto *p{detailsIf<D>()};
882 CHECK(p);
883 return *p;
884 }
885
886 Details &details() { return details_; }
887 const Details &details() const { return details_; }
888 // Assign the details of the symbol from one of the variants.
889 // Only allowed in certain cases.
890 void set_details(Details &&);
891
892 // Can the details of this symbol be replaced with the given details?
893 bool CanReplaceDetails(const Details &details) const;
894
895 // Follow use-associations and host-associations to get the ultimate entity.
896 inline Symbol &GetUltimate();
897 inline const Symbol &GetUltimate() const;
898
899 inline DeclTypeSpec *GetType();
900 inline const DeclTypeSpec *GetType() const;
901 void SetType(const DeclTypeSpec &);
902
903 const std::string *GetBindName() const;
904 void SetBindName(std::string &&);
905 bool GetIsExplicitBindName() const;
906 void SetIsExplicitBindName(bool);
907 void SetIsCDefined(bool);
908 bool IsFuncResult() const;
909 bool IsObjectArray() const;
910 const ArraySpec *GetShape() const;
911 bool IsSubprogram() const;
912 bool IsFromModFile() const;
913 bool HasExplicitInterface() const {
914 return common::visit(
916 [](const SubprogramDetails &) { return true; },
917 [](const SubprogramNameDetails &) { return true; },
918 [&](const ProcEntityDetails &x) {
919 return attrs_.test(Attr::INTRINSIC) || x.HasExplicitInterface();
920 },
921 [](const ProcBindingDetails &x) {
922 return x.symbol().HasExplicitInterface();
923 },
924 [](const UseDetails &x) {
925 return x.symbol().HasExplicitInterface();
926 },
927 [](const HostAssocDetails &x) {
928 return x.symbol().HasExplicitInterface();
929 },
930 [](const GenericDetails &x) {
931 return x.specific() && x.specific()->HasExplicitInterface();
932 },
933 [](const auto &) { return false; },
934 },
935 details_);
936 }
937 bool HasLocalLocality() const {
938 return test(Flag::LocalityLocal) || test(Flag::LocalityLocalInit);
939 }
940
941 bool operator==(const Symbol &that) const { return this == &that; }
942 bool operator!=(const Symbol &that) const { return !(*this == that); }
943
944 int Rank() const { return RankImpl(); }
945 int Corank() const { return CorankImpl(); }
946
947 // If there is a parent component, return a pointer to its derived type spec.
948 // The Scope * argument defaults to this->scope_ but should be overridden
949 // for a parameterized derived type instantiation with the instance's scope.
950 const DerivedTypeSpec *GetParentTypeSpec(const Scope * = nullptr) const;
951
952 // If a derived type's symbol refers to an extended derived type,
953 // return the parent component's symbol. The scope of the derived type
954 // can be overridden.
955 const Symbol *GetParentComponent(const Scope * = nullptr) const;
956
957 SemanticsContext &GetSemanticsContext() const;
958#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
959 LLVM_DUMP_METHOD void dump() const;
960#endif
961
962private:
963 const Scope *owner_;
964 SourceName name_;
965 Attrs attrs_;
966 Attrs implicitAttrs_; // subset of attrs_ that were not explicit
967 Flags flags_;
968 Scope *scope_{nullptr};
969 std::size_t size_{0}; // size in bytes
970 std::size_t offset_{0}; // byte offset in scope or common block
971 Details details_;
972
973 Symbol() {} // only created in class Symbols
974 std::string GetDetailsName() const;
975 friend llvm::raw_ostream &operator<<(llvm::raw_ostream &, const Symbol &);
976 friend llvm::raw_ostream &DumpForUnparse(
977 llvm::raw_ostream &, const Symbol &, bool);
978
979 static constexpr int startRecursionDepth{100};
980
981 inline const DeclTypeSpec *GetTypeImpl(int depth = startRecursionDepth) const;
982 inline int RankImpl(int depth = startRecursionDepth) const {
983 if (depth-- == 0) {
984 return 0;
985 }
986 return common::visit(
988 [&](const SubprogramDetails &sd) {
989 return sd.isFunction() ? sd.result().RankImpl(depth) : 0;
990 },
991 [](const GenericDetails &) {
992 return 0; /*TODO*/
993 },
994 [&](const ProcBindingDetails &x) {
995 return x.symbol().RankImpl(depth);
996 },
997 [&](const UseDetails &x) { return x.symbol().RankImpl(depth); },
998 [&](const HostAssocDetails &x) {
999 return x.symbol().RankImpl(depth);
1000 },
1001 [](const ObjectEntityDetails &oed) { return oed.shape().Rank(); },
1002 [&](const ProcEntityDetails &ped) {
1003 const Symbol *iface{ped.procInterface()};
1004 return iface ? iface->RankImpl(depth) : 0;
1005 },
1006 [](const AssocEntityDetails &aed) {
1007 if (auto assocRank{aed.rank()}) {
1008 // RANK(n) & RANK(*)
1009 return *assocRank;
1010 } else if (aed.IsAssumedRank()) {
1011 // RANK DEFAULT
1012 return 0;
1013 } else if (const auto &expr{aed.expr()}) {
1014 return expr->Rank();
1015 } else {
1016 return 0;
1017 }
1018 },
1019 [](const auto &) { return 0; },
1020 },
1021 details_);
1022 }
1023 inline int CorankImpl(int depth = startRecursionDepth) const {
1024 if (depth-- == 0) {
1025 return 0;
1026 }
1027 return common::visit(
1029 [&](const SubprogramDetails &sd) {
1030 return sd.isFunction() ? sd.result().CorankImpl(depth) : 0;
1031 },
1032 [](const GenericDetails &) { return 0; },
1033 [&](const ProcEntityDetails &ped) {
1034 const Symbol *iface{ped.procInterface()};
1035 return iface ? iface->CorankImpl(depth) : 0;
1036 },
1037 [&](const UseDetails &x) { return x.symbol().CorankImpl(depth); },
1038 [&](const HostAssocDetails &x) {
1039 return x.symbol().CorankImpl(depth);
1040 },
1041 [](const ObjectEntityDetails &oed) { return oed.coshape().Rank(); },
1042 [](const AssocEntityDetails &aed) {
1043 return aed.expr() ? aed.expr()->Corank() : 0;
1044 },
1045 [](const auto &) { return 0; },
1046 },
1047 details_);
1048 }
1049 template <std::size_t> friend class Symbols;
1050 template <class, std::size_t> friend class std::array;
1051};
1052
1053llvm::raw_ostream &operator<<(llvm::raw_ostream &, Symbol::Flag);
1054
1055// Manage memory for all symbols. BLOCK_SIZE symbols at a time are allocated.
1056// Make() returns a reference to the next available one. They are never
1057// deleted.
1058template <std::size_t BLOCK_SIZE> class Symbols {
1059public:
1060 Symbol &Make(const Scope &owner, const SourceName &name, const Attrs &attrs,
1061 Details &&details) {
1062 Symbol &symbol = Get();
1063 symbol.owner_ = &owner;
1064 symbol.name_ = name;
1065 symbol.attrs_ = attrs;
1066 symbol.details_ = std::move(details);
1067 return symbol;
1068 }
1069
1070private:
1071 using blockType = std::array<Symbol, BLOCK_SIZE>;
1072 std::list<blockType *> blocks_;
1073 std::size_t nextIndex_{0};
1074 blockType *currBlock_{nullptr};
1075
1076 Symbol &Get() {
1077 if (nextIndex_ == 0) {
1078 blocks_.push_back(new blockType());
1079 currBlock_ = blocks_.back();
1080 }
1081 Symbol &result = (*currBlock_)[nextIndex_];
1082 if (++nextIndex_ >= BLOCK_SIZE) {
1083 nextIndex_ = 0; // allocate a new block next time
1084 }
1085 return result;
1086 }
1087};
1088
1089// Define a few member functions here in the header so that they
1090// can be used by lib/Evaluate without inducing a dependence cycle
1091// between the two shared libraries.
1092
1093inline bool ProcEntityDetails::HasExplicitInterface() const {
1094 return procInterface_ && procInterface_->HasExplicitInterface();
1095}
1096
1097inline Symbol &Symbol::GetUltimate() {
1098 return const_cast<Symbol &>(const_cast<const Symbol *>(this)->GetUltimate());
1099}
1100inline const Symbol &Symbol::GetUltimate() const {
1101 if (const auto *details{detailsIf<UseDetails>()}) {
1102 return details->symbol().GetUltimate();
1103 } else if (const auto *details{detailsIf<HostAssocDetails>()}) {
1104 return details->symbol().GetUltimate();
1105 } else {
1106 return *this;
1107 }
1108}
1109
1110inline DeclTypeSpec *Symbol::GetType() {
1111 return const_cast<DeclTypeSpec *>(
1112 const_cast<const Symbol *>(this)->GetType());
1113}
1114
1115inline const DeclTypeSpec *Symbol::GetTypeImpl(int depth) const {
1116 if (depth-- == 0) {
1117 return nullptr;
1118 }
1119 return common::visit(
1120 common::visitors{
1121 [](const EntityDetails &x) { return x.type(); },
1122 [](const ObjectEntityDetails &x) { return x.type(); },
1123 [](const AssocEntityDetails &x) { return x.type(); },
1124 [&](const SubprogramDetails &x) {
1125 return x.isFunction() ? x.result().GetTypeImpl(depth) : nullptr;
1126 },
1127 [&](const ProcEntityDetails &x) {
1128 const Symbol *symbol{x.procInterface()};
1129 return symbol ? symbol->GetTypeImpl(depth) : x.type();
1130 },
1131 [&](const ProcBindingDetails &x) {
1132 return x.symbol().GetTypeImpl(depth);
1133 },
1134 [](const TypeParamDetails &x) { return x.type(); },
1135 [&](const UseDetails &x) { return x.symbol().GetTypeImpl(depth); },
1136 [&](const HostAssocDetails &x) {
1137 return x.symbol().GetTypeImpl(depth);
1138 },
1139 [&](const GenericDetails &x) {
1140 return x.specific() ? x.specific()->GetTypeImpl(depth) : nullptr;
1141 },
1142 [](const auto &) -> const DeclTypeSpec * { return nullptr; },
1143 },
1144 details_);
1145}
1146
1147inline const DeclTypeSpec *Symbol::GetType() const { return GetTypeImpl(); }
1148
1149// Sets and maps keyed by Symbols
1150
1152 bool operator()(const SymbolRef &x, const SymbolRef &y) const {
1153 return &*x < &*y;
1154 }
1155 bool operator()(const MutableSymbolRef &x, const MutableSymbolRef &y) const {
1156 return &*x < &*y;
1157 }
1158};
1159
1160// Symbol comparison is usually based on the order of cooked source
1161// stream creation and, when both are from the same cooked source,
1162// their positions in that cooked source stream.
1163// Don't use this comparator or SourceOrderedSymbolSet to hold
1164// Symbols that might be subject to ReplaceName().
1166 // These functions are implemented in Evaluate/tools.cpp to
1167 // satisfy complicated shared library interdependency.
1168 bool operator()(const SymbolRef &, const SymbolRef &) const;
1169 bool operator()(const MutableSymbolRef &, const MutableSymbolRef &) const;
1170};
1171
1173 bool operator()(const SymbolRef &, const SymbolRef &) const;
1174 bool operator()(const MutableSymbolRef &, const MutableSymbolRef &) const;
1175};
1176
1177using UnorderedSymbolSet = std::set<SymbolRef, SymbolAddressCompare>;
1178using SourceOrderedSymbolSet = std::set<SymbolRef, SymbolSourcePositionCompare>;
1179
1180template <typename A>
1181SourceOrderedSymbolSet OrderBySourcePosition(const A &container) {
1182 SourceOrderedSymbolSet result;
1183 for (SymbolRef x : container) {
1184 result.emplace(x);
1185 }
1186 return result;
1187}
1188
1189} // namespace Fortran::semantics
1190
1191// Define required info so that SymbolRef can be used inside llvm::DenseMap.
1192namespace llvm {
1193template <> struct DenseMapInfo<Fortran::semantics::SymbolRef> {
1194 static inline Fortran::semantics::SymbolRef getEmptyKey() {
1195 auto ptr = DenseMapInfo<const Fortran::semantics::Symbol *>::getEmptyKey();
1196 return *reinterpret_cast<Fortran::semantics::SymbolRef *>(&ptr);
1197 }
1198
1199 static inline Fortran::semantics::SymbolRef getTombstoneKey() {
1200 auto ptr =
1201 DenseMapInfo<const Fortran::semantics::Symbol *>::getTombstoneKey();
1202 return *reinterpret_cast<Fortran::semantics::SymbolRef *>(&ptr);
1203 }
1204
1205 static unsigned getHashValue(const Fortran::semantics::SymbolRef &sym) {
1206 return DenseMapInfo<const Fortran::semantics::Symbol *>::getHashValue(
1207 &sym.get());
1208 }
1209
1210 static bool isEqual(const Fortran::semantics::SymbolRef &LHS,
1211 const Fortran::semantics::SymbolRef &RHS) {
1212 return LHS == RHS;
1213 }
1214};
1215} // namespace llvm
1216#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:602
Definition symbol.h:85
Definition program-tree.h:31
Definition scope.h:58
Definition symbol.h:791
Definition symbol.h:1058
Definition symbol.h:780
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:1702
Definition type.h:240
Definition symbol.h:675