1 //===-- lib/Semantics/symbol.cpp ------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "flang/Semantics/symbol.h"
10 #include "flang/Common/idioms.h"
11 #include "flang/Evaluate/expression.h"
12 #include "flang/Semantics/scope.h"
13 #include "flang/Semantics/semantics.h"
14 #include "flang/Semantics/tools.h"
15 #include "llvm/Support/raw_ostream.h"
18 #include <type_traits>
20 namespace Fortran::semantics
{
23 static void DumpOptional(llvm::raw_ostream
&os
, const char *label
, const T
&x
) {
25 os
<< ' ' << label
<< ':' << *x
;
29 static void DumpExpr(llvm::raw_ostream
&os
, const char *label
,
30 const std::optional
<evaluate::Expr
<T
>> &x
) {
32 x
->AsFortran(os
<< ' ' << label
<< ':');
36 static void DumpBool(llvm::raw_ostream
&os
, const char *label
, bool x
) {
42 static void DumpSymbolVector(llvm::raw_ostream
&os
, const SymbolVector
&list
) {
44 for (const Symbol
&elem
: list
) {
45 os
<< sep
<< elem
.name();
50 static void DumpType(llvm::raw_ostream
&os
, const Symbol
&symbol
) {
51 if (const auto *type
{symbol
.GetType()}) {
55 static void DumpType(llvm::raw_ostream
&os
, const DeclTypeSpec
*type
) {
62 static void DumpList(llvm::raw_ostream
&os
, const char *label
, const T
&list
) {
64 os
<< ' ' << label
<< ':';
66 for (const auto &elem
: list
) {
73 void SubprogramDetails::set_moduleInterface(Symbol
&symbol
) {
74 CHECK(!moduleInterface_
);
75 moduleInterface_
= &symbol
;
78 const Scope
*ModuleDetails::parent() const {
79 return isSubmodule_
&& scope_
? &scope_
->parent() : nullptr;
81 const Scope
*ModuleDetails::ancestor() const {
82 return isSubmodule_
&& scope_
? FindModuleContaining(*scope_
) : nullptr;
84 void ModuleDetails::set_scope(const Scope
*scope
) {
86 bool scopeIsSubmodule
{scope
->parent().kind() == Scope::Kind::Module
};
87 CHECK(isSubmodule_
== scopeIsSubmodule
);
91 llvm::raw_ostream
&operator<<(
92 llvm::raw_ostream
&os
, const SubprogramDetails
&x
) {
93 DumpBool(os
, "isInterface", x
.isInterface_
);
94 DumpBool(os
, "dummy", x
.isDummy_
);
95 DumpOptional(os
, "bindName", x
.bindName());
97 DumpType(os
<< " result:", x
.result());
98 os
<< x
.result_
->name();
99 if (!x
.result_
->attrs().empty()) {
100 os
<< ", " << x
.result_
->attrs();
105 if (x
.entryScope_
->symbol()) {
106 os
<< " in " << x
.entryScope_
->symbol()->name();
111 for (const Symbol
*arg
: x
.dummyArgs_
) {
121 os
<< (sep
== '(' ? "()" : ")");
122 if (x
.stmtFunction_
) {
123 os
<< " -> " << x
.stmtFunction_
->AsFortran();
125 if (x
.moduleInterface_
) {
126 os
<< " moduleInterface: " << *x
.moduleInterface_
;
128 if (x
.defaultIgnoreTKR_
) {
129 os
<< " defaultIgnoreTKR";
131 if (x
.cudaSubprogramAttrs_
) {
132 os
<< " cudaSubprogramAttrs: "
133 << common::EnumToString(*x
.cudaSubprogramAttrs_
);
135 if (!x
.cudaLaunchBounds_
.empty()) {
136 os
<< " cudaLaunchBounds:";
137 for (auto x
: x
.cudaLaunchBounds_
) {
141 if (!x
.cudaClusterDims_
.empty()) {
142 os
<< " cudaClusterDims:";
143 for (auto x
: x
.cudaClusterDims_
) {
150 void EntityDetails::set_type(const DeclTypeSpec
&type
) {
155 void AssocEntityDetails::set_rank(int rank
) { rank_
= rank
; }
156 void AssocEntityDetails::set_IsAssumedSize() { rank_
= isAssumedSize
; }
157 void AssocEntityDetails::set_IsAssumedRank() { rank_
= isAssumedRank
; }
158 void EntityDetails::ReplaceType(const DeclTypeSpec
&type
) { type_
= &type
; }
160 ObjectEntityDetails::ObjectEntityDetails(EntityDetails
&&d
)
161 : EntityDetails(std::move(d
)) {}
163 void ObjectEntityDetails::set_shape(const ArraySpec
&shape
) {
164 CHECK(shape_
.empty());
165 for (const auto &shapeSpec
: shape
) {
166 shape_
.push_back(shapeSpec
);
169 void ObjectEntityDetails::set_coshape(const ArraySpec
&coshape
) {
170 CHECK(coshape_
.empty());
171 for (const auto &shapeSpec
: coshape
) {
172 coshape_
.push_back(shapeSpec
);
176 ProcEntityDetails::ProcEntityDetails(EntityDetails
&&d
)
177 : EntityDetails(std::move(d
)) {}
179 UseErrorDetails::UseErrorDetails(const UseDetails
&useDetails
) {
180 add_occurrence(useDetails
.location(), *GetUsedModule(useDetails
).scope());
182 UseErrorDetails
&UseErrorDetails::add_occurrence(
183 const SourceName
&location
, const Scope
&module
) {
184 occurrences_
.push_back(std::make_pair(location
, &module
));
188 void GenericDetails::AddSpecificProc(
189 const Symbol
&proc
, SourceName bindingName
) {
190 specificProcs_
.push_back(proc
);
191 bindingNames_
.push_back(bindingName
);
193 void GenericDetails::set_specific(Symbol
&specific
) {
195 specific_
= &specific
;
197 void GenericDetails::clear_specific() { specific_
= nullptr; }
198 void GenericDetails::set_derivedType(Symbol
&derivedType
) {
199 CHECK(!derivedType_
);
200 derivedType_
= &derivedType
;
202 void GenericDetails::clear_derivedType() { derivedType_
= nullptr; }
203 void GenericDetails::AddUse(const Symbol
&use
) {
204 CHECK(use
.has
<UseDetails
>());
205 uses_
.push_back(use
);
208 const Symbol
*GenericDetails::CheckSpecific() const {
209 return const_cast<GenericDetails
*>(this)->CheckSpecific();
211 Symbol
*GenericDetails::CheckSpecific() {
212 if (specific_
&& !specific_
->has
<UseErrorDetails
>()) {
213 const Symbol
&ultimate
{specific_
->GetUltimate()};
214 for (const Symbol
&proc
: specificProcs_
) {
215 if (&proc
.GetUltimate() == &ultimate
) {
225 void GenericDetails::CopyFrom(const GenericDetails
&from
) {
226 CHECK(specificProcs_
.size() == bindingNames_
.size());
227 CHECK(from
.specificProcs_
.size() == from
.bindingNames_
.size());
229 if (from
.derivedType_
) {
230 CHECK(!derivedType_
|| derivedType_
== from
.derivedType_
);
231 derivedType_
= from
.derivedType_
;
233 for (std::size_t i
{0}; i
< from
.specificProcs_
.size(); ++i
) {
234 if (llvm::none_of(specificProcs_
, [&](const Symbol
&mySymbol
) {
235 return &mySymbol
.GetUltimate() ==
236 &from
.specificProcs_
[i
]->GetUltimate();
238 specificProcs_
.push_back(from
.specificProcs_
[i
]);
239 bindingNames_
.push_back(from
.bindingNames_
[i
]);
244 // The name of the kind of details for this symbol.
245 // This is primarily for debugging.
246 std::string
DetailsToString(const Details
&details
) {
247 return common::visit(
249 [](const UnknownDetails
&) { return "Unknown"; },
250 [](const MainProgramDetails
&) { return "MainProgram"; },
251 [](const ModuleDetails
&) { return "Module"; },
252 [](const SubprogramDetails
&) { return "Subprogram"; },
253 [](const SubprogramNameDetails
&) { return "SubprogramName"; },
254 [](const EntityDetails
&) { return "Entity"; },
255 [](const ObjectEntityDetails
&) { return "ObjectEntity"; },
256 [](const ProcEntityDetails
&) { return "ProcEntity"; },
257 [](const DerivedTypeDetails
&) { return "DerivedType"; },
258 [](const UseDetails
&) { return "Use"; },
259 [](const UseErrorDetails
&) { return "UseError"; },
260 [](const HostAssocDetails
&) { return "HostAssoc"; },
261 [](const GenericDetails
&) { return "Generic"; },
262 [](const ProcBindingDetails
&) { return "ProcBinding"; },
263 [](const NamelistDetails
&) { return "Namelist"; },
264 [](const CommonBlockDetails
&) { return "CommonBlockDetails"; },
265 [](const TypeParamDetails
&) { return "TypeParam"; },
266 [](const MiscDetails
&) { return "Misc"; },
267 [](const AssocEntityDetails
&) { return "AssocEntity"; },
272 std::string
Symbol::GetDetailsName() const { return DetailsToString(details_
); }
274 void Symbol::set_details(Details
&&details
) {
275 CHECK(CanReplaceDetails(details
));
276 details_
= std::move(details
);
279 bool Symbol::CanReplaceDetails(const Details
&details
) const {
280 if (has
<UnknownDetails
>()) {
281 return true; // can always replace UnknownDetails
283 return common::visit(
285 [](const UseErrorDetails
&) { return true; },
286 [&](const ObjectEntityDetails
&) { return has
<EntityDetails
>(); },
287 [&](const ProcEntityDetails
&) { return has
<EntityDetails
>(); },
288 [&](const SubprogramDetails
&) {
289 return has
<SubprogramNameDetails
>() || has
<EntityDetails
>();
291 [&](const DerivedTypeDetails
&) {
292 const auto *derived
{this->detailsIf
<DerivedTypeDetails
>()};
293 return derived
&& derived
->isForwardReferenced();
295 [&](const UseDetails
&x
) {
296 const auto *use
{this->detailsIf
<UseDetails
>()};
297 return use
&& use
->symbol() == x
.symbol();
299 [&](const HostAssocDetails
&) {
300 return this->has
<HostAssocDetails
>();
302 [](const auto &) { return false; },
308 // Usually a symbol's name is the first occurrence in the source, but sometimes
309 // we want to replace it with one at a different location (but same characters).
310 void Symbol::ReplaceName(const SourceName
&name
) {
311 CHECK(name
== name_
);
315 void Symbol::SetType(const DeclTypeSpec
&type
) {
316 common::visit(common::visitors
{
317 [&](EntityDetails
&x
) { x
.set_type(type
); },
318 [&](ObjectEntityDetails
&x
) { x
.set_type(type
); },
319 [&](AssocEntityDetails
&x
) { x
.set_type(type
); },
320 [&](ProcEntityDetails
&x
) { x
.set_type(type
); },
321 [&](TypeParamDetails
&x
) { x
.set_type(type
); },
327 template <typename T
>
328 constexpr bool HasBindName
{std::is_convertible_v
<T
, const WithBindName
*>};
330 const std::string
*Symbol::GetBindName() const {
331 return common::visit(
332 [&](auto &x
) -> const std::string
* {
333 if constexpr (HasBindName
<decltype(&x
)>) {
342 void Symbol::SetBindName(std::string
&&name
) {
345 if constexpr (HasBindName
<decltype(&x
)>) {
346 x
.set_bindName(std::move(name
));
348 DIE("bind name not allowed on this kind of symbol");
354 bool Symbol::GetIsExplicitBindName() const {
355 return common::visit(
356 [&](auto &x
) -> bool {
357 if constexpr (HasBindName
<decltype(&x
)>) {
358 return x
.isExplicitBindName();
366 void Symbol::SetIsExplicitBindName(bool yes
) {
369 if constexpr (HasBindName
<decltype(&x
)>) {
370 x
.set_isExplicitBindName(yes
);
372 DIE("bind name not allowed on this kind of symbol");
378 void Symbol::SetIsCDefined(bool yes
) {
381 if constexpr (HasBindName
<decltype(&x
)>) {
382 x
.set_isCDefined(yes
);
384 DIE("CDEFINED not allowed on this kind of symbol");
390 bool Symbol::IsFuncResult() const {
391 return common::visit(
392 common::visitors
{[](const EntityDetails
&x
) { return x
.isFuncResult(); },
393 [](const ObjectEntityDetails
&x
) { return x
.isFuncResult(); },
394 [](const ProcEntityDetails
&x
) { return x
.isFuncResult(); },
395 [](const HostAssocDetails
&x
) { return x
.symbol().IsFuncResult(); },
396 [](const auto &) { return false; }},
400 const ArraySpec
*Symbol::GetShape() const {
401 if (const auto *details
{std::get_if
<ObjectEntityDetails
>(&details_
)}) {
402 return &details
->shape();
408 bool Symbol::IsObjectArray() const {
409 const ArraySpec
*shape
{GetShape()};
410 return shape
&& !shape
->empty();
413 bool Symbol::IsSubprogram() const {
414 return common::visit(
416 [](const SubprogramDetails
&) { return true; },
417 [](const SubprogramNameDetails
&) { return true; },
418 [](const GenericDetails
&) { return true; },
419 [](const UseDetails
&x
) { return x
.symbol().IsSubprogram(); },
420 [](const auto &) { return false; },
425 bool Symbol::IsFromModFile() const {
426 return test(Flag::ModFile
) ||
427 (!owner_
->IsTopLevel() && owner_
->symbol()->IsFromModFile());
430 llvm::raw_ostream
&operator<<(llvm::raw_ostream
&os
, const EntityDetails
&x
) {
431 DumpBool(os
, "dummy", x
.isDummy());
432 DumpBool(os
, "funcResult", x
.isFuncResult());
434 os
<< " type: " << *x
.type();
436 DumpOptional(os
, "bindName", x
.bindName());
437 DumpBool(os
, "CDEFINED", x
.isCDefined());
441 llvm::raw_ostream
&operator<<(
442 llvm::raw_ostream
&os
, const ObjectEntityDetails
&x
) {
443 os
<< *static_cast<const EntityDetails
*>(&x
);
444 DumpList(os
, "shape", x
.shape());
445 DumpList(os
, "coshape", x
.coshape());
446 DumpExpr(os
, "init", x
.init_
);
447 if (x
.unanalyzedPDTComponentInit()) {
448 os
<< " (has unanalyzedPDTComponentInit)";
450 if (!x
.ignoreTKR_
.empty()) {
451 x
.ignoreTKR_
.Dump(os
<< ' ', common::EnumToString
);
453 if (x
.cudaDataAttr()) {
454 os
<< " cudaDataAttr: " << common::EnumToString(*x
.cudaDataAttr());
459 llvm::raw_ostream
&operator<<(
460 llvm::raw_ostream
&os
, const AssocEntityDetails
&x
) {
461 os
<< *static_cast<const EntityDetails
*>(&x
);
462 if (x
.IsAssumedSize()) {
464 } else if (x
.IsAssumedRank()) {
465 os
<< " RANK DEFAULT";
466 } else if (auto assocRank
{x
.rank()}) {
467 os
<< " RANK(" << *assocRank
<< ')';
469 DumpExpr(os
, "expr", x
.expr());
473 llvm::raw_ostream
&operator<<(
474 llvm::raw_ostream
&os
, const ProcEntityDetails
&x
) {
475 if (x
.procInterface_
) {
476 if (x
.rawProcInterface_
!= x
.procInterface_
) {
477 os
<< ' ' << x
.rawProcInterface_
->name() << " ->";
479 os
<< ' ' << x
.procInterface_
->name();
481 DumpType(os
, x
.type());
483 DumpOptional(os
, "bindName", x
.bindName());
484 DumpOptional(os
, "passName", x
.passName());
486 if (const Symbol
* target
{*x
.init()}) {
487 os
<< " => " << target
->name();
492 if (x
.isCUDAKernel()) {
493 os
<< " isCUDAKernel";
498 llvm::raw_ostream
&operator<<(
499 llvm::raw_ostream
&os
, const DerivedTypeDetails
&x
) {
500 DumpBool(os
, "sequence", x
.sequence_
);
501 DumpList(os
, "components", x
.componentNames_
);
505 llvm::raw_ostream
&operator<<(llvm::raw_ostream
&os
, const GenericDetails
&x
) {
506 os
<< ' ' << x
.kind().ToString();
507 DumpBool(os
, "(specific)", x
.specific() != nullptr);
508 DumpBool(os
, "(derivedType)", x
.derivedType() != nullptr);
509 if (const auto &uses
{x
.uses()}; !uses
.empty()) {
512 for (const Symbol
&use
: uses
) {
513 const Symbol
&ultimate
{use
.GetUltimate()};
514 os
<< sep
<< ultimate
.name() << "->"
515 << ultimate
.owner().GetName().value();
521 DumpSymbolVector(os
, x
.specificProcs());
525 llvm::raw_ostream
&operator<<(llvm::raw_ostream
&os
, const Details
&details
) {
526 os
<< DetailsToString(details
);
529 [&](const UnknownDetails
&) {},
530 [&](const MainProgramDetails
&) {},
531 [&](const ModuleDetails
&x
) {
532 if (x
.isSubmodule()) {
535 auto ancestor
{x
.ancestor()->GetName().value()};
538 auto parent
{x
.parent()->GetName().value()};
539 if (ancestor
!= parent
) {
546 if (x
.isDefaultPrivate()) {
547 os
<< " isDefaultPrivate";
550 [&](const SubprogramNameDetails
&x
) {
551 os
<< ' ' << EnumToString(x
.kind());
553 [&](const UseDetails
&x
) {
554 os
<< " from " << x
.symbol().name() << " in "
555 << GetUsedModule(x
).name();
557 [&](const UseErrorDetails
&x
) {
560 for (const auto &[location
, module
] : x
.occurrences()) {
561 os
<< sep
<< " from " << module
->GetName().value() << " at "
566 [](const HostAssocDetails
&) {},
567 [&](const ProcBindingDetails
&x
) {
568 os
<< " => " << x
.symbol().name();
569 DumpOptional(os
, "passName", x
.passName());
570 if (x
.numPrivatesNotOverridden() > 0) {
571 os
<< " numPrivatesNotOverridden: "
572 << x
.numPrivatesNotOverridden();
575 [&](const NamelistDetails
&x
) {
577 DumpSymbolVector(os
, x
.objects());
579 [&](const CommonBlockDetails
&x
) {
580 DumpOptional(os
, "bindName", x
.bindName());
582 os
<< " alignment=" << x
.alignment();
585 for (const auto &object
: x
.objects()) {
586 os
<< ' ' << object
->name();
589 [&](const TypeParamDetails
&x
) {
590 DumpOptional(os
, "type", x
.type());
591 if (auto attr
{x
.attr()}) {
592 os
<< ' ' << common::EnumToString(*attr
);
596 DumpExpr(os
, "init", x
.init());
598 [&](const MiscDetails
&x
) {
599 os
<< ' ' << MiscDetails::EnumToString(x
.kind());
601 [&](const auto &x
) { os
<< x
; },
607 llvm::raw_ostream
&operator<<(llvm::raw_ostream
&o
, Symbol::Flag flag
) {
608 return o
<< Symbol::EnumToString(flag
);
611 llvm::raw_ostream
&operator<<(
612 llvm::raw_ostream
&o
, const Symbol::Flags
&flags
) {
613 std::size_t n
{flags
.count()};
615 for (std::size_t j
{0}; seen
< n
; ++j
) {
616 Symbol::Flag flag
{static_cast<Symbol::Flag
>(j
)};
617 if (flags
.test(flag
)) {
627 llvm::raw_ostream
&operator<<(llvm::raw_ostream
&os
, const Symbol
&symbol
) {
629 if (!symbol
.attrs().empty()) {
630 os
<< ", " << symbol
.attrs();
632 if (!symbol
.flags().empty()) {
633 os
<< " (" << symbol
.flags() << ')';
636 os
<< " size=" << symbol
.size_
<< " offset=" << symbol
.offset_
;
638 os
<< ": " << symbol
.details_
;
642 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
643 void Symbol::dump() const { llvm::errs() << *this << '\n'; }
646 // Output a unique name for a scope by qualifying it with the names of
647 // parent scopes. For scopes without corresponding symbols, use the kind
648 // with an index (e.g. Block1, Block2, etc.).
649 static void DumpUniqueName(llvm::raw_ostream
&os
, const Scope
&scope
) {
650 if (!scope
.IsTopLevel()) {
651 DumpUniqueName(os
, scope
.parent());
653 if (auto *scopeSymbol
{scope
.symbol()};
654 scopeSymbol
&& !scopeSymbol
->name().empty()) {
655 os
<< scopeSymbol
->name();
658 for (auto &child
: scope
.parent().children()) {
659 if (child
== scope
) {
662 if (child
.kind() == scope
.kind()) {
666 os
<< Scope::EnumToString(scope
.kind()) << index
;
671 // Dump a symbol for UnparseWithSymbols. This will be used for tests so the
672 // format should be reasonably stable.
673 llvm::raw_ostream
&DumpForUnparse(
674 llvm::raw_ostream
&os
, const Symbol
&symbol
, bool isDef
) {
675 DumpUniqueName(os
, symbol
.owner());
676 os
<< '/' << symbol
.name();
678 if (!symbol
.attrs().empty()) {
679 os
<< ' ' << symbol
.attrs();
681 if (!symbol
.flags().empty()) {
682 os
<< " (" << symbol
.flags() << ')';
684 os
<< ' ' << symbol
.GetDetailsName();
685 DumpType(os
, symbol
.GetType());
690 const DerivedTypeSpec
*Symbol::GetParentTypeSpec(const Scope
*scope
) const {
691 if (const Symbol
* parentComponent
{GetParentComponent(scope
)}) {
692 const auto &object
{parentComponent
->get
<ObjectEntityDetails
>()};
693 return &object
.type()->derivedTypeSpec();
699 const Symbol
*Symbol::GetParentComponent(const Scope
*scope
) const {
700 if (const auto *dtDetails
{detailsIf
<DerivedTypeDetails
>()}) {
701 if (const Scope
* localScope
{scope
? scope
: scope_
}) {
702 return dtDetails
->GetParentComponent(DEREF(localScope
));
708 void DerivedTypeDetails::add_component(const Symbol
&symbol
) {
709 if (symbol
.test(Symbol::Flag::ParentComp
)) {
710 CHECK(componentNames_
.empty());
712 componentNames_
.push_back(symbol
.name());
715 const Symbol
*DerivedTypeDetails::GetParentComponent(const Scope
&scope
) const {
716 if (auto extends
{GetParentComponentName()}) {
717 if (auto iter
{scope
.find(*extends
)}; iter
!= scope
.cend()) {
718 if (const Symbol
& symbol
{*iter
->second
};
719 symbol
.test(Symbol::Flag::ParentComp
)) {
727 const Symbol
*DerivedTypeDetails::GetFinalForRank(int rank
) const {
728 for (const auto &pair
: finals_
) {
729 const Symbol
&symbol
{*pair
.second
};
730 if (const auto *details
{symbol
.detailsIf
<SubprogramDetails
>()}) {
731 if (details
->dummyArgs().size() == 1) {
732 if (const Symbol
* arg
{details
->dummyArgs().at(0)}) {
733 if (const auto *object
{arg
->detailsIf
<ObjectEntityDetails
>()}) {
734 if (rank
== object
->shape().Rank() || object
->IsAssumedRank() ||
735 IsElementalProcedure(symbol
)) {
746 TypeParamDetails
&TypeParamDetails::set_attr(common::TypeParamAttr attr
) {
752 TypeParamDetails
&TypeParamDetails::set_type(const DeclTypeSpec
&type
) {
758 bool GenericKind::IsIntrinsicOperator() const {
759 return Is(OtherKind::Concat
) || Has
<common::LogicalOperator
>() ||
760 Has
<common::NumericOperator
>() || Has
<common::RelationalOperator
>();
763 bool GenericKind::IsOperator() const {
764 return IsDefinedOperator() || IsIntrinsicOperator();
767 std::string
GenericKind::ToString() const {
768 return common::visit(
770 [](const OtherKind
&x
) { return std::string
{EnumToString(x
)}; },
771 [](const common::DefinedIo
&x
) { return AsFortran(x
).ToString(); },
772 [](const auto &x
) { return std::string
{common::EnumToString(x
)}; },
777 SourceName
GenericKind::AsFortran(common::DefinedIo x
) {
778 const char *name
{common::AsFortran(x
)};
779 return {name
, std::strlen(name
)};
782 bool GenericKind::Is(GenericKind::OtherKind x
) const {
783 const OtherKind
*y
{std::get_if
<OtherKind
>(&u
)};
787 std::string
Symbol::OmpFlagToClauseName(Symbol::Flag ompFlag
) {
788 std::string clauseName
;
790 case Symbol::Flag::OmpShared
:
791 clauseName
= "SHARED";
793 case Symbol::Flag::OmpPrivate
:
794 clauseName
= "PRIVATE";
796 case Symbol::Flag::OmpLinear
:
797 clauseName
= "LINEAR";
799 case Symbol::Flag::OmpFirstPrivate
:
800 clauseName
= "FIRSTPRIVATE";
802 case Symbol::Flag::OmpLastPrivate
:
803 clauseName
= "LASTPRIVATE";
805 case Symbol::Flag::OmpMapTo
:
806 case Symbol::Flag::OmpMapFrom
:
807 case Symbol::Flag::OmpMapToFrom
:
808 case Symbol::Flag::OmpMapAlloc
:
809 case Symbol::Flag::OmpMapRelease
:
810 case Symbol::Flag::OmpMapDelete
:
813 case Symbol::Flag::OmpUseDevicePtr
:
814 clauseName
= "USE_DEVICE_PTR";
816 case Symbol::Flag::OmpUseDeviceAddr
:
817 clauseName
= "USE_DEVICE_ADDR";
819 case Symbol::Flag::OmpCopyIn
:
820 clauseName
= "COPYIN";
822 case Symbol::Flag::OmpCopyPrivate
:
823 clauseName
= "COPYPRIVATE";
825 case Symbol::Flag::OmpIsDevicePtr
:
826 clauseName
= "IS_DEVICE_PTR";
828 case Symbol::Flag::OmpHasDeviceAddr
:
829 clauseName
= "HAS_DEVICE_ADDR";
838 bool SymbolOffsetCompare::operator()(
839 const SymbolRef
&x
, const SymbolRef
&y
) const {
840 const Symbol
*xCommon
{FindCommonBlockContaining(*x
)};
841 const Symbol
*yCommon
{FindCommonBlockContaining(*y
)};
844 const SymbolSourcePositionCompare sourceCmp
;
845 if (sourceCmp(*xCommon
, *yCommon
)) {
847 } else if (sourceCmp(*yCommon
, *xCommon
)) {
849 } else if (x
->offset() == y
->offset()) {
850 return x
->size() > y
->size();
852 return x
->offset() < y
->offset();
857 } else if (yCommon
) {
859 } else if (x
->offset() == y
->offset()) {
860 return x
->size() > y
->size();
862 return x
->offset() < y
->offset();
864 return x
->GetSemanticsContext().allCookedSources().Precedes(
865 x
->name(), y
->name());
868 bool SymbolOffsetCompare::operator()(
869 const MutableSymbolRef
&x
, const MutableSymbolRef
&y
) const {
870 return (*this)(SymbolRef
{*x
}, SymbolRef
{*y
});
873 } // namespace Fortran::semantics