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