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 ¶mNameOrder() const { return paramNameOrder_; } 464 const SymbolVector ¶mDeclOrder() 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