xref: /llvm-project/flang/lib/Semantics/resolve-names-utils.h (revision 2f22656db541e4e5c3401e7bbab25277c8438a23)
1 //===-- lib/Semantics/resolve-names-utils.h ---------------------*- C++ -*-===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef FORTRAN_SEMANTICS_RESOLVE_NAMES_UTILS_H_
10 #define FORTRAN_SEMANTICS_RESOLVE_NAMES_UTILS_H_
11 
12 // Utility functions and class for use in resolve-names.cpp.
13 
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>
24 
25 namespace Fortran::parser {
26 class CharBlock;
27 struct ArraySpec;
28 struct CoarraySpec;
29 struct ComponentArraySpec;
30 struct DataRef;
31 struct DefinedOpName;
32 struct Designator;
33 struct Expr;
34 struct GenericSpec;
35 struct Name;
36 } // namespace Fortran::parser
37 
38 namespace Fortran::semantics {
39 
40 using SourceName = parser::CharBlock;
41 class SemanticsContext;
42 
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 *);
46 
47 // Create a copy of msg with a new severity.
48 parser::MessageFixedText WithSeverity(
49     const parser::MessageFixedText &msg, parser::Severity);
50 
51 bool IsIntrinsicOperator(const SemanticsContext &, const SourceName &);
52 bool IsLogicalConstant(const SemanticsContext &, const SourceName &);
53 
54 template <typename T>
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);
60     }
61   }
62   return std::nullopt;
63 }
64 
65 template <typename T>
66 std::optional<std::int64_t> EvaluateInt64(
67     SemanticsContext &context, const T &expr) {
68   return evaluate::ToInt64(EvaluateIntExpr(context, expr));
69 }
70 
71 // Analyze a generic-spec and generate a symbol name and GenericKind for it.
72 class GenericSpecInfo {
73 public:
74   explicit GenericSpecInfo(const parser::DefinedOpName &x) { Analyze(x); }
75   explicit GenericSpecInfo(const parser::GenericSpec &x) { Analyze(x); }
76 
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 &);
84 
85 private:
86   void Analyze(const parser::DefinedOpName &);
87   void Analyze(const parser::GenericSpec &);
88 
89   GenericKind kind_;
90   const parser::Name *parseName_{nullptr};
91   std::optional<SourceName> symbolName_;
92 };
93 
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 &);
102 
103 // Perform consistency checks on equivalence sets
104 class EquivalenceSets {
105 public:
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 &);
113 
114 private:
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 &)>);
130 
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
136   struct {
137     Symbol *symbol{nullptr};
138     std::vector<ConstantSubscript> subscripts;
139     std::optional<ConstantSubscript> substringStart;
140   } currObject_; // equivalence object currently being constructed
141 };
142 
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);
148 
149 } // namespace Fortran::semantics
150 #endif // FORTRAN_SEMANTICS_RESOLVE_NAMES_H_
151