164ab3302SCarolineConcatto //===-- lib/Semantics/symbol.cpp ------------------------------------------===// 264ab3302SCarolineConcatto // 364ab3302SCarolineConcatto // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 464ab3302SCarolineConcatto // See https://llvm.org/LICENSE.txt for license information. 564ab3302SCarolineConcatto // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 664ab3302SCarolineConcatto // 764ab3302SCarolineConcatto //===----------------------------------------------------------------------===// 864ab3302SCarolineConcatto 964ab3302SCarolineConcatto #include "flang/Semantics/symbol.h" 1064ab3302SCarolineConcatto #include "flang/Common/idioms.h" 1164ab3302SCarolineConcatto #include "flang/Evaluate/expression.h" 1264ab3302SCarolineConcatto #include "flang/Semantics/scope.h" 1364ab3302SCarolineConcatto #include "flang/Semantics/semantics.h" 1464ab3302SCarolineConcatto #include "flang/Semantics/tools.h" 158670e499SCaroline Concatto #include "llvm/Support/raw_ostream.h" 1619d86426SPeter Klausler #include <cstring> 1764ab3302SCarolineConcatto #include <string> 185d3249e9STim Keith #include <type_traits> 1964ab3302SCarolineConcatto 2064ab3302SCarolineConcatto namespace Fortran::semantics { 2164ab3302SCarolineConcatto 2264ab3302SCarolineConcatto template <typename T> 238670e499SCaroline Concatto static void DumpOptional(llvm::raw_ostream &os, const char *label, const T &x) { 2464ab3302SCarolineConcatto if (x) { 2564ab3302SCarolineConcatto os << ' ' << label << ':' << *x; 2664ab3302SCarolineConcatto } 2764ab3302SCarolineConcatto } 2864ab3302SCarolineConcatto template <typename T> 298670e499SCaroline Concatto static void DumpExpr(llvm::raw_ostream &os, const char *label, 3064ab3302SCarolineConcatto const std::optional<evaluate::Expr<T>> &x) { 3164ab3302SCarolineConcatto if (x) { 3264ab3302SCarolineConcatto x->AsFortran(os << ' ' << label << ':'); 3364ab3302SCarolineConcatto } 3464ab3302SCarolineConcatto } 3564ab3302SCarolineConcatto 368670e499SCaroline Concatto static void DumpBool(llvm::raw_ostream &os, const char *label, bool x) { 3764ab3302SCarolineConcatto if (x) { 3864ab3302SCarolineConcatto os << ' ' << label; 3964ab3302SCarolineConcatto } 4064ab3302SCarolineConcatto } 4164ab3302SCarolineConcatto 428670e499SCaroline Concatto static void DumpSymbolVector(llvm::raw_ostream &os, const SymbolVector &list) { 4364ab3302SCarolineConcatto char sep{' '}; 4464ab3302SCarolineConcatto for (const Symbol &elem : list) { 4564ab3302SCarolineConcatto os << sep << elem.name(); 4664ab3302SCarolineConcatto sep = ','; 4764ab3302SCarolineConcatto } 4864ab3302SCarolineConcatto } 4964ab3302SCarolineConcatto 508670e499SCaroline Concatto static void DumpType(llvm::raw_ostream &os, const Symbol &symbol) { 5164ab3302SCarolineConcatto if (const auto *type{symbol.GetType()}) { 5264ab3302SCarolineConcatto os << *type << ' '; 5364ab3302SCarolineConcatto } 5464ab3302SCarolineConcatto } 558670e499SCaroline Concatto static void DumpType(llvm::raw_ostream &os, const DeclTypeSpec *type) { 5664ab3302SCarolineConcatto if (type) { 5764ab3302SCarolineConcatto os << ' ' << *type; 5864ab3302SCarolineConcatto } 5964ab3302SCarolineConcatto } 6064ab3302SCarolineConcatto 6164ab3302SCarolineConcatto template <typename T> 628670e499SCaroline Concatto static void DumpList(llvm::raw_ostream &os, const char *label, const T &list) { 6364ab3302SCarolineConcatto if (!list.empty()) { 6464ab3302SCarolineConcatto os << ' ' << label << ':'; 6564ab3302SCarolineConcatto char sep{' '}; 6664ab3302SCarolineConcatto for (const auto &elem : list) { 6764ab3302SCarolineConcatto os << sep << elem; 6864ab3302SCarolineConcatto sep = ','; 6964ab3302SCarolineConcatto } 7064ab3302SCarolineConcatto } 7164ab3302SCarolineConcatto } 7264ab3302SCarolineConcatto 7339686557SPeter Klausler void SubprogramDetails::set_moduleInterface(Symbol &symbol) { 7439686557SPeter Klausler CHECK(!moduleInterface_); 7539686557SPeter Klausler moduleInterface_ = &symbol; 7639686557SPeter Klausler } 7739686557SPeter Klausler 7864ab3302SCarolineConcatto const Scope *ModuleDetails::parent() const { 7964ab3302SCarolineConcatto return isSubmodule_ && scope_ ? &scope_->parent() : nullptr; 8064ab3302SCarolineConcatto } 8164ab3302SCarolineConcatto const Scope *ModuleDetails::ancestor() const { 8247452b96STim Keith return isSubmodule_ && scope_ ? FindModuleContaining(*scope_) : nullptr; 8364ab3302SCarolineConcatto } 8464ab3302SCarolineConcatto void ModuleDetails::set_scope(const Scope *scope) { 8564ab3302SCarolineConcatto CHECK(!scope_); 8664ab3302SCarolineConcatto bool scopeIsSubmodule{scope->parent().kind() == Scope::Kind::Module}; 8764ab3302SCarolineConcatto CHECK(isSubmodule_ == scopeIsSubmodule); 8864ab3302SCarolineConcatto scope_ = scope; 8964ab3302SCarolineConcatto } 9064ab3302SCarolineConcatto 918670e499SCaroline Concatto llvm::raw_ostream &operator<<( 928670e499SCaroline Concatto llvm::raw_ostream &os, const SubprogramDetails &x) { 9364ab3302SCarolineConcatto DumpBool(os, "isInterface", x.isInterface_); 94c4a65434Speter klausler DumpBool(os, "dummy", x.isDummy_); 955d3249e9STim Keith DumpOptional(os, "bindName", x.bindName()); 9664ab3302SCarolineConcatto if (x.result_) { 9761b1390eSTim Keith DumpType(os << " result:", x.result()); 9861b1390eSTim Keith os << x.result_->name(); 9964ab3302SCarolineConcatto if (!x.result_->attrs().empty()) { 10064ab3302SCarolineConcatto os << ", " << x.result_->attrs(); 10164ab3302SCarolineConcatto } 10264ab3302SCarolineConcatto } 103c42f6314Speter klausler if (x.entryScope_) { 104c42f6314Speter klausler os << " entry"; 105c42f6314Speter klausler if (x.entryScope_->symbol()) { 106c42f6314Speter klausler os << " in " << x.entryScope_->symbol()->name(); 107c42f6314Speter klausler } 108c42f6314Speter klausler } 10964ab3302SCarolineConcatto char sep{'('}; 11064ab3302SCarolineConcatto os << ' '; 11161b1390eSTim Keith for (const Symbol *arg : x.dummyArgs_) { 11261b1390eSTim Keith os << sep; 11364ab3302SCarolineConcatto sep = ','; 11461b1390eSTim Keith if (arg) { 11561b1390eSTim Keith DumpType(os, *arg); 11661b1390eSTim Keith os << arg->name(); 11761b1390eSTim Keith } else { 11861b1390eSTim Keith os << '*'; 11961b1390eSTim Keith } 12064ab3302SCarolineConcatto } 12164ab3302SCarolineConcatto os << (sep == '(' ? "()" : ")"); 122412056e2STim Keith if (x.stmtFunction_) { 123412056e2STim Keith os << " -> " << x.stmtFunction_->AsFortran(); 124412056e2STim Keith } 12539686557SPeter Klausler if (x.moduleInterface_) { 12639686557SPeter Klausler os << " moduleInterface: " << *x.moduleInterface_; 12739686557SPeter Klausler } 128864cb2aaSPeter Klausler if (x.defaultIgnoreTKR_) { 129864cb2aaSPeter Klausler os << " defaultIgnoreTKR"; 130864cb2aaSPeter Klausler } 13127f71807SPeter Klausler if (x.cudaSubprogramAttrs_) { 13227f71807SPeter Klausler os << " cudaSubprogramAttrs: " 13327f71807SPeter Klausler << common::EnumToString(*x.cudaSubprogramAttrs_); 13427f71807SPeter Klausler } 13527f71807SPeter Klausler if (!x.cudaLaunchBounds_.empty()) { 13627f71807SPeter Klausler os << " cudaLaunchBounds:"; 13727f71807SPeter Klausler for (auto x : x.cudaLaunchBounds_) { 13827f71807SPeter Klausler os << ' ' << x; 13927f71807SPeter Klausler } 14027f71807SPeter Klausler } 14127f71807SPeter Klausler if (!x.cudaClusterDims_.empty()) { 14227f71807SPeter Klausler os << " cudaClusterDims:"; 14327f71807SPeter Klausler for (auto x : x.cudaClusterDims_) { 14427f71807SPeter Klausler os << ' ' << x; 14527f71807SPeter Klausler } 14627f71807SPeter Klausler } 14764ab3302SCarolineConcatto return os; 14864ab3302SCarolineConcatto } 14964ab3302SCarolineConcatto 15064ab3302SCarolineConcatto void EntityDetails::set_type(const DeclTypeSpec &type) { 15164ab3302SCarolineConcatto CHECK(!type_); 15264ab3302SCarolineConcatto type_ = &type; 15364ab3302SCarolineConcatto } 15464ab3302SCarolineConcatto 155332e6aeaSsameeran joshi void AssocEntityDetails::set_rank(int rank) { rank_ = rank; } 1564fed5959SPeter Klausler void AssocEntityDetails::set_IsAssumedSize() { rank_ = isAssumedSize; } 1574fed5959SPeter Klausler void AssocEntityDetails::set_IsAssumedRank() { rank_ = isAssumedRank; } 15864ab3302SCarolineConcatto void EntityDetails::ReplaceType(const DeclTypeSpec &type) { type_ = &type; } 15964ab3302SCarolineConcatto 160b22873b1SPeter Klausler ObjectEntityDetails::ObjectEntityDetails(EntityDetails &&d) 161635656f4SPeter Klausler : EntityDetails(std::move(d)) {} 162b22873b1SPeter Klausler 16364ab3302SCarolineConcatto void ObjectEntityDetails::set_shape(const ArraySpec &shape) { 16464ab3302SCarolineConcatto CHECK(shape_.empty()); 16564ab3302SCarolineConcatto for (const auto &shapeSpec : shape) { 16664ab3302SCarolineConcatto shape_.push_back(shapeSpec); 16764ab3302SCarolineConcatto } 16864ab3302SCarolineConcatto } 16964ab3302SCarolineConcatto void ObjectEntityDetails::set_coshape(const ArraySpec &coshape) { 17064ab3302SCarolineConcatto CHECK(coshape_.empty()); 17164ab3302SCarolineConcatto for (const auto &shapeSpec : coshape) { 17264ab3302SCarolineConcatto coshape_.push_back(shapeSpec); 17364ab3302SCarolineConcatto } 17464ab3302SCarolineConcatto } 17564ab3302SCarolineConcatto 176635656f4SPeter Klausler ProcEntityDetails::ProcEntityDetails(EntityDetails &&d) 177635656f4SPeter Klausler : EntityDetails(std::move(d)) {} 17864ab3302SCarolineConcatto 17964ab3302SCarolineConcatto UseErrorDetails::UseErrorDetails(const UseDetails &useDetails) { 180*038b42baSPeter Klausler add_occurrence(useDetails.location(), useDetails.symbol()); 18164ab3302SCarolineConcatto } 18264ab3302SCarolineConcatto UseErrorDetails &UseErrorDetails::add_occurrence( 183*038b42baSPeter Klausler const SourceName &location, const Symbol &used) { 184*038b42baSPeter Klausler occurrences_.push_back(std::make_pair(location, &used)); 18564ab3302SCarolineConcatto return *this; 18664ab3302SCarolineConcatto } 18764ab3302SCarolineConcatto 18864ab3302SCarolineConcatto void GenericDetails::AddSpecificProc( 18964ab3302SCarolineConcatto const Symbol &proc, SourceName bindingName) { 19064ab3302SCarolineConcatto specificProcs_.push_back(proc); 19164ab3302SCarolineConcatto bindingNames_.push_back(bindingName); 19264ab3302SCarolineConcatto } 19364ab3302SCarolineConcatto void GenericDetails::set_specific(Symbol &specific) { 19464ab3302SCarolineConcatto CHECK(!specific_); 19564ab3302SCarolineConcatto specific_ = &specific; 19664ab3302SCarolineConcatto } 197bfc39073SPeter Klausler void GenericDetails::clear_specific() { specific_ = nullptr; } 19864ab3302SCarolineConcatto void GenericDetails::set_derivedType(Symbol &derivedType) { 19964ab3302SCarolineConcatto CHECK(!derivedType_); 20064ab3302SCarolineConcatto derivedType_ = &derivedType; 20164ab3302SCarolineConcatto } 202227f30a5SPeter Klausler void GenericDetails::clear_derivedType() { derivedType_ = nullptr; } 20386f59de1STim Keith void GenericDetails::AddUse(const Symbol &use) { 20486f59de1STim Keith CHECK(use.has<UseDetails>()); 20586f59de1STim Keith uses_.push_back(use); 20686f59de1STim Keith } 20764ab3302SCarolineConcatto 20864ab3302SCarolineConcatto const Symbol *GenericDetails::CheckSpecific() const { 20964ab3302SCarolineConcatto return const_cast<GenericDetails *>(this)->CheckSpecific(); 21064ab3302SCarolineConcatto } 21164ab3302SCarolineConcatto Symbol *GenericDetails::CheckSpecific() { 2122b7a928dSPeter Klausler if (specific_ && !specific_->has<UseErrorDetails>()) { 213d418a03eSPeter Klausler const Symbol &ultimate{specific_->GetUltimate()}; 21464ab3302SCarolineConcatto for (const Symbol &proc : specificProcs_) { 215d418a03eSPeter Klausler if (&proc.GetUltimate() == &ultimate) { 21664ab3302SCarolineConcatto return nullptr; 21764ab3302SCarolineConcatto } 21864ab3302SCarolineConcatto } 21964ab3302SCarolineConcatto return specific_; 22064ab3302SCarolineConcatto } else { 22164ab3302SCarolineConcatto return nullptr; 22264ab3302SCarolineConcatto } 22364ab3302SCarolineConcatto } 22464ab3302SCarolineConcatto 22564ab3302SCarolineConcatto void GenericDetails::CopyFrom(const GenericDetails &from) { 22685d9745cSPete Steinfeld CHECK(specificProcs_.size() == bindingNames_.size()); 22785d9745cSPete Steinfeld CHECK(from.specificProcs_.size() == from.bindingNames_.size()); 22886f59de1STim Keith kind_ = from.kind_; 22964ab3302SCarolineConcatto if (from.derivedType_) { 23064ab3302SCarolineConcatto CHECK(!derivedType_ || derivedType_ == from.derivedType_); 23164ab3302SCarolineConcatto derivedType_ = from.derivedType_; 23264ab3302SCarolineConcatto } 23385d9745cSPete Steinfeld for (std::size_t i{0}; i < from.specificProcs_.size(); ++i) { 2348470cdd4SKazu Hirata if (llvm::none_of(specificProcs_, [&](const Symbol &mySymbol) { 2359b200074SPeter Klausler return &mySymbol.GetUltimate() == 2369b200074SPeter Klausler &from.specificProcs_[i]->GetUltimate(); 2378470cdd4SKazu Hirata })) { 23885d9745cSPete Steinfeld specificProcs_.push_back(from.specificProcs_[i]); 23985d9745cSPete Steinfeld bindingNames_.push_back(from.bindingNames_[i]); 24064ab3302SCarolineConcatto } 24164ab3302SCarolineConcatto } 24264ab3302SCarolineConcatto } 24364ab3302SCarolineConcatto 24464ab3302SCarolineConcatto // The name of the kind of details for this symbol. 24564ab3302SCarolineConcatto // This is primarily for debugging. 24664ab3302SCarolineConcatto std::string DetailsToString(const Details &details) { 247cd03e96fSPeter Klausler return common::visit( 24864ab3302SCarolineConcatto common::visitors{ 24964ab3302SCarolineConcatto [](const UnknownDetails &) { return "Unknown"; }, 25064ab3302SCarolineConcatto [](const MainProgramDetails &) { return "MainProgram"; }, 25164ab3302SCarolineConcatto [](const ModuleDetails &) { return "Module"; }, 25264ab3302SCarolineConcatto [](const SubprogramDetails &) { return "Subprogram"; }, 25364ab3302SCarolineConcatto [](const SubprogramNameDetails &) { return "SubprogramName"; }, 25464ab3302SCarolineConcatto [](const EntityDetails &) { return "Entity"; }, 25564ab3302SCarolineConcatto [](const ObjectEntityDetails &) { return "ObjectEntity"; }, 25664ab3302SCarolineConcatto [](const ProcEntityDetails &) { return "ProcEntity"; }, 25764ab3302SCarolineConcatto [](const DerivedTypeDetails &) { return "DerivedType"; }, 25864ab3302SCarolineConcatto [](const UseDetails &) { return "Use"; }, 25964ab3302SCarolineConcatto [](const UseErrorDetails &) { return "UseError"; }, 26064ab3302SCarolineConcatto [](const HostAssocDetails &) { return "HostAssoc"; }, 26164ab3302SCarolineConcatto [](const GenericDetails &) { return "Generic"; }, 26264ab3302SCarolineConcatto [](const ProcBindingDetails &) { return "ProcBinding"; }, 26364ab3302SCarolineConcatto [](const NamelistDetails &) { return "Namelist"; }, 26464ab3302SCarolineConcatto [](const CommonBlockDetails &) { return "CommonBlockDetails"; }, 26564ab3302SCarolineConcatto [](const TypeParamDetails &) { return "TypeParam"; }, 26664ab3302SCarolineConcatto [](const MiscDetails &) { return "Misc"; }, 26764ab3302SCarolineConcatto [](const AssocEntityDetails &) { return "AssocEntity"; }, 26864ab3302SCarolineConcatto }, 26964ab3302SCarolineConcatto details); 27064ab3302SCarolineConcatto } 27164ab3302SCarolineConcatto 2720d588347SPeter Klausler std::string Symbol::GetDetailsName() const { return DetailsToString(details_); } 27364ab3302SCarolineConcatto 27464ab3302SCarolineConcatto void Symbol::set_details(Details &&details) { 27564ab3302SCarolineConcatto CHECK(CanReplaceDetails(details)); 27664ab3302SCarolineConcatto details_ = std::move(details); 27764ab3302SCarolineConcatto } 27864ab3302SCarolineConcatto 27964ab3302SCarolineConcatto bool Symbol::CanReplaceDetails(const Details &details) const { 28064ab3302SCarolineConcatto if (has<UnknownDetails>()) { 28164ab3302SCarolineConcatto return true; // can always replace UnknownDetails 28264ab3302SCarolineConcatto } else { 283cd03e96fSPeter Klausler return common::visit( 28464ab3302SCarolineConcatto common::visitors{ 28564ab3302SCarolineConcatto [](const UseErrorDetails &) { return true; }, 28664ab3302SCarolineConcatto [&](const ObjectEntityDetails &) { return has<EntityDetails>(); }, 28764ab3302SCarolineConcatto [&](const ProcEntityDetails &) { return has<EntityDetails>(); }, 28864ab3302SCarolineConcatto [&](const SubprogramDetails &) { 28964ab3302SCarolineConcatto return has<SubprogramNameDetails>() || has<EntityDetails>(); 29064ab3302SCarolineConcatto }, 29164ab3302SCarolineConcatto [&](const DerivedTypeDetails &) { 292bdb40dd1SMehdi Chinoune const auto *derived{this->detailsIf<DerivedTypeDetails>()}; 29364ab3302SCarolineConcatto return derived && derived->isForwardReferenced(); 29464ab3302SCarolineConcatto }, 29586f59de1STim Keith [&](const UseDetails &x) { 296bdb40dd1SMehdi Chinoune const auto *use{this->detailsIf<UseDetails>()}; 29786f59de1STim Keith return use && use->symbol() == x.symbol(); 29886f59de1STim Keith }, 2999e855a6cSPeter Klausler [&](const HostAssocDetails &) { 3009e855a6cSPeter Klausler return this->has<HostAssocDetails>(); 3019e855a6cSPeter Klausler }, 30264ab3302SCarolineConcatto [](const auto &) { return false; }, 30364ab3302SCarolineConcatto }, 30464ab3302SCarolineConcatto details); 30564ab3302SCarolineConcatto } 30664ab3302SCarolineConcatto } 30764ab3302SCarolineConcatto 30864ab3302SCarolineConcatto // Usually a symbol's name is the first occurrence in the source, but sometimes 30964ab3302SCarolineConcatto // we want to replace it with one at a different location (but same characters). 31064ab3302SCarolineConcatto void Symbol::ReplaceName(const SourceName &name) { 31164ab3302SCarolineConcatto CHECK(name == name_); 31264ab3302SCarolineConcatto name_ = name; 31364ab3302SCarolineConcatto } 31464ab3302SCarolineConcatto 31564ab3302SCarolineConcatto void Symbol::SetType(const DeclTypeSpec &type) { 316cd03e96fSPeter Klausler common::visit(common::visitors{ 31764ab3302SCarolineConcatto [&](EntityDetails &x) { x.set_type(type); }, 31864ab3302SCarolineConcatto [&](ObjectEntityDetails &x) { x.set_type(type); }, 31964ab3302SCarolineConcatto [&](AssocEntityDetails &x) { x.set_type(type); }, 320635656f4SPeter Klausler [&](ProcEntityDetails &x) { x.set_type(type); }, 32164ab3302SCarolineConcatto [&](TypeParamDetails &x) { x.set_type(type); }, 32264ab3302SCarolineConcatto [](auto &) {}, 32364ab3302SCarolineConcatto }, 32464ab3302SCarolineConcatto details_); 32564ab3302SCarolineConcatto } 32664ab3302SCarolineConcatto 3275d3249e9STim Keith template <typename T> 3285d3249e9STim Keith constexpr bool HasBindName{std::is_convertible_v<T, const WithBindName *>}; 3295d3249e9STim Keith 3305d3249e9STim Keith const std::string *Symbol::GetBindName() const { 331cd03e96fSPeter Klausler return common::visit( 3325d3249e9STim Keith [&](auto &x) -> const std::string * { 3335d3249e9STim Keith if constexpr (HasBindName<decltype(&x)>) { 3345d3249e9STim Keith return x.bindName(); 3355d3249e9STim Keith } else { 3365d3249e9STim Keith return nullptr; 3375d3249e9STim Keith } 3385d3249e9STim Keith }, 3395d3249e9STim Keith details_); 3405d3249e9STim Keith } 3415d3249e9STim Keith 3425d3249e9STim Keith void Symbol::SetBindName(std::string &&name) { 343cd03e96fSPeter Klausler common::visit( 3445d3249e9STim Keith [&](auto &x) { 3455d3249e9STim Keith if constexpr (HasBindName<decltype(&x)>) { 3465d3249e9STim Keith x.set_bindName(std::move(name)); 3475d3249e9STim Keith } else { 3485d3249e9STim Keith DIE("bind name not allowed on this kind of symbol"); 3495d3249e9STim Keith } 3505d3249e9STim Keith }, 3515d3249e9STim Keith details_); 3525d3249e9STim Keith } 3535d3249e9STim Keith 35469e2665cSPeter Klausler bool Symbol::GetIsExplicitBindName() const { 35569e2665cSPeter Klausler return common::visit( 35669e2665cSPeter Klausler [&](auto &x) -> bool { 35769e2665cSPeter Klausler if constexpr (HasBindName<decltype(&x)>) { 35869e2665cSPeter Klausler return x.isExplicitBindName(); 35969e2665cSPeter Klausler } else { 36069e2665cSPeter Klausler return false; 36169e2665cSPeter Klausler } 36269e2665cSPeter Klausler }, 36369e2665cSPeter Klausler details_); 36469e2665cSPeter Klausler } 36569e2665cSPeter Klausler 36669e2665cSPeter Klausler void Symbol::SetIsExplicitBindName(bool yes) { 36769e2665cSPeter Klausler common::visit( 36869e2665cSPeter Klausler [&](auto &x) { 36969e2665cSPeter Klausler if constexpr (HasBindName<decltype(&x)>) { 37069e2665cSPeter Klausler x.set_isExplicitBindName(yes); 37169e2665cSPeter Klausler } else { 37269e2665cSPeter Klausler DIE("bind name not allowed on this kind of symbol"); 37369e2665cSPeter Klausler } 37469e2665cSPeter Klausler }, 37569e2665cSPeter Klausler details_); 37669e2665cSPeter Klausler } 37769e2665cSPeter Klausler 378f3c227b7SPeter Klausler void Symbol::SetIsCDefined(bool yes) { 379f3c227b7SPeter Klausler common::visit( 380f3c227b7SPeter Klausler [&](auto &x) { 381f3c227b7SPeter Klausler if constexpr (HasBindName<decltype(&x)>) { 382f3c227b7SPeter Klausler x.set_isCDefined(yes); 383f3c227b7SPeter Klausler } else { 384f3c227b7SPeter Klausler DIE("CDEFINED not allowed on this kind of symbol"); 385f3c227b7SPeter Klausler } 386f3c227b7SPeter Klausler }, 387f3c227b7SPeter Klausler details_); 388f3c227b7SPeter Klausler } 389f3c227b7SPeter Klausler 39064ab3302SCarolineConcatto bool Symbol::IsFuncResult() const { 391cd03e96fSPeter Klausler return common::visit( 39264ab3302SCarolineConcatto common::visitors{[](const EntityDetails &x) { return x.isFuncResult(); }, 39364ab3302SCarolineConcatto [](const ObjectEntityDetails &x) { return x.isFuncResult(); }, 39464ab3302SCarolineConcatto [](const ProcEntityDetails &x) { return x.isFuncResult(); }, 39564ab3302SCarolineConcatto [](const HostAssocDetails &x) { return x.symbol().IsFuncResult(); }, 39664ab3302SCarolineConcatto [](const auto &) { return false; }}, 39764ab3302SCarolineConcatto details_); 39864ab3302SCarolineConcatto } 39964ab3302SCarolineConcatto 40070d1844aSPeter Klausler const ArraySpec *Symbol::GetShape() const { 40170d1844aSPeter Klausler if (const auto *details{std::get_if<ObjectEntityDetails>(&details_)}) { 40270d1844aSPeter Klausler return &details->shape(); 40370d1844aSPeter Klausler } else { 40470d1844aSPeter Klausler return nullptr; 40570d1844aSPeter Klausler } 40670d1844aSPeter Klausler } 40770d1844aSPeter Klausler 40864ab3302SCarolineConcatto bool Symbol::IsObjectArray() const { 40970d1844aSPeter Klausler const ArraySpec *shape{GetShape()}; 41070d1844aSPeter Klausler return shape && !shape->empty(); 41164ab3302SCarolineConcatto } 41264ab3302SCarolineConcatto 41364ab3302SCarolineConcatto bool Symbol::IsSubprogram() const { 414cd03e96fSPeter Klausler return common::visit( 41564ab3302SCarolineConcatto common::visitors{ 41664ab3302SCarolineConcatto [](const SubprogramDetails &) { return true; }, 41764ab3302SCarolineConcatto [](const SubprogramNameDetails &) { return true; }, 41864ab3302SCarolineConcatto [](const GenericDetails &) { return true; }, 41964ab3302SCarolineConcatto [](const UseDetails &x) { return x.symbol().IsSubprogram(); }, 42064ab3302SCarolineConcatto [](const auto &) { return false; }, 42164ab3302SCarolineConcatto }, 42264ab3302SCarolineConcatto details_); 42364ab3302SCarolineConcatto } 42464ab3302SCarolineConcatto 42564ab3302SCarolineConcatto bool Symbol::IsFromModFile() const { 42664ab3302SCarolineConcatto return test(Flag::ModFile) || 42752a1346bSPeter Klausler (!owner_->IsTopLevel() && owner_->symbol()->IsFromModFile()); 42864ab3302SCarolineConcatto } 42964ab3302SCarolineConcatto 4308670e499SCaroline Concatto llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const EntityDetails &x) { 43164ab3302SCarolineConcatto DumpBool(os, "dummy", x.isDummy()); 43264ab3302SCarolineConcatto DumpBool(os, "funcResult", x.isFuncResult()); 43364ab3302SCarolineConcatto if (x.type()) { 43464ab3302SCarolineConcatto os << " type: " << *x.type(); 43564ab3302SCarolineConcatto } 4365d3249e9STim Keith DumpOptional(os, "bindName", x.bindName()); 437f3c227b7SPeter Klausler DumpBool(os, "CDEFINED", x.isCDefined()); 43864ab3302SCarolineConcatto return os; 43964ab3302SCarolineConcatto } 44064ab3302SCarolineConcatto 4418670e499SCaroline Concatto llvm::raw_ostream &operator<<( 4428670e499SCaroline Concatto llvm::raw_ostream &os, const ObjectEntityDetails &x) { 44364ab3302SCarolineConcatto os << *static_cast<const EntityDetails *>(&x); 44464ab3302SCarolineConcatto DumpList(os, "shape", x.shape()); 44564ab3302SCarolineConcatto DumpList(os, "coshape", x.coshape()); 44664ab3302SCarolineConcatto DumpExpr(os, "init", x.init_); 4479e7eef99SPeter Klausler if (x.unanalyzedPDTComponentInit()) { 4489e7eef99SPeter Klausler os << " (has unanalyzedPDTComponentInit)"; 4499e7eef99SPeter Klausler } 450864cb2aaSPeter Klausler if (!x.ignoreTKR_.empty()) { 451e5ccfbbfSPeter Klausler x.ignoreTKR_.Dump(os << ' ', common::EnumToString); 452864cb2aaSPeter Klausler } 45327f71807SPeter Klausler if (x.cudaDataAttr()) { 45427f71807SPeter Klausler os << " cudaDataAttr: " << common::EnumToString(*x.cudaDataAttr()); 45527f71807SPeter Klausler } 45664ab3302SCarolineConcatto return os; 45764ab3302SCarolineConcatto } 45864ab3302SCarolineConcatto 4598670e499SCaroline Concatto llvm::raw_ostream &operator<<( 4608670e499SCaroline Concatto llvm::raw_ostream &os, const AssocEntityDetails &x) { 46164ab3302SCarolineConcatto os << *static_cast<const EntityDetails *>(&x); 4624fed5959SPeter Klausler if (x.IsAssumedSize()) { 4634fed5959SPeter Klausler os << " RANK(*)"; 4644fed5959SPeter Klausler } else if (x.IsAssumedRank()) { 4654fed5959SPeter Klausler os << " RANK DEFAULT"; 4664fed5959SPeter Klausler } else if (auto assocRank{x.rank()}) { 4674fed5959SPeter Klausler os << " RANK(" << *assocRank << ')'; 468332e6aeaSsameeran joshi } 46964ab3302SCarolineConcatto DumpExpr(os, "expr", x.expr()); 47064ab3302SCarolineConcatto return os; 47164ab3302SCarolineConcatto } 47264ab3302SCarolineConcatto 4738670e499SCaroline Concatto llvm::raw_ostream &operator<<( 4748670e499SCaroline Concatto llvm::raw_ostream &os, const ProcEntityDetails &x) { 475635656f4SPeter Klausler if (x.procInterface_) { 47683ca78deSPeter Klausler if (x.rawProcInterface_ != x.procInterface_) { 47783ca78deSPeter Klausler os << ' ' << x.rawProcInterface_->name() << " ->"; 47883ca78deSPeter Klausler } 479635656f4SPeter Klausler os << ' ' << x.procInterface_->name(); 48064ab3302SCarolineConcatto } else { 481635656f4SPeter Klausler DumpType(os, x.type()); 48264ab3302SCarolineConcatto } 4835d3249e9STim Keith DumpOptional(os, "bindName", x.bindName()); 48464ab3302SCarolineConcatto DumpOptional(os, "passName", x.passName()); 48564ab3302SCarolineConcatto if (x.init()) { 48664ab3302SCarolineConcatto if (const Symbol * target{*x.init()}) { 48764ab3302SCarolineConcatto os << " => " << target->name(); 48864ab3302SCarolineConcatto } else { 48964ab3302SCarolineConcatto os << " => NULL()"; 49064ab3302SCarolineConcatto } 49164ab3302SCarolineConcatto } 49227f71807SPeter Klausler if (x.isCUDAKernel()) { 49327f71807SPeter Klausler os << " isCUDAKernel"; 49427f71807SPeter Klausler } 49564ab3302SCarolineConcatto return os; 49664ab3302SCarolineConcatto } 49764ab3302SCarolineConcatto 4988670e499SCaroline Concatto llvm::raw_ostream &operator<<( 4998670e499SCaroline Concatto llvm::raw_ostream &os, const DerivedTypeDetails &x) { 50064ab3302SCarolineConcatto DumpBool(os, "sequence", x.sequence_); 50164ab3302SCarolineConcatto DumpList(os, "components", x.componentNames_); 50264ab3302SCarolineConcatto return os; 50364ab3302SCarolineConcatto } 50464ab3302SCarolineConcatto 50586f59de1STim Keith llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const GenericDetails &x) { 50686f59de1STim Keith os << ' ' << x.kind().ToString(); 50786f59de1STim Keith DumpBool(os, "(specific)", x.specific() != nullptr); 50886f59de1STim Keith DumpBool(os, "(derivedType)", x.derivedType() != nullptr); 50986f59de1STim Keith if (const auto &uses{x.uses()}; !uses.empty()) { 51086f59de1STim Keith os << " (uses:"; 51186f59de1STim Keith char sep{' '}; 51286f59de1STim Keith for (const Symbol &use : uses) { 51386f59de1STim Keith const Symbol &ultimate{use.GetUltimate()}; 51486f59de1STim Keith os << sep << ultimate.name() << "->" 51586f59de1STim Keith << ultimate.owner().GetName().value(); 51686f59de1STim Keith sep = ','; 51786f59de1STim Keith } 51886f59de1STim Keith os << ')'; 51986f59de1STim Keith } 52086f59de1STim Keith os << " procs:"; 52186f59de1STim Keith DumpSymbolVector(os, x.specificProcs()); 52286f59de1STim Keith return os; 52386f59de1STim Keith } 52486f59de1STim Keith 5258670e499SCaroline Concatto llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const Details &details) { 52664ab3302SCarolineConcatto os << DetailsToString(details); 527cd03e96fSPeter Klausler common::visit( // 52864ab3302SCarolineConcatto common::visitors{ 52964ab3302SCarolineConcatto [&](const UnknownDetails &) {}, 53064ab3302SCarolineConcatto [&](const MainProgramDetails &) {}, 53164ab3302SCarolineConcatto [&](const ModuleDetails &x) { 53264ab3302SCarolineConcatto if (x.isSubmodule()) { 53364ab3302SCarolineConcatto os << " ("; 53464ab3302SCarolineConcatto if (x.ancestor()) { 53564ab3302SCarolineConcatto auto ancestor{x.ancestor()->GetName().value()}; 53664ab3302SCarolineConcatto os << ancestor; 53764ab3302SCarolineConcatto if (x.parent()) { 53864ab3302SCarolineConcatto auto parent{x.parent()->GetName().value()}; 53964ab3302SCarolineConcatto if (ancestor != parent) { 54064ab3302SCarolineConcatto os << ':' << parent; 54164ab3302SCarolineConcatto } 54264ab3302SCarolineConcatto } 54364ab3302SCarolineConcatto } 54464ab3302SCarolineConcatto os << ")"; 54564ab3302SCarolineConcatto } 546689de4c6SPeter Klausler if (x.isDefaultPrivate()) { 547689de4c6SPeter Klausler os << " isDefaultPrivate"; 548689de4c6SPeter Klausler } 54964ab3302SCarolineConcatto }, 55064ab3302SCarolineConcatto [&](const SubprogramNameDetails &x) { 55164ab3302SCarolineConcatto os << ' ' << EnumToString(x.kind()); 55264ab3302SCarolineConcatto }, 55364ab3302SCarolineConcatto [&](const UseDetails &x) { 55414f49599STim Keith os << " from " << x.symbol().name() << " in " 55514f49599STim Keith << GetUsedModule(x).name(); 55664ab3302SCarolineConcatto }, 55764ab3302SCarolineConcatto [&](const UseErrorDetails &x) { 55864ab3302SCarolineConcatto os << " uses:"; 5593a0352b8STim Keith char sep{':'}; 560*038b42baSPeter Klausler for (const auto &[location, sym] : x.occurrences()) { 561*038b42baSPeter Klausler os << sep << " from " << sym->name() << " at " << location; 5623a0352b8STim Keith sep = ','; 56364ab3302SCarolineConcatto } 56464ab3302SCarolineConcatto }, 56564ab3302SCarolineConcatto [](const HostAssocDetails &) {}, 56664ab3302SCarolineConcatto [&](const ProcBindingDetails &x) { 56764ab3302SCarolineConcatto os << " => " << x.symbol().name(); 56864ab3302SCarolineConcatto DumpOptional(os, "passName", x.passName()); 5697f7bbc73SPeter Klausler if (x.numPrivatesNotOverridden() > 0) { 5707f7bbc73SPeter Klausler os << " numPrivatesNotOverridden: " 5717f7bbc73SPeter Klausler << x.numPrivatesNotOverridden(); 5727f7bbc73SPeter Klausler } 57364ab3302SCarolineConcatto }, 57464ab3302SCarolineConcatto [&](const NamelistDetails &x) { 57564ab3302SCarolineConcatto os << ':'; 57664ab3302SCarolineConcatto DumpSymbolVector(os, x.objects()); 57764ab3302SCarolineConcatto }, 57864ab3302SCarolineConcatto [&](const CommonBlockDetails &x) { 5795d3249e9STim Keith DumpOptional(os, "bindName", x.bindName()); 58054b35c06STim Keith if (x.alignment()) { 58154b35c06STim Keith os << " alignment=" << x.alignment(); 582237d0e3cSTim Keith } 58364ab3302SCarolineConcatto os << ':'; 584d5c05cedSTim Keith for (const auto &object : x.objects()) { 585d5c05cedSTim Keith os << ' ' << object->name(); 58664ab3302SCarolineConcatto } 58764ab3302SCarolineConcatto }, 58864ab3302SCarolineConcatto [&](const TypeParamDetails &x) { 58964ab3302SCarolineConcatto DumpOptional(os, "type", x.type()); 590539a6b50SPeter Klausler if (auto attr{x.attr()}) { 591539a6b50SPeter Klausler os << ' ' << common::EnumToString(*attr); 592539a6b50SPeter Klausler } else { 593539a6b50SPeter Klausler os << " (no attr)"; 594539a6b50SPeter Klausler } 59564ab3302SCarolineConcatto DumpExpr(os, "init", x.init()); 59664ab3302SCarolineConcatto }, 59764ab3302SCarolineConcatto [&](const MiscDetails &x) { 59864ab3302SCarolineConcatto os << ' ' << MiscDetails::EnumToString(x.kind()); 59964ab3302SCarolineConcatto }, 60064ab3302SCarolineConcatto [&](const auto &x) { os << x; }, 60164ab3302SCarolineConcatto }, 60264ab3302SCarolineConcatto details); 60364ab3302SCarolineConcatto return os; 60464ab3302SCarolineConcatto } 60564ab3302SCarolineConcatto 6068670e499SCaroline Concatto llvm::raw_ostream &operator<<(llvm::raw_ostream &o, Symbol::Flag flag) { 60764ab3302SCarolineConcatto return o << Symbol::EnumToString(flag); 60864ab3302SCarolineConcatto } 60964ab3302SCarolineConcatto 6108670e499SCaroline Concatto llvm::raw_ostream &operator<<( 6118670e499SCaroline Concatto llvm::raw_ostream &o, const Symbol::Flags &flags) { 61264ab3302SCarolineConcatto std::size_t n{flags.count()}; 61364ab3302SCarolineConcatto std::size_t seen{0}; 61464ab3302SCarolineConcatto for (std::size_t j{0}; seen < n; ++j) { 61564ab3302SCarolineConcatto Symbol::Flag flag{static_cast<Symbol::Flag>(j)}; 61664ab3302SCarolineConcatto if (flags.test(flag)) { 61764ab3302SCarolineConcatto if (seen++ > 0) { 61864ab3302SCarolineConcatto o << ", "; 61964ab3302SCarolineConcatto } 62064ab3302SCarolineConcatto o << flag; 62164ab3302SCarolineConcatto } 62264ab3302SCarolineConcatto } 62364ab3302SCarolineConcatto return o; 62464ab3302SCarolineConcatto } 62564ab3302SCarolineConcatto 6268670e499SCaroline Concatto llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const Symbol &symbol) { 62764ab3302SCarolineConcatto os << symbol.name(); 62864ab3302SCarolineConcatto if (!symbol.attrs().empty()) { 62964ab3302SCarolineConcatto os << ", " << symbol.attrs(); 63064ab3302SCarolineConcatto } 63164ab3302SCarolineConcatto if (!symbol.flags().empty()) { 63264ab3302SCarolineConcatto os << " (" << symbol.flags() << ')'; 63364ab3302SCarolineConcatto } 634c353ebbfSTim Keith if (symbol.size_) { 635c353ebbfSTim Keith os << " size=" << symbol.size_ << " offset=" << symbol.offset_; 636c353ebbfSTim Keith } 63764ab3302SCarolineConcatto os << ": " << symbol.details_; 63864ab3302SCarolineConcatto return os; 63964ab3302SCarolineConcatto } 64064ab3302SCarolineConcatto 641fdcbb540SJean Perier #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 642fdcbb540SJean Perier void Symbol::dump() const { llvm::errs() << *this << '\n'; } 643fdcbb540SJean Perier #endif 644fdcbb540SJean Perier 64564ab3302SCarolineConcatto // Output a unique name for a scope by qualifying it with the names of 64664ab3302SCarolineConcatto // parent scopes. For scopes without corresponding symbols, use the kind 64764ab3302SCarolineConcatto // with an index (e.g. Block1, Block2, etc.). 6488670e499SCaroline Concatto static void DumpUniqueName(llvm::raw_ostream &os, const Scope &scope) { 64952a1346bSPeter Klausler if (!scope.IsTopLevel()) { 65064ab3302SCarolineConcatto DumpUniqueName(os, scope.parent()); 65164ab3302SCarolineConcatto os << '/'; 65264ab3302SCarolineConcatto if (auto *scopeSymbol{scope.symbol()}; 65364ab3302SCarolineConcatto scopeSymbol && !scopeSymbol->name().empty()) { 65464ab3302SCarolineConcatto os << scopeSymbol->name(); 65564ab3302SCarolineConcatto } else { 65664ab3302SCarolineConcatto int index{1}; 65764ab3302SCarolineConcatto for (auto &child : scope.parent().children()) { 65864ab3302SCarolineConcatto if (child == scope) { 65964ab3302SCarolineConcatto break; 66064ab3302SCarolineConcatto } 66164ab3302SCarolineConcatto if (child.kind() == scope.kind()) { 66264ab3302SCarolineConcatto ++index; 66364ab3302SCarolineConcatto } 66464ab3302SCarolineConcatto } 66564ab3302SCarolineConcatto os << Scope::EnumToString(scope.kind()) << index; 66664ab3302SCarolineConcatto } 66764ab3302SCarolineConcatto } 66864ab3302SCarolineConcatto } 66964ab3302SCarolineConcatto 67064ab3302SCarolineConcatto // Dump a symbol for UnparseWithSymbols. This will be used for tests so the 67164ab3302SCarolineConcatto // format should be reasonably stable. 6728670e499SCaroline Concatto llvm::raw_ostream &DumpForUnparse( 6738670e499SCaroline Concatto llvm::raw_ostream &os, const Symbol &symbol, bool isDef) { 67464ab3302SCarolineConcatto DumpUniqueName(os, symbol.owner()); 67564ab3302SCarolineConcatto os << '/' << symbol.name(); 67664ab3302SCarolineConcatto if (isDef) { 67764ab3302SCarolineConcatto if (!symbol.attrs().empty()) { 67864ab3302SCarolineConcatto os << ' ' << symbol.attrs(); 67964ab3302SCarolineConcatto } 68064ab3302SCarolineConcatto if (!symbol.flags().empty()) { 68164ab3302SCarolineConcatto os << " (" << symbol.flags() << ')'; 68264ab3302SCarolineConcatto } 68364ab3302SCarolineConcatto os << ' ' << symbol.GetDetailsName(); 68464ab3302SCarolineConcatto DumpType(os, symbol.GetType()); 68564ab3302SCarolineConcatto } 68664ab3302SCarolineConcatto return os; 68764ab3302SCarolineConcatto } 68864ab3302SCarolineConcatto 68964ab3302SCarolineConcatto const DerivedTypeSpec *Symbol::GetParentTypeSpec(const Scope *scope) const { 69064ab3302SCarolineConcatto if (const Symbol * parentComponent{GetParentComponent(scope)}) { 69164ab3302SCarolineConcatto const auto &object{parentComponent->get<ObjectEntityDetails>()}; 69264ab3302SCarolineConcatto return &object.type()->derivedTypeSpec(); 69364ab3302SCarolineConcatto } else { 69464ab3302SCarolineConcatto return nullptr; 69564ab3302SCarolineConcatto } 69664ab3302SCarolineConcatto } 69764ab3302SCarolineConcatto 69864ab3302SCarolineConcatto const Symbol *Symbol::GetParentComponent(const Scope *scope) const { 69964ab3302SCarolineConcatto if (const auto *dtDetails{detailsIf<DerivedTypeDetails>()}) { 700398fcf22SPeter Steinfeld if (const Scope * localScope{scope ? scope : scope_}) { 701398fcf22SPeter Steinfeld return dtDetails->GetParentComponent(DEREF(localScope)); 70264ab3302SCarolineConcatto } 703398fcf22SPeter Steinfeld } 70464ab3302SCarolineConcatto return nullptr; 70564ab3302SCarolineConcatto } 70664ab3302SCarolineConcatto 70764ab3302SCarolineConcatto void DerivedTypeDetails::add_component(const Symbol &symbol) { 70864ab3302SCarolineConcatto if (symbol.test(Symbol::Flag::ParentComp)) { 70964ab3302SCarolineConcatto CHECK(componentNames_.empty()); 71064ab3302SCarolineConcatto } 71164ab3302SCarolineConcatto componentNames_.push_back(symbol.name()); 71264ab3302SCarolineConcatto } 71364ab3302SCarolineConcatto 71464ab3302SCarolineConcatto const Symbol *DerivedTypeDetails::GetParentComponent(const Scope &scope) const { 71564ab3302SCarolineConcatto if (auto extends{GetParentComponentName()}) { 71664ab3302SCarolineConcatto if (auto iter{scope.find(*extends)}; iter != scope.cend()) { 71764ab3302SCarolineConcatto if (const Symbol & symbol{*iter->second}; 71864ab3302SCarolineConcatto symbol.test(Symbol::Flag::ParentComp)) { 71964ab3302SCarolineConcatto return &symbol; 72064ab3302SCarolineConcatto } 72164ab3302SCarolineConcatto } 72264ab3302SCarolineConcatto } 72364ab3302SCarolineConcatto return nullptr; 72464ab3302SCarolineConcatto } 72564ab3302SCarolineConcatto 726c1168676Speter klausler const Symbol *DerivedTypeDetails::GetFinalForRank(int rank) const { 727c1168676Speter klausler for (const auto &pair : finals_) { 728c1168676Speter klausler const Symbol &symbol{*pair.second}; 729c1168676Speter klausler if (const auto *details{symbol.detailsIf<SubprogramDetails>()}) { 730c1168676Speter klausler if (details->dummyArgs().size() == 1) { 731c1168676Speter klausler if (const Symbol * arg{details->dummyArgs().at(0)}) { 732c1168676Speter klausler if (const auto *object{arg->detailsIf<ObjectEntityDetails>()}) { 733c1168676Speter klausler if (rank == object->shape().Rank() || object->IsAssumedRank() || 7346052025bSPeter Klausler IsElementalProcedure(symbol)) { 735c1168676Speter klausler return &symbol; 736c1168676Speter klausler } 737c1168676Speter klausler } 738c1168676Speter klausler } 739c1168676Speter klausler } 740c1168676Speter klausler } 741c1168676Speter klausler } 742c1168676Speter klausler return nullptr; 743c1168676Speter klausler } 744c1168676Speter klausler 745539a6b50SPeter Klausler TypeParamDetails &TypeParamDetails::set_attr(common::TypeParamAttr attr) { 746539a6b50SPeter Klausler CHECK(!attr_); 747539a6b50SPeter Klausler attr_ = attr; 748539a6b50SPeter Klausler return *this; 749539a6b50SPeter Klausler } 750539a6b50SPeter Klausler 751539a6b50SPeter Klausler TypeParamDetails &TypeParamDetails::set_type(const DeclTypeSpec &type) { 75264ab3302SCarolineConcatto CHECK(!type_); 75364ab3302SCarolineConcatto type_ = &type; 754539a6b50SPeter Klausler return *this; 75564ab3302SCarolineConcatto } 75664ab3302SCarolineConcatto 75764ab3302SCarolineConcatto bool GenericKind::IsIntrinsicOperator() const { 75864ab3302SCarolineConcatto return Is(OtherKind::Concat) || Has<common::LogicalOperator>() || 75964ab3302SCarolineConcatto Has<common::NumericOperator>() || Has<common::RelationalOperator>(); 76064ab3302SCarolineConcatto } 76164ab3302SCarolineConcatto 76264ab3302SCarolineConcatto bool GenericKind::IsOperator() const { 76364ab3302SCarolineConcatto return IsDefinedOperator() || IsIntrinsicOperator(); 76464ab3302SCarolineConcatto } 76564ab3302SCarolineConcatto 76664ab3302SCarolineConcatto std::string GenericKind::ToString() const { 767cd03e96fSPeter Klausler return common::visit( 76864ab3302SCarolineConcatto common::visitors{ 769bcba39a5SPeter Klausler [](const OtherKind &x) { return std::string{EnumToString(x)}; }, 7707cf1608bSPeter Klausler [](const common::DefinedIo &x) { return AsFortran(x).ToString(); }, 771bcba39a5SPeter Klausler [](const auto &x) { return std::string{common::EnumToString(x)}; }, 77264ab3302SCarolineConcatto }, 77364ab3302SCarolineConcatto u); 77464ab3302SCarolineConcatto } 77564ab3302SCarolineConcatto 7767cf1608bSPeter Klausler SourceName GenericKind::AsFortran(common::DefinedIo x) { 7777cf1608bSPeter Klausler const char *name{common::AsFortran(x)}; 77819d86426SPeter Klausler return {name, std::strlen(name)}; 77919d86426SPeter Klausler } 78019d86426SPeter Klausler 78164ab3302SCarolineConcatto bool GenericKind::Is(GenericKind::OtherKind x) const { 78264ab3302SCarolineConcatto const OtherKind *y{std::get_if<OtherKind>(&u)}; 78364ab3302SCarolineConcatto return y && *y == x; 78464ab3302SCarolineConcatto } 78564ab3302SCarolineConcatto 7866d1c183cSRaghu Maddhipatla std::string Symbol::OmpFlagToClauseName(Symbol::Flag ompFlag) { 7876d1c183cSRaghu Maddhipatla std::string clauseName; 7886d1c183cSRaghu Maddhipatla switch (ompFlag) { 7896d1c183cSRaghu Maddhipatla case Symbol::Flag::OmpShared: 7906d1c183cSRaghu Maddhipatla clauseName = "SHARED"; 7916d1c183cSRaghu Maddhipatla break; 7926d1c183cSRaghu Maddhipatla case Symbol::Flag::OmpPrivate: 7936d1c183cSRaghu Maddhipatla clauseName = "PRIVATE"; 7946d1c183cSRaghu Maddhipatla break; 7956d1c183cSRaghu Maddhipatla case Symbol::Flag::OmpLinear: 7966d1c183cSRaghu Maddhipatla clauseName = "LINEAR"; 7976d1c183cSRaghu Maddhipatla break; 7986d1c183cSRaghu Maddhipatla case Symbol::Flag::OmpFirstPrivate: 7996d1c183cSRaghu Maddhipatla clauseName = "FIRSTPRIVATE"; 8006d1c183cSRaghu Maddhipatla break; 8016d1c183cSRaghu Maddhipatla case Symbol::Flag::OmpLastPrivate: 8026d1c183cSRaghu Maddhipatla clauseName = "LASTPRIVATE"; 8036d1c183cSRaghu Maddhipatla break; 8046d1c183cSRaghu Maddhipatla case Symbol::Flag::OmpMapTo: 8056d1c183cSRaghu Maddhipatla case Symbol::Flag::OmpMapFrom: 8066d1c183cSRaghu Maddhipatla case Symbol::Flag::OmpMapToFrom: 8076d1c183cSRaghu Maddhipatla case Symbol::Flag::OmpMapAlloc: 8086d1c183cSRaghu Maddhipatla case Symbol::Flag::OmpMapRelease: 8096d1c183cSRaghu Maddhipatla case Symbol::Flag::OmpMapDelete: 8106d1c183cSRaghu Maddhipatla clauseName = "MAP"; 8116d1c183cSRaghu Maddhipatla break; 8126d1c183cSRaghu Maddhipatla case Symbol::Flag::OmpUseDevicePtr: 8136d1c183cSRaghu Maddhipatla clauseName = "USE_DEVICE_PTR"; 8146d1c183cSRaghu Maddhipatla break; 8156d1c183cSRaghu Maddhipatla case Symbol::Flag::OmpUseDeviceAddr: 8166d1c183cSRaghu Maddhipatla clauseName = "USE_DEVICE_ADDR"; 8176d1c183cSRaghu Maddhipatla break; 8186d1c183cSRaghu Maddhipatla case Symbol::Flag::OmpCopyIn: 8196d1c183cSRaghu Maddhipatla clauseName = "COPYIN"; 8206d1c183cSRaghu Maddhipatla break; 8216d1c183cSRaghu Maddhipatla case Symbol::Flag::OmpCopyPrivate: 8226d1c183cSRaghu Maddhipatla clauseName = "COPYPRIVATE"; 8236d1c183cSRaghu Maddhipatla break; 82480b571c6SRaghu Maddhipatla case Symbol::Flag::OmpIsDevicePtr: 82580b571c6SRaghu Maddhipatla clauseName = "IS_DEVICE_PTR"; 82680b571c6SRaghu Maddhipatla break; 82780b571c6SRaghu Maddhipatla case Symbol::Flag::OmpHasDeviceAddr: 82880b571c6SRaghu Maddhipatla clauseName = "HAS_DEVICE_ADDR"; 82980b571c6SRaghu Maddhipatla break; 8306d1c183cSRaghu Maddhipatla default: 8316d1c183cSRaghu Maddhipatla clauseName = ""; 8326d1c183cSRaghu Maddhipatla break; 8336d1c183cSRaghu Maddhipatla } 8346d1c183cSRaghu Maddhipatla return clauseName; 8356d1c183cSRaghu Maddhipatla } 8366d1c183cSRaghu Maddhipatla 83774d5c3c0SPeter Steinfeld bool SymbolOffsetCompare::operator()( 83874d5c3c0SPeter Steinfeld const SymbolRef &x, const SymbolRef &y) const { 839d60a0220Speter klausler const Symbol *xCommon{FindCommonBlockContaining(*x)}; 840d60a0220Speter klausler const Symbol *yCommon{FindCommonBlockContaining(*y)}; 841d60a0220Speter klausler if (xCommon) { 842d60a0220Speter klausler if (yCommon) { 843d60a0220Speter klausler const SymbolSourcePositionCompare sourceCmp; 844d60a0220Speter klausler if (sourceCmp(*xCommon, *yCommon)) { 845d60a0220Speter klausler return true; 846d60a0220Speter klausler } else if (sourceCmp(*yCommon, *xCommon)) { 847d60a0220Speter klausler return false; 848d60a0220Speter klausler } else if (x->offset() == y->offset()) { 849d60a0220Speter klausler return x->size() > y->size(); 850d60a0220Speter klausler } else { 851d60a0220Speter klausler return x->offset() < y->offset(); 852d60a0220Speter klausler } 853d60a0220Speter klausler } else { 854d60a0220Speter klausler return false; 855d60a0220Speter klausler } 856d60a0220Speter klausler } else if (yCommon) { 857d60a0220Speter klausler return true; 858d60a0220Speter klausler } else if (x->offset() == y->offset()) { 859d60a0220Speter klausler return x->size() > y->size(); 860d60a0220Speter klausler } else { 861d60a0220Speter klausler return x->offset() < y->offset(); 862d60a0220Speter klausler } 863d60a0220Speter klausler return x->GetSemanticsContext().allCookedSources().Precedes( 864d60a0220Speter klausler x->name(), y->name()); 865d60a0220Speter klausler } 86619d86426SPeter Klausler 867d60a0220Speter klausler bool SymbolOffsetCompare::operator()( 868d60a0220Speter klausler const MutableSymbolRef &x, const MutableSymbolRef &y) const { 869d60a0220Speter klausler return (*this)(SymbolRef{*x}, SymbolRef{*y}); 870d60a0220Speter klausler } 871d60a0220Speter klausler 8721f879005STim Keith } // namespace Fortran::semantics 873