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 &);
44const Name &GetFirstName(const AccObject &);
45
46// Checks whether a scalar-int-constant-expr is a direct BOZ literal constant,
47// rather than an expression that contains one.
48bool IsBOZLiteral(const ScalarIntConstantExpr &);
49
50// When a parse tree node is an instance of a specific type wrapped in
51// layers of packaging, return a pointer to that object.
52// Implemented with mutually recursive template functions that are
53// wrapped in a struct to avoid prototypes.
55
56 template <typename A, typename B> static const A *Unwrap(B *p) {
57 if (p) {
58 return Unwrap<A>(*p);
59 } else {
60 return nullptr;
61 }
62 }
63
64 template <typename A, typename B, bool COPY>
65 static const A *Unwrap(const common::Indirection<B, COPY> &x) {
66 return Unwrap<A>(x.value());
67 }
68
69 template <typename A, typename... Bs>
70 static const A *Unwrap(const std::variant<Bs...> &x) {
71 return common::visit([](const auto &y) { return Unwrap<A>(y); }, x);
72 }
73
74 template <typename A, std::size_t J = 0, typename... Bs>
75 static const A *Unwrap(const std::tuple<Bs...> &x) {
76 if constexpr (J < sizeof...(Bs)) {
77 if (auto result{Unwrap<A>(std::get<J>(x))}) {
78 return result;
79 }
80 return Unwrap<A, (J + 1)>(x);
81 } else {
82 return nullptr;
83 }
84 }
85
86 template <typename A, typename B>
87 static const A *Unwrap(const std::optional<B> &o) {
88 if (o) {
89 return Unwrap<A>(*o);
90 } else {
91 return nullptr;
92 }
93 }
94
95 template <typename A, typename B>
96 static const A *Unwrap(const UnlabeledStatement<B> &x) {
97 return Unwrap<A>(x.statement);
98 }
99 template <typename A, typename B>
100 static const A *Unwrap(const Statement<B> &x) {
101 return Unwrap<A>(x.statement);
102 }
103
104 template <typename A, typename B> static const A *Unwrap(B &x) {
105 if constexpr (std::is_same_v<std::decay_t<A>, std::decay_t<B>>) {
106 return &x;
107 } else if constexpr (ConstraintTrait<B>) {
108 return Unwrap<A>(x.thing);
109 } else if constexpr (WrapperTrait<B>) {
110 return Unwrap<A>(x.v);
111 } else if constexpr (UnionTrait<B>) {
112 return Unwrap<A>(x.u);
113 } else {
114 return nullptr;
115 }
116 }
117};
118
119template <typename A, typename B> const A *Unwrap(const B &x) {
120 return UnwrapperHelper::Unwrap<A>(x);
121}
122template <typename A, typename B> A *Unwrap(B &x) {
123 return const_cast<A *>(Unwrap<A, B>(const_cast<const B &>(x)));
124}
125template <typename A, typename B> const A &UnwrapRef(const B &x) {
126 return DEREF(Unwrap<A>(x));
127}
128template <typename A, typename B> A &UnwrapRef(B &x) {
129 return DEREF(Unwrap<A>(x));
130}
131
132// Get the CoindexedNamedObject if the entity is a coindexed object.
133const CoindexedNamedObject *GetCoindexedNamedObject(const AllocateObject &);
134const CoindexedNamedObject *GetCoindexedNamedObject(const DataRef &);
135const CoindexedNamedObject *GetCoindexedNamedObject(const Designator &);
136const CoindexedNamedObject *GetCoindexedNamedObject(const Variable &);
137
138// Detects parse tree nodes with "source" members.
139template <typename A, typename = int> struct HasSource : std::false_type {};
140template <typename A>
141struct HasSource<A, decltype(static_cast<void>(A::source), 0)>
142 : std::true_type {};
143
144// Detects parse tree nodes with "typedExpr", "typedCall", &c. members.
145template <typename A, typename = int> struct HasTypedExpr : std::false_type {};
146template <typename A>
147struct HasTypedExpr<A, decltype(static_cast<void>(A::typedExpr), 0)>
148 : std::true_type {};
149template <typename A, typename = int> struct HasTypedCall : std::false_type {};
150template <typename A>
151struct HasTypedCall<A, decltype(static_cast<void>(A::typedCall), 0)>
152 : std::true_type {};
153template <typename A, typename = int>
154struct HasTypedAssignment : std::false_type {};
155template <typename A>
156struct HasTypedAssignment<A, decltype(static_cast<void>(A::typedAssignment), 0)>
157 : std::true_type {};
158
159// GetSource()
160
161template <bool GET_FIRST> struct GetSourceHelper {
162
163 using Result = std::optional<CharBlock>;
164
165 template <typename A> static Result GetSource(A *p) {
166 if (p) {
167 return GetSource(*p);
168 } else {
169 return std::nullopt;
170 }
171 }
172 template <typename A>
173 static Result GetSource(const common::Indirection<A> &x) {
174 return GetSource(x.value());
175 }
176
177 template <typename A, bool COPY>
178 static Result GetSource(const common::Indirection<A, COPY> &x) {
179 return GetSource(x.value());
180 }
181
182 template <typename... As>
183 static Result GetSource(const std::variant<As...> &x) {
184 return common::visit([](const auto &y) { return GetSource(y); }, x);
185 }
186
187 template <std::size_t J = 0, typename... As>
188 static Result GetSource(const std::tuple<As...> &x) {
189 if constexpr (J < sizeof...(As)) {
190 constexpr std::size_t index{GET_FIRST ? J : sizeof...(As) - J - 1};
191 if (auto result{GetSource(std::get<index>(x))}) {
192 return result;
193 }
194 return GetSource<(J + 1)>(x);
195 } else {
196 return {};
197 }
198 }
199
200 template <typename A> static Result GetSource(const std::optional<A> &o) {
201 if (o) {
202 return GetSource(*o);
203 } else {
204 return {};
205 }
206 }
207
208 template <typename A> static Result GetSource(const std::list<A> &x) {
209 if constexpr (GET_FIRST) {
210 for (const A &y : x) {
211 if (auto result{GetSource(y)}) {
212 return result;
213 }
214 }
215 } else {
216 for (auto iter{x.rbegin()}; iter != x.rend(); ++iter) {
217 if (auto result{GetSource(*iter)}) {
218 return result;
219 }
220 }
221 }
222 return {};
223 }
224
225 template <typename A> static Result GetSource(const std::vector<A> &x) {
226 if constexpr (GET_FIRST) {
227 for (const A &y : x) {
228 if (auto result{GetSource(y)}) {
229 return result;
230 }
231 }
232 } else {
233 for (auto iter{x.rbegin()}; iter != x.rend(); ++iter) {
234 if (auto result{GetSource(*iter)}) {
235 return result;
236 }
237 }
238 }
239 return {};
240 }
241
242 template <typename A> static Result GetSource(A &x) {
243 if constexpr (HasSource<A>::value) {
244 return x.source;
245 } else if constexpr (ConstraintTrait<A>) {
246 return GetSource(x.thing);
247 } else if constexpr (WrapperTrait<A>) {
248 return GetSource(x.v);
249 } else if constexpr (UnionTrait<A>) {
250 return GetSource(x.u);
251 } else if constexpr (TupleTrait<A>) {
252 return GetSource(x.t);
253 } else {
254 return {};
255 }
256 }
257};
258
259template <typename A> std::optional<CharBlock> GetSource(const A &x) {
260 return GetSourceHelper<true>::GetSource(x);
261}
262template <typename A> std::optional<CharBlock> GetSource(A &x) {
263 return GetSourceHelper<true>::GetSource(const_cast<const A &>(x));
264}
265
266template <typename A> std::optional<CharBlock> GetLastSource(const A &x) {
267 return GetSourceHelper<false>::GetSource(x);
268}
269template <typename A> std::optional<CharBlock> GetLastSource(A &x) {
270 return GetSourceHelper<false>::GetSource(const_cast<const A &>(x));
271}
272
273// Checks whether the assignment statement has a single variable on the RHS.
274bool CheckForSingleVariableOnRHS(const AssignmentStmt &);
275
276const Name *GetDesignatorNameIfDataRef(const Designator &);
277
278// Is the template argument "Statement<T>" for some T?
279template <typename T> struct IsStatement {
280 static constexpr bool value{false};
281};
282template <typename T> struct IsStatement<Statement<T>> {
283 static constexpr bool value{true};
284};
285
286std::optional<Label> GetStatementLabel(const ExecutionPartConstruct &);
287
288std::optional<Label> GetFinalLabel(const Block &);
289std::optional<Label> GetFinalLabel(const OpenMPConstruct &);
290std::optional<Label> GetFinalLabel(const OpenACCConstruct &);
291
292} // namespace Fortran::parser
293#endif // FORTRAN_PARSER_TOOLS_H_
Definition indirection.h:31
Definition check-expression.h:19
Definition parse-tree.h:5578
Definition parse-tree.h:1954
Definition parse-tree.h:2047
Definition parse-tree.h:3328
Definition parse-tree.h:1934
Definition parse-tree.h:1850
Definition parse-tree.h:1889
Definition parse-tree.h:1424
Definition parse-tree.h:558
Definition parse-tree.h:3333
Definition tools.h:161
Definition tools.h:139
Definition tools.h:149
Definition tools.h:145
Definition tools.h:279
Definition parse-tree.h:591
Definition parse-tree.h:5857
Definition parse-tree.h:5553
Definition parse-tree.h:1929
Definition parse-tree.h:3272
Definition parse-tree.h:361
Definition parse-tree.h:1919
Definition parse-tree.h:1867
Definition parse-tree.h:356
Definition parse-tree.h:1897