9#ifndef FORTRAN_SEMANTICS_TOOLS_H_
10#define FORTRAN_SEMANTICS_TOOLS_H_
15#include "flang/Common/visit.h"
16#include "flang/Evaluate/expression.h"
17#include "flang/Evaluate/shape.h"
18#include "flang/Evaluate/type.h"
19#include "flang/Evaluate/variable.h"
20#include "flang/Parser/message.h"
21#include "flang/Parser/parse-tree.h"
22#include "flang/Semantics/attr.h"
23#include "flang/Semantics/expression.h"
24#include "flang/Semantics/semantics.h"
25#include "flang/Support/Fortran.h"
28namespace Fortran::semantics {
37const Scope &GetTopLevelUnitContaining(
const Scope &);
38const Scope &GetTopLevelUnitContaining(
const Symbol &);
39const Scope &GetProgramUnitContaining(
const Scope &);
40const Scope &GetProgramUnitContaining(
const Symbol &);
41const Scope &GetProgramUnitOrBlockConstructContaining(
const Scope &);
42const Scope &GetProgramUnitOrBlockConstructContaining(
const Symbol &);
44const Scope *FindModuleContaining(
const Scope &);
45const Scope *FindModuleOrSubmoduleContaining(
const Scope &);
46const Scope *FindModuleFileContaining(
const Scope &);
47const Scope *FindPureProcedureContaining(
const Scope &);
48const Scope *FindOpenACCConstructContaining(
const Scope *);
49bool HasOpenACCRoutineDirective(
const Scope *);
53const Symbol *FindOverriddenBinding(
54 const Symbol &,
bool &isInaccessibleDeferred);
62const EquivalenceSet *FindEquivalenceSet(
const Symbol &);
64enum class Tristate { No, Yes, Maybe };
65inline Tristate ToTristate(
bool x) {
return x ? Tristate::Yes : Tristate::No; }
69Tristate IsDefinedAssignment(
70 const std::optional<evaluate::DynamicType> &lhsType,
int lhsRank,
71 const std::optional<evaluate::DynamicType> &rhsType,
int rhsRank);
73bool IsIntrinsicRelational(common::RelationalOperator,
74 const evaluate::DynamicType &,
int,
const evaluate::DynamicType &,
int);
75bool IsIntrinsicNumeric(
const evaluate::DynamicType &);
76bool IsIntrinsicNumeric(
77 const evaluate::DynamicType &,
int,
const evaluate::DynamicType &,
int);
78bool IsIntrinsicLogical(
const evaluate::DynamicType &);
79bool IsIntrinsicLogical(
80 const evaluate::DynamicType &,
int,
const evaluate::DynamicType &,
int);
81bool IsIntrinsicConcat(
82 const evaluate::DynamicType &,
int,
const evaluate::DynamicType &,
int);
84bool IsGenericDefinedOp(
const Symbol &);
85bool IsDefinedOperator(SourceName);
86std::string MakeOpName(SourceName);
87bool IsCommonBlockContaining(
const Symbol &,
const Symbol &);
92bool DoesScopeContain(
const Scope *maybeAncestor,
const Scope &maybeDescendent);
93bool DoesScopeContain(
const Scope *,
const Symbol &);
96bool IsHostAssociated(
const Symbol &,
const Scope &);
97bool IsHostAssociatedIntoSubprogram(
const Symbol &,
const Scope &);
98inline bool IsStmtFunction(
const Symbol &symbol) {
100 return subprogram && subprogram->stmtFunction();
102bool IsInStmtFunction(
const Symbol &);
103bool IsStmtFunctionDummy(
const Symbol &);
104bool IsStmtFunctionResult(
const Symbol &);
105bool IsPointerDummy(
const Symbol &);
106bool IsBindCProcedure(
const Symbol &);
107bool IsBindCProcedure(
const Scope &);
109const Symbol *IsFunctionResultWithSameNameAsFunction(
const Symbol &);
110bool IsOrContainsEventOrLockComponent(
const Symbol &);
111bool IsOrContainsNotifyComponent(
const Symbol &);
112bool CanBeTypeBoundProc(
const Symbol &);
118bool HasDeclarationInitializer(
const Symbol &);
120bool IsInitialized(
const Symbol &,
bool ignoreDATAstatements =
false,
121 bool ignoreAllocatable =
false,
bool ignorePointer =
true);
123bool IsDestructible(
const Symbol &,
const Symbol *derivedType =
nullptr);
124bool HasIntrinsicTypeName(
const Symbol &);
125bool IsSeparateModuleProcedureInterface(
const Symbol *);
126bool HasAlternateReturns(
const Symbol &);
127bool IsAutomaticallyDestroyed(
const Symbol &);
131 const std::function<
bool(
const Symbol &)> &predicate);
132const Symbol *FindUltimateComponent(
133 const Symbol &symbol,
const std::function<
bool(
const Symbol &)> &predicate);
138const Symbol *FindImmediateComponent(
141inline bool IsPointer(
const Symbol &symbol) {
142 return symbol.attrs().test(Attr::POINTER);
144inline bool IsAllocatable(
const Symbol &symbol) {
145 return symbol.attrs().test(Attr::ALLOCATABLE);
147inline bool IsValue(
const Symbol &symbol) {
148 return symbol.attrs().test(Attr::VALUE);
151inline bool IsAllocatableOrPointer(
const Symbol &symbol) {
152 return IsPointer(symbol) || IsAllocatable(symbol);
154inline bool IsNamedConstant(
const Symbol &symbol) {
155 return symbol.attrs().test(Attr::PARAMETER);
157inline bool IsOptional(
const Symbol &symbol) {
158 return symbol.attrs().test(Attr::OPTIONAL);
160inline bool IsIntentIn(
const Symbol &symbol) {
161 return symbol.attrs().test(Attr::INTENT_IN);
163inline bool IsIntentInOut(
const Symbol &symbol) {
164 return symbol.attrs().test(Attr::INTENT_INOUT);
166inline bool IsIntentOut(
const Symbol &symbol) {
167 return symbol.attrs().test(Attr::INTENT_OUT);
169inline bool IsProtected(
const Symbol &symbol) {
170 return symbol.attrs().test(Attr::PROTECTED);
172inline bool IsImpliedDoIndex(
const Symbol &symbol) {
173 return symbol.owner().kind() == Scope::Kind::ImpliedDos;
175SymbolVector FinalsForDerivedTypeInstantiation(
const DerivedTypeSpec &);
178 std::set<const DerivedTypeSpec *> * =
nullptr,
179 bool withImpureFinalizer =
false);
181 std::set<const DerivedTypeSpec *> * =
nullptr,
182 bool withImpureFinalizer =
false, std::optional<int> rank = std::nullopt);
183const Symbol *HasImpureFinal(
184 const Symbol &, std::optional<int> rank = std::nullopt);
194bool IsInBlankCommon(
const Symbol &);
195bool IsAssumedLengthCharacter(
const Symbol &);
196bool IsExternal(
const Symbol &);
197bool IsModuleProcedure(
const Symbol &);
198bool HasCoarray(
const parser::Expr &);
199bool IsAssumedType(
const Symbol &);
200bool IsPolymorphic(
const Symbol &);
201bool IsUnlimitedPolymorphic(
const Symbol &);
202bool IsPolymorphicAllocatable(
const Symbol &);
204bool IsDeviceAllocatable(
const Symbol &symbol);
206inline bool IsCUDADeviceContext(
const Scope *scope) {
208 if (
const Symbol * symbol{scope->symbol()}) {
210 if (
auto attrs{subp->cudaSubprogramAttrs()}) {
211 return *attrs != common::CUDASubprogramAttrs::Host;
219inline bool HasCUDAAttr(
const Symbol &sym) {
221 if (details->cudaDataAttr()) {
228bool HasCUDAComponent(
const Symbol &sym);
230inline bool IsCUDADevice(
const Symbol &sym) {
232 return details->cudaDataAttr() &&
233 *details->cudaDataAttr() == common::CUDADataAttr::Device;
238inline bool IsCUDAShared(
const Symbol &sym) {
240 return details->cudaDataAttr() &&
241 *details->cudaDataAttr() == common::CUDADataAttr::Shared;
246inline bool NeedCUDAAlloc(
const Symbol &sym) {
251 if (details->cudaDataAttr() &&
252 (*details->cudaDataAttr() == common::CUDADataAttr::Device ||
253 *details->cudaDataAttr() == common::CUDADataAttr::Managed ||
254 *details->cudaDataAttr() == common::CUDADataAttr::Unified ||
255 *details->cudaDataAttr() == common::CUDADataAttr::Shared ||
256 *details->cudaDataAttr() == common::CUDADataAttr::Pinned)) {
263bool CanCUDASymbolBeGlobal(
const Symbol &sym);
265const Scope *FindCUDADeviceContext(
const Scope *);
266std::optional<common::CUDADataAttr> GetCUDADataAttr(
const Symbol *);
271std::optional<parser::MessageFormattedText> CheckAccessibleSymbol(
272 const Scope &,
const Symbol &,
bool inStructureConstructor =
false);
275bool IsImageControlStmt(
const parser::ExecutableConstruct &);
277parser::CharBlock GetImageControlStmtLocation(
278 const parser::ExecutableConstruct &);
282std::optional<parser::MessageFixedText> GetImageControlStmtCoarrayMsg(
283 const parser::ExecutableConstruct &);
288SymbolVector OrderParameterDeclarations(
const Symbol &);
291SymbolVector OrderParameterNames(
const Symbol &);
295 DeclTypeSpec::Category = DeclTypeSpec::TypeDerived);
300const Symbol *FindSeparateModuleSubprogramInterface(
const Symbol *);
305const Symbol *FindExternallyVisibleObject(
306 const Symbol &,
const Scope &,
bool isPointerDefinition);
309const Symbol *FindExternallyVisibleObject(
const A &,
const Scope &) {
314const Symbol *FindExternallyVisibleObject(
315 const evaluate::Designator<T> &designator,
const Scope &scope) {
316 if (
const Symbol * symbol{designator.GetBaseObject().symbol()}) {
317 return FindExternallyVisibleObject(*symbol, scope,
false);
318 }
else if (std::holds_alternative<evaluate::CoarrayRef>(designator.u)) {
320 return designator.GetBaseObject().symbol();
327const Symbol *FindExternallyVisibleObject(
328 const evaluate::Expr<T> &expr,
const Scope &scope) {
329 return common::visit(
330 [&](
const auto &x) {
return FindExternallyVisibleObject(x, scope); },
338using SomeExpr = evaluate::Expr<evaluate::SomeType>;
340bool ExprHasTypeCategory(
341 const SomeExpr &expr,
const common::TypeCategory &type);
342bool ExprTypeKindIsDefault(
348 GetExprHelper() : crashIfNoExpr_{
true} {}
358 return Get(x.value());
360 template <
typename T>
const SomeExpr *Get(
const std::optional<T> &x) {
361 return x ? Get(*x) :
nullptr;
363 template <
typename T>
const SomeExpr *Get(
const T &x) {
366 if constexpr (ConstraintTrait<T>) {
368 }
else if constexpr (WrapperTrait<T>) {
377 const bool crashIfNoExpr_{
false};
390const SomeExpr *GetExpr(SemanticsContext &context,
const T &x) {
391 return GetExprHelper{&context}.Get(x);
393template <
typename T>
const SomeExpr *GetExpr(
const T &x) {
397const evaluate::Assignment *GetAssignment(
const parser::AssignmentStmt &);
398const evaluate::Assignment *GetAssignment(
399 const parser::PointerAssignmentStmt &);
401template <
typename T> std::optional<std::int64_t> GetIntValue(
const T &x) {
402 if (
const auto *expr{GetExpr(
nullptr, x)}) {
403 return evaluate::ToInt64(*expr);
409template <
typename T>
bool IsZero(
const T &expr) {
410 auto value{GetIntValue(expr)};
411 return value && *value == 0;
415enum class ProcedureDefinitionClass {
426ProcedureDefinitionClass ClassifyProcedure(
const Symbol &);
433std::list<std::list<SymbolRef>> GetStorageAssociations(
const Scope &);
511ENUM_CLASS(ComponentKind, Ordered, Direct, Ultimate, Potential,
Scope,
514template <ComponentKind componentKind>
class ComponentIterator {
516 ComponentIterator(
const DerivedTypeSpec &derived) : derived_{derived} {}
517 class const_iterator {
519 using iterator_category = std::forward_iterator_tag;
520 using value_type = SymbolRef;
521 using difference_type = void;
522 using pointer =
const Symbol *;
523 using reference =
const Symbol &;
525 static const_iterator Create(
const DerivedTypeSpec &);
527 const_iterator &operator++() {
531 const_iterator operator++(
int) {
532 const_iterator tmp(*
this);
536 reference operator*()
const {
537 CHECK(!componentPath_.empty());
538 return DEREF(componentPath_.back().component());
540 pointer operator->()
const {
return &**
this; }
542 bool operator==(
const const_iterator &other)
const {
543 return componentPath_ == other.componentPath_;
545 bool operator!=(
const const_iterator &other)
const {
546 return !(*
this == other);
551 explicit operator bool()
const {
return !componentPath_.empty(); }
554 SymbolVector GetComponentPath()
const;
563 std::string BuildResultDesignatorName()
const;
566 using name_iterator =
567 std::conditional_t<componentKind == ComponentKind::Scope,
568 typename Scope::const_iterator,
569 typename std::list<SourceName>::const_iterator>;
571 class ComponentPathNode {
573 explicit ComponentPathNode(
const DerivedTypeSpec &derived)
574 : derived_{derived} {
575 if constexpr (componentKind == ComponentKind::Scope) {
576 const Scope &scope{DEREF(derived.GetScope())};
577 nameIterator_ = scope.cbegin();
578 nameEnd_ = scope.cend();
580 const std::list<SourceName> &nameList{
581 derived.typeSymbol().get<DerivedTypeDetails>().componentNames()};
582 nameIterator_ = nameList.cbegin();
583 nameEnd_ = nameList.cend();
586 const Symbol *component()
const {
return component_; }
587 void set_component(
const Symbol &component) { component_ = &component; }
588 bool visited()
const {
return visited_; }
589 void set_visited(
bool yes) { visited_ = yes; }
590 bool descended()
const {
return descended_; }
591 void set_descended(
bool yes) { descended_ = yes; }
592 name_iterator &nameIterator() {
return nameIterator_; }
593 name_iterator nameEnd() {
return nameEnd_; }
594 const Symbol &GetTypeSymbol()
const {
return derived_->typeSymbol(); }
595 const Scope &GetScope()
const {
596 return derived_->scope() ? *derived_->scope()
597 : DEREF(GetTypeSymbol().scope());
599 bool operator==(
const ComponentPathNode &that)
const {
600 return &*derived_ == &*that.derived_ &&
601 nameIterator_ == that.nameIterator_ &&
602 component_ == that.component_;
606 common::Reference<const DerivedTypeSpec> derived_;
607 name_iterator nameEnd_;
608 name_iterator nameIterator_;
609 const Symbol *component_{
nullptr};
610 bool visited_{
false};
611 bool descended_{
false};
614 const DerivedTypeSpec *PlanComponentTraversal(
615 const Symbol &component)
const;
620 std::vector<ComponentPathNode> componentPath_;
623 const_iterator begin() {
return cbegin(); }
624 const_iterator end() {
return cend(); }
625 const_iterator cbegin() {
return const_iterator::Create(derived_); }
626 const_iterator cend() {
return const_iterator{}; }
629 const DerivedTypeSpec &derived_;
632extern template class ComponentIterator<ComponentKind::Ordered>;
633extern template class ComponentIterator<ComponentKind::Direct>;
634extern template class ComponentIterator<ComponentKind::Ultimate>;
635extern template class ComponentIterator<ComponentKind::Potential>;
636extern template class ComponentIterator<ComponentKind::Scope>;
637extern template class ComponentIterator<ComponentKind::PotentialAndPointer>;
638using OrderedComponentIterator = ComponentIterator<ComponentKind::Ordered>;
639using DirectComponentIterator = ComponentIterator<ComponentKind::Direct>;
640using UltimateComponentIterator = ComponentIterator<ComponentKind::Ultimate>;
641using PotentialComponentIterator = ComponentIterator<ComponentKind::Potential>;
642using ScopeComponentIterator = ComponentIterator<ComponentKind::Scope>;
643using PotentialAndPointerComponentIterator =
644 ComponentIterator<ComponentKind::PotentialAndPointer>;
652PotentialComponentIterator::const_iterator FindEventOrLockPotentialComponent(
654PotentialComponentIterator::const_iterator FindNotifyPotentialComponent(
656PotentialComponentIterator::const_iterator FindCoarrayPotentialComponent(
658PotentialAndPointerComponentIterator::const_iterator
660UltimateComponentIterator::const_iterator FindCoarrayUltimateComponent(
662UltimateComponentIterator::const_iterator FindPointerUltimateComponent(
664UltimateComponentIterator::const_iterator FindAllocatableUltimateComponent(
666DirectComponentIterator::const_iterator FindAllocatableOrPointerDirectComponent(
668PotentialComponentIterator::const_iterator
670UltimateComponentIterator::const_iterator
679 : context_{context}, labels_{labels},
680 constructSourcePosition_{constructSourcePosition}, construct_{
682 template <
typename T>
bool Pre(
const T &) {
return true; }
684 currentStatementSourcePosition_ = statement.source;
688 template <
typename T>
void Post(
const T &) {}
690 void Post(
const parser::GotoStmt &gotoStmt);
695 void Post(
const parser::AltReturnSpec &altReturnSpec);
696 void Post(
const parser::ErrLabel &errLabel);
697 void Post(
const parser::EndLabel &endLabel);
698 void Post(
const parser::EorLabel &eorLabel);
699 void CheckLabelUse(
const parser::Label &labelUsed);
703 std::set<parser::Label> labels_;
706 const char *construct_{
nullptr};
714const std::optional<parser::Name> &MaybeGetNodeName(
715 const ConstructNode &construct);
718std::optional<ArraySpec> ToArraySpec(
720std::optional<ArraySpec> ToArraySpec(
729std::forward_list<std::string> GetAllNames(
740void WarnOnDeferredLengthCharacterScalar(
SemanticsContext &,
const SomeExpr *,
743bool CouldBeDataPointerValuedFunction(
const Symbol *);
745template <
typename R,
typename T>
746std::optional<R> GetConstExpr(
SemanticsContext &semanticsContext,
const T &x) {
747 using DefaultCharConstantType = evaluate::Ascii;
748 if (
const auto *expr{GetExpr(semanticsContext, x)}) {
749 const auto foldExpr{evaluate::Fold(
750 semanticsContext.foldingContext(), common::Clone(*expr))};
751 if constexpr (std::is_same_v<R, std::string>) {
752 return evaluate::GetScalarConstantValue<DefaultCharConstantType>(
760std::string GetModuleOrSubmoduleName(
const Symbol &);
763std::string GetCommonBlockObjectName(
const Symbol &,
bool underscoring);
768bool AreSameModuleSymbol(
const Symbol &,
const Symbol &);
Definition indirection.h:31
Definition char-block.h:28
Definition semantics.h:67
Definition parse-tree.h:1898
Definition parse-tree.h:3438
Definition parse-tree.h:3443
Definition parse-tree.h:3448
Definition parse-tree.h:2496
Definition parse-tree.h:1467
Definition parse-tree.h:1682
Definition parse-tree.h:1974
Definition parse-tree.h:359
Definition parse-tree.h:1841