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