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