FLANG
tools.h
1//===-- include/flang/Parser/tools.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_PARSER_TOOLS_H_
10#define FORTRAN_PARSER_TOOLS_H_
11
12#include "parse-tree.h"
13
14namespace Fortran::parser {
15
16// GetLastName() isolates and returns a reference to the rightmost Name
17// in a variable (i.e., the Name whose symbol's type determines the type
18// of the variable or expression).
19const Name &GetLastName(const Name &);
20const Name &GetLastName(const StructureComponent &);
21const Name &GetLastName(const DataRef &);
22const Name &GetLastName(const Substring &);
23const Name &GetLastName(const Designator &);
24const Name &GetLastName(const ProcComponentRef &);
25const Name &GetLastName(const ProcedureDesignator &);
26const Name &GetLastName(const Call &);
27const Name &GetLastName(const FunctionReference &);
28const Name &GetLastName(const Variable &);
29const Name &GetLastName(const AllocateObject &);
30
31// GetFirstName() isolates and returns a reference to the leftmost Name
32// in a variable or entity declaration.
33const Name &GetFirstName(const Name &);
34const Name &GetFirstName(const StructureComponent &);
35const Name &GetFirstName(const DataRef &);
36const Name &GetFirstName(const Substring &);
37const Name &GetFirstName(const Designator &);
38const Name &GetFirstName(const ProcComponentRef &);
39const Name &GetFirstName(const ProcedureDesignator &);
40const Name &GetFirstName(const Call &);
41const Name &GetFirstName(const FunctionReference &);
42const Name &GetFirstName(const Variable &);
43const Name &GetFirstName(const EntityDecl &);
44
45// When a parse tree node is an instance of a specific type wrapped in
46// layers of packaging, return a pointer to that object.
47// Implemented with mutually recursive template functions that are
48// wrapped in a struct to avoid prototypes.
50
51 template <typename A, typename B> static const A *Unwrap(B *p) {
52 if (p) {
53 return Unwrap<A>(*p);
54 } else {
55 return nullptr;
56 }
57 }
58
59 template <typename A, typename B, bool COPY>
60 static const A *Unwrap(const common::Indirection<B, COPY> &x) {
61 return Unwrap<A>(x.value());
62 }
63
64 template <typename A, typename... Bs>
65 static const A *Unwrap(const std::variant<Bs...> &x) {
66 return common::visit([](const auto &y) { return Unwrap<A>(y); }, x);
67 }
68
69 template <typename A, std::size_t J = 0, typename... Bs>
70 static const A *Unwrap(const std::tuple<Bs...> &x) {
71 if constexpr (J < sizeof...(Bs)) {
72 if (auto result{Unwrap<A>(std::get<J>(x))}) {
73 return result;
74 }
75 return Unwrap<A, (J + 1)>(x);
76 } else {
77 return nullptr;
78 }
79 }
80
81 template <typename A, typename B>
82 static const A *Unwrap(const std::optional<B> &o) {
83 if (o) {
84 return Unwrap<A>(*o);
85 } else {
86 return nullptr;
87 }
88 }
89
90 template <typename A, typename B>
91 static const A *Unwrap(const UnlabeledStatement<B> &x) {
92 return Unwrap<A>(x.statement);
93 }
94 template <typename A, typename B>
95 static const A *Unwrap(const Statement<B> &x) {
96 return Unwrap<A>(x.statement);
97 }
98
99 template <typename A, typename B> static const A *Unwrap(B &x) {
100 if constexpr (std::is_same_v<std::decay_t<A>, std::decay_t<B>>) {
101 return &x;
102 } else if constexpr (ConstraintTrait<B>) {
103 return Unwrap<A>(x.thing);
104 } else if constexpr (WrapperTrait<B>) {
105 return Unwrap<A>(x.v);
106 } else if constexpr (UnionTrait<B>) {
107 return Unwrap<A>(x.u);
108 } else {
109 return nullptr;
110 }
111 }
112};
113
114template <typename A, typename B> const A *Unwrap(const B &x) {
115 return UnwrapperHelper::Unwrap<A>(x);
116}
117template <typename A, typename B> A *Unwrap(B &x) {
118 return const_cast<A *>(Unwrap<A, B>(const_cast<const B &>(x)));
119}
120template <typename A, typename B> const A &UnwrapRef(const B &x) {
121 return DEREF(Unwrap<A>(x));
122}
123template <typename A, typename B> A &UnwrapRef(B &x) {
124 return DEREF(Unwrap<A>(x));
125}
126
127// Get the CoindexedNamedObject if the entity is a coindexed object.
128const CoindexedNamedObject *GetCoindexedNamedObject(const AllocateObject &);
129const CoindexedNamedObject *GetCoindexedNamedObject(const DataRef &);
130const CoindexedNamedObject *GetCoindexedNamedObject(const Designator &);
131const CoindexedNamedObject *GetCoindexedNamedObject(const Variable &);
132
133// Detects parse tree nodes with "source" members.
134template <typename A, typename = int> struct HasSource : std::false_type {};
135template <typename A>
136struct HasSource<A, decltype(static_cast<void>(A::source), 0)>
137 : std::true_type {};
138
139// Detects parse tree nodes with "typedExpr", "typedCall", &c. members.
140template <typename A, typename = int> struct HasTypedExpr : std::false_type {};
141template <typename A>
142struct HasTypedExpr<A, decltype(static_cast<void>(A::typedExpr), 0)>
143 : std::true_type {};
144template <typename A, typename = int> struct HasTypedCall : std::false_type {};
145template <typename A>
146struct HasTypedCall<A, decltype(static_cast<void>(A::typedCall), 0)>
147 : std::true_type {};
148template <typename A, typename = int>
149struct HasTypedAssignment : std::false_type {};
150template <typename A>
151struct HasTypedAssignment<A, decltype(static_cast<void>(A::typedAssignment), 0)>
152 : std::true_type {};
153
154// GetSource()
155
156template <bool GET_FIRST> struct GetSourceHelper {
157
158 using Result = std::optional<CharBlock>;
159
160 template <typename A> static Result GetSource(A *p) {
161 if (p) {
162 return GetSource(*p);
163 } else {
164 return std::nullopt;
165 }
166 }
167 template <typename A>
168 static Result GetSource(const common::Indirection<A> &x) {
169 return GetSource(x.value());
170 }
171
172 template <typename A, bool COPY>
173 static Result GetSource(const common::Indirection<A, COPY> &x) {
174 return GetSource(x.value());
175 }
176
177 template <typename... As>
178 static Result GetSource(const std::variant<As...> &x) {
179 return common::visit([](const auto &y) { return GetSource(y); }, x);
180 }
181
182 template <std::size_t J = 0, typename... As>
183 static Result GetSource(const std::tuple<As...> &x) {
184 if constexpr (J < sizeof...(As)) {
185 constexpr std::size_t index{GET_FIRST ? J : sizeof...(As) - J - 1};
186 if (auto result{GetSource(std::get<index>(x))}) {
187 return result;
188 }
189 return GetSource<(J + 1)>(x);
190 } else {
191 return {};
192 }
193 }
194
195 template <typename A> static Result GetSource(const std::optional<A> &o) {
196 if (o) {
197 return GetSource(*o);
198 } else {
199 return {};
200 }
201 }
202
203 template <typename A> static Result GetSource(const std::list<A> &x) {
204 if constexpr (GET_FIRST) {
205 for (const A &y : x) {
206 if (auto result{GetSource(y)}) {
207 return result;
208 }
209 }
210 } else {
211 for (auto iter{x.rbegin()}; iter != x.rend(); ++iter) {
212 if (auto result{GetSource(*iter)}) {
213 return result;
214 }
215 }
216 }
217 return {};
218 }
219
220 template <typename A> static Result GetSource(const std::vector<A> &x) {
221 if constexpr (GET_FIRST) {
222 for (const A &y : x) {
223 if (auto result{GetSource(y)}) {
224 return result;
225 }
226 }
227 } else {
228 for (auto iter{x.rbegin()}; iter != x.rend(); ++iter) {
229 if (auto result{GetSource(*iter)}) {
230 return result;
231 }
232 }
233 }
234 return {};
235 }
236
237 template <typename A> static Result GetSource(A &x) {
238 if constexpr (HasSource<A>::value) {
239 return x.source;
240 } else if constexpr (ConstraintTrait<A>) {
241 return GetSource(x.thing);
242 } else if constexpr (WrapperTrait<A>) {
243 return GetSource(x.v);
244 } else if constexpr (UnionTrait<A>) {
245 return GetSource(x.u);
246 } else if constexpr (TupleTrait<A>) {
247 return GetSource(x.t);
248 } else {
249 return {};
250 }
251 }
252};
253
254template <typename A> std::optional<CharBlock> GetSource(const A &x) {
255 return GetSourceHelper<true>::GetSource(x);
256}
257template <typename A> std::optional<CharBlock> GetSource(A &x) {
258 return GetSourceHelper<true>::GetSource(const_cast<const A &>(x));
259}
260
261template <typename A> std::optional<CharBlock> GetLastSource(const A &x) {
262 return GetSourceHelper<false>::GetSource(x);
263}
264template <typename A> std::optional<CharBlock> GetLastSource(A &x) {
265 return GetSourceHelper<false>::GetSource(const_cast<const A &>(x));
266}
267
268// Checks whether the assignment statement has a single variable on the RHS.
269bool CheckForSingleVariableOnRHS(const AssignmentStmt &);
270
271const Name *GetDesignatorNameIfDataRef(const Designator &);
272
273} // namespace Fortran::parser
274#endif // FORTRAN_PARSER_TOOLS_H_
Definition indirection.h:31
Definition check-expression.h:19
Definition parse-tree.h:1936
Definition parse-tree.h:2029
Definition parse-tree.h:3271
Definition parse-tree.h:1915
Definition parse-tree.h:1831
Definition parse-tree.h:1870
Definition parse-tree.h:1410
Definition parse-tree.h:3276
Definition tools.h:156
Definition tools.h:134
Definition tools.h:144
Definition tools.h:140
Definition parse-tree.h:587
Definition parse-tree.h:1910
Definition parse-tree.h:3243
Definition parse-tree.h:359
Definition parse-tree.h:1900
Definition parse-tree.h:1848
Definition parse-tree.h:354
Definition parse-tree.h:1878