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