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/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
27namespace llvm {
28class raw_ostream;
29}
30namespace Fortran::parser {
31struct Expr;
32}
33
34namespace Fortran::semantics {
35
39
40class Scope;
41class Symbol;
42class ProgramTree;
43
44using SymbolRef = common::Reference<const Symbol>;
45using SymbolVector = std::vector<SymbolRef>;
46using MutableSymbolRef = common::Reference<Symbol>;
47using MutableSymbolVector = std::vector<MutableSymbolRef>;
48
49// Mixin for details with OpenMP declarative constructs.
51 using OmpAtomicOrderType = common::OmpAtomicDefaultMemOrderType;
52
53public:
54 ENUM_CLASS(RequiresFlag, ReverseOffload, UnifiedAddress, UnifiedSharedMemory,
55 DynamicAllocators);
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
74private:
75 std::optional<RequiresFlags> ompRequires_;
76 std::optional<OmpAtomicOrderType> ompAtomicDefaultMemOrder_;
77};
78
79// A module or submodule.
81public:
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
97private:
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
106public:
107private:
108};
109
111public:
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
121private:
122 std::optional<std::string> bindName_;
123 bool isExplicitBindName_{false};
124 bool isCDefined_{false};
125};
126
127// Device type specific OpenACC routine information
129public:
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
149private:
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.
164public:
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
174private:
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).
183public:
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
241private:
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.
266ENUM_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.
273public:
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
280private:
281 SubprogramKind kind_;
283};
284
285// A name from an entity-decl -- could be object or function.
287public:
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
297private:
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.
308public:
310 explicit AssocEntityDetails(SomeExpr &&expr) : expr_{std::move(expr)} {}
311 AssocEntityDetails(const 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
336private:
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};
344llvm::raw_ostream &operator<<(llvm::raw_ostream &, const AssocEntityDetails &);
345
346// An entity known to be an object.
348public:
350 ObjectEntityDetails(const 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
389private:
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.
407public:
408 std::optional<SourceName> passName() const { return passName_; }
409 void set_passName(const SourceName &passName) { passName_ = passName; }
410
411private:
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.
419public:
420 ProcEntityDetails() = default;
421 explicit ProcEntityDetails(EntityDetails &&);
422 ProcEntityDetails(const 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
446private:
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.
462public:
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
497private:
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
516public:
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
523private:
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
530public:
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
537private:
538 SymbolVector objects_;
539};
540
542public:
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
553private:
554 MutableSymbolVector objects_;
555 std::size_t alignment_{0}; // required alignment in bytes
556};
557
559public:
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
566private:
567 Kind kind_;
568};
569
571public:
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
583private:
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.
592public:
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
598private:
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.
606public:
608 UseErrorDetails &add_occurrence(const SourceName &, const Scope &);
609 using listType = std::list<std::pair<SourceName, const Scope *>>;
610 const listType occurrences() const { return occurrences_; };
611
612private:
613 listType occurrences_;
614};
615
616// A symbol host-associated from an enclosing scope.
618public:
619 HostAssocDetails(const Symbol &symbol) : symbol_{symbol} {}
620 const Symbol &symbol() const { return symbol_; }
621 bool implicitOrSpecExprError{false};
622 bool implicitOrExplicitTypeError{false};
623
624private:
625 SymbolRef symbol_;
626};
627
628// A GenericKind is one of: generic name, defined operator,
629// defined assignment, intrinsic operator, or defined I/O.
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
645private:
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.
654public:
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
687private:
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};
699llvm::raw_ostream &operator<<(llvm::raw_ostream &, const GenericDetails &);
700
702
703using Details = std::variant<UnknownDetails, MainProgramDetails, ModuleDetails,
709llvm::raw_ostream &operator<<(llvm::raw_ostream &, const Details &);
710std::string DetailsToString(const Details &);
711
712class Symbol {
713public:
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);
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(
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
881private:
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(
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(
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
972llvm::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.
977template <std::size_t BLOCK_SIZE> class Symbols {
978public:
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
989private:
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
1012inline bool ProcEntityDetails::HasExplicitInterface() const {
1013 return procInterface_ && procInterface_->HasExplicitInterface();
1014}
1015
1016inline Symbol &Symbol::GetUltimate() {
1017 return const_cast<Symbol &>(const_cast<const Symbol *>(this)->GetUltimate());
1018}
1019inline 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
1029inline DeclTypeSpec *Symbol::GetType() {
1030 return const_cast<DeclTypeSpec *>(
1031 const_cast<const Symbol *>(this)->GetType());
1032}
1033
1034inline 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
1063inline const DeclTypeSpec *Symbol::GetType() const { return GetTypeImpl(); }
1064
1065// Sets and maps keyed by Symbols
1066
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().
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
1089 bool operator()(const SymbolRef &, const SymbolRef &) const;
1090 bool operator()(const MutableSymbolRef &, const MutableSymbolRef &) const;
1091};
1092
1093using UnorderedSymbolSet = std::set<SymbolRef, SymbolAddressCompare>;
1094using SourceOrderedSymbolSet = std::set<SymbolRef, SymbolSourcePositionCompare>;
1095
1096template <typename A>
1097SourceOrderedSymbolSet 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.
1108namespace llvm {
1109template <> 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_
Definition: enum-set.h:28
Definition: reference.h:18
Definition: char-block.h:28
Definition: type.h:353
Definition: symbol.h:286
Definition: symbol.h:653
Definition: symbol.h:617
Definition: symbol.h:558
Definition: symbol.h:80
Definition: symbol.h:529
Definition: program-tree.h:31
Definition: scope.h:58
Definition: semantics.h:67
Definition: symbol.h:712
Definition: symbol.h:977
Definition: symbol.h:570
Definition: symbol.h:701
Definition: symbol.h:591
Definition: symbol.h:605
Definition: symbol.h:110
Definition: symbol.h:406
Definition: check-expression.h:19
Definition: bit-population-count.h:20
Definition: idioms.h:61
Definition: parse-tree.h:1700
Definition: type.h:238
Definition: symbol.h:630