1 //===-- lib/Semantics/resolve-names-utils.h ---------------------*- C++ -*-===//
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 #ifndef FORTRAN_SEMANTICS_RESOLVE_NAMES_UTILS_H_
10 #define FORTRAN_SEMANTICS_RESOLVE_NAMES_UTILS_H_
12 // Utility functions and class for use in resolve-names.cpp.
14 #include "flang/Evaluate/fold.h"
15 #include "flang/Parser/message.h"
16 #include "flang/Parser/tools.h"
17 #include "flang/Semantics/expression.h"
18 #include "flang/Semantics/scope.h"
19 #include "flang/Semantics/semantics.h"
20 #include "flang/Semantics/symbol.h"
21 #include "flang/Semantics/type.h"
22 #include "llvm/Support/raw_ostream.h"
23 #include <forward_list>
25 namespace Fortran::parser
{
29 struct ComponentArraySpec
;
36 } // namespace Fortran::parser
38 namespace Fortran::semantics
{
40 using SourceName
= parser::CharBlock
;
41 class SemanticsContext
;
43 // Record that a Name has been resolved to a Symbol
44 Symbol
&Resolve(const parser::Name
&, Symbol
&);
45 Symbol
*Resolve(const parser::Name
&, Symbol
*);
47 // Create a copy of msg with a new severity.
48 parser::MessageFixedText
WithSeverity(
49 const parser::MessageFixedText
&msg
, parser::Severity
);
51 bool IsIntrinsicOperator(const SemanticsContext
&, const SourceName
&);
52 bool IsLogicalConstant(const SemanticsContext
&, const SourceName
&);
55 MaybeIntExpr
EvaluateIntExpr(SemanticsContext
&context
, const T
&expr
) {
56 if (MaybeExpr maybeExpr
{
57 Fold(context
.foldingContext(), AnalyzeExpr(context
, expr
))}) {
58 if (auto *intExpr
{evaluate::UnwrapExpr
<SomeIntExpr
>(*maybeExpr
)}) {
59 return std::move(*intExpr
);
66 std::optional
<std::int64_t> EvaluateInt64(
67 SemanticsContext
&context
, const T
&expr
) {
68 return evaluate::ToInt64(EvaluateIntExpr(context
, expr
));
71 // Analyze a generic-spec and generate a symbol name and GenericKind for it.
72 class GenericSpecInfo
{
74 explicit GenericSpecInfo(const parser::DefinedOpName
&x
) { Analyze(x
); }
75 explicit GenericSpecInfo(const parser::GenericSpec
&x
) { Analyze(x
); }
77 GenericKind
kind() const { return kind_
; }
78 const SourceName
&symbolName() const { return symbolName_
.value(); }
79 // Set the GenericKind in this symbol and resolve the corresponding
80 // name if there is one
81 void Resolve(Symbol
*) const;
82 friend llvm::raw_ostream
&operator<<(
83 llvm::raw_ostream
&, const GenericSpecInfo
&);
86 void Analyze(const parser::DefinedOpName
&);
87 void Analyze(const parser::GenericSpec
&);
90 const parser::Name
*parseName_
{nullptr};
91 std::optional
<SourceName
> symbolName_
;
94 // Analyze a parser::ArraySpec or parser::CoarraySpec
95 ArraySpec
AnalyzeArraySpec(SemanticsContext
&, const parser::ArraySpec
&);
96 ArraySpec
AnalyzeArraySpec(
97 SemanticsContext
&, const parser::ComponentArraySpec
&);
98 ArraySpec
AnalyzeDeferredShapeSpecList(
99 SemanticsContext
&, const parser::DeferredShapeSpecList
&);
100 ArraySpec
AnalyzeCoarraySpec(
101 SemanticsContext
&context
, const parser::CoarraySpec
&);
103 // Perform consistency checks on equivalence sets
104 class EquivalenceSets
{
106 EquivalenceSets(SemanticsContext
&context
) : context_
{context
} {}
107 std::vector
<EquivalenceSet
> &sets() { return sets_
; };
108 // Resolve this designator and add to the current equivalence set
109 void AddToSet(const parser::Designator
&);
110 // Finish the current equivalence set: determine if it overlaps
111 // with any of the others and perform necessary merges if it does.
112 void FinishSet(const parser::CharBlock
&);
115 bool CheckCanEquivalence(
116 const parser::CharBlock
&, const Symbol
&, const Symbol
&);
117 void MergeInto(const parser::CharBlock
&, EquivalenceSet
&, std::size_t);
118 const EquivalenceObject
*Find(const EquivalenceSet
&, const Symbol
&);
119 bool CheckDesignator(const parser::Designator
&);
120 bool CheckDataRef(const parser::CharBlock
&, const parser::DataRef
&);
121 bool CheckObject(const parser::Name
&);
122 bool CheckArrayBound(const parser::Expr
&);
123 bool CheckSubstringBound(const parser::Expr
&, bool);
124 bool IsCharacterSequenceType(const DeclTypeSpec
*);
125 bool IsDefaultKindNumericType(const IntrinsicTypeSpec
&);
126 bool IsDefaultNumericSequenceType(const DeclTypeSpec
*);
127 static bool IsAnyNumericSequenceType(const DeclTypeSpec
*);
128 static bool IsSequenceType(
129 const DeclTypeSpec
*, std::function
<bool(const IntrinsicTypeSpec
&)>);
131 SemanticsContext
&context_
;
132 std::vector
<EquivalenceSet
> sets_
; // all equivalence sets in this scope
133 // Map object to index of set it is in
134 std::map
<EquivalenceObject
, std::size_t> objectToSet_
;
135 EquivalenceSet currSet_
; // equivalence set currently being constructed
137 Symbol
*symbol
{nullptr};
138 std::vector
<ConstantSubscript
> subscripts
;
139 std::optional
<ConstantSubscript
> substringStart
;
140 } currObject_
; // equivalence object currently being constructed
143 // Duplicates a subprogram's dummy arguments and result, if any, and
144 // maps all of the symbols in their expressions.
145 struct SymbolAndTypeMappings
;
146 void MapSubprogramToNewSymbols(const Symbol
&oldSymbol
, Symbol
&newSymbol
,
147 Scope
&newScope
, SymbolAndTypeMappings
* = nullptr);
149 } // namespace Fortran::semantics
150 #endif // FORTRAN_SEMANTICS_RESOLVE_NAMES_H_