xref: /llvm-project/flang/lib/Semantics/symbol.cpp (revision 038b42ba5b47b1aa2d47ef5706a713f6bfbbc37c)
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