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 "llvm/ADT/DenseMapInfo.h"
18 
19 #include <array>
20 #include <functional>
21 #include <list>
22 #include <optional>
23 #include <set>
24 #include <vector>
25 
26 namespace llvm {
27 class raw_ostream;
28 }
29 namespace Fortran::parser {
30 struct Expr;
31 }
32 
33 namespace Fortran::semantics {
34 
35 /// A Symbol consists of common information (name, owner, and attributes)
36 /// and details information specific to the kind of symbol, represented by the
37 /// *Details classes.
38 
39 class Scope;
40 class Symbol;
41 class ProgramTree;
42 
43 using SymbolRef = common::Reference<const Symbol>;
44 using SymbolVector = std::vector<SymbolRef>;
45 using MutableSymbolRef = common::Reference<Symbol>;
46 using MutableSymbolVector = std::vector<MutableSymbolRef>;
47 
48 // A module or submodule.
49 class ModuleDetails {
50 public:
51   ModuleDetails(bool isSubmodule = false) : isSubmodule_{isSubmodule} {}
isSubmodule()52   bool isSubmodule() const { return isSubmodule_; }
scope()53   const Scope *scope() const { return scope_; }
54   const Scope *ancestor() const; // for submodule; nullptr for module
55   const Scope *parent() const; // for submodule; nullptr for module
56   void set_scope(const Scope *);
57 
58 private:
59   bool isSubmodule_;
60   const Scope *scope_{nullptr};
61 };
62 
63 class MainProgramDetails {
64 public:
65 private:
66 };
67 
68 class WithBindName {
69 public:
bindName()70   const std::string *bindName() const {
71     return bindName_ ? &*bindName_ : nullptr;
72   }
set_bindName(std::string && name)73   void set_bindName(std::string &&name) { bindName_ = std::move(name); }
74 
75 private:
76   std::optional<std::string> bindName_;
77 };
78 
79 // A subroutine or function definition, or a subprogram interface defined
80 // in an INTERFACE block as part of the definition of a dummy procedure
81 // or a procedure pointer (with just POINTER).
82 class SubprogramDetails : public WithBindName {
83 public:
isFunction()84   bool isFunction() const { return result_ != nullptr; }
isInterface()85   bool isInterface() const { return isInterface_; }
86   void set_isInterface(bool value = true) { isInterface_ = value; }
isDummy()87   bool isDummy() const { return isDummy_; }
88   void set_isDummy(bool value = true) { isDummy_ = value; }
entryScope()89   Scope *entryScope() { return entryScope_; }
entryScope()90   const Scope *entryScope() const { return entryScope_; }
set_entryScope(Scope & scope)91   void set_entryScope(Scope &scope) { entryScope_ = &scope; }
result()92   const Symbol &result() const {
93     CHECK(isFunction());
94     return *result_;
95   }
set_result(Symbol & result)96   void set_result(Symbol &result) {
97     CHECK(!result_);
98     result_ = &result;
99   }
dummyArgs()100   const std::vector<Symbol *> &dummyArgs() const { return dummyArgs_; }
add_dummyArg(Symbol & symbol)101   void add_dummyArg(Symbol &symbol) { dummyArgs_.push_back(&symbol); }
add_alternateReturn()102   void add_alternateReturn() { dummyArgs_.push_back(nullptr); }
stmtFunction()103   const MaybeExpr &stmtFunction() const { return stmtFunction_; }
set_stmtFunction(SomeExpr && expr)104   void set_stmtFunction(SomeExpr &&expr) { stmtFunction_ = std::move(expr); }
moduleInterface()105   Symbol *moduleInterface() { return moduleInterface_; }
moduleInterface()106   const Symbol *moduleInterface() const { return moduleInterface_; }
107   void set_moduleInterface(Symbol &);
108 
109 private:
110   bool isInterface_{false}; // true if this represents an interface-body
111   bool isDummy_{false}; // true when interface of dummy procedure
112   std::vector<Symbol *> dummyArgs_; // nullptr -> alternate return indicator
113   Symbol *result_{nullptr};
114   Scope *entryScope_{nullptr}; // if ENTRY, points to subprogram's scope
115   MaybeExpr stmtFunction_;
116   // For MODULE FUNCTION or SUBROUTINE, this is the symbol of its declared
117   // interface.  For MODULE PROCEDURE, this is the declared interface if it
118   // appeared in an ancestor (sub)module.
119   Symbol *moduleInterface_{nullptr};
120 
121   friend llvm::raw_ostream &operator<<(
122       llvm::raw_ostream &, const SubprogramDetails &);
123 };
124 
125 // For SubprogramNameDetails, the kind indicates whether it is the name
126 // of a module subprogram or an internal subprogram or ENTRY.
ENUM_CLASS(SubprogramKind,Module,Internal)127 ENUM_CLASS(SubprogramKind, Module, Internal)
128 
129 // Symbol with SubprogramNameDetails is created when we scan for module and
130 // internal procedure names, to record that there is a subprogram with this
131 // name. Later they are replaced by SubprogramDetails with dummy and result
132 // type information.
133 class SubprogramNameDetails {
134 public:
135   SubprogramNameDetails(SubprogramKind kind, ProgramTree &node)
136       : kind_{kind}, node_{node} {}
137   SubprogramNameDetails() = delete;
138   SubprogramKind kind() const { return kind_; }
139   ProgramTree &node() const { return *node_; }
140 
141 private:
142   SubprogramKind kind_;
143   common::Reference<ProgramTree> node_;
144 };
145 
146 // A name from an entity-decl -- could be object or function.
147 class EntityDetails : public WithBindName {
148 public:
149   explicit EntityDetails(bool isDummy = false) : isDummy_{isDummy} {}
type()150   const DeclTypeSpec *type() const { return type_; }
151   void set_type(const DeclTypeSpec &);
152   void ReplaceType(const DeclTypeSpec &);
isDummy()153   bool isDummy() const { return isDummy_; }
154   void set_isDummy(bool value = true) { isDummy_ = value; }
isFuncResult()155   bool isFuncResult() const { return isFuncResult_; }
set_funcResult(bool x)156   void set_funcResult(bool x) { isFuncResult_ = x; }
157 
158 private:
159   bool isDummy_{false};
160   bool isFuncResult_{false};
161   const DeclTypeSpec *type_{nullptr};
162   friend llvm::raw_ostream &operator<<(
163       llvm::raw_ostream &, const EntityDetails &);
164 };
165 
166 // Symbol is associated with a name or expression in a SELECT TYPE or ASSOCIATE.
167 class AssocEntityDetails : public EntityDetails {
168 public:
AssocEntityDetails()169   AssocEntityDetails() {}
AssocEntityDetails(SomeExpr && expr)170   explicit AssocEntityDetails(SomeExpr &&expr) : expr_{std::move(expr)} {}
171   AssocEntityDetails(const AssocEntityDetails &) = default;
172   AssocEntityDetails(AssocEntityDetails &&) = default;
173   AssocEntityDetails &operator=(const AssocEntityDetails &) = default;
174   AssocEntityDetails &operator=(AssocEntityDetails &&) = default;
expr()175   const MaybeExpr &expr() const { return expr_; }
176   void set_rank(int rank);
rank()177   std::optional<int> rank() const { return rank_; }
178 
179 private:
180   MaybeExpr expr_;
181   std::optional<int> rank_;
182 };
183 llvm::raw_ostream &operator<<(llvm::raw_ostream &, const AssocEntityDetails &);
184 
185 // An entity known to be an object.
186 class ObjectEntityDetails : public EntityDetails {
187 public:
188   explicit ObjectEntityDetails(EntityDetails &&);
189   ObjectEntityDetails(const ObjectEntityDetails &) = default;
190   ObjectEntityDetails &operator=(const ObjectEntityDetails &) = default;
EntityDetails(isDummy)191   ObjectEntityDetails(bool isDummy = false) : EntityDetails(isDummy) {}
init()192   MaybeExpr &init() { return init_; }
init()193   const MaybeExpr &init() const { return init_; }
set_init(MaybeExpr && expr)194   void set_init(MaybeExpr &&expr) { init_ = std::move(expr); }
unanalyzedPDTComponentInit()195   const parser::Expr *unanalyzedPDTComponentInit() const {
196     return unanalyzedPDTComponentInit_;
197   }
set_unanalyzedPDTComponentInit(const parser::Expr * expr)198   void set_unanalyzedPDTComponentInit(const parser::Expr *expr) {
199     unanalyzedPDTComponentInit_ = expr;
200   }
shape()201   ArraySpec &shape() { return shape_; }
shape()202   const ArraySpec &shape() const { return shape_; }
coshape()203   ArraySpec &coshape() { return coshape_; }
coshape()204   const ArraySpec &coshape() const { return coshape_; }
205   void set_shape(const ArraySpec &);
206   void set_coshape(const ArraySpec &);
commonBlock()207   const Symbol *commonBlock() const { return commonBlock_; }
set_commonBlock(const Symbol & commonBlock)208   void set_commonBlock(const Symbol &commonBlock) {
209     commonBlock_ = &commonBlock;
210   }
IsArray()211   bool IsArray() const { return !shape_.empty(); }
IsCoarray()212   bool IsCoarray() const { return !coshape_.empty(); }
CanBeAssumedShape()213   bool CanBeAssumedShape() const {
214     return isDummy() && shape_.CanBeAssumedShape();
215   }
CanBeDeferredShape()216   bool CanBeDeferredShape() const { return shape_.CanBeDeferredShape(); }
IsAssumedSize()217   bool IsAssumedSize() const { return isDummy() && shape_.CanBeAssumedSize(); }
IsAssumedRank()218   bool IsAssumedRank() const { return isDummy() && shape_.IsAssumedRank(); }
219 
220 private:
221   MaybeExpr init_;
222   const parser::Expr *unanalyzedPDTComponentInit_{nullptr};
223   ArraySpec shape_;
224   ArraySpec coshape_;
225   const Symbol *commonBlock_{nullptr}; // common block this object is in
226   friend llvm::raw_ostream &operator<<(
227       llvm::raw_ostream &, const ObjectEntityDetails &);
228 };
229 
230 // Mixin for details with passed-object dummy argument.
231 // If a procedure pointer component or type-bound procedure does not have
232 // the NOPASS attribute on its symbol, then PASS is assumed; the name
233 // is optional; if it is missing, the first dummy argument of the procedure's
234 // interface is the passed-object dummy argument.
235 class WithPassArg {
236 public:
passName()237   std::optional<SourceName> passName() const { return passName_; }
set_passName(const SourceName & passName)238   void set_passName(const SourceName &passName) { passName_ = passName; }
239 
240 private:
241   std::optional<SourceName> passName_;
242 };
243 
244 // A procedure pointer (other than one defined with POINTER and an
245 // INTERFACE block), a dummy procedure (without an INTERFACE but with
246 // EXTERNAL or use in a procedure reference), or external procedure.
247 class ProcEntityDetails : public EntityDetails, public WithPassArg {
248 public:
249   ProcEntityDetails() = default;
250   explicit ProcEntityDetails(EntityDetails &&d);
251 
interface()252   const ProcInterface &interface() const { return interface_; }
interface()253   ProcInterface &interface() { return interface_; }
set_interface(const ProcInterface & interface)254   void set_interface(const ProcInterface &interface) { interface_ = interface; }
IsInterfaceSet()255   bool IsInterfaceSet() {
256     return interface_.symbol() != nullptr || interface_.type() != nullptr;
257   }
258   inline bool HasExplicitInterface() const;
259 
260   // Be advised: !init().has_value() => uninitialized pointer,
261   // while *init() == nullptr => explicit NULL() initialization.
init()262   std::optional<const Symbol *> init() const { return init_; }
set_init(const Symbol & symbol)263   void set_init(const Symbol &symbol) { init_ = &symbol; }
set_init(std::nullptr_t)264   void set_init(std::nullptr_t) { init_ = nullptr; }
265 
266 private:
267   ProcInterface interface_;
268   std::optional<const Symbol *> init_;
269   friend llvm::raw_ostream &operator<<(
270       llvm::raw_ostream &, const ProcEntityDetails &);
271 };
272 
273 // These derived type details represent the characteristics of a derived
274 // type definition that are shared by all instantiations of that type.
275 // The DerivedTypeSpec instances whose type symbols share these details
276 // each own a scope into which the components' symbols have been cloned
277 // and specialized for each distinct set of type parameter values.
278 class DerivedTypeDetails {
279 public:
paramNames()280   const std::list<SourceName> &paramNames() const { return paramNames_; }
paramDecls()281   const SymbolVector &paramDecls() const { return paramDecls_; }
sequence()282   bool sequence() const { return sequence_; }
isDECStructure()283   bool isDECStructure() const { return isDECStructure_; }
finals()284   std::map<SourceName, SymbolRef> &finals() { return finals_; }
finals()285   const std::map<SourceName, SymbolRef> &finals() const { return finals_; }
isForwardReferenced()286   bool isForwardReferenced() const { return isForwardReferenced_; }
add_paramName(const SourceName & name)287   void add_paramName(const SourceName &name) { paramNames_.push_back(name); }
add_paramDecl(const Symbol & symbol)288   void add_paramDecl(const Symbol &symbol) { paramDecls_.push_back(symbol); }
289   void add_component(const Symbol &);
290   void set_sequence(bool x = true) { sequence_ = x; }
291   void set_isDECStructure(bool x = true) { isDECStructure_ = x; }
set_isForwardReferenced(bool value)292   void set_isForwardReferenced(bool value) { isForwardReferenced_ = value; }
componentNames()293   const std::list<SourceName> &componentNames() const {
294     return componentNames_;
295   }
296 
297   // If this derived type extends another, locate the parent component's symbol.
298   const Symbol *GetParentComponent(const Scope &) const;
299 
GetParentComponentName()300   std::optional<SourceName> GetParentComponentName() const {
301     if (componentNames_.empty()) {
302       return std::nullopt;
303     } else {
304       return componentNames_.front();
305     }
306   }
307 
308   const Symbol *GetFinalForRank(int) const;
309 
310 private:
311   // These are (1) the names of the derived type parameters in the order
312   // in which they appear on the type definition statement(s), and (2) the
313   // symbols that correspond to those names in the order in which their
314   // declarations appear in the derived type definition(s).
315   std::list<SourceName> paramNames_;
316   SymbolVector paramDecls_;
317   // These are the names of the derived type's components in component
318   // order.  A parent component, if any, appears first in this list.
319   std::list<SourceName> componentNames_;
320   std::map<SourceName, SymbolRef> finals_; // FINAL :: subr
321   bool sequence_{false};
322   bool isDECStructure_{false};
323   bool isForwardReferenced_{false};
324   friend llvm::raw_ostream &operator<<(
325       llvm::raw_ostream &, const DerivedTypeDetails &);
326 };
327 
328 class ProcBindingDetails : public WithPassArg {
329 public:
ProcBindingDetails(const Symbol & symbol)330   explicit ProcBindingDetails(const Symbol &symbol) : symbol_{symbol} {}
symbol()331   const Symbol &symbol() const { return symbol_; }
332 
333 private:
334   SymbolRef symbol_; // procedure bound to; may be forward
335 };
336 
337 class NamelistDetails {
338 public:
objects()339   const SymbolVector &objects() const { return objects_; }
add_object(const Symbol & object)340   void add_object(const Symbol &object) { objects_.push_back(object); }
add_objects(const SymbolVector & objects)341   void add_objects(const SymbolVector &objects) {
342     objects_.insert(objects_.end(), objects.begin(), objects.end());
343   }
344 
345 private:
346   SymbolVector objects_;
347 };
348 
349 class CommonBlockDetails : public WithBindName {
350 public:
objects()351   MutableSymbolVector &objects() { return objects_; }
objects()352   const MutableSymbolVector &objects() const { return objects_; }
add_object(Symbol & object)353   void add_object(Symbol &object) { objects_.emplace_back(object); }
alignment()354   std::size_t alignment() const { return alignment_; }
set_alignment(std::size_t alignment)355   void set_alignment(std::size_t alignment) { alignment_ = alignment; }
356 
357 private:
358   MutableSymbolVector objects_;
359   std::size_t alignment_{0}; // required alignment in bytes
360 };
361 
362 class MiscDetails {
363 public:
364   ENUM_CLASS(Kind, None, ConstructName, ScopeName, PassName, ComplexPartRe,
365       ComplexPartIm, KindParamInquiry, LenParamInquiry, SelectRankAssociateName,
366       SelectTypeAssociateName, TypeBoundDefinedOp);
MiscDetails(Kind kind)367   MiscDetails(Kind kind) : kind_{kind} {}
kind()368   Kind kind() const { return kind_; }
369 
370 private:
371   Kind kind_;
372 };
373 
374 class TypeParamDetails {
375 public:
TypeParamDetails(common::TypeParamAttr attr)376   explicit TypeParamDetails(common::TypeParamAttr attr) : attr_{attr} {}
377   TypeParamDetails(const TypeParamDetails &) = default;
attr()378   common::TypeParamAttr attr() const { return attr_; }
init()379   MaybeIntExpr &init() { return init_; }
init()380   const MaybeIntExpr &init() const { return init_; }
set_init(MaybeIntExpr && expr)381   void set_init(MaybeIntExpr &&expr) { init_ = std::move(expr); }
type()382   const DeclTypeSpec *type() const { return type_; }
383   void set_type(const DeclTypeSpec &);
384   void ReplaceType(const DeclTypeSpec &);
385 
386 private:
387   common::TypeParamAttr attr_;
388   MaybeIntExpr init_;
389   const DeclTypeSpec *type_{nullptr};
390 };
391 
392 // Record the USE of a symbol: location is where (USE statement or renaming);
393 // symbol is in the USEd module.
394 class UseDetails {
395 public:
UseDetails(const SourceName & location,const Symbol & symbol)396   UseDetails(const SourceName &location, const Symbol &symbol)
397       : location_{location}, symbol_{symbol} {}
location()398   const SourceName &location() const { return location_; }
symbol()399   const Symbol &symbol() const { return symbol_; }
400 
401 private:
402   SourceName location_;
403   SymbolRef symbol_;
404 };
405 
406 // A symbol with ambiguous use-associations. Record where they were so
407 // we can report the error if it is used.
408 class UseErrorDetails {
409 public:
410   UseErrorDetails(const UseDetails &);
411   UseErrorDetails &add_occurrence(const SourceName &, const Scope &);
412   using listType = std::list<std::pair<SourceName, const Scope *>>;
occurrences()413   const listType occurrences() const { return occurrences_; };
414 
415 private:
416   listType occurrences_;
417 };
418 
419 // A symbol host-associated from an enclosing scope.
420 class HostAssocDetails {
421 public:
HostAssocDetails(const Symbol & symbol)422   HostAssocDetails(const Symbol &symbol) : symbol_{symbol} {}
symbol()423   const Symbol &symbol() const { return symbol_; }
424   bool implicitOrSpecExprError{false};
425   bool implicitOrExplicitTypeError{false};
426 
427 private:
428   SymbolRef symbol_;
429 };
430 
431 // A GenericKind is one of: generic name, defined operator,
432 // defined assignment, intrinsic operator, or defined I/O.
433 struct GenericKind {
ENUM_CLASSGenericKind434   ENUM_CLASS(OtherKind, Name, DefinedOp, Assignment, Concat)
435   ENUM_CLASS(DefinedIo, // defined io
436       ReadFormatted, ReadUnformatted, WriteFormatted, WriteUnformatted)
437   GenericKind() : u{OtherKind::Name} {}
GenericKindGenericKind438   template <typename T> GenericKind(const T &x) { u = x; }
IsNameGenericKind439   bool IsName() const { return Is(OtherKind::Name); }
IsAssignmentGenericKind440   bool IsAssignment() const { return Is(OtherKind::Assignment); }
IsDefinedOperatorGenericKind441   bool IsDefinedOperator() const { return Is(OtherKind::DefinedOp); }
442   bool IsIntrinsicOperator() const;
443   bool IsOperator() const;
444   std::string ToString() const;
445   static SourceName AsFortran(DefinedIo);
446   std::variant<OtherKind, common::NumericOperator, common::LogicalOperator,
447       common::RelationalOperator, DefinedIo>
448       u;
449 
450 private:
HasGenericKind451   template <typename T> bool Has() const {
452     return std::holds_alternative<T>(u);
453   }
454   bool Is(OtherKind) const;
455 };
456 
457 // A generic interface or type-bound generic.
458 class GenericDetails {
459 public:
GenericDetails()460   GenericDetails() {}
461 
kind()462   GenericKind kind() const { return kind_; }
set_kind(GenericKind kind)463   void set_kind(GenericKind kind) { kind_ = kind; }
464 
specificProcs()465   const SymbolVector &specificProcs() const { return specificProcs_; }
bindingNames()466   const std::vector<SourceName> &bindingNames() const { return bindingNames_; }
467   void AddSpecificProc(const Symbol &, SourceName bindingName);
uses()468   const SymbolVector &uses() const { return uses_; }
469 
470   // specific and derivedType indicate a specific procedure or derived type
471   // with the same name as this generic. Only one of them may be set.
specific()472   Symbol *specific() { return specific_; }
specific()473   const Symbol *specific() const { return specific_; }
474   void set_specific(Symbol &specific);
derivedType()475   Symbol *derivedType() { return derivedType_; }
derivedType()476   const Symbol *derivedType() const { return derivedType_; }
477   void set_derivedType(Symbol &derivedType);
478   void AddUse(const Symbol &);
479 
480   // Copy in specificProcs, specific, and derivedType from another generic
481   void CopyFrom(const GenericDetails &);
482 
483   // Check that specific is one of the specificProcs. If not, return the
484   // specific as a raw pointer.
485   const Symbol *CheckSpecific() const;
486   Symbol *CheckSpecific();
487 
488 private:
489   GenericKind kind_;
490   // all of the specific procedures for this generic
491   SymbolVector specificProcs_;
492   std::vector<SourceName> bindingNames_;
493   // Symbols used from other modules merged into this one
494   SymbolVector uses_;
495   // a specific procedure with the same name as this generic, if any
496   Symbol *specific_{nullptr};
497   // a derived type with the same name as this generic, if any
498   Symbol *derivedType_{nullptr};
499 };
500 llvm::raw_ostream &operator<<(llvm::raw_ostream &, const GenericDetails &);
501 
502 class UnknownDetails {};
503 
504 using Details = std::variant<UnknownDetails, MainProgramDetails, ModuleDetails,
505     SubprogramDetails, SubprogramNameDetails, EntityDetails,
506     ObjectEntityDetails, ProcEntityDetails, AssocEntityDetails,
507     DerivedTypeDetails, UseDetails, UseErrorDetails, HostAssocDetails,
508     GenericDetails, ProcBindingDetails, NamelistDetails, CommonBlockDetails,
509     TypeParamDetails, MiscDetails>;
510 llvm::raw_ostream &operator<<(llvm::raw_ostream &, const Details &);
511 std::string DetailsToString(const Details &);
512 
513 class Symbol {
514 public:
515   ENUM_CLASS(Flag,
516       Function, // symbol is a function
517       Subroutine, // symbol is a subroutine
518       StmtFunction, // symbol is a statement function (Function is set too)
519       Implicit, // symbol is implicitly typed
520       ImplicitOrError, // symbol must be implicitly typed or it's an error
521       ModFile, // symbol came from .mod file
522       ParentComp, // symbol is the "parent component" of an extended type
523       CrayPointer, CrayPointee,
524       LocalityLocal, // named in LOCAL locality-spec
525       LocalityLocalInit, // named in LOCAL_INIT locality-spec
526       LocalityShared, // named in SHARED locality-spec
527       InDataStmt, // initialized in a DATA statement, =>object, or /init/
528       InNamelist, // in a Namelist group
529       CompilerCreated, // A compiler created symbol
530       // For compiler created symbols that are constant but cannot legally have
531       // the PARAMETER attribute.
532       ReadOnly,
533       // OpenACC data-sharing attribute
534       AccPrivate, AccFirstPrivate, AccShared,
535       // OpenACC data-mapping attribute
536       AccCopyIn, AccCopyOut, AccCreate, AccDelete, AccPresent,
537       // OpenACC miscellaneous flags
538       AccCommonBlock, AccThreadPrivate, AccReduction, AccNone, AccPreDetermined,
539       // OpenMP data-sharing attribute
540       OmpShared, OmpPrivate, OmpLinear, OmpFirstPrivate, OmpLastPrivate,
541       // OpenMP data-mapping attribute
542       OmpMapTo, OmpMapFrom, OmpMapAlloc, OmpMapRelease, OmpMapDelete,
543       // OpenMP data-copying attribute
544       OmpCopyIn, OmpCopyPrivate,
545       // OpenMP miscellaneous flags
546       OmpCommonBlock, OmpReduction, OmpAligned, OmpNontemporal, OmpAllocate,
547       OmpDeclarativeAllocateDirective, OmpExecutableAllocateDirective,
548       OmpDeclareSimd, OmpDeclareTarget, OmpThreadprivate, OmpDeclareReduction,
549       OmpFlushed, OmpCriticalLock, OmpIfSpecified, OmpNone, OmpPreDetermined);
550   using Flags = common::EnumSet<Flag, Flag_enumSize>;
551 
owner()552   const Scope &owner() const { return *owner_; }
name()553   const SourceName &name() const { return name_; }
attrs()554   Attrs &attrs() { return attrs_; }
attrs()555   const Attrs &attrs() const { return attrs_; }
flags()556   Flags &flags() { return flags_; }
flags()557   const Flags &flags() const { return flags_; }
test(Flag flag)558   bool test(Flag flag) const { return flags_.test(flag); }
559   void set(Flag flag, bool value = true) { flags_.set(flag, value); }
560   // The Scope introduced by this symbol, if any.
scope()561   Scope *scope() { return scope_; }
scope()562   const Scope *scope() const { return scope_; }
set_scope(Scope * scope)563   void set_scope(Scope *scope) { scope_ = scope; }
size()564   std::size_t size() const { return size_; }
set_size(std::size_t size)565   void set_size(std::size_t size) { size_ = size; }
offset()566   std::size_t offset() const { return offset_; }
set_offset(std::size_t offset)567   void set_offset(std::size_t offset) { offset_ = offset; }
568   // Give the symbol a name with a different source location but same chars.
569   void ReplaceName(const SourceName &);
570 
571   // Does symbol have this type of details?
has()572   template <typename D> bool has() const {
573     return std::holds_alternative<D>(details_);
574   }
575 
576   // Return a non-owning pointer to details if it is type D, else nullptr.
detailsIf()577   template <typename D> D *detailsIf() { return std::get_if<D>(&details_); }
detailsIf()578   template <typename D> const D *detailsIf() const {
579     return std::get_if<D>(&details_);
580   }
581 
582   // Return a reference to the details which must be of type D.
get()583   template <typename D> D &get() {
584     return const_cast<D &>(const_cast<const Symbol *>(this)->get<D>());
585   }
get()586   template <typename D> const D &get() const {
587     const auto *p{detailsIf<D>()};
588     CHECK(p);
589     return *p;
590   }
591 
details()592   Details &details() { return details_; }
details()593   const Details &details() const { return details_; }
594   // Assign the details of the symbol from one of the variants.
595   // Only allowed in certain cases.
596   void set_details(Details &&);
597 
598   // Can the details of this symbol be replaced with the given details?
599   bool CanReplaceDetails(const Details &details) const;
600 
601   // Follow use-associations and host-associations to get the ultimate entity.
602   inline Symbol &GetUltimate();
603   inline const Symbol &GetUltimate() const;
604 
605   inline DeclTypeSpec *GetType();
606   inline const DeclTypeSpec *GetType() const;
607   void SetType(const DeclTypeSpec &);
608 
609   const std::string *GetBindName() const;
610   void SetBindName(std::string &&);
611   bool IsFuncResult() const;
612   bool IsObjectArray() const;
613   bool IsSubprogram() const;
614   bool IsFromModFile() const;
HasExplicitInterface()615   bool HasExplicitInterface() const {
616     return common::visit(common::visitors{
617                              [](const SubprogramDetails &) { return true; },
618                              [](const SubprogramNameDetails &) { return true; },
619                              [&](const ProcEntityDetails &x) {
620                                return attrs_.test(Attr::INTRINSIC) ||
621                                    x.HasExplicitInterface();
622                              },
623                              [](const ProcBindingDetails &x) {
624                                return x.symbol().HasExplicitInterface();
625                              },
626                              [](const UseDetails &x) {
627                                return x.symbol().HasExplicitInterface();
628                              },
629                              [](const HostAssocDetails &x) {
630                                return x.symbol().HasExplicitInterface();
631                              },
632                              [](const auto &) { return false; },
633                          },
634         details_);
635   }
636 
637   bool operator==(const Symbol &that) const { return this == &that; }
638   bool operator!=(const Symbol &that) const { return !(*this == that); }
639 
Rank()640   int Rank() const { return RankImpl(); }
641 
Corank()642   int Corank() const {
643     return common::visit(
644         common::visitors{
645             [](const SubprogramDetails &sd) {
646               return sd.isFunction() ? sd.result().Corank() : 0;
647             },
648             [](const GenericDetails &) {
649               return 0; /*TODO*/
650             },
651             [](const UseDetails &x) { return x.symbol().Corank(); },
652             [](const HostAssocDetails &x) { return x.symbol().Corank(); },
653             [](const ObjectEntityDetails &oed) { return oed.coshape().Rank(); },
654             [](const auto &) { return 0; },
655         },
656         details_);
657   }
658 
659   // If there is a parent component, return a pointer to its derived type spec.
660   // The Scope * argument defaults to this->scope_ but should be overridden
661   // for a parameterized derived type instantiation with the instance's scope.
662   const DerivedTypeSpec *GetParentTypeSpec(const Scope * = nullptr) const;
663 
664   // If a derived type's symbol refers to an extended derived type,
665   // return the parent component's symbol.  The scope of the derived type
666   // can be overridden.
667   const Symbol *GetParentComponent(const Scope * = nullptr) const;
668 
669   SemanticsContext &GetSemanticsContext() const;
670 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
671   LLVM_DUMP_METHOD void dump() const;
672 #endif
673 
674 private:
675   const Scope *owner_;
676   SourceName name_;
677   Attrs attrs_;
678   Flags flags_;
679   Scope *scope_{nullptr};
680   std::size_t size_{0}; // size in bytes
681   std::size_t offset_{0}; // byte offset in scope or common block
682   Details details_;
683 
Symbol()684   Symbol() {} // only created in class Symbols
685   const std::string GetDetailsName() const;
686   friend llvm::raw_ostream &operator<<(llvm::raw_ostream &, const Symbol &);
687   friend llvm::raw_ostream &DumpForUnparse(
688       llvm::raw_ostream &, const Symbol &, bool);
689 
690   static constexpr int startRecursionDepth{100};
691 
692   inline const DeclTypeSpec *GetTypeImpl(int depth = startRecursionDepth) const;
693   inline int RankImpl(int depth = startRecursionDepth) const {
694     if (depth-- == 0) {
695       return 0;
696     }
697     return common::visit(
698         common::visitors{
699             [&](const SubprogramDetails &sd) {
700               return sd.isFunction() ? sd.result().RankImpl(depth) : 0;
701             },
702             [](const GenericDetails &) {
703               return 0; /*TODO*/
704             },
705             [&](const ProcBindingDetails &x) {
706               return x.symbol().RankImpl(depth);
707             },
708             [&](const UseDetails &x) { return x.symbol().RankImpl(depth); },
709             [&](const HostAssocDetails &x) {
710               return x.symbol().RankImpl(depth);
711             },
712             [](const ObjectEntityDetails &oed) { return oed.shape().Rank(); },
713             [&](const ProcEntityDetails &ped) {
714               const Symbol *iface{ped.interface().symbol()};
715               return iface ? iface->RankImpl(depth) : 0;
716             },
717             [](const AssocEntityDetails &aed) {
718               if (const auto &expr{aed.expr()}) {
719                 if (auto assocRank{aed.rank()}) {
720                   return *assocRank;
721                 } else {
722                   return expr->Rank();
723                 }
724               } else {
725                 return 0;
726               }
727             },
728             [](const auto &) { return 0; },
729         },
730         details_);
731   }
732   template <std::size_t> friend class Symbols;
733   template <class, std::size_t> friend class std::array;
734 };
735 
736 llvm::raw_ostream &operator<<(llvm::raw_ostream &, Symbol::Flag);
737 
738 // Manage memory for all symbols. BLOCK_SIZE symbols at a time are allocated.
739 // Make() returns a reference to the next available one. They are never
740 // deleted.
741 template <std::size_t BLOCK_SIZE> class Symbols {
742 public:
Make(const Scope & owner,const SourceName & name,const Attrs & attrs,Details && details)743   Symbol &Make(const Scope &owner, const SourceName &name, const Attrs &attrs,
744       Details &&details) {
745     Symbol &symbol = Get();
746     symbol.owner_ = &owner;
747     symbol.name_ = name;
748     symbol.attrs_ = attrs;
749     symbol.details_ = std::move(details);
750     return symbol;
751   }
752 
753 private:
754   using blockType = std::array<Symbol, BLOCK_SIZE>;
755   std::list<blockType *> blocks_;
756   std::size_t nextIndex_{0};
757   blockType *currBlock_{nullptr};
758 
Get()759   Symbol &Get() {
760     if (nextIndex_ == 0) {
761       blocks_.push_back(new blockType());
762       currBlock_ = blocks_.back();
763     }
764     Symbol &result = (*currBlock_)[nextIndex_];
765     if (++nextIndex_ >= BLOCK_SIZE) {
766       nextIndex_ = 0; // allocate a new block next time
767     }
768     return result;
769   }
770 };
771 
772 // Define a few member functions here in the header so that they
773 // can be used by lib/Evaluate without inducing a dependence cycle
774 // between the two shared libraries.
775 
HasExplicitInterface()776 inline bool ProcEntityDetails::HasExplicitInterface() const {
777   if (auto *symbol{interface_.symbol()}) {
778     return symbol->HasExplicitInterface();
779   }
780   return false;
781 }
782 
GetUltimate()783 inline Symbol &Symbol::GetUltimate() {
784   return const_cast<Symbol &>(const_cast<const Symbol *>(this)->GetUltimate());
785 }
GetUltimate()786 inline const Symbol &Symbol::GetUltimate() const {
787   if (const auto *details{detailsIf<UseDetails>()}) {
788     return details->symbol().GetUltimate();
789   } else if (const auto *details{detailsIf<HostAssocDetails>()}) {
790     return details->symbol().GetUltimate();
791   } else {
792     return *this;
793   }
794 }
795 
GetType()796 inline DeclTypeSpec *Symbol::GetType() {
797   return const_cast<DeclTypeSpec *>(
798       const_cast<const Symbol *>(this)->GetType());
799 }
800 
GetTypeImpl(int depth)801 inline const DeclTypeSpec *Symbol::GetTypeImpl(int depth) const {
802   if (depth-- == 0) {
803     return nullptr;
804   }
805   return common::visit(
806       common::visitors{
807           [](const EntityDetails &x) { return x.type(); },
808           [](const ObjectEntityDetails &x) { return x.type(); },
809           [](const AssocEntityDetails &x) { return x.type(); },
810           [&](const SubprogramDetails &x) {
811             return x.isFunction() ? x.result().GetTypeImpl(depth) : nullptr;
812           },
813           [&](const ProcEntityDetails &x) {
814             const Symbol *symbol{x.interface().symbol()};
815             return symbol ? symbol->GetTypeImpl(depth) : x.interface().type();
816           },
817           [&](const ProcBindingDetails &x) {
818             return x.symbol().GetTypeImpl(depth);
819           },
820           [](const TypeParamDetails &x) { return x.type(); },
821           [&](const UseDetails &x) { return x.symbol().GetTypeImpl(depth); },
822           [&](const HostAssocDetails &x) {
823             return x.symbol().GetTypeImpl(depth);
824           },
825           [](const auto &) -> const DeclTypeSpec * { return nullptr; },
826       },
827       details_);
828 }
829 
GetType()830 inline const DeclTypeSpec *Symbol::GetType() const { return GetTypeImpl(); }
831 
832 // Sets and maps keyed by Symbols
833 
834 struct SymbolAddressCompare {
operatorSymbolAddressCompare835   bool operator()(const SymbolRef &x, const SymbolRef &y) const {
836     return &*x < &*y;
837   }
operatorSymbolAddressCompare838   bool operator()(const MutableSymbolRef &x, const MutableSymbolRef &y) const {
839     return &*x < &*y;
840   }
841 };
842 
843 // Symbol comparison is usually based on the order of cooked source
844 // stream creation and, when both are from the same cooked source,
845 // their positions in that cooked source stream.
846 // Don't use this comparator or OrderedSymbolSet to hold
847 // Symbols that might be subject to ReplaceName().
848 struct SymbolSourcePositionCompare {
849   // These functions are implemented in Evaluate/tools.cpp to
850   // satisfy complicated shared library interdependency.
851   bool operator()(const SymbolRef &, const SymbolRef &) const;
852   bool operator()(const MutableSymbolRef &, const MutableSymbolRef &) const;
853 };
854 
855 struct SymbolOffsetCompare {
856   bool operator()(const SymbolRef &, const SymbolRef &) const;
857   bool operator()(const MutableSymbolRef &, const MutableSymbolRef &) const;
858 };
859 
860 using UnorderedSymbolSet = std::set<SymbolRef, SymbolAddressCompare>;
861 using SourceOrderedSymbolSet = std::set<SymbolRef, SymbolSourcePositionCompare>;
862 
863 template <typename A>
OrderBySourcePosition(const A & container)864 SourceOrderedSymbolSet OrderBySourcePosition(const A &container) {
865   SourceOrderedSymbolSet result;
866   for (SymbolRef x : container) {
867     result.emplace(x);
868   }
869   return result;
870 }
871 
872 } // namespace Fortran::semantics
873 
874 // Define required  info so that SymbolRef can be used inside llvm::DenseMap.
875 namespace llvm {
876 template <> struct DenseMapInfo<Fortran::semantics::SymbolRef> {
877   static inline Fortran::semantics::SymbolRef getEmptyKey() {
878     auto ptr = DenseMapInfo<const Fortran::semantics::Symbol *>::getEmptyKey();
879     return *reinterpret_cast<Fortran::semantics::SymbolRef *>(&ptr);
880   }
881 
882   static inline Fortran::semantics::SymbolRef getTombstoneKey() {
883     auto ptr =
884         DenseMapInfo<const Fortran::semantics::Symbol *>::getTombstoneKey();
885     return *reinterpret_cast<Fortran::semantics::SymbolRef *>(&ptr);
886   }
887 
888   static unsigned getHashValue(const Fortran::semantics::SymbolRef &sym) {
889     return DenseMapInfo<const Fortran::semantics::Symbol *>::getHashValue(
890         &sym.get());
891   }
892 
893   static bool isEqual(const Fortran::semantics::SymbolRef &LHS,
894       const Fortran::semantics::SymbolRef &RHS) {
895     return LHS == RHS;
896   }
897 };
898 } // namespace llvm
899 #endif // FORTRAN_SEMANTICS_SYMBOL_H_
900