1 //===-- include/flang/Parser/parse-tree.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_PARSE_TREE_H_
10 #define FORTRAN_PARSER_PARSE_TREE_H_
11
12 // Defines the classes used to represent successful reductions of productions
13 // in the Fortran grammar. The names and content of these definitions
14 // adhere closely to the syntax specifications in the language standard (q.v.)
15 // that are transcribed here and referenced via their requirement numbers.
16 // The representations of some productions that may also be of use in the
17 // run-time I/O support library have been isolated into a distinct header file
18 // (viz., format-specification.h).
19
20 #include "char-block.h"
21 #include "characters.h"
22 #include "format-specification.h"
23 #include "message.h"
24 #include "provenance.h"
25 #include "flang/Common/Fortran.h"
26 #include "flang/Common/idioms.h"
27 #include "flang/Common/indirection.h"
28 #include "llvm/Frontend/OpenACC/ACC.h.inc"
29 #include "llvm/Frontend/OpenMP/OMPConstants.h"
30 #include <cinttypes>
31 #include <list>
32 #include <memory>
33 #include <optional>
34 #include <string>
35 #include <tuple>
36 #include <type_traits>
37 #include <utility>
38 #include <variant>
39
40 // Parse tree node class types do not have default constructors. They
41 // explicitly declare "T() {} = delete;" to make this clear. This restriction
42 // prevents the introduction of what would be a viral requirement to include
43 // std::monostate among most std::variant<> discriminated union members.
44
45 // Parse tree node class types do not have copy constructors or copy assignment
46 // operators. They are explicitly declared "= delete;" to make this clear,
47 // although a C++ compiler wouldn't default them anyway due to the presence
48 // of explicitly defaulted move constructors and move assignments.
49
50 CLASS_TRAIT(EmptyTrait)
CLASS_TRAIT(WrapperTrait)51 CLASS_TRAIT(WrapperTrait)
52 CLASS_TRAIT(UnionTrait)
53 CLASS_TRAIT(TupleTrait)
54 CLASS_TRAIT(ConstraintTrait)
55
56 // Some parse tree nodes have fields in them to cache the results of a
57 // successful semantic analysis later. Their types are forward declared
58 // here.
59 namespace Fortran::semantics {
60 class Symbol;
61 class DeclTypeSpec;
62 class DerivedTypeSpec;
63 } // namespace Fortran::semantics
64
65 // Expressions in the parse tree have owning pointers that can be set to
66 // type-checked generic expression representations by semantic analysis.
67 namespace Fortran::evaluate {
68 struct GenericExprWrapper; // forward definition, wraps Expr<SomeType>
69 struct GenericAssignmentWrapper; // forward definition, represent assignment
70 class ProcedureRef; // forward definition, represents a CALL statement
71 } // namespace Fortran::evaluate
72
73 // Most non-template classes in this file use these default definitions
74 // for their move constructor and move assignment operator=, and disable
75 // their copy constructor and copy assignment operator=.
76 #define COPY_AND_ASSIGN_BOILERPLATE(classname) \
77 classname(classname &&) = default; \
78 classname &operator=(classname &&) = default; \
79 classname(const classname &) = delete; \
80 classname &operator=(const classname &) = delete
81
82 // Almost all classes in this file have no default constructor.
83 #define BOILERPLATE(classname) \
84 COPY_AND_ASSIGN_BOILERPLATE(classname); \
85 classname() = delete
86
87 // Empty classes are often used below as alternatives in std::variant<>
88 // discriminated unions.
89 #define EMPTY_CLASS(classname) \
90 struct classname { \
91 classname() {} \
92 classname(const classname &) {} \
93 classname(classname &&) {} \
94 classname &operator=(const classname &) { return *this; }; \
95 classname &operator=(classname &&) { return *this; }; \
96 using EmptyTrait = std::true_type; \
97 }
98
99 // Many classes below simply wrap a std::variant<> discriminated union,
100 // which is conventionally named "u".
101 #define UNION_CLASS_BOILERPLATE(classname) \
102 template <typename A, typename = common::NoLvalue<A>> \
103 classname(A &&x) : u(std::move(x)) {} \
104 using UnionTrait = std::true_type; \
105 BOILERPLATE(classname)
106
107 // Many other classes below simply wrap a std::tuple<> structure, which
108 // is conventionally named "t".
109 #define TUPLE_CLASS_BOILERPLATE(classname) \
110 template <typename... Ts, typename = common::NoLvalue<Ts...>> \
111 classname(Ts &&... args) : t(std::move(args)...) {} \
112 using TupleTrait = std::true_type; \
113 BOILERPLATE(classname)
114
115 // Many other classes below simply wrap a single data member, which is
116 // conventionally named "v".
117 #define WRAPPER_CLASS_BOILERPLATE(classname, type) \
118 BOILERPLATE(classname); \
119 classname(type &&x) : v(std::move(x)) {} \
120 using WrapperTrait = std::true_type; \
121 type v
122
123 #define WRAPPER_CLASS(classname, type) \
124 struct classname { \
125 WRAPPER_CLASS_BOILERPLATE(classname, type); \
126 }
127
128 namespace Fortran::parser {
129
130 // These are the unavoidable recursively-defined productions of Fortran.
131 // Some references to the representations of their parses require
132 // indirection. The Indirect<> pointer wrapper class is used to
133 // enforce ownership semantics and non-nullability.
134 struct SpecificationPart; // R504
135 struct ExecutableConstruct; // R514
136 struct ActionStmt; // R515
137 struct AcImpliedDo; // R774
138 struct DataImpliedDo; // R840
139 struct Designator; // R901
140 struct Variable; // R902
141 struct Expr; // R1001
142 struct WhereConstruct; // R1042
143 struct ForallConstruct; // R1050
144 struct InputImpliedDo; // R1218
145 struct OutputImpliedDo; // R1218
146 struct FunctionReference; // R1520
147 struct FunctionSubprogram; // R1529
148 struct SubroutineSubprogram; // R1534
149
150 // These additional forward references are declared so that the order of
151 // class definitions in this header file can remain reasonably consistent
152 // with order of the the requirement productions in the grammar.
153 struct DerivedTypeDef; // R726
154 struct EnumDef; // R759
155 struct TypeDeclarationStmt; // R801
156 struct AccessStmt; // R827
157 struct AllocatableStmt; // R829
158 struct AsynchronousStmt; // R831
159 struct BindStmt; // R832
160 struct CodimensionStmt; // R834
161 struct ContiguousStmt; // R836
162 struct DataStmt; // R837
163 struct DataStmtValue; // R843
164 struct DimensionStmt; // R848
165 struct IntentStmt; // R849
166 struct OptionalStmt; // R850
167 struct ParameterStmt; // R851
168 struct OldParameterStmt;
169 struct PointerStmt; // R853
170 struct ProtectedStmt; // R855
171 struct SaveStmt; // R856
172 struct TargetStmt; // R859
173 struct ValueStmt; // R861
174 struct VolatileStmt; // R862
175 struct ImplicitStmt; // R863
176 struct ImportStmt; // R867
177 struct NamelistStmt; // R868
178 struct EquivalenceStmt; // R870
179 struct CommonStmt; // R873
180 struct Substring; // R908
181 struct CharLiteralConstantSubstring;
182 struct DataRef; // R911
183 struct StructureComponent; // R913
184 struct CoindexedNamedObject; // R914
185 struct ArrayElement; // R917
186 struct AllocateStmt; // R927
187 struct NullifyStmt; // R939
188 struct DeallocateStmt; // R941
189 struct AssignmentStmt; // R1032
190 struct PointerAssignmentStmt; // R1033
191 struct WhereStmt; // R1041, R1045, R1046
192 struct ForallStmt; // R1055
193 struct AssociateConstruct; // R1102
194 struct BlockConstruct; // R1107
195 struct ChangeTeamConstruct; // R1111
196 struct CriticalConstruct; // R1116
197 struct DoConstruct; // R1119
198 struct LabelDoStmt; // R1121
199 struct ConcurrentHeader; // R1125
200 struct EndDoStmt; // R1132
201 struct CycleStmt; // R1133
202 struct IfConstruct; // R1134
203 struct IfStmt; // R1139
204 struct CaseConstruct; // R1140
205 struct SelectRankConstruct; // R1148
206 struct SelectTypeConstruct; // R1152
207 struct ExitStmt; // R1156
208 struct GotoStmt; // R1157
209 struct ComputedGotoStmt; // R1158
210 struct StopStmt; // R1160, R1161
211 struct SyncAllStmt; // R1164
212 struct SyncImagesStmt; // R1166
213 struct SyncMemoryStmt; // R1168
214 struct SyncTeamStmt; // R1169
215 struct EventPostStmt; // R1170, R1171
216 struct EventWaitStmt; // R1172, R1173, R1174
217 struct FormTeamStmt; // R1175, R1176, R1177
218 struct LockStmt; // R1178
219 struct UnlockStmt; // R1180
220 struct OpenStmt; // R1204
221 struct CloseStmt; // R1208
222 struct ReadStmt; // R1210
223 struct WriteStmt; // R1211
224 struct PrintStmt; // R1212
225 struct WaitStmt; // R1222
226 struct BackspaceStmt; // R1224
227 struct EndfileStmt; // R1225
228 struct RewindStmt; // R1226
229 struct FlushStmt; // R1228
230 struct InquireStmt; // R1230
231 struct FormatStmt; // R1301
232 struct MainProgram; // R1401
233 struct Module; // R1404
234 struct UseStmt; // R1409
235 struct Submodule; // R1416
236 struct BlockData; // R1420
237 struct InterfaceBlock; // R1501
238 struct GenericSpec; // R1508
239 struct GenericStmt; // R1510
240 struct ExternalStmt; // R1511
241 struct ProcedureDeclarationStmt; // R1512
242 struct IntrinsicStmt; // R1519
243 struct Call; // R1520 & R1521
244 struct CallStmt; // R1521
245 struct ProcedureDesignator; // R1522
246 struct ActualArg; // R1524
247 struct SeparateModuleSubprogram; // R1538
248 struct EntryStmt; // R1541
249 struct ReturnStmt; // R1542
250 struct StmtFunctionStmt; // R1544
251
252 // Directives, extensions, and deprecated statements
253 struct CompilerDirective;
254 struct BasedPointerStmt;
255 struct StructureDef;
256 struct ArithmeticIfStmt;
257 struct AssignStmt;
258 struct AssignedGotoStmt;
259 struct PauseStmt;
260 struct OpenACCConstruct;
261 struct OpenACCDeclarativeConstruct;
262 struct OpenMPConstruct;
263 struct OpenMPDeclarativeConstruct;
264 struct OmpEndLoopDirective;
265
266 // Cooked character stream locations
267 using Location = const char *;
268
269 // A parse tree node with provenance only
270 struct Verbatim {
271 BOILERPLATE(Verbatim);
272 using EmptyTrait = std::true_type;
273 CharBlock source;
274 };
275
276 // Implicit definitions of the Standard
277
278 // R403 scalar-xyz -> xyz
279 // These template class wrappers correspond to the Standard's modifiers
280 // scalar-xyz, constant-xzy, int-xzy, default-char-xyz, & logical-xyz.
281 template <typename A> struct Scalar {
282 using ConstraintTrait = std::true_type;
283 Scalar(Scalar &&that) = default;
ScalarScalar284 Scalar(A &&that) : thing(std::move(that)) {}
285 Scalar &operator=(Scalar &&) = default;
286 A thing;
287 };
288
289 template <typename A> struct Constant {
290 using ConstraintTrait = std::true_type;
291 Constant(Constant &&that) = default;
ConstantConstant292 Constant(A &&that) : thing(std::move(that)) {}
293 Constant &operator=(Constant &&) = default;
294 A thing;
295 };
296
297 template <typename A> struct Integer {
298 using ConstraintTrait = std::true_type;
299 Integer(Integer &&that) = default;
IntegerInteger300 Integer(A &&that) : thing(std::move(that)) {}
301 Integer &operator=(Integer &&) = default;
302 A thing;
303 };
304
305 template <typename A> struct Logical {
306 using ConstraintTrait = std::true_type;
307 Logical(Logical &&that) = default;
LogicalLogical308 Logical(A &&that) : thing(std::move(that)) {}
309 Logical &operator=(Logical &&) = default;
310 A thing;
311 };
312
313 template <typename A> struct DefaultChar {
314 using ConstraintTrait = std::true_type;
315 DefaultChar(DefaultChar &&that) = default;
DefaultCharDefaultChar316 DefaultChar(A &&that) : thing(std::move(that)) {}
317 DefaultChar &operator=(DefaultChar &&) = default;
318 A thing;
319 };
320
321 using LogicalExpr = Logical<common::Indirection<Expr>>; // R1024
322 using DefaultCharExpr = DefaultChar<common::Indirection<Expr>>; // R1025
323 using IntExpr = Integer<common::Indirection<Expr>>; // R1026
324 using ConstantExpr = Constant<common::Indirection<Expr>>; // R1029
325 using IntConstantExpr = Integer<ConstantExpr>; // R1031
326 using ScalarLogicalExpr = Scalar<LogicalExpr>;
327 using ScalarIntExpr = Scalar<IntExpr>;
328 using ScalarIntConstantExpr = Scalar<IntConstantExpr>;
329 using ScalarDefaultCharExpr = Scalar<DefaultCharExpr>;
330 // R1030 default-char-constant-expr is used in the Standard only as part of
331 // scalar-default-char-constant-expr.
332 using ScalarDefaultCharConstantExpr = Scalar<DefaultChar<ConstantExpr>>;
333
334 // R611 label -> digit [digit]...
335 using Label = std::uint64_t; // validated later, must be in [1..99999]
336
337 // A wrapper for xzy-stmt productions that are statements, so that
338 // source provenances and labels have a uniform representation.
339 template <typename A> struct UnlabeledStatement {
UnlabeledStatementUnlabeledStatement340 explicit UnlabeledStatement(A &&s) : statement(std::move(s)) {}
341 CharBlock source;
342 A statement;
343 };
344 template <typename A> struct Statement : public UnlabeledStatement<A> {
StatementStatement345 Statement(std::optional<long> &&lab, A &&s)
346 : UnlabeledStatement<A>{std::move(s)}, label(std::move(lab)) {}
347 std::optional<Label> label;
348 };
349
350 // Error recovery marker
351 EMPTY_CLASS(ErrorRecovery);
352
353 // R513 other-specification-stmt ->
354 // access-stmt | allocatable-stmt | asynchronous-stmt | bind-stmt |
355 // codimension-stmt | contiguous-stmt | dimension-stmt | external-stmt |
356 // intent-stmt | intrinsic-stmt | namelist-stmt | optional-stmt |
357 // pointer-stmt | protected-stmt | save-stmt | target-stmt |
358 // volatile-stmt | value-stmt | common-stmt | equivalence-stmt
359 // Extension: (Cray) based POINTER statement
360 struct OtherSpecificationStmt {
361 UNION_CLASS_BOILERPLATE(OtherSpecificationStmt);
362 std::variant<common::Indirection<AccessStmt>,
363 common::Indirection<AllocatableStmt>,
364 common::Indirection<AsynchronousStmt>, common::Indirection<BindStmt>,
365 common::Indirection<CodimensionStmt>, common::Indirection<ContiguousStmt>,
366 common::Indirection<DimensionStmt>, common::Indirection<ExternalStmt>,
367 common::Indirection<IntentStmt>, common::Indirection<IntrinsicStmt>,
368 common::Indirection<NamelistStmt>, common::Indirection<OptionalStmt>,
369 common::Indirection<PointerStmt>, common::Indirection<ProtectedStmt>,
370 common::Indirection<SaveStmt>, common::Indirection<TargetStmt>,
371 common::Indirection<ValueStmt>, common::Indirection<VolatileStmt>,
372 common::Indirection<CommonStmt>, common::Indirection<EquivalenceStmt>,
373 common::Indirection<BasedPointerStmt>>
374 u;
375 };
376
377 // R508 specification-construct ->
378 // derived-type-def | enum-def | generic-stmt | interface-block |
379 // parameter-stmt | procedure-declaration-stmt |
380 // other-specification-stmt | type-declaration-stmt
381 struct SpecificationConstruct {
382 UNION_CLASS_BOILERPLATE(SpecificationConstruct);
383 std::variant<common::Indirection<DerivedTypeDef>,
384 common::Indirection<EnumDef>, Statement<common::Indirection<GenericStmt>>,
385 common::Indirection<InterfaceBlock>,
386 Statement<common::Indirection<ParameterStmt>>,
387 Statement<common::Indirection<OldParameterStmt>>,
388 Statement<common::Indirection<ProcedureDeclarationStmt>>,
389 Statement<OtherSpecificationStmt>,
390 Statement<common::Indirection<TypeDeclarationStmt>>,
391 common::Indirection<StructureDef>,
392 common::Indirection<OpenACCDeclarativeConstruct>,
393 common::Indirection<OpenMPDeclarativeConstruct>,
394 common::Indirection<CompilerDirective>>
395 u;
396 };
397
398 // R506 implicit-part-stmt ->
399 // implicit-stmt | parameter-stmt | format-stmt | entry-stmt
400 struct ImplicitPartStmt {
401 UNION_CLASS_BOILERPLATE(ImplicitPartStmt);
402 std::variant<Statement<common::Indirection<ImplicitStmt>>,
403 Statement<common::Indirection<ParameterStmt>>,
404 Statement<common::Indirection<OldParameterStmt>>,
405 Statement<common::Indirection<FormatStmt>>,
406 Statement<common::Indirection<EntryStmt>>>
407 u;
408 };
409
410 // R505 implicit-part -> [implicit-part-stmt]... implicit-stmt
411 WRAPPER_CLASS(ImplicitPart, std::list<ImplicitPartStmt>);
412
413 // R507 declaration-construct ->
414 // specification-construct | data-stmt | format-stmt |
415 // entry-stmt | stmt-function-stmt
416 struct DeclarationConstruct {
417 UNION_CLASS_BOILERPLATE(DeclarationConstruct);
418 std::variant<SpecificationConstruct, Statement<common::Indirection<DataStmt>>,
419 Statement<common::Indirection<FormatStmt>>,
420 Statement<common::Indirection<EntryStmt>>,
421 Statement<common::Indirection<StmtFunctionStmt>>, ErrorRecovery>
422 u;
423 };
424
425 // R504 specification-part -> [use-stmt]... [import-stmt]... [implicit-part]
426 // [declaration-construct]...
427 // TODO: transfer any statements after the last IMPLICIT (if any)
428 // from the implicit part to the declaration constructs
429 struct SpecificationPart {
430 TUPLE_CLASS_BOILERPLATE(SpecificationPart);
431 std::tuple<std::list<OpenACCDeclarativeConstruct>,
432 std::list<OpenMPDeclarativeConstruct>,
433 std::list<Statement<common::Indirection<UseStmt>>>,
434 std::list<Statement<common::Indirection<ImportStmt>>>, ImplicitPart,
435 std::list<DeclarationConstruct>>
436 t;
437 };
438
439 // R512 internal-subprogram -> function-subprogram | subroutine-subprogram
440 struct InternalSubprogram {
441 UNION_CLASS_BOILERPLATE(InternalSubprogram);
442 std::variant<common::Indirection<FunctionSubprogram>,
443 common::Indirection<SubroutineSubprogram>>
444 u;
445 };
446
447 // R1543 contains-stmt -> CONTAINS
448 EMPTY_CLASS(ContainsStmt);
449
450 // R511 internal-subprogram-part -> contains-stmt [internal-subprogram]...
451 struct InternalSubprogramPart {
452 TUPLE_CLASS_BOILERPLATE(InternalSubprogramPart);
453 std::tuple<Statement<ContainsStmt>, std::list<InternalSubprogram>> t;
454 };
455
456 // R1159 continue-stmt -> CONTINUE
457 EMPTY_CLASS(ContinueStmt);
458
459 // R1163 fail-image-stmt -> FAIL IMAGE
460 EMPTY_CLASS(FailImageStmt);
461
462 // R515 action-stmt ->
463 // allocate-stmt | assignment-stmt | backspace-stmt | call-stmt |
464 // close-stmt | continue-stmt | cycle-stmt | deallocate-stmt |
465 // endfile-stmt | error-stop-stmt | event-post-stmt | event-wait-stmt |
466 // exit-stmt | fail-image-stmt | flush-stmt | form-team-stmt |
467 // goto-stmt | if-stmt | inquire-stmt | lock-stmt | nullify-stmt |
468 // open-stmt | pointer-assignment-stmt | print-stmt | read-stmt |
469 // return-stmt | rewind-stmt | stop-stmt | sync-all-stmt |
470 // sync-images-stmt | sync-memory-stmt | sync-team-stmt | unlock-stmt |
471 // wait-stmt | where-stmt | write-stmt | computed-goto-stmt | forall-stmt
472 struct ActionStmt {
473 UNION_CLASS_BOILERPLATE(ActionStmt);
474 std::variant<common::Indirection<AllocateStmt>,
475 common::Indirection<AssignmentStmt>, common::Indirection<BackspaceStmt>,
476 common::Indirection<CallStmt>, common::Indirection<CloseStmt>,
477 ContinueStmt, common::Indirection<CycleStmt>,
478 common::Indirection<DeallocateStmt>, common::Indirection<EndfileStmt>,
479 common::Indirection<EventPostStmt>, common::Indirection<EventWaitStmt>,
480 common::Indirection<ExitStmt>, FailImageStmt,
481 common::Indirection<FlushStmt>, common::Indirection<FormTeamStmt>,
482 common::Indirection<GotoStmt>, common::Indirection<IfStmt>,
483 common::Indirection<InquireStmt>, common::Indirection<LockStmt>,
484 common::Indirection<NullifyStmt>, common::Indirection<OpenStmt>,
485 common::Indirection<PointerAssignmentStmt>,
486 common::Indirection<PrintStmt>, common::Indirection<ReadStmt>,
487 common::Indirection<ReturnStmt>, common::Indirection<RewindStmt>,
488 common::Indirection<StopStmt>, common::Indirection<SyncAllStmt>,
489 common::Indirection<SyncImagesStmt>, common::Indirection<SyncMemoryStmt>,
490 common::Indirection<SyncTeamStmt>, common::Indirection<UnlockStmt>,
491 common::Indirection<WaitStmt>, common::Indirection<WhereStmt>,
492 common::Indirection<WriteStmt>, common::Indirection<ComputedGotoStmt>,
493 common::Indirection<ForallStmt>, common::Indirection<ArithmeticIfStmt>,
494 common::Indirection<AssignStmt>, common::Indirection<AssignedGotoStmt>,
495 common::Indirection<PauseStmt>>
496 u;
497 };
498
499 // R514 executable-construct ->
500 // action-stmt | associate-construct | block-construct |
501 // case-construct | change-team-construct | critical-construct |
502 // do-construct | if-construct | select-rank-construct |
503 // select-type-construct | where-construct | forall-construct
504 struct ExecutableConstruct {
505 UNION_CLASS_BOILERPLATE(ExecutableConstruct);
506 std::variant<Statement<ActionStmt>, common::Indirection<AssociateConstruct>,
507 common::Indirection<BlockConstruct>, common::Indirection<CaseConstruct>,
508 common::Indirection<ChangeTeamConstruct>,
509 common::Indirection<CriticalConstruct>,
510 Statement<common::Indirection<LabelDoStmt>>,
511 Statement<common::Indirection<EndDoStmt>>,
512 common::Indirection<DoConstruct>, common::Indirection<IfConstruct>,
513 common::Indirection<SelectRankConstruct>,
514 common::Indirection<SelectTypeConstruct>,
515 common::Indirection<WhereConstruct>, common::Indirection<ForallConstruct>,
516 common::Indirection<CompilerDirective>,
517 common::Indirection<OpenACCConstruct>,
518 common::Indirection<OpenMPConstruct>,
519 common::Indirection<OmpEndLoopDirective>>
520 u;
521 };
522
523 // R510 execution-part-construct ->
524 // executable-construct | format-stmt | entry-stmt | data-stmt
525 // Extension (PGI/Intel): also accept NAMELIST in execution part
526 struct ExecutionPartConstruct {
527 UNION_CLASS_BOILERPLATE(ExecutionPartConstruct);
528 std::variant<ExecutableConstruct, Statement<common::Indirection<FormatStmt>>,
529 Statement<common::Indirection<EntryStmt>>,
530 Statement<common::Indirection<DataStmt>>,
531 Statement<common::Indirection<NamelistStmt>>, ErrorRecovery>
532 u;
533 };
534
535 // R509 execution-part -> executable-construct [execution-part-construct]...
536 WRAPPER_CLASS(ExecutionPart, std::list<ExecutionPartConstruct>);
537
538 // R502 program-unit ->
539 // main-program | external-subprogram | module | submodule | block-data
540 // R503 external-subprogram -> function-subprogram | subroutine-subprogram
541 struct ProgramUnit {
542 UNION_CLASS_BOILERPLATE(ProgramUnit);
543 std::variant<common::Indirection<MainProgram>,
544 common::Indirection<FunctionSubprogram>,
545 common::Indirection<SubroutineSubprogram>, common::Indirection<Module>,
546 common::Indirection<Submodule>, common::Indirection<BlockData>>
547 u;
548 };
549
550 // R501 program -> program-unit [program-unit]...
551 // This is the top-level production.
552 WRAPPER_CLASS(Program, std::list<ProgramUnit>);
553
554 // R603 name -> letter [alphanumeric-character]...
555 struct Name {
ToStringName556 std::string ToString() const { return source.ToString(); }
557 CharBlock source;
558 mutable semantics::Symbol *symbol{nullptr}; // filled in during semantics
559 };
560
561 // R516 keyword -> name
562 WRAPPER_CLASS(Keyword, Name);
563
564 // R606 named-constant -> name
565 WRAPPER_CLASS(NamedConstant, Name);
566
567 // R1003 defined-unary-op -> . letter [letter]... .
568 // R1023 defined-binary-op -> . letter [letter]... .
569 // R1414 local-defined-operator -> defined-unary-op | defined-binary-op
570 // R1415 use-defined-operator -> defined-unary-op | defined-binary-op
571 // The Name here is stored with the dots; e.g., .FOO.
572 WRAPPER_CLASS(DefinedOpName, Name);
573
574 // R608 intrinsic-operator ->
575 // ** | * | / | + | - | // | .LT. | .LE. | .EQ. | .NE. | .GE. | .GT. |
576 // .NOT. | .AND. | .OR. | .EQV. | .NEQV.
577 // R609 defined-operator ->
578 // defined-unary-op | defined-binary-op | extended-intrinsic-op
579 // R610 extended-intrinsic-op -> intrinsic-operator
580 struct DefinedOperator {
581 UNION_CLASS_BOILERPLATE(DefinedOperator);
582 ENUM_CLASS(IntrinsicOperator, Power, Multiply, Divide, Add, Subtract, Concat,
583 LT, LE, EQ, NE, GE, GT, NOT, AND, OR, EQV, NEQV)
584 std::variant<DefinedOpName, IntrinsicOperator> u;
585 };
586
587 // R804 object-name -> name
588 using ObjectName = Name;
589
590 // R867 import-stmt ->
591 // IMPORT [[::] import-name-list] |
592 // IMPORT , ONLY : import-name-list | IMPORT , NONE | IMPORT , ALL
593 struct ImportStmt {
594 BOILERPLATE(ImportStmt);
ImportStmtImportStmt595 ImportStmt(common::ImportKind &&k) : kind{k} {}
ImportStmtImportStmt596 ImportStmt(std::list<Name> &&n) : names(std::move(n)) {}
597 ImportStmt(common::ImportKind &&, std::list<Name> &&);
598 common::ImportKind kind{common::ImportKind::Default};
599 std::list<Name> names;
600 };
601
602 // R868 namelist-stmt ->
603 // NAMELIST / namelist-group-name / namelist-group-object-list
604 // [[,] / namelist-group-name / namelist-group-object-list]...
605 // R869 namelist-group-object -> variable-name
606 struct NamelistStmt {
607 struct Group {
608 TUPLE_CLASS_BOILERPLATE(Group);
609 std::tuple<Name, std::list<Name>> t;
610 };
611 WRAPPER_CLASS_BOILERPLATE(NamelistStmt, std::list<Group>);
612 };
613
614 // R701 type-param-value -> scalar-int-expr | * | :
615 EMPTY_CLASS(Star);
616
617 struct TypeParamValue {
618 UNION_CLASS_BOILERPLATE(TypeParamValue);
619 EMPTY_CLASS(Deferred); // :
620 std::variant<ScalarIntExpr, Star, Deferred> u;
621 };
622
623 // R706 kind-selector -> ( [KIND =] scalar-int-constant-expr )
624 // Legacy extension: kind-selector -> * digit-string
625 // N.B. These are not semantically identical in the case of COMPLEX.
626 struct KindSelector {
627 UNION_CLASS_BOILERPLATE(KindSelector);
628 WRAPPER_CLASS(StarSize, std::uint64_t);
629 std::variant<ScalarIntConstantExpr, StarSize> u;
630 };
631
632 // R705 integer-type-spec -> INTEGER [kind-selector]
633 WRAPPER_CLASS(IntegerTypeSpec, std::optional<KindSelector>);
634
635 // R723 char-length -> ( type-param-value ) | digit-string
636 struct CharLength {
637 UNION_CLASS_BOILERPLATE(CharLength);
638 std::variant<TypeParamValue, std::uint64_t> u;
639 };
640
641 // R722 length-selector -> ( [LEN =] type-param-value ) | * char-length [,]
642 struct LengthSelector {
643 UNION_CLASS_BOILERPLATE(LengthSelector);
644 std::variant<TypeParamValue, CharLength> u;
645 };
646
647 // R721 char-selector ->
648 // length-selector |
649 // ( LEN = type-param-value , KIND = scalar-int-constant-expr ) |
650 // ( type-param-value , [KIND =] scalar-int-constant-expr ) |
651 // ( KIND = scalar-int-constant-expr [, LEN = type-param-value] )
652 struct CharSelector {
653 UNION_CLASS_BOILERPLATE(CharSelector);
654 struct LengthAndKind {
655 BOILERPLATE(LengthAndKind);
LengthAndKindCharSelector::LengthAndKind656 LengthAndKind(std::optional<TypeParamValue> &&l, ScalarIntConstantExpr &&k)
657 : length(std::move(l)), kind(std::move(k)) {}
658 std::optional<TypeParamValue> length;
659 ScalarIntConstantExpr kind;
660 };
CharSelectorCharSelector661 CharSelector(TypeParamValue &&l, ScalarIntConstantExpr &&k)
662 : u{LengthAndKind{std::make_optional(std::move(l)), std::move(k)}} {}
CharSelectorCharSelector663 CharSelector(ScalarIntConstantExpr &&k, std::optional<TypeParamValue> &&l)
664 : u{LengthAndKind{std::move(l), std::move(k)}} {}
665 std::variant<LengthSelector, LengthAndKind> u;
666 };
667
668 // R704 intrinsic-type-spec ->
669 // integer-type-spec | REAL [kind-selector] | DOUBLE PRECISION |
670 // COMPLEX [kind-selector] | CHARACTER [char-selector] |
671 // LOGICAL [kind-selector]
672 // Extensions: DOUBLE COMPLEX
673 struct IntrinsicTypeSpec {
674 UNION_CLASS_BOILERPLATE(IntrinsicTypeSpec);
675 struct Real {
676 BOILERPLATE(Real);
RealIntrinsicTypeSpec::Real677 Real(std::optional<KindSelector> &&k) : kind{std::move(k)} {}
678 std::optional<KindSelector> kind;
679 };
680 EMPTY_CLASS(DoublePrecision);
681 struct Complex {
682 BOILERPLATE(Complex);
ComplexIntrinsicTypeSpec::Complex683 Complex(std::optional<KindSelector> &&k) : kind{std::move(k)} {}
684 std::optional<KindSelector> kind;
685 };
686 struct Character {
687 BOILERPLATE(Character);
CharacterIntrinsicTypeSpec::Character688 Character(std::optional<CharSelector> &&s) : selector{std::move(s)} {}
689 std::optional<CharSelector> selector;
690 };
691 struct Logical {
692 BOILERPLATE(Logical);
LogicalIntrinsicTypeSpec::Logical693 Logical(std::optional<KindSelector> &&k) : kind{std::move(k)} {}
694 std::optional<KindSelector> kind;
695 };
696 EMPTY_CLASS(DoubleComplex);
697 std::variant<IntegerTypeSpec, Real, DoublePrecision, Complex, Character,
698 Logical, DoubleComplex>
699 u;
700 };
701
702 // R755 type-param-spec -> [keyword =] type-param-value
703 struct TypeParamSpec {
704 TUPLE_CLASS_BOILERPLATE(TypeParamSpec);
705 std::tuple<std::optional<Keyword>, TypeParamValue> t;
706 };
707
708 // R754 derived-type-spec -> type-name [(type-param-spec-list)]
709 struct DerivedTypeSpec {
710 TUPLE_CLASS_BOILERPLATE(DerivedTypeSpec);
711 mutable const semantics::DerivedTypeSpec *derivedTypeSpec{nullptr};
712 std::tuple<Name, std::list<TypeParamSpec>> t;
713 };
714
715 // R702 type-spec -> intrinsic-type-spec | derived-type-spec
716 struct TypeSpec {
717 UNION_CLASS_BOILERPLATE(TypeSpec);
718 mutable const semantics::DeclTypeSpec *declTypeSpec{nullptr};
719 std::variant<IntrinsicTypeSpec, DerivedTypeSpec> u;
720 };
721
722 // R703 declaration-type-spec ->
723 // intrinsic-type-spec | TYPE ( intrinsic-type-spec ) |
724 // TYPE ( derived-type-spec ) | CLASS ( derived-type-spec ) |
725 // CLASS ( * ) | TYPE ( * )
726 // Legacy extension: RECORD /struct/
727 struct DeclarationTypeSpec {
728 UNION_CLASS_BOILERPLATE(DeclarationTypeSpec);
729 struct Type {
730 BOILERPLATE(Type);
TypeDeclarationTypeSpec::Type731 Type(DerivedTypeSpec &&dt) : derived(std::move(dt)) {}
732 DerivedTypeSpec derived;
733 };
734 struct Class {
735 BOILERPLATE(Class);
ClassDeclarationTypeSpec::Class736 Class(DerivedTypeSpec &&dt) : derived(std::move(dt)) {}
737 DerivedTypeSpec derived;
738 };
739 EMPTY_CLASS(ClassStar);
740 EMPTY_CLASS(TypeStar);
741 WRAPPER_CLASS(Record, Name);
742 std::variant<IntrinsicTypeSpec, Type, Class, ClassStar, TypeStar, Record> u;
743 };
744
745 // R709 kind-param -> digit-string | scalar-int-constant-name
746 struct KindParam {
747 UNION_CLASS_BOILERPLATE(KindParam);
748 std::variant<std::uint64_t, Scalar<Integer<Constant<Name>>>> u;
749 };
750
751 // R707 signed-int-literal-constant -> [sign] int-literal-constant
752 struct SignedIntLiteralConstant {
753 TUPLE_CLASS_BOILERPLATE(SignedIntLiteralConstant);
754 CharBlock source;
755 std::tuple<CharBlock, std::optional<KindParam>> t;
756 };
757
758 // R708 int-literal-constant -> digit-string [_ kind-param]
759 struct IntLiteralConstant {
760 TUPLE_CLASS_BOILERPLATE(IntLiteralConstant);
761 std::tuple<CharBlock, std::optional<KindParam>> t;
762 };
763
764 // R712 sign -> + | -
765 enum class Sign { Positive, Negative };
766
767 // R714 real-literal-constant ->
768 // significand [exponent-letter exponent] [_ kind-param] |
769 // digit-string exponent-letter exponent [_ kind-param]
770 // R715 significand -> digit-string . [digit-string] | . digit-string
771 // R717 exponent -> signed-digit-string
772 struct RealLiteralConstant {
773 BOILERPLATE(RealLiteralConstant);
774 struct Real {
775 COPY_AND_ASSIGN_BOILERPLATE(Real);
RealRealLiteralConstant::Real776 Real() {}
777 CharBlock source;
778 };
RealLiteralConstantRealLiteralConstant779 RealLiteralConstant(Real &&r, std::optional<KindParam> &&k)
780 : real{std::move(r)}, kind{std::move(k)} {}
781 Real real;
782 std::optional<KindParam> kind;
783 };
784
785 // R713 signed-real-literal-constant -> [sign] real-literal-constant
786 struct SignedRealLiteralConstant {
787 TUPLE_CLASS_BOILERPLATE(SignedRealLiteralConstant);
788 std::tuple<std::optional<Sign>, RealLiteralConstant> t;
789 };
790
791 // R719 real-part ->
792 // signed-int-literal-constant | signed-real-literal-constant |
793 // named-constant
794 // R720 imag-part ->
795 // signed-int-literal-constant | signed-real-literal-constant |
796 // named-constant
797 struct ComplexPart {
798 UNION_CLASS_BOILERPLATE(ComplexPart);
799 std::variant<SignedIntLiteralConstant, SignedRealLiteralConstant,
800 NamedConstant>
801 u;
802 };
803
804 // R718 complex-literal-constant -> ( real-part , imag-part )
805 struct ComplexLiteralConstant {
806 TUPLE_CLASS_BOILERPLATE(ComplexLiteralConstant);
807 std::tuple<ComplexPart, ComplexPart> t; // real, imaginary
808 };
809
810 // Extension: signed COMPLEX constant
811 struct SignedComplexLiteralConstant {
812 TUPLE_CLASS_BOILERPLATE(SignedComplexLiteralConstant);
813 std::tuple<Sign, ComplexLiteralConstant> t;
814 };
815
816 // R724 char-literal-constant ->
817 // [kind-param _] ' [rep-char]... ' |
818 // [kind-param _] " [rep-char]... "
819 struct CharLiteralConstant {
820 TUPLE_CLASS_BOILERPLATE(CharLiteralConstant);
821 std::tuple<std::optional<KindParam>, std::string> t;
GetStringCharLiteralConstant822 std::string GetString() const { return std::get<std::string>(t); }
823 };
824
825 // legacy extension
826 struct HollerithLiteralConstant {
827 WRAPPER_CLASS_BOILERPLATE(HollerithLiteralConstant, std::string);
GetStringHollerithLiteralConstant828 std::string GetString() const { return v; }
829 };
830
831 // R725 logical-literal-constant ->
832 // .TRUE. [_ kind-param] | .FALSE. [_ kind-param]
833 struct LogicalLiteralConstant {
834 TUPLE_CLASS_BOILERPLATE(LogicalLiteralConstant);
835 std::tuple<bool, std::optional<KindParam>> t;
836 };
837
838 // R764 boz-literal-constant -> binary-constant | octal-constant | hex-constant
839 // R765 binary-constant -> B ' digit [digit]... ' | B " digit [digit]... "
840 // R766 octal-constant -> O ' digit [digit]... ' | O " digit [digit]... "
841 // R767 hex-constant ->
842 // Z ' hex-digit [hex-digit]... ' | Z " hex-digit [hex-digit]... "
843 // The constant must be large enough to hold any real or integer scalar
844 // of any supported kind (F'2018 7.7).
845 WRAPPER_CLASS(BOZLiteralConstant, std::string);
846
847 // R605 literal-constant ->
848 // int-literal-constant | real-literal-constant |
849 // complex-literal-constant | logical-literal-constant |
850 // char-literal-constant | boz-literal-constant
851 struct LiteralConstant {
852 UNION_CLASS_BOILERPLATE(LiteralConstant);
853 std::variant<HollerithLiteralConstant, IntLiteralConstant,
854 RealLiteralConstant, ComplexLiteralConstant, BOZLiteralConstant,
855 CharLiteralConstant, LogicalLiteralConstant>
856 u;
857 };
858
859 // R604 constant -> literal-constant | named-constant
860 // Renamed to dodge a clash with Constant<> template class.
861 struct ConstantValue {
862 UNION_CLASS_BOILERPLATE(ConstantValue);
863 std::variant<LiteralConstant, NamedConstant> u;
864 };
865
866 // R807 access-spec -> PUBLIC | PRIVATE
867 struct AccessSpec {
868 ENUM_CLASS(Kind, Public, Private)
869 WRAPPER_CLASS_BOILERPLATE(AccessSpec, Kind);
870 };
871
872 // R728 type-attr-spec ->
873 // ABSTRACT | access-spec | BIND(C) | EXTENDS ( parent-type-name )
874 EMPTY_CLASS(Abstract);
875 struct TypeAttrSpec {
876 UNION_CLASS_BOILERPLATE(TypeAttrSpec);
877 EMPTY_CLASS(BindC);
878 WRAPPER_CLASS(Extends, Name);
879 std::variant<Abstract, AccessSpec, BindC, Extends> u;
880 };
881
882 // R727 derived-type-stmt ->
883 // TYPE [[, type-attr-spec-list] ::] type-name [( type-param-name-list )]
884 struct DerivedTypeStmt {
885 TUPLE_CLASS_BOILERPLATE(DerivedTypeStmt);
886 std::tuple<std::list<TypeAttrSpec>, Name, std::list<Name>> t;
887 };
888
889 // R731 sequence-stmt -> SEQUENCE
890 EMPTY_CLASS(SequenceStmt);
891
892 // R745 private-components-stmt -> PRIVATE
893 // R747 binding-private-stmt -> PRIVATE
894 EMPTY_CLASS(PrivateStmt);
895
896 // R729 private-or-sequence -> private-components-stmt | sequence-stmt
897 struct PrivateOrSequence {
898 UNION_CLASS_BOILERPLATE(PrivateOrSequence);
899 std::variant<PrivateStmt, SequenceStmt> u;
900 };
901
902 // R733 type-param-decl -> type-param-name [= scalar-int-constant-expr]
903 struct TypeParamDecl {
904 TUPLE_CLASS_BOILERPLATE(TypeParamDecl);
905 std::tuple<Name, std::optional<ScalarIntConstantExpr>> t;
906 };
907
908 // R732 type-param-def-stmt ->
909 // integer-type-spec , type-param-attr-spec :: type-param-decl-list
910 // R734 type-param-attr-spec -> KIND | LEN
911 struct TypeParamDefStmt {
912 TUPLE_CLASS_BOILERPLATE(TypeParamDefStmt);
913 std::tuple<IntegerTypeSpec, common::TypeParamAttr, std::list<TypeParamDecl>>
914 t;
915 };
916
917 // R1028 specification-expr -> scalar-int-expr
918 WRAPPER_CLASS(SpecificationExpr, ScalarIntExpr);
919
920 // R816 explicit-shape-spec -> [lower-bound :] upper-bound
921 // R817 lower-bound -> specification-expr
922 // R818 upper-bound -> specification-expr
923 struct ExplicitShapeSpec {
924 TUPLE_CLASS_BOILERPLATE(ExplicitShapeSpec);
925 std::tuple<std::optional<SpecificationExpr>, SpecificationExpr> t;
926 };
927
928 // R810 deferred-coshape-spec -> :
929 // deferred-coshape-spec-list is just a count of the colons (i.e., the rank).
930 WRAPPER_CLASS(DeferredCoshapeSpecList, int);
931
932 // R811 explicit-coshape-spec ->
933 // [[lower-cobound :] upper-cobound ,]... [lower-cobound :] *
934 // R812 lower-cobound -> specification-expr
935 // R813 upper-cobound -> specification-expr
936 struct ExplicitCoshapeSpec {
937 TUPLE_CLASS_BOILERPLATE(ExplicitCoshapeSpec);
938 std::tuple<std::list<ExplicitShapeSpec>, std::optional<SpecificationExpr>> t;
939 };
940
941 // R809 coarray-spec -> deferred-coshape-spec-list | explicit-coshape-spec
942 struct CoarraySpec {
943 UNION_CLASS_BOILERPLATE(CoarraySpec);
944 std::variant<DeferredCoshapeSpecList, ExplicitCoshapeSpec> u;
945 };
946
947 // R820 deferred-shape-spec -> :
948 // deferred-shape-spec-list is just a count of the colons (i.e., the rank).
949 WRAPPER_CLASS(DeferredShapeSpecList, int);
950
951 // R740 component-array-spec ->
952 // explicit-shape-spec-list | deferred-shape-spec-list
953 struct ComponentArraySpec {
954 UNION_CLASS_BOILERPLATE(ComponentArraySpec);
955 std::variant<std::list<ExplicitShapeSpec>, DeferredShapeSpecList> u;
956 };
957
958 // R738 component-attr-spec ->
959 // access-spec | ALLOCATABLE |
960 // CODIMENSION lbracket coarray-spec rbracket |
961 // CONTIGUOUS | DIMENSION ( component-array-spec ) | POINTER
962 EMPTY_CLASS(Allocatable);
963 EMPTY_CLASS(Pointer);
964 EMPTY_CLASS(Contiguous);
965 struct ComponentAttrSpec {
966 UNION_CLASS_BOILERPLATE(ComponentAttrSpec);
967 std::variant<AccessSpec, Allocatable, CoarraySpec, Contiguous,
968 ComponentArraySpec, Pointer, ErrorRecovery>
969 u;
970 };
971
972 // R806 null-init -> function-reference
973 // TODO replace with semantic check on expression
974 EMPTY_CLASS(NullInit);
975
976 // R744 initial-data-target -> designator
977 using InitialDataTarget = common::Indirection<Designator>;
978
979 // R743 component-initialization ->
980 // = constant-expr | => null-init | => initial-data-target
981 // R805 initialization ->
982 // = constant-expr | => null-init | => initial-data-target
983 // Universal extension: initialization -> / data-stmt-value-list /
984 struct Initialization {
985 UNION_CLASS_BOILERPLATE(Initialization);
986 std::variant<ConstantExpr, NullInit, InitialDataTarget,
987 std::list<common::Indirection<DataStmtValue>>>
988 u;
989 };
990
991 // R739 component-decl ->
992 // component-name [( component-array-spec )]
993 // [lbracket coarray-spec rbracket] [* char-length]
994 // [component-initialization]
995 struct ComponentDecl {
996 TUPLE_CLASS_BOILERPLATE(ComponentDecl);
997 std::tuple<Name, std::optional<ComponentArraySpec>,
998 std::optional<CoarraySpec>, std::optional<CharLength>,
999 std::optional<Initialization>>
1000 t;
1001 };
1002
1003 // R737 data-component-def-stmt ->
1004 // declaration-type-spec [[, component-attr-spec-list] ::]
1005 // component-decl-list
1006 struct DataComponentDefStmt {
1007 TUPLE_CLASS_BOILERPLATE(DataComponentDefStmt);
1008 std::tuple<DeclarationTypeSpec, std::list<ComponentAttrSpec>,
1009 std::list<ComponentDecl>>
1010 t;
1011 };
1012
1013 // R742 proc-component-attr-spec ->
1014 // access-spec | NOPASS | PASS [(arg-name)] | POINTER
1015 EMPTY_CLASS(NoPass);
1016 WRAPPER_CLASS(Pass, std::optional<Name>);
1017 struct ProcComponentAttrSpec {
1018 UNION_CLASS_BOILERPLATE(ProcComponentAttrSpec);
1019 std::variant<AccessSpec, NoPass, Pass, Pointer> u;
1020 };
1021
1022 // R1517 proc-pointer-init -> null-init | initial-proc-target
1023 // R1518 initial-proc-target -> procedure-name
1024 struct ProcPointerInit {
1025 UNION_CLASS_BOILERPLATE(ProcPointerInit);
1026 std::variant<NullInit, Name> u;
1027 };
1028
1029 // R1513 proc-interface -> interface-name | declaration-type-spec
1030 // R1516 interface-name -> name
1031 struct ProcInterface {
1032 UNION_CLASS_BOILERPLATE(ProcInterface);
1033 std::variant<Name, DeclarationTypeSpec> u;
1034 };
1035
1036 // R1515 proc-decl -> procedure-entity-name [=> proc-pointer-init]
1037 struct ProcDecl {
1038 TUPLE_CLASS_BOILERPLATE(ProcDecl);
1039 std::tuple<Name, std::optional<ProcPointerInit>> t;
1040 };
1041
1042 // R741 proc-component-def-stmt ->
1043 // PROCEDURE ( [proc-interface] ) , proc-component-attr-spec-list
1044 // :: proc-decl-list
1045 struct ProcComponentDefStmt {
1046 TUPLE_CLASS_BOILERPLATE(ProcComponentDefStmt);
1047 std::tuple<std::optional<ProcInterface>, std::list<ProcComponentAttrSpec>,
1048 std::list<ProcDecl>>
1049 t;
1050 };
1051
1052 // R736 component-def-stmt -> data-component-def-stmt | proc-component-def-stmt
1053 struct ComponentDefStmt {
1054 UNION_CLASS_BOILERPLATE(ComponentDefStmt);
1055 std::variant<DataComponentDefStmt, ProcComponentDefStmt, ErrorRecovery
1056 // , TypeParamDefStmt -- PGI accidental extension, not enabled
1057 >
1058 u;
1059 };
1060
1061 // R752 bind-attr ->
1062 // access-spec | DEFERRED | NON_OVERRIDABLE | NOPASS | PASS [(arg-name)]
1063 struct BindAttr {
1064 UNION_CLASS_BOILERPLATE(BindAttr);
1065 EMPTY_CLASS(Deferred);
1066 EMPTY_CLASS(Non_Overridable);
1067 std::variant<AccessSpec, Deferred, Non_Overridable, NoPass, Pass> u;
1068 };
1069
1070 // R750 type-bound-proc-decl -> binding-name [=> procedure-name]
1071 struct TypeBoundProcDecl {
1072 TUPLE_CLASS_BOILERPLATE(TypeBoundProcDecl);
1073 std::tuple<Name, std::optional<Name>> t;
1074 };
1075
1076 // R749 type-bound-procedure-stmt ->
1077 // PROCEDURE [[, bind-attr-list] ::] type-bound-proc-decl-list |
1078 // PROCEDURE ( interface-name ) , bind-attr-list :: binding-name-list
1079 // The second form, with interface-name, requires DEFERRED in bind-attr-list,
1080 // and thus can appear only in an abstract type.
1081 struct TypeBoundProcedureStmt {
1082 UNION_CLASS_BOILERPLATE(TypeBoundProcedureStmt);
1083 struct WithoutInterface {
1084 BOILERPLATE(WithoutInterface);
WithoutInterfaceTypeBoundProcedureStmt::WithoutInterface1085 WithoutInterface(
1086 std::list<BindAttr> &&as, std::list<TypeBoundProcDecl> &&ds)
1087 : attributes(std::move(as)), declarations(std::move(ds)) {}
1088 std::list<BindAttr> attributes;
1089 std::list<TypeBoundProcDecl> declarations;
1090 };
1091 struct WithInterface {
1092 BOILERPLATE(WithInterface);
WithInterfaceTypeBoundProcedureStmt::WithInterface1093 WithInterface(Name &&n, std::list<BindAttr> &&as, std::list<Name> &&bs)
1094 : interfaceName(std::move(n)), attributes(std::move(as)),
1095 bindingNames(std::move(bs)) {}
1096 Name interfaceName;
1097 std::list<BindAttr> attributes;
1098 std::list<Name> bindingNames;
1099 };
1100 std::variant<WithoutInterface, WithInterface> u;
1101 };
1102
1103 // R751 type-bound-generic-stmt ->
1104 // GENERIC [, access-spec] :: generic-spec => binding-name-list
1105 struct TypeBoundGenericStmt {
1106 TUPLE_CLASS_BOILERPLATE(TypeBoundGenericStmt);
1107 std::tuple<std::optional<AccessSpec>, common::Indirection<GenericSpec>,
1108 std::list<Name>>
1109 t;
1110 };
1111
1112 // R753 final-procedure-stmt -> FINAL [::] final-subroutine-name-list
1113 WRAPPER_CLASS(FinalProcedureStmt, std::list<Name>);
1114
1115 // R748 type-bound-proc-binding ->
1116 // type-bound-procedure-stmt | type-bound-generic-stmt |
1117 // final-procedure-stmt
1118 struct TypeBoundProcBinding {
1119 UNION_CLASS_BOILERPLATE(TypeBoundProcBinding);
1120 std::variant<TypeBoundProcedureStmt, TypeBoundGenericStmt, FinalProcedureStmt,
1121 ErrorRecovery>
1122 u;
1123 };
1124
1125 // R746 type-bound-procedure-part ->
1126 // contains-stmt [binding-private-stmt] [type-bound-proc-binding]...
1127 struct TypeBoundProcedurePart {
1128 TUPLE_CLASS_BOILERPLATE(TypeBoundProcedurePart);
1129 std::tuple<Statement<ContainsStmt>, std::optional<Statement<PrivateStmt>>,
1130 std::list<Statement<TypeBoundProcBinding>>>
1131 t;
1132 };
1133
1134 // R730 end-type-stmt -> END TYPE [type-name]
1135 WRAPPER_CLASS(EndTypeStmt, std::optional<Name>);
1136
1137 // R726 derived-type-def ->
1138 // derived-type-stmt [type-param-def-stmt]... [private-or-sequence]...
1139 // [component-part] [type-bound-procedure-part] end-type-stmt
1140 // R735 component-part -> [component-def-stmt]...
1141 struct DerivedTypeDef {
1142 TUPLE_CLASS_BOILERPLATE(DerivedTypeDef);
1143 std::tuple<Statement<DerivedTypeStmt>, std::list<Statement<TypeParamDefStmt>>,
1144 std::list<Statement<PrivateOrSequence>>,
1145 std::list<Statement<ComponentDefStmt>>,
1146 std::optional<TypeBoundProcedurePart>, Statement<EndTypeStmt>>
1147 t;
1148 };
1149
1150 // R758 component-data-source -> expr | data-target | proc-target
1151 // R1037 data-target -> expr
1152 // R1040 proc-target -> expr | procedure-name | proc-component-ref
1153 WRAPPER_CLASS(ComponentDataSource, common::Indirection<Expr>);
1154
1155 // R757 component-spec -> [keyword =] component-data-source
1156 struct ComponentSpec {
1157 TUPLE_CLASS_BOILERPLATE(ComponentSpec);
1158 std::tuple<std::optional<Keyword>, ComponentDataSource> t;
1159 };
1160
1161 // R756 structure-constructor -> derived-type-spec ( [component-spec-list] )
1162 struct StructureConstructor {
1163 TUPLE_CLASS_BOILERPLATE(StructureConstructor);
1164 std::tuple<DerivedTypeSpec, std::list<ComponentSpec>> t;
1165 };
1166
1167 // R760 enum-def-stmt -> ENUM, BIND(C)
1168 EMPTY_CLASS(EnumDefStmt);
1169
1170 // R762 enumerator -> named-constant [= scalar-int-constant-expr]
1171 struct Enumerator {
1172 TUPLE_CLASS_BOILERPLATE(Enumerator);
1173 std::tuple<NamedConstant, std::optional<ScalarIntConstantExpr>> t;
1174 };
1175
1176 // R761 enumerator-def-stmt -> ENUMERATOR [::] enumerator-list
1177 WRAPPER_CLASS(EnumeratorDefStmt, std::list<Enumerator>);
1178
1179 // R763 end-enum-stmt -> END ENUM
1180 EMPTY_CLASS(EndEnumStmt);
1181
1182 // R759 enum-def ->
1183 // enum-def-stmt enumerator-def-stmt [enumerator-def-stmt]...
1184 // end-enum-stmt
1185 struct EnumDef {
1186 TUPLE_CLASS_BOILERPLATE(EnumDef);
1187 std::tuple<Statement<EnumDefStmt>, std::list<Statement<EnumeratorDefStmt>>,
1188 Statement<EndEnumStmt>>
1189 t;
1190 };
1191
1192 // R773 ac-value -> expr | ac-implied-do
1193 struct AcValue {
1194 struct Triplet { // PGI/Intel extension
1195 TUPLE_CLASS_BOILERPLATE(Triplet);
1196 std::tuple<ScalarIntExpr, ScalarIntExpr, std::optional<ScalarIntExpr>> t;
1197 };
1198 UNION_CLASS_BOILERPLATE(AcValue);
1199 std::variant<Triplet, common::Indirection<Expr>,
1200 common::Indirection<AcImpliedDo>>
1201 u;
1202 };
1203
1204 // R770 ac-spec -> type-spec :: | [type-spec ::] ac-value-list
1205 struct AcSpec {
1206 BOILERPLATE(AcSpec);
AcSpecAcSpec1207 AcSpec(std::optional<TypeSpec> &&ts, std::list<AcValue> &&xs)
1208 : type(std::move(ts)), values(std::move(xs)) {}
AcSpecAcSpec1209 explicit AcSpec(TypeSpec &&ts) : type{std::move(ts)} {}
1210 std::optional<TypeSpec> type;
1211 std::list<AcValue> values;
1212 };
1213
1214 // R769 array-constructor -> (/ ac-spec /) | lbracket ac-spec rbracket
1215 WRAPPER_CLASS(ArrayConstructor, AcSpec);
1216
1217 // R1124 do-variable -> scalar-int-variable-name
1218 using DoVariable = Scalar<Integer<Name>>;
1219
1220 template <typename VAR, typename BOUND> struct LoopBounds {
1221 LoopBounds(LoopBounds &&that) = default;
LoopBoundsLoopBounds1222 LoopBounds(
1223 VAR &&name, BOUND &&lower, BOUND &&upper, std::optional<BOUND> &&step)
1224 : name{std::move(name)}, lower{std::move(lower)}, upper{std::move(upper)},
1225 step{std::move(step)} {}
1226 LoopBounds &operator=(LoopBounds &&) = default;
1227 VAR name;
1228 BOUND lower, upper;
1229 std::optional<BOUND> step;
1230 };
1231
1232 using ScalarName = Scalar<Name>;
1233 using ScalarExpr = Scalar<common::Indirection<Expr>>;
1234
1235 // R775 ac-implied-do-control ->
1236 // [integer-type-spec ::] ac-do-variable = scalar-int-expr ,
1237 // scalar-int-expr [, scalar-int-expr]
1238 // R776 ac-do-variable -> do-variable
1239 struct AcImpliedDoControl {
1240 TUPLE_CLASS_BOILERPLATE(AcImpliedDoControl);
1241 using Bounds = LoopBounds<DoVariable, ScalarIntExpr>;
1242 std::tuple<std::optional<IntegerTypeSpec>, Bounds> t;
1243 };
1244
1245 // R774 ac-implied-do -> ( ac-value-list , ac-implied-do-control )
1246 struct AcImpliedDo {
1247 TUPLE_CLASS_BOILERPLATE(AcImpliedDo);
1248 std::tuple<std::list<AcValue>, AcImpliedDoControl> t;
1249 };
1250
1251 // R808 language-binding-spec ->
1252 // BIND ( C [, NAME = scalar-default-char-constant-expr] )
1253 // R1528 proc-language-binding-spec -> language-binding-spec
1254 WRAPPER_CLASS(
1255 LanguageBindingSpec, std::optional<ScalarDefaultCharConstantExpr>);
1256
1257 // R852 named-constant-def -> named-constant = constant-expr
1258 struct NamedConstantDef {
1259 TUPLE_CLASS_BOILERPLATE(NamedConstantDef);
1260 std::tuple<NamedConstant, ConstantExpr> t;
1261 };
1262
1263 // R851 parameter-stmt -> PARAMETER ( named-constant-def-list )
1264 WRAPPER_CLASS(ParameterStmt, std::list<NamedConstantDef>);
1265
1266 // R819 assumed-shape-spec -> [lower-bound] :
1267 WRAPPER_CLASS(AssumedShapeSpec, std::optional<SpecificationExpr>);
1268
1269 // R821 assumed-implied-spec -> [lower-bound :] *
1270 WRAPPER_CLASS(AssumedImpliedSpec, std::optional<SpecificationExpr>);
1271
1272 // R822 assumed-size-spec -> explicit-shape-spec-list , assumed-implied-spec
1273 struct AssumedSizeSpec {
1274 TUPLE_CLASS_BOILERPLATE(AssumedSizeSpec);
1275 std::tuple<std::list<ExplicitShapeSpec>, AssumedImpliedSpec> t;
1276 };
1277
1278 // R823 implied-shape-or-assumed-size-spec -> assumed-implied-spec
1279 // R824 implied-shape-spec -> assumed-implied-spec , assumed-implied-spec-list
1280 // I.e., when the assumed-implied-spec-list has a single item, it constitutes an
1281 // implied-shape-or-assumed-size-spec; otherwise, an implied-shape-spec.
1282 WRAPPER_CLASS(ImpliedShapeSpec, std::list<AssumedImpliedSpec>);
1283
1284 // R825 assumed-rank-spec -> ..
1285 EMPTY_CLASS(AssumedRankSpec);
1286
1287 // R815 array-spec ->
1288 // explicit-shape-spec-list | assumed-shape-spec-list |
1289 // deferred-shape-spec-list | assumed-size-spec | implied-shape-spec |
1290 // implied-shape-or-assumed-size-spec | assumed-rank-spec
1291 struct ArraySpec {
1292 UNION_CLASS_BOILERPLATE(ArraySpec);
1293 std::variant<std::list<ExplicitShapeSpec>, std::list<AssumedShapeSpec>,
1294 DeferredShapeSpecList, AssumedSizeSpec, ImpliedShapeSpec, AssumedRankSpec>
1295 u;
1296 };
1297
1298 // R826 intent-spec -> IN | OUT | INOUT
1299 struct IntentSpec {
1300 ENUM_CLASS(Intent, In, Out, InOut)
1301 WRAPPER_CLASS_BOILERPLATE(IntentSpec, Intent);
1302 };
1303
1304 // R802 attr-spec ->
1305 // access-spec | ALLOCATABLE | ASYNCHRONOUS |
1306 // CODIMENSION lbracket coarray-spec rbracket | CONTIGUOUS |
1307 // DIMENSION ( array-spec ) | EXTERNAL | INTENT ( intent-spec ) |
1308 // INTRINSIC | language-binding-spec | OPTIONAL | PARAMETER | POINTER |
1309 // PROTECTED | SAVE | TARGET | VALUE | VOLATILE
1310 EMPTY_CLASS(Asynchronous);
1311 EMPTY_CLASS(External);
1312 EMPTY_CLASS(Intrinsic);
1313 EMPTY_CLASS(Optional);
1314 EMPTY_CLASS(Parameter);
1315 EMPTY_CLASS(Protected);
1316 EMPTY_CLASS(Save);
1317 EMPTY_CLASS(Target);
1318 EMPTY_CLASS(Value);
1319 EMPTY_CLASS(Volatile);
1320 struct AttrSpec {
1321 UNION_CLASS_BOILERPLATE(AttrSpec);
1322 std::variant<AccessSpec, Allocatable, Asynchronous, CoarraySpec, Contiguous,
1323 ArraySpec, External, IntentSpec, Intrinsic, LanguageBindingSpec, Optional,
1324 Parameter, Pointer, Protected, Save, Target, Value, Volatile>
1325 u;
1326 };
1327
1328 // R803 entity-decl ->
1329 // object-name [( array-spec )] [lbracket coarray-spec rbracket]
1330 // [* char-length] [initialization] |
1331 // function-name [* char-length]
1332 struct EntityDecl {
1333 TUPLE_CLASS_BOILERPLATE(EntityDecl);
1334 std::tuple<ObjectName, std::optional<ArraySpec>, std::optional<CoarraySpec>,
1335 std::optional<CharLength>, std::optional<Initialization>>
1336 t;
1337 };
1338
1339 // R801 type-declaration-stmt ->
1340 // declaration-type-spec [[, attr-spec]... ::] entity-decl-list
1341 struct TypeDeclarationStmt {
1342 TUPLE_CLASS_BOILERPLATE(TypeDeclarationStmt);
1343 std::tuple<DeclarationTypeSpec, std::list<AttrSpec>, std::list<EntityDecl>> t;
1344 };
1345
1346 // R828 access-id -> access-name | generic-spec
1347 struct AccessId {
1348 UNION_CLASS_BOILERPLATE(AccessId);
1349 std::variant<Name, common::Indirection<GenericSpec>> u;
1350 };
1351
1352 // R827 access-stmt -> access-spec [[::] access-id-list]
1353 struct AccessStmt {
1354 TUPLE_CLASS_BOILERPLATE(AccessStmt);
1355 std::tuple<AccessSpec, std::list<AccessId>> t;
1356 };
1357
1358 // R830 allocatable-decl ->
1359 // object-name [( array-spec )] [lbracket coarray-spec rbracket]
1360 // R860 target-decl ->
1361 // object-name [( array-spec )] [lbracket coarray-spec rbracket]
1362 struct ObjectDecl {
1363 TUPLE_CLASS_BOILERPLATE(ObjectDecl);
1364 std::tuple<ObjectName, std::optional<ArraySpec>, std::optional<CoarraySpec>>
1365 t;
1366 };
1367
1368 // R829 allocatable-stmt -> ALLOCATABLE [::] allocatable-decl-list
1369 WRAPPER_CLASS(AllocatableStmt, std::list<ObjectDecl>);
1370
1371 // R831 asynchronous-stmt -> ASYNCHRONOUS [::] object-name-list
1372 WRAPPER_CLASS(AsynchronousStmt, std::list<ObjectName>);
1373
1374 // R833 bind-entity -> entity-name | / common-block-name /
1375 struct BindEntity {
1376 TUPLE_CLASS_BOILERPLATE(BindEntity);
1377 ENUM_CLASS(Kind, Object, Common)
1378 std::tuple<Kind, Name> t;
1379 };
1380
1381 // R832 bind-stmt -> language-binding-spec [::] bind-entity-list
1382 struct BindStmt {
1383 TUPLE_CLASS_BOILERPLATE(BindStmt);
1384 std::tuple<LanguageBindingSpec, std::list<BindEntity>> t;
1385 };
1386
1387 // R835 codimension-decl -> coarray-name lbracket coarray-spec rbracket
1388 struct CodimensionDecl {
1389 TUPLE_CLASS_BOILERPLATE(CodimensionDecl);
1390 std::tuple<Name, CoarraySpec> t;
1391 };
1392
1393 // R834 codimension-stmt -> CODIMENSION [::] codimension-decl-list
1394 WRAPPER_CLASS(CodimensionStmt, std::list<CodimensionDecl>);
1395
1396 // R836 contiguous-stmt -> CONTIGUOUS [::] object-name-list
1397 WRAPPER_CLASS(ContiguousStmt, std::list<ObjectName>);
1398
1399 // R847 constant-subobject -> designator
1400 // R846 int-constant-subobject -> constant-subobject
1401 using ConstantSubobject = Constant<common::Indirection<Designator>>;
1402
1403 // Represents an analyzed expression
1404 using TypedExpr = common::ForwardOwningPointer<evaluate::GenericExprWrapper>;
1405
1406 // R845 data-stmt-constant ->
1407 // scalar-constant | scalar-constant-subobject |
1408 // signed-int-literal-constant | signed-real-literal-constant |
1409 // null-init | initial-data-target |
1410 // constant-structure-constructor <- added "constant-"
1411 struct DataStmtConstant {
1412 UNION_CLASS_BOILERPLATE(DataStmtConstant);
1413 CharBlock source;
1414 mutable TypedExpr typedExpr;
1415 std::variant<Scalar<ConstantValue>, Scalar<ConstantSubobject>,
1416 SignedIntLiteralConstant, SignedRealLiteralConstant,
1417 SignedComplexLiteralConstant, NullInit, InitialDataTarget,
1418 StructureConstructor>
1419 u;
1420 };
1421
1422 // R844 data-stmt-repeat -> scalar-int-constant | scalar-int-constant-subobject
1423 // R607 int-constant -> constant
1424 // R604 constant -> literal-constant | named-constant
1425 // (only literal-constant -> int-literal-constant applies)
1426 struct DataStmtRepeat {
1427 UNION_CLASS_BOILERPLATE(DataStmtRepeat);
1428 std::variant<IntLiteralConstant, Scalar<Integer<ConstantSubobject>>> u;
1429 };
1430
1431 // R843 data-stmt-value -> [data-stmt-repeat *] data-stmt-constant
1432 struct DataStmtValue {
1433 TUPLE_CLASS_BOILERPLATE(DataStmtValue);
1434 mutable std::int64_t repetitions{1}; // replaced during semantics
1435 std::tuple<std::optional<DataStmtRepeat>, DataStmtConstant> t;
1436 };
1437
1438 // R841 data-i-do-object ->
1439 // array-element | scalar-structure-component | data-implied-do
1440 struct DataIDoObject {
1441 UNION_CLASS_BOILERPLATE(DataIDoObject);
1442 std::variant<Scalar<common::Indirection<Designator>>,
1443 common::Indirection<DataImpliedDo>>
1444 u;
1445 };
1446
1447 // R840 data-implied-do ->
1448 // ( data-i-do-object-list , [integer-type-spec ::] data-i-do-variable
1449 // = scalar-int-constant-expr , scalar-int-constant-expr
1450 // [, scalar-int-constant-expr] )
1451 // R842 data-i-do-variable -> do-variable
1452 struct DataImpliedDo {
1453 TUPLE_CLASS_BOILERPLATE(DataImpliedDo);
1454 using Bounds = LoopBounds<DoVariable, ScalarIntConstantExpr>;
1455 std::tuple<std::list<DataIDoObject>, std::optional<IntegerTypeSpec>, Bounds>
1456 t;
1457 };
1458
1459 // R839 data-stmt-object -> variable | data-implied-do
1460 struct DataStmtObject {
1461 UNION_CLASS_BOILERPLATE(DataStmtObject);
1462 std::variant<common::Indirection<Variable>, DataImpliedDo> u;
1463 };
1464
1465 // R838 data-stmt-set -> data-stmt-object-list / data-stmt-value-list /
1466 struct DataStmtSet {
1467 TUPLE_CLASS_BOILERPLATE(DataStmtSet);
1468 std::tuple<std::list<DataStmtObject>, std::list<DataStmtValue>> t;
1469 };
1470
1471 // R837 data-stmt -> DATA data-stmt-set [[,] data-stmt-set]...
1472 WRAPPER_CLASS(DataStmt, std::list<DataStmtSet>);
1473
1474 // R848 dimension-stmt ->
1475 // DIMENSION [::] array-name ( array-spec )
1476 // [, array-name ( array-spec )]...
1477 struct DimensionStmt {
1478 struct Declaration {
1479 TUPLE_CLASS_BOILERPLATE(Declaration);
1480 std::tuple<Name, ArraySpec> t;
1481 };
1482 WRAPPER_CLASS_BOILERPLATE(DimensionStmt, std::list<Declaration>);
1483 };
1484
1485 // R849 intent-stmt -> INTENT ( intent-spec ) [::] dummy-arg-name-list
1486 struct IntentStmt {
1487 TUPLE_CLASS_BOILERPLATE(IntentStmt);
1488 std::tuple<IntentSpec, std::list<Name>> t;
1489 };
1490
1491 // R850 optional-stmt -> OPTIONAL [::] dummy-arg-name-list
1492 WRAPPER_CLASS(OptionalStmt, std::list<Name>);
1493
1494 // R854 pointer-decl ->
1495 // object-name [( deferred-shape-spec-list )] | proc-entity-name
1496 struct PointerDecl {
1497 TUPLE_CLASS_BOILERPLATE(PointerDecl);
1498 std::tuple<Name, std::optional<DeferredShapeSpecList>> t;
1499 };
1500
1501 // R853 pointer-stmt -> POINTER [::] pointer-decl-list
1502 WRAPPER_CLASS(PointerStmt, std::list<PointerDecl>);
1503
1504 // R855 protected-stmt -> PROTECTED [::] entity-name-list
1505 WRAPPER_CLASS(ProtectedStmt, std::list<Name>);
1506
1507 // R857 saved-entity -> object-name | proc-pointer-name | / common-block-name /
1508 // R858 proc-pointer-name -> name
1509 struct SavedEntity {
1510 TUPLE_CLASS_BOILERPLATE(SavedEntity);
1511 ENUM_CLASS(Kind, Entity, Common)
1512 std::tuple<Kind, Name> t;
1513 };
1514
1515 // R856 save-stmt -> SAVE [[::] saved-entity-list]
1516 WRAPPER_CLASS(SaveStmt, std::list<SavedEntity>);
1517
1518 // R859 target-stmt -> TARGET [::] target-decl-list
1519 WRAPPER_CLASS(TargetStmt, std::list<ObjectDecl>);
1520
1521 // R861 value-stmt -> VALUE [::] dummy-arg-name-list
1522 WRAPPER_CLASS(ValueStmt, std::list<Name>);
1523
1524 // R862 volatile-stmt -> VOLATILE [::] object-name-list
1525 WRAPPER_CLASS(VolatileStmt, std::list<ObjectName>);
1526
1527 // R865 letter-spec -> letter [- letter]
1528 struct LetterSpec {
1529 TUPLE_CLASS_BOILERPLATE(LetterSpec);
1530 std::tuple<Location, std::optional<Location>> t;
1531 };
1532
1533 // R864 implicit-spec -> declaration-type-spec ( letter-spec-list )
1534 struct ImplicitSpec {
1535 TUPLE_CLASS_BOILERPLATE(ImplicitSpec);
1536 std::tuple<DeclarationTypeSpec, std::list<LetterSpec>> t;
1537 };
1538
1539 // R863 implicit-stmt ->
1540 // IMPLICIT implicit-spec-list |
1541 // IMPLICIT NONE [( [implicit-name-spec-list] )]
1542 // R866 implicit-name-spec -> EXTERNAL | TYPE
1543 struct ImplicitStmt {
1544 UNION_CLASS_BOILERPLATE(ImplicitStmt);
1545 ENUM_CLASS(ImplicitNoneNameSpec, External, Type) // R866
1546 std::variant<std::list<ImplicitSpec>, std::list<ImplicitNoneNameSpec>> u;
1547 };
1548
1549 // R874 common-block-object -> variable-name [( array-spec )]
1550 struct CommonBlockObject {
1551 TUPLE_CLASS_BOILERPLATE(CommonBlockObject);
1552 std::tuple<Name, std::optional<ArraySpec>> t;
1553 };
1554
1555 // R873 common-stmt ->
1556 // COMMON [/ [common-block-name] /] common-block-object-list
1557 // [[,] / [common-block-name] / common-block-object-list]...
1558 struct CommonStmt {
1559 struct Block {
1560 TUPLE_CLASS_BOILERPLATE(Block);
1561 std::tuple<std::optional<Name>, std::list<CommonBlockObject>> t;
1562 };
1563 BOILERPLATE(CommonStmt);
1564 CommonStmt(std::optional<Name> &&, std::list<CommonBlockObject> &&,
1565 std::list<Block> &&);
1566 std::list<Block> blocks;
1567 };
1568
1569 // R872 equivalence-object -> variable-name | array-element | substring
1570 WRAPPER_CLASS(EquivalenceObject, common::Indirection<Designator>);
1571
1572 // R870 equivalence-stmt -> EQUIVALENCE equivalence-set-list
1573 // R871 equivalence-set -> ( equivalence-object , equivalence-object-list )
1574 WRAPPER_CLASS(EquivalenceStmt, std::list<std::list<EquivalenceObject>>);
1575
1576 // R910 substring-range -> [scalar-int-expr] : [scalar-int-expr]
1577 struct SubstringRange {
1578 TUPLE_CLASS_BOILERPLATE(SubstringRange);
1579 std::tuple<std::optional<ScalarIntExpr>, std::optional<ScalarIntExpr>> t;
1580 };
1581
1582 // R919 subscript -> scalar-int-expr
1583 using Subscript = ScalarIntExpr;
1584
1585 // R921 subscript-triplet -> [subscript] : [subscript] [: stride]
1586 struct SubscriptTriplet {
1587 TUPLE_CLASS_BOILERPLATE(SubscriptTriplet);
1588 std::tuple<std::optional<Subscript>, std::optional<Subscript>,
1589 std::optional<Subscript>>
1590 t;
1591 };
1592
1593 // R920 section-subscript -> subscript | subscript-triplet | vector-subscript
1594 // R923 vector-subscript -> int-expr
1595 struct SectionSubscript {
1596 UNION_CLASS_BOILERPLATE(SectionSubscript);
1597 std::variant<IntExpr, SubscriptTriplet> u;
1598 };
1599
1600 // R925 cosubscript -> scalar-int-expr
1601 using Cosubscript = ScalarIntExpr;
1602
1603 // R1115 team-value -> scalar-expr
1604 WRAPPER_CLASS(TeamValue, Scalar<common::Indirection<Expr>>);
1605
1606 // R926 image-selector-spec ->
1607 // STAT = stat-variable | TEAM = team-value |
1608 // TEAM_NUMBER = scalar-int-expr
1609 struct ImageSelectorSpec {
1610 WRAPPER_CLASS(Stat, Scalar<Integer<common::Indirection<Variable>>>);
1611 WRAPPER_CLASS(Team_Number, ScalarIntExpr);
1612 UNION_CLASS_BOILERPLATE(ImageSelectorSpec);
1613 std::variant<Stat, TeamValue, Team_Number> u;
1614 };
1615
1616 // R924 image-selector ->
1617 // lbracket cosubscript-list [, image-selector-spec-list] rbracket
1618 struct ImageSelector {
1619 TUPLE_CLASS_BOILERPLATE(ImageSelector);
1620 std::tuple<std::list<Cosubscript>, std::list<ImageSelectorSpec>> t;
1621 };
1622
1623 // R1001 - R1022 expressions
1624 struct Expr {
1625 UNION_CLASS_BOILERPLATE(Expr);
1626
1627 WRAPPER_CLASS(IntrinsicUnary, common::Indirection<Expr>);
1628 struct Parentheses : public IntrinsicUnary {
1629 using IntrinsicUnary::IntrinsicUnary;
1630 };
1631 struct UnaryPlus : public IntrinsicUnary {
1632 using IntrinsicUnary::IntrinsicUnary;
1633 };
1634 struct Negate : public IntrinsicUnary {
1635 using IntrinsicUnary::IntrinsicUnary;
1636 };
1637 struct NOT : public IntrinsicUnary {
1638 using IntrinsicUnary::IntrinsicUnary;
1639 };
1640
1641 WRAPPER_CLASS(PercentLoc, common::Indirection<Variable>); // %LOC(v) extension
1642
1643 struct DefinedUnary {
1644 TUPLE_CLASS_BOILERPLATE(DefinedUnary);
1645 std::tuple<DefinedOpName, common::Indirection<Expr>> t;
1646 };
1647
1648 struct IntrinsicBinary {
1649 TUPLE_CLASS_BOILERPLATE(IntrinsicBinary);
1650 std::tuple<common::Indirection<Expr>, common::Indirection<Expr>> t;
1651 };
1652 struct Power : public IntrinsicBinary {
1653 using IntrinsicBinary::IntrinsicBinary;
1654 };
1655 struct Multiply : public IntrinsicBinary {
1656 using IntrinsicBinary::IntrinsicBinary;
1657 };
1658 struct Divide : public IntrinsicBinary {
1659 using IntrinsicBinary::IntrinsicBinary;
1660 };
1661 struct Add : public IntrinsicBinary {
1662 using IntrinsicBinary::IntrinsicBinary;
1663 };
1664 struct Subtract : public IntrinsicBinary {
1665 using IntrinsicBinary::IntrinsicBinary;
1666 };
1667 struct Concat : public IntrinsicBinary {
1668 using IntrinsicBinary::IntrinsicBinary;
1669 };
1670 struct LT : public IntrinsicBinary {
1671 using IntrinsicBinary::IntrinsicBinary;
1672 };
1673 struct LE : public IntrinsicBinary {
1674 using IntrinsicBinary::IntrinsicBinary;
1675 };
1676 struct EQ : public IntrinsicBinary {
1677 using IntrinsicBinary::IntrinsicBinary;
1678 };
1679 struct NE : public IntrinsicBinary {
1680 using IntrinsicBinary::IntrinsicBinary;
1681 };
1682 struct GE : public IntrinsicBinary {
1683 using IntrinsicBinary::IntrinsicBinary;
1684 };
1685 struct GT : public IntrinsicBinary {
1686 using IntrinsicBinary::IntrinsicBinary;
1687 };
1688 struct AND : public IntrinsicBinary {
1689 using IntrinsicBinary::IntrinsicBinary;
1690 };
1691 struct OR : public IntrinsicBinary {
1692 using IntrinsicBinary::IntrinsicBinary;
1693 };
1694 struct EQV : public IntrinsicBinary {
1695 using IntrinsicBinary::IntrinsicBinary;
1696 };
1697 struct NEQV : public IntrinsicBinary {
1698 using IntrinsicBinary::IntrinsicBinary;
1699 };
1700
1701 // PGI/XLF extension: (x,y), not both constant
1702 struct ComplexConstructor : public IntrinsicBinary {
1703 using IntrinsicBinary::IntrinsicBinary;
1704 };
1705
1706 struct DefinedBinary {
1707 TUPLE_CLASS_BOILERPLATE(DefinedBinary);
1708 std::tuple<DefinedOpName, common::Indirection<Expr>,
1709 common::Indirection<Expr>>
1710 t;
1711 };
1712
1713 explicit Expr(Designator &&);
1714 explicit Expr(FunctionReference &&);
1715
1716 mutable TypedExpr typedExpr;
1717
1718 CharBlock source;
1719
1720 std::variant<common::Indirection<CharLiteralConstantSubstring>,
1721 LiteralConstant, common::Indirection<Designator>, ArrayConstructor,
1722 StructureConstructor, common::Indirection<FunctionReference>, Parentheses,
1723 UnaryPlus, Negate, NOT, PercentLoc, DefinedUnary, Power, Multiply, Divide,
1724 Add, Subtract, Concat, LT, LE, EQ, NE, GE, GT, AND, OR, EQV, NEQV,
1725 DefinedBinary, ComplexConstructor>
1726 u;
1727 };
1728
1729 // R912 part-ref -> part-name [( section-subscript-list )] [image-selector]
1730 struct PartRef {
1731 BOILERPLATE(PartRef);
PartRefPartRef1732 PartRef(Name &&n, std::list<SectionSubscript> &&ss,
1733 std::optional<ImageSelector> &&is)
1734 : name{std::move(n)},
1735 subscripts(std::move(ss)), imageSelector{std::move(is)} {}
1736 Name name;
1737 std::list<SectionSubscript> subscripts;
1738 std::optional<ImageSelector> imageSelector;
1739 };
1740
1741 // R911 data-ref -> part-ref [% part-ref]...
1742 struct DataRef {
1743 UNION_CLASS_BOILERPLATE(DataRef);
1744 explicit DataRef(std::list<PartRef> &&);
1745 std::variant<Name, common::Indirection<StructureComponent>,
1746 common::Indirection<ArrayElement>,
1747 common::Indirection<CoindexedNamedObject>>
1748 u;
1749 };
1750
1751 // R908 substring -> parent-string ( substring-range )
1752 // R909 parent-string ->
1753 // scalar-variable-name | array-element | coindexed-named-object |
1754 // scalar-structure-component | scalar-char-literal-constant |
1755 // scalar-named-constant
1756 // Substrings of character literals have been factored out into their
1757 // own productions so that they can't appear as designators in any context
1758 // other than a primary expression.
1759 struct Substring {
1760 TUPLE_CLASS_BOILERPLATE(Substring);
1761 std::tuple<DataRef, SubstringRange> t;
1762 };
1763
1764 struct CharLiteralConstantSubstring {
1765 TUPLE_CLASS_BOILERPLATE(CharLiteralConstantSubstring);
1766 std::tuple<CharLiteralConstant, SubstringRange> t;
1767 };
1768
1769 // R901 designator -> object-name | array-element | array-section |
1770 // coindexed-named-object | complex-part-designator |
1771 // structure-component | substring
1772 struct Designator {
1773 UNION_CLASS_BOILERPLATE(Designator);
1774 bool EndsInBareName() const;
1775 CharBlock source;
1776 std::variant<DataRef, Substring> u;
1777 };
1778
1779 // R902 variable -> designator | function-reference
1780 struct Variable {
1781 UNION_CLASS_BOILERPLATE(Variable);
1782 mutable TypedExpr typedExpr;
1783 parser::CharBlock GetSource() const;
1784 std::variant<common::Indirection<Designator>,
1785 common::Indirection<FunctionReference>>
1786 u;
1787 };
1788
1789 // R904 logical-variable -> variable
1790 // Appears only as part of scalar-logical-variable.
1791 using ScalarLogicalVariable = Scalar<Logical<Variable>>;
1792
1793 // R906 default-char-variable -> variable
1794 // Appears only as part of scalar-default-char-variable.
1795 using ScalarDefaultCharVariable = Scalar<DefaultChar<Variable>>;
1796
1797 // R907 int-variable -> variable
1798 // Appears only as part of scalar-int-variable.
1799 using ScalarIntVariable = Scalar<Integer<Variable>>;
1800
1801 // R913 structure-component -> data-ref
1802 struct StructureComponent {
1803 BOILERPLATE(StructureComponent);
StructureComponentStructureComponent1804 StructureComponent(DataRef &&dr, Name &&n)
1805 : base{std::move(dr)}, component(std::move(n)) {}
1806 DataRef base;
1807 Name component;
1808 };
1809
1810 // R1039 proc-component-ref -> scalar-variable % procedure-component-name
1811 // C1027 constrains the scalar-variable to be a data-ref without coindices.
1812 struct ProcComponentRef {
1813 WRAPPER_CLASS_BOILERPLATE(ProcComponentRef, Scalar<StructureComponent>);
1814 };
1815
1816 // R914 coindexed-named-object -> data-ref
1817 struct CoindexedNamedObject {
1818 BOILERPLATE(CoindexedNamedObject);
CoindexedNamedObjectCoindexedNamedObject1819 CoindexedNamedObject(DataRef &&dr, ImageSelector &&is)
1820 : base{std::move(dr)}, imageSelector{std::move(is)} {}
1821 DataRef base;
1822 ImageSelector imageSelector;
1823 };
1824
1825 // R917 array-element -> data-ref
1826 struct ArrayElement {
1827 BOILERPLATE(ArrayElement);
ArrayElementArrayElement1828 ArrayElement(DataRef &&dr, std::list<SectionSubscript> &&ss)
1829 : base{std::move(dr)}, subscripts(std::move(ss)) {}
1830 Substring ConvertToSubstring();
1831 StructureConstructor ConvertToStructureConstructor(
1832 const semantics::DerivedTypeSpec &);
1833 DataRef base;
1834 std::list<SectionSubscript> subscripts;
1835 };
1836
1837 // R933 allocate-object -> variable-name | structure-component
1838 struct AllocateObject {
1839 UNION_CLASS_BOILERPLATE(AllocateObject);
1840 std::variant<Name, StructureComponent> u;
1841 };
1842
1843 // R935 lower-bound-expr -> scalar-int-expr
1844 // R936 upper-bound-expr -> scalar-int-expr
1845 using BoundExpr = ScalarIntExpr;
1846
1847 // R934 allocate-shape-spec -> [lower-bound-expr :] upper-bound-expr
1848 // R938 allocate-coshape-spec -> [lower-bound-expr :] upper-bound-expr
1849 struct AllocateShapeSpec {
1850 TUPLE_CLASS_BOILERPLATE(AllocateShapeSpec);
1851 std::tuple<std::optional<BoundExpr>, BoundExpr> t;
1852 };
1853
1854 using AllocateCoshapeSpec = AllocateShapeSpec;
1855
1856 // R937 allocate-coarray-spec ->
1857 // [allocate-coshape-spec-list ,] [lower-bound-expr :] *
1858 struct AllocateCoarraySpec {
1859 TUPLE_CLASS_BOILERPLATE(AllocateCoarraySpec);
1860 std::tuple<std::list<AllocateCoshapeSpec>, std::optional<BoundExpr>> t;
1861 };
1862
1863 // R932 allocation ->
1864 // allocate-object [( allocate-shape-spec-list )]
1865 // [lbracket allocate-coarray-spec rbracket]
1866 struct Allocation {
1867 TUPLE_CLASS_BOILERPLATE(Allocation);
1868 std::tuple<AllocateObject, std::list<AllocateShapeSpec>,
1869 std::optional<AllocateCoarraySpec>>
1870 t;
1871 };
1872
1873 // R929 stat-variable -> scalar-int-variable
1874 WRAPPER_CLASS(StatVariable, ScalarIntVariable);
1875
1876 // R930 errmsg-variable -> scalar-default-char-variable
1877 // R1207 iomsg-variable -> scalar-default-char-variable
1878 WRAPPER_CLASS(MsgVariable, ScalarDefaultCharVariable);
1879
1880 // R942 dealloc-opt -> STAT = stat-variable | ERRMSG = errmsg-variable
1881 // R1165 sync-stat -> STAT = stat-variable | ERRMSG = errmsg-variable
1882 struct StatOrErrmsg {
1883 UNION_CLASS_BOILERPLATE(StatOrErrmsg);
1884 std::variant<StatVariable, MsgVariable> u;
1885 };
1886
1887 // R928 alloc-opt ->
1888 // ERRMSG = errmsg-variable | MOLD = source-expr |
1889 // SOURCE = source-expr | STAT = stat-variable
1890 // R931 source-expr -> expr
1891 struct AllocOpt {
1892 UNION_CLASS_BOILERPLATE(AllocOpt);
1893 WRAPPER_CLASS(Mold, common::Indirection<Expr>);
1894 WRAPPER_CLASS(Source, common::Indirection<Expr>);
1895 std::variant<Mold, Source, StatOrErrmsg> u;
1896 };
1897
1898 // R927 allocate-stmt ->
1899 // ALLOCATE ( [type-spec ::] allocation-list [, alloc-opt-list] )
1900 struct AllocateStmt {
1901 TUPLE_CLASS_BOILERPLATE(AllocateStmt);
1902 std::tuple<std::optional<TypeSpec>, std::list<Allocation>,
1903 std::list<AllocOpt>>
1904 t;
1905 };
1906
1907 // R940 pointer-object ->
1908 // variable-name | structure-component | proc-pointer-name
1909 struct PointerObject {
1910 UNION_CLASS_BOILERPLATE(PointerObject);
1911 std::variant<Name, StructureComponent> u;
1912 };
1913
1914 // R939 nullify-stmt -> NULLIFY ( pointer-object-list )
1915 WRAPPER_CLASS(NullifyStmt, std::list<PointerObject>);
1916
1917 // R941 deallocate-stmt ->
1918 // DEALLOCATE ( allocate-object-list [, dealloc-opt-list] )
1919 struct DeallocateStmt {
1920 TUPLE_CLASS_BOILERPLATE(DeallocateStmt);
1921 std::tuple<std::list<AllocateObject>, std::list<StatOrErrmsg>> t;
1922 };
1923
1924 // R1032 assignment-stmt -> variable = expr
1925 struct AssignmentStmt {
1926 TUPLE_CLASS_BOILERPLATE(AssignmentStmt);
1927 using TypedAssignment =
1928 common::ForwardOwningPointer<evaluate::GenericAssignmentWrapper>;
1929 mutable TypedAssignment typedAssignment;
1930 std::tuple<Variable, Expr> t;
1931 };
1932
1933 // R1035 bounds-spec -> lower-bound-expr :
1934 WRAPPER_CLASS(BoundsSpec, BoundExpr);
1935
1936 // R1036 bounds-remapping -> lower-bound-expr : upper-bound-expr
1937 struct BoundsRemapping {
1938 TUPLE_CLASS_BOILERPLATE(BoundsRemapping);
1939 std::tuple<BoundExpr, BoundExpr> t;
1940 };
1941
1942 // R1033 pointer-assignment-stmt ->
1943 // data-pointer-object [( bounds-spec-list )] => data-target |
1944 // data-pointer-object ( bounds-remapping-list ) => data-target |
1945 // proc-pointer-object => proc-target
1946 // R1034 data-pointer-object ->
1947 // variable-name | scalar-variable % data-pointer-component-name
1948 // R1038 proc-pointer-object -> proc-pointer-name | proc-component-ref
1949 struct PointerAssignmentStmt {
1950 struct Bounds {
1951 UNION_CLASS_BOILERPLATE(Bounds);
1952 std::variant<std::list<BoundsRemapping>, std::list<BoundsSpec>> u;
1953 };
1954 TUPLE_CLASS_BOILERPLATE(PointerAssignmentStmt);
1955 mutable AssignmentStmt::TypedAssignment typedAssignment;
1956 std::tuple<DataRef, Bounds, Expr> t;
1957 };
1958
1959 // R1041 where-stmt -> WHERE ( mask-expr ) where-assignment-stmt
1960 // R1045 where-assignment-stmt -> assignment-stmt
1961 // R1046 mask-expr -> logical-expr
1962 struct WhereStmt {
1963 TUPLE_CLASS_BOILERPLATE(WhereStmt);
1964 std::tuple<LogicalExpr, AssignmentStmt> t;
1965 };
1966
1967 // R1043 where-construct-stmt -> [where-construct-name :] WHERE ( mask-expr )
1968 struct WhereConstructStmt {
1969 TUPLE_CLASS_BOILERPLATE(WhereConstructStmt);
1970 std::tuple<std::optional<Name>, LogicalExpr> t;
1971 };
1972
1973 // R1044 where-body-construct ->
1974 // where-assignment-stmt | where-stmt | where-construct
1975 struct WhereBodyConstruct {
1976 UNION_CLASS_BOILERPLATE(WhereBodyConstruct);
1977 std::variant<Statement<AssignmentStmt>, Statement<WhereStmt>,
1978 common::Indirection<WhereConstruct>>
1979 u;
1980 };
1981
1982 // R1047 masked-elsewhere-stmt ->
1983 // ELSEWHERE ( mask-expr ) [where-construct-name]
1984 struct MaskedElsewhereStmt {
1985 TUPLE_CLASS_BOILERPLATE(MaskedElsewhereStmt);
1986 std::tuple<LogicalExpr, std::optional<Name>> t;
1987 };
1988
1989 // R1048 elsewhere-stmt -> ELSEWHERE [where-construct-name]
1990 WRAPPER_CLASS(ElsewhereStmt, std::optional<Name>);
1991
1992 // R1049 end-where-stmt -> END WHERE [where-construct-name]
1993 WRAPPER_CLASS(EndWhereStmt, std::optional<Name>);
1994
1995 // R1042 where-construct ->
1996 // where-construct-stmt [where-body-construct]...
1997 // [masked-elsewhere-stmt [where-body-construct]...]...
1998 // [elsewhere-stmt [where-body-construct]...] end-where-stmt
1999 struct WhereConstruct {
2000 struct MaskedElsewhere {
2001 TUPLE_CLASS_BOILERPLATE(MaskedElsewhere);
2002 std::tuple<Statement<MaskedElsewhereStmt>, std::list<WhereBodyConstruct>> t;
2003 };
2004 struct Elsewhere {
2005 TUPLE_CLASS_BOILERPLATE(Elsewhere);
2006 std::tuple<Statement<ElsewhereStmt>, std::list<WhereBodyConstruct>> t;
2007 };
2008 TUPLE_CLASS_BOILERPLATE(WhereConstruct);
2009 std::tuple<Statement<WhereConstructStmt>, std::list<WhereBodyConstruct>,
2010 std::list<MaskedElsewhere>, std::optional<Elsewhere>,
2011 Statement<EndWhereStmt>>
2012 t;
2013 };
2014
2015 // R1051 forall-construct-stmt ->
2016 // [forall-construct-name :] FORALL concurrent-header
2017 struct ForallConstructStmt {
2018 TUPLE_CLASS_BOILERPLATE(ForallConstructStmt);
2019 std::tuple<std::optional<Name>, common::Indirection<ConcurrentHeader>> t;
2020 };
2021
2022 // R1053 forall-assignment-stmt -> assignment-stmt | pointer-assignment-stmt
2023 struct ForallAssignmentStmt {
2024 UNION_CLASS_BOILERPLATE(ForallAssignmentStmt);
2025 std::variant<AssignmentStmt, PointerAssignmentStmt> u;
2026 };
2027
2028 // R1055 forall-stmt -> FORALL concurrent-header forall-assignment-stmt
2029 struct ForallStmt {
2030 TUPLE_CLASS_BOILERPLATE(ForallStmt);
2031 std::tuple<common::Indirection<ConcurrentHeader>,
2032 UnlabeledStatement<ForallAssignmentStmt>>
2033 t;
2034 };
2035
2036 // R1052 forall-body-construct ->
2037 // forall-assignment-stmt | where-stmt | where-construct |
2038 // forall-construct | forall-stmt
2039 struct ForallBodyConstruct {
2040 UNION_CLASS_BOILERPLATE(ForallBodyConstruct);
2041 std::variant<Statement<ForallAssignmentStmt>, Statement<WhereStmt>,
2042 WhereConstruct, common::Indirection<ForallConstruct>,
2043 Statement<ForallStmt>>
2044 u;
2045 };
2046
2047 // R1054 end-forall-stmt -> END FORALL [forall-construct-name]
2048 WRAPPER_CLASS(EndForallStmt, std::optional<Name>);
2049
2050 // R1050 forall-construct ->
2051 // forall-construct-stmt [forall-body-construct]... end-forall-stmt
2052 struct ForallConstruct {
2053 TUPLE_CLASS_BOILERPLATE(ForallConstruct);
2054 std::tuple<Statement<ForallConstructStmt>, std::list<ForallBodyConstruct>,
2055 Statement<EndForallStmt>>
2056 t;
2057 };
2058
2059 // R1101 block -> [execution-part-construct]...
2060 using Block = std::list<ExecutionPartConstruct>;
2061
2062 // R1105 selector -> expr | variable
2063 struct Selector {
2064 UNION_CLASS_BOILERPLATE(Selector);
2065 std::variant<Expr, Variable> u;
2066 };
2067
2068 // R1104 association -> associate-name => selector
2069 struct Association {
2070 TUPLE_CLASS_BOILERPLATE(Association);
2071 std::tuple<Name, Selector> t;
2072 };
2073
2074 // R1103 associate-stmt ->
2075 // [associate-construct-name :] ASSOCIATE ( association-list )
2076 struct AssociateStmt {
2077 TUPLE_CLASS_BOILERPLATE(AssociateStmt);
2078 std::tuple<std::optional<Name>, std::list<Association>> t;
2079 };
2080
2081 // R1106 end-associate-stmt -> END ASSOCIATE [associate-construct-name]
2082 WRAPPER_CLASS(EndAssociateStmt, std::optional<Name>);
2083
2084 // R1102 associate-construct -> associate-stmt block end-associate-stmt
2085 struct AssociateConstruct {
2086 TUPLE_CLASS_BOILERPLATE(AssociateConstruct);
2087 std::tuple<Statement<AssociateStmt>, Block, Statement<EndAssociateStmt>> t;
2088 };
2089
2090 // R1108 block-stmt -> [block-construct-name :] BLOCK
2091 WRAPPER_CLASS(BlockStmt, std::optional<Name>);
2092
2093 // R1110 end-block-stmt -> END BLOCK [block-construct-name]
2094 WRAPPER_CLASS(EndBlockStmt, std::optional<Name>);
2095
2096 // R1109 block-specification-part ->
2097 // [use-stmt]... [import-stmt]...
2098 // [[declaration-construct]... specification-construct]
2099 WRAPPER_CLASS(BlockSpecificationPart, SpecificationPart);
2100 // TODO: Because BlockSpecificationPart just wraps the more general
2101 // SpecificationPart, it can misrecognize an ImplicitPart as part of
2102 // the BlockSpecificationPart during parsing, and we have to detect and
2103 // flag such usage in semantics.
2104
2105 // R1107 block-construct ->
2106 // block-stmt [block-specification-part] block end-block-stmt
2107 struct BlockConstruct {
2108 TUPLE_CLASS_BOILERPLATE(BlockConstruct);
2109 std::tuple<Statement<BlockStmt>, BlockSpecificationPart, Block,
2110 Statement<EndBlockStmt>>
2111 t;
2112 };
2113
2114 // R1113 coarray-association -> codimension-decl => selector
2115 struct CoarrayAssociation {
2116 TUPLE_CLASS_BOILERPLATE(CoarrayAssociation);
2117 std::tuple<CodimensionDecl, Selector> t;
2118 };
2119
2120 // R1112 change-team-stmt ->
2121 // [team-construct-name :] CHANGE TEAM
2122 // ( team-value [, coarray-association-list] [, sync-stat-list] )
2123 struct ChangeTeamStmt {
2124 TUPLE_CLASS_BOILERPLATE(ChangeTeamStmt);
2125 std::tuple<std::optional<Name>, TeamValue, std::list<CoarrayAssociation>,
2126 std::list<StatOrErrmsg>>
2127 t;
2128 };
2129
2130 // R1114 end-change-team-stmt ->
2131 // END TEAM [( [sync-stat-list] )] [team-construct-name]
2132 struct EndChangeTeamStmt {
2133 TUPLE_CLASS_BOILERPLATE(EndChangeTeamStmt);
2134 std::tuple<std::list<StatOrErrmsg>, std::optional<Name>> t;
2135 };
2136
2137 // R1111 change-team-construct -> change-team-stmt block end-change-team-stmt
2138 struct ChangeTeamConstruct {
2139 TUPLE_CLASS_BOILERPLATE(ChangeTeamConstruct);
2140 std::tuple<Statement<ChangeTeamStmt>, Block, Statement<EndChangeTeamStmt>> t;
2141 };
2142
2143 // R1117 critical-stmt ->
2144 // [critical-construct-name :] CRITICAL [( [sync-stat-list] )]
2145 struct CriticalStmt {
2146 TUPLE_CLASS_BOILERPLATE(CriticalStmt);
2147 std::tuple<std::optional<Name>, std::list<StatOrErrmsg>> t;
2148 };
2149
2150 // R1118 end-critical-stmt -> END CRITICAL [critical-construct-name]
2151 WRAPPER_CLASS(EndCriticalStmt, std::optional<Name>);
2152
2153 // R1116 critical-construct -> critical-stmt block end-critical-stmt
2154 struct CriticalConstruct {
2155 TUPLE_CLASS_BOILERPLATE(CriticalConstruct);
2156 std::tuple<Statement<CriticalStmt>, Block, Statement<EndCriticalStmt>> t;
2157 };
2158
2159 // R1126 concurrent-control ->
2160 // index-name = concurrent-limit : concurrent-limit [: concurrent-step]
2161 // R1127 concurrent-limit -> scalar-int-expr
2162 // R1128 concurrent-step -> scalar-int-expr
2163 struct ConcurrentControl {
2164 TUPLE_CLASS_BOILERPLATE(ConcurrentControl);
2165 std::tuple<Name, ScalarIntExpr, ScalarIntExpr, std::optional<ScalarIntExpr>>
2166 t;
2167 };
2168
2169 // R1125 concurrent-header ->
2170 // ( [integer-type-spec ::] concurrent-control-list
2171 // [, scalar-mask-expr] )
2172 struct ConcurrentHeader {
2173 TUPLE_CLASS_BOILERPLATE(ConcurrentHeader);
2174 std::tuple<std::optional<IntegerTypeSpec>, std::list<ConcurrentControl>,
2175 std::optional<ScalarLogicalExpr>>
2176 t;
2177 };
2178
2179 // R1130 locality-spec ->
2180 // LOCAL ( variable-name-list ) | LOCAL_INIT ( variable-name-list ) |
2181 // SHARED ( variable-name-list ) | DEFAULT ( NONE )
2182 struct LocalitySpec {
2183 UNION_CLASS_BOILERPLATE(LocalitySpec);
2184 WRAPPER_CLASS(Local, std::list<Name>);
2185 WRAPPER_CLASS(LocalInit, std::list<Name>);
2186 WRAPPER_CLASS(Shared, std::list<Name>);
2187 EMPTY_CLASS(DefaultNone);
2188 std::variant<Local, LocalInit, Shared, DefaultNone> u;
2189 };
2190
2191 // R1123 loop-control ->
2192 // [,] do-variable = scalar-int-expr , scalar-int-expr
2193 // [, scalar-int-expr] |
2194 // [,] WHILE ( scalar-logical-expr ) |
2195 // [,] CONCURRENT concurrent-header concurrent-locality
2196 // R1129 concurrent-locality -> [locality-spec]...
2197 struct LoopControl {
2198 UNION_CLASS_BOILERPLATE(LoopControl);
2199 struct Concurrent {
2200 TUPLE_CLASS_BOILERPLATE(Concurrent);
2201 std::tuple<ConcurrentHeader, std::list<LocalitySpec>> t;
2202 };
2203 using Bounds = LoopBounds<ScalarName, ScalarExpr>;
2204 std::variant<Bounds, ScalarLogicalExpr, Concurrent> u;
2205 };
2206
2207 // R1121 label-do-stmt -> [do-construct-name :] DO label [loop-control]
2208 struct LabelDoStmt {
2209 TUPLE_CLASS_BOILERPLATE(LabelDoStmt);
2210 std::tuple<std::optional<Name>, Label, std::optional<LoopControl>> t;
2211 };
2212
2213 // R1122 nonlabel-do-stmt -> [do-construct-name :] DO [loop-control]
2214 struct NonLabelDoStmt {
2215 TUPLE_CLASS_BOILERPLATE(NonLabelDoStmt);
2216 std::tuple<std::optional<Name>, std::optional<LoopControl>> t;
2217 };
2218
2219 // R1132 end-do-stmt -> END DO [do-construct-name]
2220 WRAPPER_CLASS(EndDoStmt, std::optional<Name>);
2221
2222 // R1131 end-do -> end-do-stmt | continue-stmt
2223
2224 // R1119 do-construct -> do-stmt block end-do
2225 // R1120 do-stmt -> nonlabel-do-stmt | label-do-stmt
2226 // TODO: deprecated: DO loop ending on statement types other than END DO and
2227 // CONTINUE; multiple "label DO" loops ending on the same label
2228 struct DoConstruct {
2229 TUPLE_CLASS_BOILERPLATE(DoConstruct);
2230 const std::optional<LoopControl> &GetLoopControl() const;
2231 bool IsDoNormal() const;
2232 bool IsDoWhile() const;
2233 bool IsDoConcurrent() const;
2234 std::tuple<Statement<NonLabelDoStmt>, Block, Statement<EndDoStmt>> t;
2235 };
2236
2237 // R1133 cycle-stmt -> CYCLE [do-construct-name]
2238 WRAPPER_CLASS(CycleStmt, std::optional<Name>);
2239
2240 // R1135 if-then-stmt -> [if-construct-name :] IF ( scalar-logical-expr ) THEN
2241 struct IfThenStmt {
2242 TUPLE_CLASS_BOILERPLATE(IfThenStmt);
2243 std::tuple<std::optional<Name>, ScalarLogicalExpr> t;
2244 };
2245
2246 // R1136 else-if-stmt ->
2247 // ELSE IF ( scalar-logical-expr ) THEN [if-construct-name]
2248 struct ElseIfStmt {
2249 TUPLE_CLASS_BOILERPLATE(ElseIfStmt);
2250 std::tuple<ScalarLogicalExpr, std::optional<Name>> t;
2251 };
2252
2253 // R1137 else-stmt -> ELSE [if-construct-name]
2254 WRAPPER_CLASS(ElseStmt, std::optional<Name>);
2255
2256 // R1138 end-if-stmt -> END IF [if-construct-name]
2257 WRAPPER_CLASS(EndIfStmt, std::optional<Name>);
2258
2259 // R1134 if-construct ->
2260 // if-then-stmt block [else-if-stmt block]...
2261 // [else-stmt block] end-if-stmt
2262 struct IfConstruct {
2263 struct ElseIfBlock {
2264 TUPLE_CLASS_BOILERPLATE(ElseIfBlock);
2265 std::tuple<Statement<ElseIfStmt>, Block> t;
2266 };
2267 struct ElseBlock {
2268 TUPLE_CLASS_BOILERPLATE(ElseBlock);
2269 std::tuple<Statement<ElseStmt>, Block> t;
2270 };
2271 TUPLE_CLASS_BOILERPLATE(IfConstruct);
2272 std::tuple<Statement<IfThenStmt>, Block, std::list<ElseIfBlock>,
2273 std::optional<ElseBlock>, Statement<EndIfStmt>>
2274 t;
2275 };
2276
2277 // R1139 if-stmt -> IF ( scalar-logical-expr ) action-stmt
2278 struct IfStmt {
2279 TUPLE_CLASS_BOILERPLATE(IfStmt);
2280 std::tuple<ScalarLogicalExpr, UnlabeledStatement<ActionStmt>> t;
2281 };
2282
2283 // R1141 select-case-stmt -> [case-construct-name :] SELECT CASE ( case-expr )
2284 // R1144 case-expr -> scalar-expr
2285 struct SelectCaseStmt {
2286 TUPLE_CLASS_BOILERPLATE(SelectCaseStmt);
2287 std::tuple<std::optional<Name>, Scalar<Expr>> t;
2288 };
2289
2290 // R1147 case-value -> scalar-constant-expr
2291 using CaseValue = Scalar<ConstantExpr>;
2292
2293 // R1146 case-value-range ->
2294 // case-value | case-value : | : case-value | case-value : case-value
2295 struct CaseValueRange {
2296 UNION_CLASS_BOILERPLATE(CaseValueRange);
2297 struct Range {
2298 BOILERPLATE(Range);
RangeCaseValueRange::Range2299 Range(std::optional<CaseValue> &&l, std::optional<CaseValue> &&u)
2300 : lower{std::move(l)}, upper{std::move(u)} {}
2301 std::optional<CaseValue> lower, upper; // not both missing
2302 };
2303 std::variant<CaseValue, Range> u;
2304 };
2305
2306 // R1145 case-selector -> ( case-value-range-list ) | DEFAULT
2307 EMPTY_CLASS(Default);
2308
2309 struct CaseSelector {
2310 UNION_CLASS_BOILERPLATE(CaseSelector);
2311 std::variant<std::list<CaseValueRange>, Default> u;
2312 };
2313
2314 // R1142 case-stmt -> CASE case-selector [case-construct-name]
2315 struct CaseStmt {
2316 TUPLE_CLASS_BOILERPLATE(CaseStmt);
2317 std::tuple<CaseSelector, std::optional<Name>> t;
2318 };
2319
2320 // R1143 end-select-stmt -> END SELECT [case-construct-name]
2321 // R1151 end-select-rank-stmt -> END SELECT [select-construct-name]
2322 // R1155 end-select-type-stmt -> END SELECT [select-construct-name]
2323 WRAPPER_CLASS(EndSelectStmt, std::optional<Name>);
2324
2325 // R1140 case-construct ->
2326 // select-case-stmt [case-stmt block]... end-select-stmt
2327 struct CaseConstruct {
2328 struct Case {
2329 TUPLE_CLASS_BOILERPLATE(Case);
2330 std::tuple<Statement<CaseStmt>, Block> t;
2331 };
2332 TUPLE_CLASS_BOILERPLATE(CaseConstruct);
2333 std::tuple<Statement<SelectCaseStmt>, std::list<Case>,
2334 Statement<EndSelectStmt>>
2335 t;
2336 };
2337
2338 // R1149 select-rank-stmt ->
2339 // [select-construct-name :] SELECT RANK
2340 // ( [associate-name =>] selector )
2341 struct SelectRankStmt {
2342 TUPLE_CLASS_BOILERPLATE(SelectRankStmt);
2343 std::tuple<std::optional<Name>, std::optional<Name>, Selector> t;
2344 };
2345
2346 // R1150 select-rank-case-stmt ->
2347 // RANK ( scalar-int-constant-expr ) [select-construct-name] |
2348 // RANK ( * ) [select-construct-name] |
2349 // RANK DEFAULT [select-construct-name]
2350 struct SelectRankCaseStmt {
2351 struct Rank {
2352 UNION_CLASS_BOILERPLATE(Rank);
2353 std::variant<ScalarIntConstantExpr, Star, Default> u;
2354 };
2355 TUPLE_CLASS_BOILERPLATE(SelectRankCaseStmt);
2356 std::tuple<Rank, std::optional<Name>> t;
2357 };
2358
2359 // R1148 select-rank-construct ->
2360 // select-rank-stmt [select-rank-case-stmt block]...
2361 // end-select-rank-stmt
2362 struct SelectRankConstruct {
2363 TUPLE_CLASS_BOILERPLATE(SelectRankConstruct);
2364 struct RankCase {
2365 TUPLE_CLASS_BOILERPLATE(RankCase);
2366 std::tuple<Statement<SelectRankCaseStmt>, Block> t;
2367 };
2368 std::tuple<Statement<SelectRankStmt>, std::list<RankCase>,
2369 Statement<EndSelectStmt>>
2370 t;
2371 };
2372
2373 // R1153 select-type-stmt ->
2374 // [select-construct-name :] SELECT TYPE
2375 // ( [associate-name =>] selector )
2376 struct SelectTypeStmt {
2377 TUPLE_CLASS_BOILERPLATE(SelectTypeStmt);
2378 std::tuple<std::optional<Name>, std::optional<Name>, Selector> t;
2379 };
2380
2381 // R1154 type-guard-stmt ->
2382 // TYPE IS ( type-spec ) [select-construct-name] |
2383 // CLASS IS ( derived-type-spec ) [select-construct-name] |
2384 // CLASS DEFAULT [select-construct-name]
2385 struct TypeGuardStmt {
2386 struct Guard {
2387 UNION_CLASS_BOILERPLATE(Guard);
2388 std::variant<TypeSpec, DerivedTypeSpec, Default> u;
2389 };
2390 TUPLE_CLASS_BOILERPLATE(TypeGuardStmt);
2391 std::tuple<Guard, std::optional<Name>> t;
2392 };
2393
2394 // R1152 select-type-construct ->
2395 // select-type-stmt [type-guard-stmt block]... end-select-type-stmt
2396 struct SelectTypeConstruct {
2397 TUPLE_CLASS_BOILERPLATE(SelectTypeConstruct);
2398 struct TypeCase {
2399 TUPLE_CLASS_BOILERPLATE(TypeCase);
2400 std::tuple<Statement<TypeGuardStmt>, Block> t;
2401 };
2402 std::tuple<Statement<SelectTypeStmt>, std::list<TypeCase>,
2403 Statement<EndSelectStmt>>
2404 t;
2405 };
2406
2407 // R1156 exit-stmt -> EXIT [construct-name]
2408 WRAPPER_CLASS(ExitStmt, std::optional<Name>);
2409
2410 // R1157 goto-stmt -> GO TO label
2411 WRAPPER_CLASS(GotoStmt, Label);
2412
2413 // R1158 computed-goto-stmt -> GO TO ( label-list ) [,] scalar-int-expr
2414 struct ComputedGotoStmt {
2415 TUPLE_CLASS_BOILERPLATE(ComputedGotoStmt);
2416 std::tuple<std::list<Label>, ScalarIntExpr> t;
2417 };
2418
2419 // R1162 stop-code -> scalar-default-char-expr | scalar-int-expr
2420 // We can't distinguish character expressions from integer
2421 // expressions during parsing, so we just parse an expr and
2422 // check its type later.
2423 WRAPPER_CLASS(StopCode, Scalar<Expr>);
2424
2425 // R1160 stop-stmt -> STOP [stop-code] [, QUIET = scalar-logical-expr]
2426 // R1161 error-stop-stmt ->
2427 // ERROR STOP [stop-code] [, QUIET = scalar-logical-expr]
2428 struct StopStmt {
2429 ENUM_CLASS(Kind, Stop, ErrorStop)
2430 TUPLE_CLASS_BOILERPLATE(StopStmt);
2431 std::tuple<Kind, std::optional<StopCode>, std::optional<ScalarLogicalExpr>> t;
2432 };
2433
2434 // R1164 sync-all-stmt -> SYNC ALL [( [sync-stat-list] )]
2435 WRAPPER_CLASS(SyncAllStmt, std::list<StatOrErrmsg>);
2436
2437 // R1166 sync-images-stmt -> SYNC IMAGES ( image-set [, sync-stat-list] )
2438 // R1167 image-set -> int-expr | *
2439 struct SyncImagesStmt {
2440 struct ImageSet {
2441 UNION_CLASS_BOILERPLATE(ImageSet);
2442 std::variant<IntExpr, Star> u;
2443 };
2444 TUPLE_CLASS_BOILERPLATE(SyncImagesStmt);
2445 std::tuple<ImageSet, std::list<StatOrErrmsg>> t;
2446 };
2447
2448 // R1168 sync-memory-stmt -> SYNC MEMORY [( [sync-stat-list] )]
2449 WRAPPER_CLASS(SyncMemoryStmt, std::list<StatOrErrmsg>);
2450
2451 // R1169 sync-team-stmt -> SYNC TEAM ( team-value [, sync-stat-list] )
2452 struct SyncTeamStmt {
2453 TUPLE_CLASS_BOILERPLATE(SyncTeamStmt);
2454 std::tuple<TeamValue, std::list<StatOrErrmsg>> t;
2455 };
2456
2457 // R1171 event-variable -> scalar-variable
2458 using EventVariable = Scalar<Variable>;
2459
2460 // R1170 event-post-stmt -> EVENT POST ( event-variable [, sync-stat-list] )
2461 struct EventPostStmt {
2462 TUPLE_CLASS_BOILERPLATE(EventPostStmt);
2463 std::tuple<EventVariable, std::list<StatOrErrmsg>> t;
2464 };
2465
2466 // R1172 event-wait-stmt ->
2467 // EVENT WAIT ( event-variable [, event-wait-spec-list] )
2468 // R1173 event-wait-spec -> until-spec | sync-stat
2469 // R1174 until-spec -> UNTIL_COUNT = scalar-int-expr
2470 struct EventWaitStmt {
2471 struct EventWaitSpec {
2472 UNION_CLASS_BOILERPLATE(EventWaitSpec);
2473 std::variant<ScalarIntExpr, StatOrErrmsg> u;
2474 };
2475 TUPLE_CLASS_BOILERPLATE(EventWaitStmt);
2476 std::tuple<EventVariable, std::list<EventWaitSpec>> t;
2477 };
2478
2479 // R1177 team-variable -> scalar-variable
2480 using TeamVariable = Scalar<Variable>;
2481
2482 // R1175 form-team-stmt ->
2483 // FORM TEAM ( team-number , team-variable [, form-team-spec-list] )
2484 // R1176 team-number -> scalar-int-expr
2485 // R1178 form-team-spec -> NEW_INDEX = scalar-int-expr | sync-stat
2486 struct FormTeamStmt {
2487 struct FormTeamSpec {
2488 UNION_CLASS_BOILERPLATE(FormTeamSpec);
2489 std::variant<ScalarIntExpr, StatOrErrmsg> u;
2490 };
2491 TUPLE_CLASS_BOILERPLATE(FormTeamStmt);
2492 std::tuple<ScalarIntExpr, TeamVariable, std::list<FormTeamSpec>> t;
2493 };
2494
2495 // R1182 lock-variable -> scalar-variable
2496 using LockVariable = Scalar<Variable>;
2497
2498 // R1179 lock-stmt -> LOCK ( lock-variable [, lock-stat-list] )
2499 // R1180 lock-stat -> ACQUIRED_LOCK = scalar-logical-variable | sync-stat
2500 struct LockStmt {
2501 struct LockStat {
2502 UNION_CLASS_BOILERPLATE(LockStat);
2503 std::variant<Scalar<Logical<Variable>>, StatOrErrmsg> u;
2504 };
2505 TUPLE_CLASS_BOILERPLATE(LockStmt);
2506 std::tuple<LockVariable, std::list<LockStat>> t;
2507 };
2508
2509 // R1181 unlock-stmt -> UNLOCK ( lock-variable [, sync-stat-list] )
2510 struct UnlockStmt {
2511 TUPLE_CLASS_BOILERPLATE(UnlockStmt);
2512 std::tuple<LockVariable, std::list<StatOrErrmsg>> t;
2513 };
2514
2515 // R1202 file-unit-number -> scalar-int-expr
2516 WRAPPER_CLASS(FileUnitNumber, ScalarIntExpr);
2517
2518 // R1201 io-unit -> file-unit-number | * | internal-file-variable
2519 // R1203 internal-file-variable -> char-variable
2520 // R905 char-variable -> variable
2521 // When Variable appears as an IoUnit, it must be character of a default,
2522 // ASCII, or Unicode kind; this constraint is not automatically checked.
2523 // The parse is ambiguous and is repaired if necessary once the types of
2524 // symbols are known.
2525 struct IoUnit {
2526 UNION_CLASS_BOILERPLATE(IoUnit);
2527 std::variant<Variable, FileUnitNumber, Star> u;
2528 };
2529
2530 // R1206 file-name-expr -> scalar-default-char-expr
2531 using FileNameExpr = ScalarDefaultCharExpr;
2532
2533 // R1205 connect-spec ->
2534 // [UNIT =] file-unit-number | ACCESS = scalar-default-char-expr |
2535 // ACTION = scalar-default-char-expr |
2536 // ASYNCHRONOUS = scalar-default-char-expr |
2537 // BLANK = scalar-default-char-expr |
2538 // DECIMAL = scalar-default-char-expr |
2539 // DELIM = scalar-default-char-expr |
2540 // ENCODING = scalar-default-char-expr | ERR = label |
2541 // FILE = file-name-expr | FORM = scalar-default-char-expr |
2542 // IOMSG = iomsg-variable | IOSTAT = scalar-int-variable |
2543 // NEWUNIT = scalar-int-variable | PAD = scalar-default-char-expr |
2544 // POSITION = scalar-default-char-expr | RECL = scalar-int-expr |
2545 // ROUND = scalar-default-char-expr | SIGN = scalar-default-char-expr |
2546 // STATUS = scalar-default-char-expr
2547 // @ | CONVERT = scalar-default-char-variable
2548 // | DISPOSE = scalar-default-char-variable
2549 WRAPPER_CLASS(StatusExpr, ScalarDefaultCharExpr);
2550 WRAPPER_CLASS(ErrLabel, Label);
2551
2552 struct ConnectSpec {
2553 UNION_CLASS_BOILERPLATE(ConnectSpec);
2554 struct CharExpr {
2555 ENUM_CLASS(Kind, Access, Action, Asynchronous, Blank, Decimal, Delim,
2556 Encoding, Form, Pad, Position, Round, Sign,
2557 /* extensions: */ Convert, Dispose)
2558 TUPLE_CLASS_BOILERPLATE(CharExpr);
2559 std::tuple<Kind, ScalarDefaultCharExpr> t;
2560 };
2561 WRAPPER_CLASS(Recl, ScalarIntExpr);
2562 WRAPPER_CLASS(Newunit, ScalarIntVariable);
2563 std::variant<FileUnitNumber, FileNameExpr, CharExpr, MsgVariable,
2564 StatVariable, Recl, Newunit, ErrLabel, StatusExpr>
2565 u;
2566 };
2567
2568 // R1204 open-stmt -> OPEN ( connect-spec-list )
2569 WRAPPER_CLASS(OpenStmt, std::list<ConnectSpec>);
2570
2571 // R1208 close-stmt -> CLOSE ( close-spec-list )
2572 // R1209 close-spec ->
2573 // [UNIT =] file-unit-number | IOSTAT = scalar-int-variable |
2574 // IOMSG = iomsg-variable | ERR = label |
2575 // STATUS = scalar-default-char-expr
2576 struct CloseStmt {
2577 struct CloseSpec {
2578 UNION_CLASS_BOILERPLATE(CloseSpec);
2579 std::variant<FileUnitNumber, StatVariable, MsgVariable, ErrLabel,
2580 StatusExpr>
2581 u;
2582 };
2583 WRAPPER_CLASS_BOILERPLATE(CloseStmt, std::list<CloseSpec>);
2584 };
2585
2586 // R1215 format -> default-char-expr | label | *
2587 // deprecated(ASSIGN): | scalar-int-name
2588 struct Format {
2589 UNION_CLASS_BOILERPLATE(Format);
2590 std::variant<Expr, Label, Star> u;
2591 };
2592
2593 // R1214 id-variable -> scalar-int-variable
2594 WRAPPER_CLASS(IdVariable, ScalarIntVariable);
2595
2596 // R1213 io-control-spec ->
2597 // [UNIT =] io-unit | [FMT =] format | [NML =] namelist-group-name |
2598 // ADVANCE = scalar-default-char-expr |
2599 // ASYNCHRONOUS = scalar-default-char-constant-expr |
2600 // BLANK = scalar-default-char-expr |
2601 // DECIMAL = scalar-default-char-expr |
2602 // DELIM = scalar-default-char-expr | END = label | EOR = label |
2603 // ERR = label | ID = id-variable | IOMSG = iomsg-variable |
2604 // IOSTAT = scalar-int-variable | PAD = scalar-default-char-expr |
2605 // POS = scalar-int-expr | REC = scalar-int-expr |
2606 // ROUND = scalar-default-char-expr | SIGN = scalar-default-char-expr |
2607 // SIZE = scalar-int-variable
2608 WRAPPER_CLASS(EndLabel, Label);
2609 WRAPPER_CLASS(EorLabel, Label);
2610 struct IoControlSpec {
2611 UNION_CLASS_BOILERPLATE(IoControlSpec);
2612 struct CharExpr {
2613 ENUM_CLASS(Kind, Advance, Blank, Decimal, Delim, Pad, Round, Sign)
2614 TUPLE_CLASS_BOILERPLATE(CharExpr);
2615 std::tuple<Kind, ScalarDefaultCharExpr> t;
2616 };
2617 WRAPPER_CLASS(Asynchronous, ScalarDefaultCharConstantExpr);
2618 WRAPPER_CLASS(Pos, ScalarIntExpr);
2619 WRAPPER_CLASS(Rec, ScalarIntExpr);
2620 WRAPPER_CLASS(Size, ScalarIntVariable);
2621 std::variant<IoUnit, Format, Name, CharExpr, Asynchronous, EndLabel, EorLabel,
2622 ErrLabel, IdVariable, MsgVariable, StatVariable, Pos, Rec, Size>
2623 u;
2624 };
2625
2626 // R1216 input-item -> variable | io-implied-do
2627 struct InputItem {
2628 UNION_CLASS_BOILERPLATE(InputItem);
2629 std::variant<Variable, common::Indirection<InputImpliedDo>> u;
2630 };
2631
2632 // R1210 read-stmt ->
2633 // READ ( io-control-spec-list ) [input-item-list] |
2634 // READ format [, input-item-list]
2635 struct ReadStmt {
2636 BOILERPLATE(ReadStmt);
ReadStmtReadStmt2637 ReadStmt(std::optional<IoUnit> &&i, std::optional<Format> &&f,
2638 std::list<IoControlSpec> &&cs, std::list<InputItem> &&its)
2639 : iounit{std::move(i)}, format{std::move(f)}, controls(std::move(cs)),
2640 items(std::move(its)) {}
2641 std::optional<IoUnit> iounit; // if first in controls without UNIT= &/or
2642 // followed by untagged format/namelist
2643 std::optional<Format> format; // if second in controls without FMT=/NML=, or
2644 // no (io-control-spec-list); might be
2645 // an untagged namelist group name
2646 std::list<IoControlSpec> controls;
2647 std::list<InputItem> items;
2648 };
2649
2650 // R1217 output-item -> expr | io-implied-do
2651 struct OutputItem {
2652 UNION_CLASS_BOILERPLATE(OutputItem);
2653 std::variant<Expr, common::Indirection<OutputImpliedDo>> u;
2654 };
2655
2656 // R1211 write-stmt -> WRITE ( io-control-spec-list ) [output-item-list]
2657 struct WriteStmt {
2658 BOILERPLATE(WriteStmt);
WriteStmtWriteStmt2659 WriteStmt(std::optional<IoUnit> &&i, std::optional<Format> &&f,
2660 std::list<IoControlSpec> &&cs, std::list<OutputItem> &&its)
2661 : iounit{std::move(i)}, format{std::move(f)}, controls(std::move(cs)),
2662 items(std::move(its)) {}
2663 std::optional<IoUnit> iounit; // if first in controls without UNIT= &/or
2664 // followed by untagged format/namelist
2665 std::optional<Format> format; // if second in controls without FMT=/NML=;
2666 // might be an untagged namelist group, too
2667 std::list<IoControlSpec> controls;
2668 std::list<OutputItem> items;
2669 };
2670
2671 // R1212 print-stmt PRINT format [, output-item-list]
2672 struct PrintStmt {
2673 TUPLE_CLASS_BOILERPLATE(PrintStmt);
2674 std::tuple<Format, std::list<OutputItem>> t;
2675 };
2676
2677 // R1220 io-implied-do-control ->
2678 // do-variable = scalar-int-expr , scalar-int-expr [, scalar-int-expr]
2679 using IoImpliedDoControl = LoopBounds<DoVariable, ScalarIntExpr>;
2680
2681 // R1218 io-implied-do -> ( io-implied-do-object-list , io-implied-do-control )
2682 // R1219 io-implied-do-object -> input-item | output-item
2683 struct InputImpliedDo {
2684 TUPLE_CLASS_BOILERPLATE(InputImpliedDo);
2685 std::tuple<std::list<InputItem>, IoImpliedDoControl> t;
2686 };
2687
2688 struct OutputImpliedDo {
2689 TUPLE_CLASS_BOILERPLATE(OutputImpliedDo);
2690 std::tuple<std::list<OutputItem>, IoImpliedDoControl> t;
2691 };
2692
2693 // R1223 wait-spec ->
2694 // [UNIT =] file-unit-number | END = label | EOR = label | ERR = label |
2695 // ID = scalar-int-expr | IOMSG = iomsg-variable |
2696 // IOSTAT = scalar-int-variable
2697 WRAPPER_CLASS(IdExpr, ScalarIntExpr);
2698 struct WaitSpec {
2699 UNION_CLASS_BOILERPLATE(WaitSpec);
2700 std::variant<FileUnitNumber, EndLabel, EorLabel, ErrLabel, IdExpr,
2701 MsgVariable, StatVariable>
2702 u;
2703 };
2704
2705 // R1222 wait-stmt -> WAIT ( wait-spec-list )
2706 WRAPPER_CLASS(WaitStmt, std::list<WaitSpec>);
2707
2708 // R1227 position-spec ->
2709 // [UNIT =] file-unit-number | IOMSG = iomsg-variable |
2710 // IOSTAT = scalar-int-variable | ERR = label
2711 // R1229 flush-spec ->
2712 // [UNIT =] file-unit-number | IOSTAT = scalar-int-variable |
2713 // IOMSG = iomsg-variable | ERR = label
2714 struct PositionOrFlushSpec {
2715 UNION_CLASS_BOILERPLATE(PositionOrFlushSpec);
2716 std::variant<FileUnitNumber, MsgVariable, StatVariable, ErrLabel> u;
2717 };
2718
2719 // R1224 backspace-stmt ->
2720 // BACKSPACE file-unit-number | BACKSPACE ( position-spec-list )
2721 WRAPPER_CLASS(BackspaceStmt, std::list<PositionOrFlushSpec>);
2722
2723 // R1225 endfile-stmt ->
2724 // ENDFILE file-unit-number | ENDFILE ( position-spec-list )
2725 WRAPPER_CLASS(EndfileStmt, std::list<PositionOrFlushSpec>);
2726
2727 // R1226 rewind-stmt -> REWIND file-unit-number | REWIND ( position-spec-list )
2728 WRAPPER_CLASS(RewindStmt, std::list<PositionOrFlushSpec>);
2729
2730 // R1228 flush-stmt -> FLUSH file-unit-number | FLUSH ( flush-spec-list )
2731 WRAPPER_CLASS(FlushStmt, std::list<PositionOrFlushSpec>);
2732
2733 // R1231 inquire-spec ->
2734 // [UNIT =] file-unit-number | FILE = file-name-expr |
2735 // ACCESS = scalar-default-char-variable |
2736 // ACTION = scalar-default-char-variable |
2737 // ASYNCHRONOUS = scalar-default-char-variable |
2738 // BLANK = scalar-default-char-variable |
2739 // DECIMAL = scalar-default-char-variable |
2740 // DELIM = scalar-default-char-variable |
2741 // DIRECT = scalar-default-char-variable |
2742 // ENCODING = scalar-default-char-variable |
2743 // ERR = label | EXIST = scalar-logical-variable |
2744 // FORM = scalar-default-char-variable |
2745 // FORMATTED = scalar-default-char-variable |
2746 // ID = scalar-int-expr | IOMSG = iomsg-variable |
2747 // IOSTAT = scalar-int-variable |
2748 // NAME = scalar-default-char-variable |
2749 // NAMED = scalar-logical-variable |
2750 // NEXTREC = scalar-int-variable | NUMBER = scalar-int-variable |
2751 // OPENED = scalar-logical-variable |
2752 // PAD = scalar-default-char-variable |
2753 // PENDING = scalar-logical-variable | POS = scalar-int-variable |
2754 // POSITION = scalar-default-char-variable |
2755 // READ = scalar-default-char-variable |
2756 // READWRITE = scalar-default-char-variable |
2757 // RECL = scalar-int-variable | ROUND = scalar-default-char-variable |
2758 // SEQUENTIAL = scalar-default-char-variable |
2759 // SIGN = scalar-default-char-variable |
2760 // SIZE = scalar-int-variable |
2761 // STREAM = scalar-default-char-variable |
2762 // STATUS = scalar-default-char-variable |
2763 // UNFORMATTED = scalar-default-char-variable |
2764 // WRITE = scalar-default-char-variable
2765 // @ | CONVERT = scalar-default-char-variable
2766 // | DISPOSE = scalar-default-char-variable
2767 struct InquireSpec {
2768 UNION_CLASS_BOILERPLATE(InquireSpec);
2769 struct CharVar {
2770 ENUM_CLASS(Kind, Access, Action, Asynchronous, Blank, Decimal, Delim,
2771 Direct, Encoding, Form, Formatted, Iomsg, Name, Pad, Position, Read,
2772 Readwrite, Round, Sequential, Sign, Stream, Status, Unformatted, Write,
2773 /* extensions: */ Convert, Dispose)
2774 TUPLE_CLASS_BOILERPLATE(CharVar);
2775 std::tuple<Kind, ScalarDefaultCharVariable> t;
2776 };
2777 struct IntVar {
2778 ENUM_CLASS(Kind, Iostat, Nextrec, Number, Pos, Recl, Size)
2779 TUPLE_CLASS_BOILERPLATE(IntVar);
2780 std::tuple<Kind, ScalarIntVariable> t;
2781 };
2782 struct LogVar {
2783 ENUM_CLASS(Kind, Exist, Named, Opened, Pending)
2784 TUPLE_CLASS_BOILERPLATE(LogVar);
2785 std::tuple<Kind, Scalar<Logical<Variable>>> t;
2786 };
2787 std::variant<FileUnitNumber, FileNameExpr, CharVar, IntVar, LogVar, IdExpr,
2788 ErrLabel>
2789 u;
2790 };
2791
2792 // R1230 inquire-stmt ->
2793 // INQUIRE ( inquire-spec-list ) |
2794 // INQUIRE ( IOLENGTH = scalar-int-variable ) output-item-list
2795 struct InquireStmt {
2796 UNION_CLASS_BOILERPLATE(InquireStmt);
2797 struct Iolength {
2798 TUPLE_CLASS_BOILERPLATE(Iolength);
2799 std::tuple<ScalarIntVariable, std::list<OutputItem>> t;
2800 };
2801 std::variant<std::list<InquireSpec>, Iolength> u;
2802 };
2803
2804 // R1301 format-stmt -> FORMAT format-specification
2805 WRAPPER_CLASS(FormatStmt, format::FormatSpecification);
2806
2807 // R1402 program-stmt -> PROGRAM program-name
2808 WRAPPER_CLASS(ProgramStmt, Name);
2809
2810 // R1403 end-program-stmt -> END [PROGRAM [program-name]]
2811 WRAPPER_CLASS(EndProgramStmt, std::optional<Name>);
2812
2813 // R1401 main-program ->
2814 // [program-stmt] [specification-part] [execution-part]
2815 // [internal-subprogram-part] end-program-stmt
2816 struct MainProgram {
2817 TUPLE_CLASS_BOILERPLATE(MainProgram);
2818 std::tuple<std::optional<Statement<ProgramStmt>>, SpecificationPart,
2819 ExecutionPart, std::optional<InternalSubprogramPart>,
2820 Statement<EndProgramStmt>>
2821 t;
2822 };
2823
2824 // R1405 module-stmt -> MODULE module-name
2825 WRAPPER_CLASS(ModuleStmt, Name);
2826
2827 // R1408 module-subprogram ->
2828 // function-subprogram | subroutine-subprogram |
2829 // separate-module-subprogram
2830 struct ModuleSubprogram {
2831 UNION_CLASS_BOILERPLATE(ModuleSubprogram);
2832 std::variant<common::Indirection<FunctionSubprogram>,
2833 common::Indirection<SubroutineSubprogram>,
2834 common::Indirection<SeparateModuleSubprogram>>
2835 u;
2836 };
2837
2838 // R1407 module-subprogram-part -> contains-stmt [module-subprogram]...
2839 struct ModuleSubprogramPart {
2840 TUPLE_CLASS_BOILERPLATE(ModuleSubprogramPart);
2841 std::tuple<Statement<ContainsStmt>, std::list<ModuleSubprogram>> t;
2842 };
2843
2844 // R1406 end-module-stmt -> END [MODULE [module-name]]
2845 WRAPPER_CLASS(EndModuleStmt, std::optional<Name>);
2846
2847 // R1404 module ->
2848 // module-stmt [specification-part] [module-subprogram-part]
2849 // end-module-stmt
2850 struct Module {
2851 TUPLE_CLASS_BOILERPLATE(Module);
2852 std::tuple<Statement<ModuleStmt>, SpecificationPart,
2853 std::optional<ModuleSubprogramPart>, Statement<EndModuleStmt>>
2854 t;
2855 };
2856
2857 // R1411 rename ->
2858 // local-name => use-name |
2859 // OPERATOR ( local-defined-operator ) =>
2860 // OPERATOR ( use-defined-operator )
2861 struct Rename {
2862 UNION_CLASS_BOILERPLATE(Rename);
2863 struct Names {
2864 TUPLE_CLASS_BOILERPLATE(Names);
2865 std::tuple<Name, Name> t;
2866 };
2867 struct Operators {
2868 TUPLE_CLASS_BOILERPLATE(Operators);
2869 std::tuple<DefinedOpName, DefinedOpName> t;
2870 };
2871 std::variant<Names, Operators> u;
2872 };
2873
2874 // R1418 parent-identifier -> ancestor-module-name [: parent-submodule-name]
2875 struct ParentIdentifier {
2876 TUPLE_CLASS_BOILERPLATE(ParentIdentifier);
2877 std::tuple<Name, std::optional<Name>> t;
2878 };
2879
2880 // R1417 submodule-stmt -> SUBMODULE ( parent-identifier ) submodule-name
2881 struct SubmoduleStmt {
2882 TUPLE_CLASS_BOILERPLATE(SubmoduleStmt);
2883 std::tuple<ParentIdentifier, Name> t;
2884 };
2885
2886 // R1419 end-submodule-stmt -> END [SUBMODULE [submodule-name]]
2887 WRAPPER_CLASS(EndSubmoduleStmt, std::optional<Name>);
2888
2889 // R1416 submodule ->
2890 // submodule-stmt [specification-part] [module-subprogram-part]
2891 // end-submodule-stmt
2892 struct Submodule {
2893 TUPLE_CLASS_BOILERPLATE(Submodule);
2894 std::tuple<Statement<SubmoduleStmt>, SpecificationPart,
2895 std::optional<ModuleSubprogramPart>, Statement<EndSubmoduleStmt>>
2896 t;
2897 };
2898
2899 // R1421 block-data-stmt -> BLOCK DATA [block-data-name]
2900 WRAPPER_CLASS(BlockDataStmt, std::optional<Name>);
2901
2902 // R1422 end-block-data-stmt -> END [BLOCK DATA [block-data-name]]
2903 WRAPPER_CLASS(EndBlockDataStmt, std::optional<Name>);
2904
2905 // R1420 block-data -> block-data-stmt [specification-part] end-block-data-stmt
2906 struct BlockData {
2907 TUPLE_CLASS_BOILERPLATE(BlockData);
2908 std::tuple<Statement<BlockDataStmt>, SpecificationPart,
2909 Statement<EndBlockDataStmt>>
2910 t;
2911 };
2912
2913 // R1508 generic-spec ->
2914 // generic-name | OPERATOR ( defined-operator ) |
2915 // ASSIGNMENT ( = ) | defined-io-generic-spec
2916 // R1509 defined-io-generic-spec ->
2917 // READ ( FORMATTED ) | READ ( UNFORMATTED ) |
2918 // WRITE ( FORMATTED ) | WRITE ( UNFORMATTED )
2919 struct GenericSpec {
2920 UNION_CLASS_BOILERPLATE(GenericSpec);
2921 EMPTY_CLASS(Assignment);
2922 EMPTY_CLASS(ReadFormatted);
2923 EMPTY_CLASS(ReadUnformatted);
2924 EMPTY_CLASS(WriteFormatted);
2925 EMPTY_CLASS(WriteUnformatted);
2926 CharBlock source;
2927 std::variant<Name, DefinedOperator, Assignment, ReadFormatted,
2928 ReadUnformatted, WriteFormatted, WriteUnformatted>
2929 u;
2930 };
2931
2932 // R1510 generic-stmt ->
2933 // GENERIC [, access-spec] :: generic-spec => specific-procedure-list
2934 struct GenericStmt {
2935 TUPLE_CLASS_BOILERPLATE(GenericStmt);
2936 std::tuple<std::optional<AccessSpec>, GenericSpec, std::list<Name>> t;
2937 };
2938
2939 // R1503 interface-stmt -> INTERFACE [generic-spec] | ABSTRACT INTERFACE
2940 struct InterfaceStmt {
2941 UNION_CLASS_BOILERPLATE(InterfaceStmt);
2942 // Workaround for clang with libstc++10 bug
InterfaceStmtInterfaceStmt2943 InterfaceStmt(Abstract x) : u{x} {}
2944
2945 std::variant<std::optional<GenericSpec>, Abstract> u;
2946 };
2947
2948 // R1412 only -> generic-spec | only-use-name | rename
2949 // R1413 only-use-name -> use-name
2950 struct Only {
2951 UNION_CLASS_BOILERPLATE(Only);
2952 std::variant<common::Indirection<GenericSpec>, Name, Rename> u;
2953 };
2954
2955 // R1409 use-stmt ->
2956 // USE [[, module-nature] ::] module-name [, rename-list] |
2957 // USE [[, module-nature] ::] module-name , ONLY : [only-list]
2958 // R1410 module-nature -> INTRINSIC | NON_INTRINSIC
2959 struct UseStmt {
2960 BOILERPLATE(UseStmt);
ENUM_CLASSUseStmt2961 ENUM_CLASS(ModuleNature, Intrinsic, Non_Intrinsic) // R1410
2962 template <typename A>
2963 UseStmt(std::optional<ModuleNature> &&nat, Name &&n, std::list<A> &&x)
2964 : nature(std::move(nat)), moduleName(std::move(n)), u(std::move(x)) {}
2965 std::optional<ModuleNature> nature;
2966 Name moduleName;
2967 std::variant<std::list<Rename>, std::list<Only>> u;
2968 };
2969
2970 // R1514 proc-attr-spec ->
2971 // access-spec | proc-language-binding-spec | INTENT ( intent-spec ) |
2972 // OPTIONAL | POINTER | PROTECTED | SAVE
2973 struct ProcAttrSpec {
2974 UNION_CLASS_BOILERPLATE(ProcAttrSpec);
2975 std::variant<AccessSpec, LanguageBindingSpec, IntentSpec, Optional, Pointer,
2976 Protected, Save>
2977 u;
2978 };
2979
2980 // R1512 procedure-declaration-stmt ->
2981 // PROCEDURE ( [proc-interface] ) [[, proc-attr-spec]... ::]
2982 // proc-decl-list
2983 struct ProcedureDeclarationStmt {
2984 TUPLE_CLASS_BOILERPLATE(ProcedureDeclarationStmt);
2985 std::tuple<std::optional<ProcInterface>, std::list<ProcAttrSpec>,
2986 std::list<ProcDecl>>
2987 t;
2988 };
2989
2990 // R1527 prefix-spec ->
2991 // declaration-type-spec | ELEMENTAL | IMPURE | MODULE |
2992 // NON_RECURSIVE | PURE | RECURSIVE
2993 struct PrefixSpec {
2994 UNION_CLASS_BOILERPLATE(PrefixSpec);
2995 EMPTY_CLASS(Elemental);
2996 EMPTY_CLASS(Impure);
2997 EMPTY_CLASS(Module);
2998 EMPTY_CLASS(Non_Recursive);
2999 EMPTY_CLASS(Pure);
3000 EMPTY_CLASS(Recursive);
3001 std::variant<DeclarationTypeSpec, Elemental, Impure, Module, Non_Recursive,
3002 Pure, Recursive>
3003 u;
3004 };
3005
3006 // R1532 suffix ->
3007 // proc-language-binding-spec [RESULT ( result-name )] |
3008 // RESULT ( result-name ) [proc-language-binding-spec]
3009 struct Suffix {
3010 BOILERPLATE(Suffix);
SuffixSuffix3011 Suffix(LanguageBindingSpec &&lbs, std::optional<Name> &&rn)
3012 : binding(std::move(lbs)), resultName(std::move(rn)) {}
SuffixSuffix3013 Suffix(Name &&rn, std::optional<LanguageBindingSpec> &&lbs)
3014 : binding(std::move(lbs)), resultName(std::move(rn)) {}
3015 std::optional<LanguageBindingSpec> binding;
3016 std::optional<Name> resultName;
3017 };
3018
3019 // R1530 function-stmt ->
3020 // [prefix] FUNCTION function-name ( [dummy-arg-name-list] ) [suffix]
3021 // R1526 prefix -> prefix-spec [prefix-spec]...
3022 // R1531 dummy-arg-name -> name
3023 struct FunctionStmt {
3024 TUPLE_CLASS_BOILERPLATE(FunctionStmt);
3025 std::tuple<std::list<PrefixSpec>, Name, std::list<Name>,
3026 std::optional<Suffix>>
3027 t;
3028 };
3029
3030 // R1533 end-function-stmt -> END [FUNCTION [function-name]]
3031 WRAPPER_CLASS(EndFunctionStmt, std::optional<Name>);
3032
3033 // R1536 dummy-arg -> dummy-arg-name | *
3034 struct DummyArg {
3035 UNION_CLASS_BOILERPLATE(DummyArg);
3036 std::variant<Name, Star> u;
3037 };
3038
3039 // R1535 subroutine-stmt ->
3040 // [prefix] SUBROUTINE subroutine-name [( [dummy-arg-list] )
3041 // [proc-language-binding-spec]]
3042 struct SubroutineStmt {
3043 TUPLE_CLASS_BOILERPLATE(SubroutineStmt);
3044 std::tuple<std::list<PrefixSpec>, Name, std::list<DummyArg>,
3045 std::optional<LanguageBindingSpec>>
3046 t;
3047 };
3048
3049 // R1537 end-subroutine-stmt -> END [SUBROUTINE [subroutine-name]]
3050 WRAPPER_CLASS(EndSubroutineStmt, std::optional<Name>);
3051
3052 // R1505 interface-body ->
3053 // function-stmt [specification-part] end-function-stmt |
3054 // subroutine-stmt [specification-part] end-subroutine-stmt
3055 struct InterfaceBody {
3056 UNION_CLASS_BOILERPLATE(InterfaceBody);
3057 struct Function {
3058 TUPLE_CLASS_BOILERPLATE(Function);
3059 std::tuple<Statement<FunctionStmt>, common::Indirection<SpecificationPart>,
3060 Statement<EndFunctionStmt>>
3061 t;
3062 };
3063 struct Subroutine {
3064 TUPLE_CLASS_BOILERPLATE(Subroutine);
3065 std::tuple<Statement<SubroutineStmt>,
3066 common::Indirection<SpecificationPart>, Statement<EndSubroutineStmt>>
3067 t;
3068 };
3069 std::variant<Function, Subroutine> u;
3070 };
3071
3072 // R1506 procedure-stmt -> [MODULE] PROCEDURE [::] specific-procedure-list
3073 struct ProcedureStmt {
3074 ENUM_CLASS(Kind, ModuleProcedure, Procedure)
3075 TUPLE_CLASS_BOILERPLATE(ProcedureStmt);
3076 std::tuple<Kind, std::list<Name>> t;
3077 };
3078
3079 // R1502 interface-specification -> interface-body | procedure-stmt
3080 struct InterfaceSpecification {
3081 UNION_CLASS_BOILERPLATE(InterfaceSpecification);
3082 std::variant<InterfaceBody, Statement<ProcedureStmt>> u;
3083 };
3084
3085 // R1504 end-interface-stmt -> END INTERFACE [generic-spec]
3086 WRAPPER_CLASS(EndInterfaceStmt, std::optional<GenericSpec>);
3087
3088 // R1501 interface-block ->
3089 // interface-stmt [interface-specification]... end-interface-stmt
3090 struct InterfaceBlock {
3091 TUPLE_CLASS_BOILERPLATE(InterfaceBlock);
3092 std::tuple<Statement<InterfaceStmt>, std::list<InterfaceSpecification>,
3093 Statement<EndInterfaceStmt>>
3094 t;
3095 };
3096
3097 // R1511 external-stmt -> EXTERNAL [::] external-name-list
3098 WRAPPER_CLASS(ExternalStmt, std::list<Name>);
3099
3100 // R1519 intrinsic-stmt -> INTRINSIC [::] intrinsic-procedure-name-list
3101 WRAPPER_CLASS(IntrinsicStmt, std::list<Name>);
3102
3103 // R1522 procedure-designator ->
3104 // procedure-name | proc-component-ref | data-ref % binding-name
3105 struct ProcedureDesignator {
3106 UNION_CLASS_BOILERPLATE(ProcedureDesignator);
3107 std::variant<Name, ProcComponentRef> u;
3108 };
3109
3110 // R1525 alt-return-spec -> * label
3111 WRAPPER_CLASS(AltReturnSpec, Label);
3112
3113 // R1524 actual-arg ->
3114 // expr | variable | procedure-name | proc-component-ref |
3115 // alt-return-spec
3116 struct ActualArg {
3117 WRAPPER_CLASS(PercentRef, Variable); // %REF(v) extension
3118 WRAPPER_CLASS(PercentVal, Expr); // %VAL(x) extension
3119 UNION_CLASS_BOILERPLATE(ActualArg);
ActualArgActualArg3120 ActualArg(Expr &&x) : u{common::Indirection<Expr>(std::move(x))} {}
3121 std::variant<common::Indirection<Expr>, AltReturnSpec, PercentRef, PercentVal>
3122 u;
3123 };
3124
3125 // R1523 actual-arg-spec -> [keyword =] actual-arg
3126 struct ActualArgSpec {
3127 TUPLE_CLASS_BOILERPLATE(ActualArgSpec);
3128 std::tuple<std::optional<Keyword>, ActualArg> t;
3129 };
3130
3131 // R1520 function-reference -> procedure-designator ( [actual-arg-spec-list] )
3132 struct Call {
3133 TUPLE_CLASS_BOILERPLATE(Call);
3134 CharBlock source;
3135 std::tuple<ProcedureDesignator, std::list<ActualArgSpec>> t;
3136 };
3137
3138 struct FunctionReference {
3139 WRAPPER_CLASS_BOILERPLATE(FunctionReference, Call);
3140 Designator ConvertToArrayElementRef();
3141 StructureConstructor ConvertToStructureConstructor(
3142 const semantics::DerivedTypeSpec &);
3143 };
3144
3145 // R1521 call-stmt -> CALL procedure-designator [( [actual-arg-spec-list] )]
3146 struct CallStmt {
3147 WRAPPER_CLASS_BOILERPLATE(CallStmt, Call);
3148 mutable common::ForwardOwningPointer<evaluate::ProcedureRef>
3149 typedCall; // filled by semantics
3150 };
3151
3152 // R1529 function-subprogram ->
3153 // function-stmt [specification-part] [execution-part]
3154 // [internal-subprogram-part] end-function-stmt
3155 struct FunctionSubprogram {
3156 TUPLE_CLASS_BOILERPLATE(FunctionSubprogram);
3157 std::tuple<Statement<FunctionStmt>, SpecificationPart, ExecutionPart,
3158 std::optional<InternalSubprogramPart>, Statement<EndFunctionStmt>>
3159 t;
3160 };
3161
3162 // R1534 subroutine-subprogram ->
3163 // subroutine-stmt [specification-part] [execution-part]
3164 // [internal-subprogram-part] end-subroutine-stmt
3165 struct SubroutineSubprogram {
3166 TUPLE_CLASS_BOILERPLATE(SubroutineSubprogram);
3167 std::tuple<Statement<SubroutineStmt>, SpecificationPart, ExecutionPart,
3168 std::optional<InternalSubprogramPart>, Statement<EndSubroutineStmt>>
3169 t;
3170 };
3171
3172 // R1539 mp-subprogram-stmt -> MODULE PROCEDURE procedure-name
3173 WRAPPER_CLASS(MpSubprogramStmt, Name);
3174
3175 // R1540 end-mp-subprogram-stmt -> END [PROCEDURE [procedure-name]]
3176 WRAPPER_CLASS(EndMpSubprogramStmt, std::optional<Name>);
3177
3178 // R1538 separate-module-subprogram ->
3179 // mp-subprogram-stmt [specification-part] [execution-part]
3180 // [internal-subprogram-part] end-mp-subprogram-stmt
3181 struct SeparateModuleSubprogram {
3182 TUPLE_CLASS_BOILERPLATE(SeparateModuleSubprogram);
3183 std::tuple<Statement<MpSubprogramStmt>, SpecificationPart, ExecutionPart,
3184 std::optional<InternalSubprogramPart>, Statement<EndMpSubprogramStmt>>
3185 t;
3186 };
3187
3188 // R1541 entry-stmt -> ENTRY entry-name [( [dummy-arg-list] ) [suffix]]
3189 struct EntryStmt {
3190 TUPLE_CLASS_BOILERPLATE(EntryStmt);
3191 std::tuple<Name, std::list<DummyArg>, std::optional<Suffix>> t;
3192 };
3193
3194 // R1542 return-stmt -> RETURN [scalar-int-expr]
3195 WRAPPER_CLASS(ReturnStmt, std::optional<ScalarIntExpr>);
3196
3197 // R1544 stmt-function-stmt ->
3198 // function-name ( [dummy-arg-name-list] ) = scalar-expr
3199 struct StmtFunctionStmt {
3200 TUPLE_CLASS_BOILERPLATE(StmtFunctionStmt);
3201 std::tuple<Name, std::list<Name>, Scalar<Expr>> t;
3202 Statement<ActionStmt> ConvertToAssignment();
3203 };
3204
3205 // Compiler directives
3206 // !DIR$ IGNORE_TKR [ [(tkr...)] name ]...
3207 // !DIR$ name...
3208 struct CompilerDirective {
3209 UNION_CLASS_BOILERPLATE(CompilerDirective);
3210 struct IgnoreTKR {
3211 TUPLE_CLASS_BOILERPLATE(IgnoreTKR);
3212 std::tuple<std::list<const char *>, Name> t;
3213 };
3214 CharBlock source;
3215 std::variant<std::list<IgnoreTKR>, std::list<Name>> u;
3216 };
3217
3218 // Legacy extensions
3219 struct BasedPointer {
3220 TUPLE_CLASS_BOILERPLATE(BasedPointer);
3221 std::tuple<ObjectName, ObjectName, std::optional<ArraySpec>> t;
3222 };
3223 WRAPPER_CLASS(BasedPointerStmt, std::list<BasedPointer>);
3224
3225 struct Union;
3226 struct StructureDef;
3227
3228 struct StructureField {
3229 UNION_CLASS_BOILERPLATE(StructureField);
3230 std::variant<Statement<DataComponentDefStmt>,
3231 common::Indirection<StructureDef>, common::Indirection<Union>>
3232 u;
3233 };
3234
3235 struct Map {
3236 EMPTY_CLASS(MapStmt);
3237 EMPTY_CLASS(EndMapStmt);
3238 TUPLE_CLASS_BOILERPLATE(Map);
3239 std::tuple<Statement<MapStmt>, std::list<StructureField>,
3240 Statement<EndMapStmt>>
3241 t;
3242 };
3243
3244 struct Union {
3245 EMPTY_CLASS(UnionStmt);
3246 EMPTY_CLASS(EndUnionStmt);
3247 TUPLE_CLASS_BOILERPLATE(Union);
3248 std::tuple<Statement<UnionStmt>, std::list<Map>, Statement<EndUnionStmt>> t;
3249 };
3250
3251 struct StructureStmt {
3252 TUPLE_CLASS_BOILERPLATE(StructureStmt);
3253 std::tuple<Name, bool /*slashes*/, std::list<EntityDecl>> t;
3254 };
3255
3256 struct StructureDef {
3257 EMPTY_CLASS(EndStructureStmt);
3258 TUPLE_CLASS_BOILERPLATE(StructureDef);
3259 std::tuple<Statement<StructureStmt>, std::list<StructureField>,
3260 Statement<EndStructureStmt>>
3261 t;
3262 };
3263
3264 // Old style PARAMETER statement without parentheses.
3265 // Types are determined entirely from the right-hand sides, not the names.
3266 WRAPPER_CLASS(OldParameterStmt, std::list<NamedConstantDef>);
3267
3268 // Deprecations
3269 struct ArithmeticIfStmt {
3270 TUPLE_CLASS_BOILERPLATE(ArithmeticIfStmt);
3271 std::tuple<Expr, Label, Label, Label> t;
3272 };
3273
3274 struct AssignStmt {
3275 TUPLE_CLASS_BOILERPLATE(AssignStmt);
3276 std::tuple<Label, Name> t;
3277 };
3278
3279 struct AssignedGotoStmt {
3280 TUPLE_CLASS_BOILERPLATE(AssignedGotoStmt);
3281 std::tuple<Name, std::list<Label>> t;
3282 };
3283
3284 WRAPPER_CLASS(PauseStmt, std::optional<StopCode>);
3285
3286 // Parse tree nodes for OpenMP 4.5 directives and clauses
3287
3288 // 2.5 proc-bind-clause -> PROC_BIND (MASTER | CLOSE | SPREAD)
3289 struct OmpProcBindClause {
3290 ENUM_CLASS(Type, Close, Master, Spread)
3291 WRAPPER_CLASS_BOILERPLATE(OmpProcBindClause, Type);
3292 };
3293
3294 // 2.15.3.1 default-clause -> DEFAULT (PRIVATE | FIRSTPRIVATE | SHARED | NONE)
3295 struct OmpDefaultClause {
3296 ENUM_CLASS(Type, Private, Firstprivate, Shared, None)
3297 WRAPPER_CLASS_BOILERPLATE(OmpDefaultClause, Type);
3298 };
3299
3300 // 2.1 Directives or clauses may accept a list or extended-list.
3301 // A list item is a variable, array section or common block name (enclosed
3302 // in slashes). An extended list item is a list item or a procedure Name.
3303 // variable-name | / common-block / | array-sections
3304 struct OmpObject {
3305 UNION_CLASS_BOILERPLATE(OmpObject);
3306 std::variant<Designator, /*common block*/ Name> u;
3307 };
3308
3309 WRAPPER_CLASS(OmpObjectList, std::list<OmpObject>);
3310
3311 // 2.15.5.1 map-type -> TO | FROM | TOFROM | ALLOC | RELEASE | DELETE
3312 struct OmpMapType {
3313 TUPLE_CLASS_BOILERPLATE(OmpMapType);
3314 EMPTY_CLASS(Always);
3315 ENUM_CLASS(Type, To, From, Tofrom, Alloc, Release, Delete)
3316 std::tuple<std::optional<Always>, Type> t;
3317 };
3318
3319 // 2.15.5.1 map -> MAP ([ [ALWAYS[,]] map-type : ] variable-name-list)
3320 struct OmpMapClause {
3321 TUPLE_CLASS_BOILERPLATE(OmpMapClause);
3322 std::tuple<std::optional<OmpMapType>, OmpObjectList> t;
3323 };
3324
3325 // 2.15.5.2 defaultmap -> DEFAULTMAP (implicit-behavior[:variable-category])
3326 struct OmpDefaultmapClause {
3327 TUPLE_CLASS_BOILERPLATE(OmpDefaultmapClause);
3328 ENUM_CLASS(ImplicitBehavior, Tofrom)
3329 ENUM_CLASS(VariableCategory, Scalar)
3330 std::tuple<ImplicitBehavior, std::optional<VariableCategory>> t;
3331 };
3332
3333 // 2.7.1 sched-modifier -> MONOTONIC | NONMONOTONIC | SIMD
3334 struct OmpScheduleModifierType {
3335 ENUM_CLASS(ModType, Monotonic, Nonmonotonic, Simd)
3336 WRAPPER_CLASS_BOILERPLATE(OmpScheduleModifierType, ModType);
3337 };
3338
3339 struct OmpScheduleModifier {
3340 TUPLE_CLASS_BOILERPLATE(OmpScheduleModifier);
3341 WRAPPER_CLASS(Modifier1, OmpScheduleModifierType);
3342 WRAPPER_CLASS(Modifier2, OmpScheduleModifierType);
3343 std::tuple<Modifier1, std::optional<Modifier2>> t;
3344 };
3345
3346 // 2.7.1 schedule-clause -> SCHEDULE ([sched-modifier1] [, sched-modifier2]:]
3347 // kind[, chunk_size])
3348 struct OmpScheduleClause {
3349 TUPLE_CLASS_BOILERPLATE(OmpScheduleClause);
3350 ENUM_CLASS(ScheduleType, Static, Dynamic, Guided, Auto, Runtime)
3351 std::tuple<std::optional<OmpScheduleModifier>, ScheduleType,
3352 std::optional<ScalarIntExpr>>
3353 t;
3354 };
3355
3356 // 2.12 if-clause -> IF ([ directive-name-modifier :] scalar-logical-expr)
3357 struct OmpIfClause {
3358 TUPLE_CLASS_BOILERPLATE(OmpIfClause);
3359 ENUM_CLASS(DirectiveNameModifier, Parallel, Target, TargetEnterData,
3360 TargetExitData, TargetData, TargetUpdate, Taskloop, Task)
3361 std::tuple<std::optional<DirectiveNameModifier>, ScalarLogicalExpr> t;
3362 };
3363
3364 // 2.8.1 aligned-clause -> ALIGNED (variable-name-list[ : scalar-constant])
3365 struct OmpAlignedClause {
3366 TUPLE_CLASS_BOILERPLATE(OmpAlignedClause);
3367 std::tuple<std::list<Name>, std::optional<ScalarIntConstantExpr>> t;
3368 };
3369
3370 // 2.15.3.7 linear-modifier -> REF | VAL | UVAL
3371 struct OmpLinearModifier {
3372 ENUM_CLASS(Type, Ref, Val, Uval)
3373 WRAPPER_CLASS_BOILERPLATE(OmpLinearModifier, Type);
3374 };
3375
3376 // 2.15.3.7 linear-clause -> LINEAR (linear-list[ : linear-step])
3377 // linear-list -> list | linear-modifier(list)
3378 struct OmpLinearClause {
3379 UNION_CLASS_BOILERPLATE(OmpLinearClause);
3380 struct WithModifier {
3381 BOILERPLATE(WithModifier);
WithModifierOmpLinearClause::WithModifier3382 WithModifier(OmpLinearModifier &&m, std::list<Name> &&n,
3383 std::optional<ScalarIntConstantExpr> &&s)
3384 : modifier(std::move(m)), names(std::move(n)), step(std::move(s)) {}
3385 OmpLinearModifier modifier;
3386 std::list<Name> names;
3387 std::optional<ScalarIntConstantExpr> step;
3388 };
3389 struct WithoutModifier {
3390 BOILERPLATE(WithoutModifier);
WithoutModifierOmpLinearClause::WithoutModifier3391 WithoutModifier(
3392 std::list<Name> &&n, std::optional<ScalarIntConstantExpr> &&s)
3393 : names(std::move(n)), step(std::move(s)) {}
3394 std::list<Name> names;
3395 std::optional<ScalarIntConstantExpr> step;
3396 };
3397 std::variant<WithModifier, WithoutModifier> u;
3398 };
3399
3400 // 2.15.3.6 reduction-identifier -> + | - | * | .AND. | .OR. | .EQV. | .NEQV. |
3401 // MAX | MIN | IAND | IOR | IEOR
3402 struct OmpReductionOperator {
3403 UNION_CLASS_BOILERPLATE(OmpReductionOperator);
3404 std::variant<DefinedOperator, ProcedureDesignator> u;
3405 };
3406
3407 // 2.15.3.6 reduction-clause -> REDUCTION (reduction-identifier:
3408 // variable-name-list)
3409 struct OmpReductionClause {
3410 TUPLE_CLASS_BOILERPLATE(OmpReductionClause);
3411 std::tuple<OmpReductionOperator, std::list<Designator>> t;
3412 };
3413
3414 // 2.13.9 depend-vec-length -> +/- non-negative-constant
3415 struct OmpDependSinkVecLength {
3416 TUPLE_CLASS_BOILERPLATE(OmpDependSinkVecLength);
3417 std::tuple<DefinedOperator, ScalarIntConstantExpr> t;
3418 };
3419
3420 // 2.13.9 depend-vec -> iterator [+/- depend-vec-length],...,iterator[...]
3421 struct OmpDependSinkVec {
3422 TUPLE_CLASS_BOILERPLATE(OmpDependSinkVec);
3423 std::tuple<Name, std::optional<OmpDependSinkVecLength>> t;
3424 };
3425
3426 // 2.13.9 depend-type -> IN | OUT | INOUT | SOURCE | SINK
3427 struct OmpDependenceType {
3428 ENUM_CLASS(Type, In, Out, Inout, Source, Sink)
3429 WRAPPER_CLASS_BOILERPLATE(OmpDependenceType, Type);
3430 };
3431
3432 // 2.13.9 depend-clause -> DEPEND (((IN | OUT | INOUT) : variable-name-list) |
3433 // SOURCE | SINK : depend-vec)
3434 struct OmpDependClause {
3435 UNION_CLASS_BOILERPLATE(OmpDependClause);
3436 EMPTY_CLASS(Source);
3437 WRAPPER_CLASS(Sink, std::list<OmpDependSinkVec>);
3438 struct InOut {
3439 TUPLE_CLASS_BOILERPLATE(InOut);
3440 std::tuple<OmpDependenceType, std::list<Designator>> t;
3441 };
3442 std::variant<Source, Sink, InOut> u;
3443 };
3444
3445 // 2.7.1 nowait-clause -> NOWAIT
3446 EMPTY_CLASS(OmpNowait);
3447
3448 // OpenMP Clauses
3449 struct OmpClause {
3450 UNION_CLASS_BOILERPLATE(OmpClause);
3451 EMPTY_CLASS(Inbranch);
3452 EMPTY_CLASS(Mergeable);
3453 EMPTY_CLASS(Nogroup);
3454 EMPTY_CLASS(Notinbranch);
3455 EMPTY_CLASS(Simd);
3456 EMPTY_CLASS(Threads);
3457 EMPTY_CLASS(Untied);
3458 WRAPPER_CLASS(Collapse, ScalarIntConstantExpr);
3459 WRAPPER_CLASS(Copyin, OmpObjectList);
3460 WRAPPER_CLASS(Copyprivate, OmpObjectList);
3461 WRAPPER_CLASS(Device, ScalarIntExpr);
3462 WRAPPER_CLASS(DistSchedule, std::optional<ScalarIntExpr>);
3463 WRAPPER_CLASS(Final, ScalarLogicalExpr);
3464 WRAPPER_CLASS(Firstprivate, OmpObjectList);
3465 WRAPPER_CLASS(From, OmpObjectList);
3466 WRAPPER_CLASS(Grainsize, ScalarIntExpr);
3467 WRAPPER_CLASS(IsDevicePtr, std::list<Name>);
3468 WRAPPER_CLASS(Lastprivate, OmpObjectList);
3469 WRAPPER_CLASS(Link, OmpObjectList);
3470 WRAPPER_CLASS(NumTasks, ScalarIntExpr);
3471 WRAPPER_CLASS(NumTeams, ScalarIntExpr);
3472 WRAPPER_CLASS(NumThreads, ScalarIntExpr);
3473 WRAPPER_CLASS(Ordered, std::optional<ScalarIntConstantExpr>);
3474 WRAPPER_CLASS(Priority, ScalarIntExpr);
3475 WRAPPER_CLASS(Private, OmpObjectList);
3476 WRAPPER_CLASS(Safelen, ScalarIntConstantExpr);
3477 WRAPPER_CLASS(Shared, OmpObjectList);
3478 WRAPPER_CLASS(Simdlen, ScalarIntConstantExpr);
3479 WRAPPER_CLASS(ThreadLimit, ScalarIntExpr);
3480 WRAPPER_CLASS(To, OmpObjectList);
3481 WRAPPER_CLASS(Uniform, std::list<Name>);
3482 WRAPPER_CLASS(UseDevicePtr, std::list<Name>);
3483 CharBlock source;
3484 std::variant<Inbranch, Mergeable, Nogroup, Notinbranch, OmpNowait, Untied,
3485 Threads, Simd, Collapse, Copyin, Copyprivate, Device, DistSchedule, Final,
3486 Firstprivate, From, Grainsize, Lastprivate, NumTasks, NumTeams,
3487 NumThreads, Ordered, Priority, Private, Safelen, Shared, Simdlen,
3488 ThreadLimit, To, Link, Uniform, UseDevicePtr, IsDevicePtr,
3489 OmpAlignedClause, OmpDefaultClause, OmpDefaultmapClause, OmpDependClause,
3490 OmpIfClause, OmpLinearClause, OmpMapClause, OmpProcBindClause,
3491 OmpReductionClause, OmpScheduleClause>
3492 u;
3493 };
3494
3495 struct OmpClauseList {
3496 WRAPPER_CLASS_BOILERPLATE(OmpClauseList, std::list<OmpClause>);
3497 CharBlock source;
3498 };
3499
3500 // 2.7.2 SECTIONS
3501 // 2.11.2 PARALLEL SECTIONS
3502 struct OmpSectionsDirective {
3503 WRAPPER_CLASS_BOILERPLATE(OmpSectionsDirective, llvm::omp::Directive);
3504 CharBlock source;
3505 };
3506
3507 struct OmpBeginSectionsDirective {
3508 TUPLE_CLASS_BOILERPLATE(OmpBeginSectionsDirective);
3509 std::tuple<OmpSectionsDirective, OmpClauseList> t;
3510 CharBlock source;
3511 };
3512 struct OmpEndSectionsDirective {
3513 TUPLE_CLASS_BOILERPLATE(OmpEndSectionsDirective);
3514 std::tuple<OmpSectionsDirective, OmpClauseList> t;
3515 CharBlock source;
3516 };
3517
3518 // [!$omp section]
3519 // structured-block
3520 // [!$omp section
3521 // structured-block]
3522 // ...
3523 WRAPPER_CLASS(OmpSectionBlocks, std::list<Block>);
3524
3525 struct OpenMPSectionsConstruct {
3526 TUPLE_CLASS_BOILERPLATE(OpenMPSectionsConstruct);
3527 std::tuple<OmpBeginSectionsDirective, OmpSectionBlocks,
3528 OmpEndSectionsDirective>
3529 t;
3530 };
3531
3532 // OpenMP directive beginning or ending a block
3533 struct OmpBlockDirective {
3534 WRAPPER_CLASS_BOILERPLATE(OmpBlockDirective, llvm::omp::Directive);
3535 CharBlock source;
3536 };
3537
3538 // 2.10.6 declare-target -> DECLARE TARGET (extended-list) |
3539 // DECLARE TARGET [declare-target-clause[ [,]
3540 // declare-target-clause]...]
3541 struct OmpDeclareTargetWithList {
3542 WRAPPER_CLASS_BOILERPLATE(OmpDeclareTargetWithList, OmpObjectList);
3543 CharBlock source;
3544 };
3545
3546 struct OmpDeclareTargetWithClause {
3547 WRAPPER_CLASS_BOILERPLATE(OmpDeclareTargetWithClause, OmpClauseList);
3548 CharBlock source;
3549 };
3550
3551 struct OmpDeclareTargetSpecifier {
3552 UNION_CLASS_BOILERPLATE(OmpDeclareTargetSpecifier);
3553 std::variant<OmpDeclareTargetWithList, OmpDeclareTargetWithClause> u;
3554 };
3555
3556 struct OpenMPDeclareTargetConstruct {
3557 TUPLE_CLASS_BOILERPLATE(OpenMPDeclareTargetConstruct);
3558 CharBlock source;
3559 std::tuple<Verbatim, OmpDeclareTargetSpecifier> t;
3560 };
3561
3562 // 2.16 declare-reduction -> DECLARE REDUCTION (reduction-identifier : type-list
3563 // : combiner) [initializer-clause]
3564 struct OmpReductionCombiner {
3565 UNION_CLASS_BOILERPLATE(OmpReductionCombiner);
3566 WRAPPER_CLASS(FunctionCombiner, Call);
3567 std::variant<AssignmentStmt, FunctionCombiner> u;
3568 };
3569
3570 WRAPPER_CLASS(OmpReductionInitializerClause, Expr);
3571
3572 struct OpenMPDeclareReductionConstruct {
3573 TUPLE_CLASS_BOILERPLATE(OpenMPDeclareReductionConstruct);
3574 CharBlock source;
3575 std::tuple<Verbatim, OmpReductionOperator, std::list<DeclarationTypeSpec>,
3576 OmpReductionCombiner, std::optional<OmpReductionInitializerClause>>
3577 t;
3578 };
3579
3580 // 2.8.2 declare-simd -> DECLARE SIMD [(proc-name)] [declare-simd-clause[ [,]
3581 // declare-simd-clause]...]
3582 struct OpenMPDeclareSimdConstruct {
3583 TUPLE_CLASS_BOILERPLATE(OpenMPDeclareSimdConstruct);
3584 CharBlock source;
3585 std::tuple<Verbatim, std::optional<Name>, OmpClauseList> t;
3586 };
3587
3588 // 2.15.2 threadprivate -> THREADPRIVATE (variable-name-list)
3589 struct OpenMPThreadprivate {
3590 TUPLE_CLASS_BOILERPLATE(OpenMPThreadprivate);
3591 CharBlock source;
3592 std::tuple<Verbatim, OmpObjectList> t;
3593 };
3594
3595 struct OpenMPDeclarativeConstruct {
3596 UNION_CLASS_BOILERPLATE(OpenMPDeclarativeConstruct);
3597 CharBlock source;
3598 std::variant<OpenMPDeclareReductionConstruct, OpenMPDeclareSimdConstruct,
3599 OpenMPDeclareTargetConstruct, OpenMPThreadprivate>
3600 u;
3601 };
3602
3603 // 2.13.2 CRITICAL [Name] <block> END CRITICAL [Name]
3604 struct OmpCriticalDirective {
3605 TUPLE_CLASS_BOILERPLATE(OmpCriticalDirective);
3606 WRAPPER_CLASS(Hint, ConstantExpr);
3607 CharBlock source;
3608 std::tuple<Verbatim, std::optional<Name>, std::optional<Hint>> t;
3609 };
3610 struct OmpEndCriticalDirective {
3611 TUPLE_CLASS_BOILERPLATE(OmpEndCriticalDirective);
3612 CharBlock source;
3613 std::tuple<Verbatim, std::optional<Name>> t;
3614 };
3615 struct OpenMPCriticalConstruct {
3616 TUPLE_CLASS_BOILERPLATE(OpenMPCriticalConstruct);
3617 std::tuple<OmpCriticalDirective, Block, OmpEndCriticalDirective> t;
3618 };
3619
3620 // 2.13.6 atomic -> ATOMIC [seq_cst[,]] atomic-clause [[,]seq_cst] |
3621 // ATOMIC [seq_cst]
3622 // atomic-clause -> READ | WRITE | UPDATE | CAPTURE
3623
3624 // END ATOMIC
3625 EMPTY_CLASS(OmpEndAtomic);
3626
3627 // ATOMIC Memory related clause
3628 struct OmpMemoryClause {
3629 ENUM_CLASS(MemoryOrder, SeqCst)
3630 WRAPPER_CLASS_BOILERPLATE(OmpMemoryClause, MemoryOrder);
3631 CharBlock source;
3632 };
3633
3634 WRAPPER_CLASS(OmpMemoryClauseList, std::list<OmpMemoryClause>);
3635 WRAPPER_CLASS(OmpMemoryClausePostList, std::list<OmpMemoryClause>);
3636
3637 // ATOMIC READ
3638 struct OmpAtomicRead {
3639 TUPLE_CLASS_BOILERPLATE(OmpAtomicRead);
3640 std::tuple<OmpMemoryClauseList, Verbatim, OmpMemoryClausePostList,
3641 Statement<AssignmentStmt>, std::optional<OmpEndAtomic>>
3642 t;
3643 };
3644
3645 // ATOMIC WRITE
3646 struct OmpAtomicWrite {
3647 TUPLE_CLASS_BOILERPLATE(OmpAtomicWrite);
3648 std::tuple<OmpMemoryClauseList, Verbatim, OmpMemoryClausePostList,
3649 Statement<AssignmentStmt>, std::optional<OmpEndAtomic>>
3650 t;
3651 };
3652
3653 // ATOMIC UPDATE
3654 struct OmpAtomicUpdate {
3655 TUPLE_CLASS_BOILERPLATE(OmpAtomicUpdate);
3656 std::tuple<OmpMemoryClauseList, Verbatim, OmpMemoryClausePostList,
3657 Statement<AssignmentStmt>, std::optional<OmpEndAtomic>>
3658 t;
3659 };
3660
3661 // ATOMIC CAPTURE
3662 struct OmpAtomicCapture {
3663 TUPLE_CLASS_BOILERPLATE(OmpAtomicCapture);
3664 WRAPPER_CLASS(Stmt1, Statement<AssignmentStmt>);
3665 WRAPPER_CLASS(Stmt2, Statement<AssignmentStmt>);
3666 std::tuple<OmpMemoryClauseList, Verbatim, OmpMemoryClausePostList, Stmt1,
3667 Stmt2, OmpEndAtomic>
3668 t;
3669 };
3670
3671 // ATOMIC
3672 struct OmpAtomic {
3673 TUPLE_CLASS_BOILERPLATE(OmpAtomic);
3674 std::tuple<Verbatim, OmpMemoryClauseList, Statement<AssignmentStmt>,
3675 std::optional<OmpEndAtomic>>
3676 t;
3677 };
3678
3679 struct OpenMPAtomicConstruct {
3680 UNION_CLASS_BOILERPLATE(OpenMPAtomicConstruct);
3681 std::variant<OmpAtomicRead, OmpAtomicWrite, OmpAtomicCapture, OmpAtomicUpdate,
3682 OmpAtomic>
3683 u;
3684 };
3685
3686 // OpenMP directives that associate with loop(s)
3687 struct OmpLoopDirective {
3688 WRAPPER_CLASS_BOILERPLATE(OmpLoopDirective, llvm::omp::Directive);
3689 CharBlock source;
3690 };
3691
3692 // 2.14.1 construct-type-clause -> PARALLEL | SECTIONS | DO | TASKGROUP
3693 struct OmpCancelType {
3694 ENUM_CLASS(Type, Parallel, Sections, Do, Taskgroup)
3695 WRAPPER_CLASS_BOILERPLATE(OmpCancelType, Type);
3696 CharBlock source;
3697 };
3698
3699 // 2.14.2 cancellation-point -> CANCELLATION POINT construct-type-clause
3700 struct OpenMPCancellationPointConstruct {
3701 TUPLE_CLASS_BOILERPLATE(OpenMPCancellationPointConstruct);
3702 CharBlock source;
3703 std::tuple<Verbatim, OmpCancelType> t;
3704 };
3705
3706 // 2.14.1 cancel -> CANCEL construct-type-clause [ [,] if-clause]
3707 struct OpenMPCancelConstruct {
3708 TUPLE_CLASS_BOILERPLATE(OpenMPCancelConstruct);
3709 WRAPPER_CLASS(If, ScalarLogicalExpr);
3710 CharBlock source;
3711 std::tuple<Verbatim, OmpCancelType, std::optional<If>> t;
3712 };
3713
3714 // 2.17.8 Flush Construct [OpenMP 5.0]
3715 // memory-order-clause -> acq_rel
3716 // release
3717 // acquire
3718 struct OmpFlushMemoryClause {
3719 ENUM_CLASS(FlushMemoryOrder, AcqRel, Release, Acquire)
3720 WRAPPER_CLASS_BOILERPLATE(OmpFlushMemoryClause, FlushMemoryOrder);
3721 CharBlock source;
3722 };
3723
3724 // 2.17.8 flush -> FLUSH [memory-order-clause] [(variable-name-list)]
3725 struct OpenMPFlushConstruct {
3726 TUPLE_CLASS_BOILERPLATE(OpenMPFlushConstruct);
3727 CharBlock source;
3728 std::tuple<Verbatim, std::optional<OmpFlushMemoryClause>,
3729 std::optional<OmpObjectList>>
3730 t;
3731 };
3732
3733 struct OmpSimpleStandaloneDirective {
3734 WRAPPER_CLASS_BOILERPLATE(OmpSimpleStandaloneDirective, llvm::omp::Directive);
3735 CharBlock source;
3736 };
3737
3738 struct OpenMPSimpleStandaloneConstruct {
3739 TUPLE_CLASS_BOILERPLATE(OpenMPSimpleStandaloneConstruct);
3740 CharBlock source;
3741 std::tuple<OmpSimpleStandaloneDirective, OmpClauseList> t;
3742 };
3743
3744 struct OpenMPStandaloneConstruct {
3745 UNION_CLASS_BOILERPLATE(OpenMPStandaloneConstruct);
3746 CharBlock source;
3747 std::variant<OpenMPSimpleStandaloneConstruct, OpenMPFlushConstruct,
3748 OpenMPCancelConstruct, OpenMPCancellationPointConstruct>
3749 u;
3750 };
3751
3752 struct OmpBeginLoopDirective {
3753 TUPLE_CLASS_BOILERPLATE(OmpBeginLoopDirective);
3754 std::tuple<OmpLoopDirective, OmpClauseList> t;
3755 CharBlock source;
3756 };
3757
3758 struct OmpEndLoopDirective {
3759 TUPLE_CLASS_BOILERPLATE(OmpEndLoopDirective);
3760 std::tuple<OmpLoopDirective, OmpClauseList> t;
3761 CharBlock source;
3762 };
3763
3764 struct OmpBeginBlockDirective {
3765 TUPLE_CLASS_BOILERPLATE(OmpBeginBlockDirective);
3766 std::tuple<OmpBlockDirective, OmpClauseList> t;
3767 CharBlock source;
3768 };
3769
3770 struct OmpEndBlockDirective {
3771 TUPLE_CLASS_BOILERPLATE(OmpEndBlockDirective);
3772 std::tuple<OmpBlockDirective, OmpClauseList> t;
3773 CharBlock source;
3774 };
3775
3776 struct OpenMPBlockConstruct {
3777 TUPLE_CLASS_BOILERPLATE(OpenMPBlockConstruct);
3778 std::tuple<OmpBeginBlockDirective, Block, OmpEndBlockDirective> t;
3779 };
3780
3781 // OpenMP directives enclosing do loop
3782 struct OpenMPLoopConstruct {
3783 TUPLE_CLASS_BOILERPLATE(OpenMPLoopConstruct);
OpenMPLoopConstructOpenMPLoopConstruct3784 OpenMPLoopConstruct(OmpBeginLoopDirective &&a)
3785 : t({std::move(a), std::nullopt, std::nullopt}) {}
3786 std::tuple<OmpBeginLoopDirective, std::optional<DoConstruct>,
3787 std::optional<OmpEndLoopDirective>>
3788 t;
3789 };
3790
3791 struct OpenMPConstruct {
3792 UNION_CLASS_BOILERPLATE(OpenMPConstruct);
3793 std::variant<OpenMPStandaloneConstruct, OpenMPSectionsConstruct,
3794 OpenMPLoopConstruct, OpenMPBlockConstruct, OpenMPAtomicConstruct,
3795 OpenMPCriticalConstruct>
3796 u;
3797 };
3798
3799 // Parse tree nodes for OpenACC 3.0 directives and clauses
3800
3801 struct AccObject {
3802 UNION_CLASS_BOILERPLATE(AccObject);
3803 std::variant<Designator, /*common block*/ Name> u;
3804 };
3805
3806 WRAPPER_CLASS(AccObjectList, std::list<AccObject>);
3807
3808 // OpenACC directive beginning or ending a block
3809 struct AccBlockDirective {
3810 WRAPPER_CLASS_BOILERPLATE(AccBlockDirective, llvm::acc::Directive);
3811 CharBlock source;
3812 };
3813
3814 struct AccLoopDirective {
3815 WRAPPER_CLASS_BOILERPLATE(AccLoopDirective, llvm::acc::Directive);
3816 CharBlock source;
3817 };
3818
3819 struct AccStandaloneDirective {
3820 WRAPPER_CLASS_BOILERPLATE(AccStandaloneDirective, llvm::acc::Directive);
3821 CharBlock source;
3822 };
3823
3824 // 2.11 Combined constructs
3825 struct AccCombinedDirective {
3826 WRAPPER_CLASS_BOILERPLATE(AccCombinedDirective, llvm::acc::Directive);
3827 CharBlock source;
3828 };
3829
3830 struct AccDeclarativeDirective {
3831 WRAPPER_CLASS_BOILERPLATE(AccDeclarativeDirective, llvm::acc::Directive);
3832 CharBlock source;
3833 };
3834
3835 // OpenACC Clauses
3836 struct AccDefaultClause {
3837 ENUM_CLASS(Arg, None, Present)
3838 WRAPPER_CLASS_BOILERPLATE(AccDefaultClause, Arg);
3839 CharBlock source;
3840 };
3841
3842 struct AccDataModifier {
3843 ENUM_CLASS(Modifier, ReadOnly, Zero)
3844 WRAPPER_CLASS_BOILERPLATE(AccDataModifier, Modifier);
3845 CharBlock source;
3846 };
3847
3848 struct AccObjectListWithModifier {
3849 TUPLE_CLASS_BOILERPLATE(AccObjectListWithModifier);
3850 std::tuple<std::optional<AccDataModifier>, AccObjectList> t;
3851 };
3852
3853 // 2.5.13: + | * | max | min | iand | ior | ieor | .and. | .or. | .eqv. | .neqv.
3854 struct AccReductionOperator {
3855 UNION_CLASS_BOILERPLATE(AccReductionOperator);
3856 std::variant<DefinedOperator, ProcedureDesignator> u;
3857 };
3858
3859 struct AccObjectListWithReduction {
3860 TUPLE_CLASS_BOILERPLATE(AccObjectListWithReduction);
3861 std::tuple<AccReductionOperator, AccObjectList> t;
3862 };
3863
3864 struct AccWaitArgument {
3865 TUPLE_CLASS_BOILERPLATE(AccWaitArgument);
3866 std::tuple<std::optional<ScalarIntExpr>, std::list<ScalarIntExpr>> t;
3867 };
3868
3869 struct AccSizeExpr {
3870 TUPLE_CLASS_BOILERPLATE(AccSizeExpr);
3871 CharBlock source;
3872 std::tuple<std::optional<ScalarIntExpr>> t; // if null then *
3873 };
3874
3875 struct AccSizeExprList {
3876 WRAPPER_CLASS_BOILERPLATE(AccSizeExprList, std::list<AccSizeExpr>);
3877 };
3878
3879 struct AccGangArgument {
3880 TUPLE_CLASS_BOILERPLATE(AccGangArgument);
3881 std::tuple<std::optional<ScalarIntExpr>, std::optional<AccSizeExpr>> t;
3882 };
3883
3884 struct AccClause {
3885 UNION_CLASS_BOILERPLATE(AccClause);
3886
3887 EMPTY_CLASS(Auto);
3888 WRAPPER_CLASS(Async, std::optional<ScalarIntExpr>);
3889 WRAPPER_CLASS(Attach, AccObjectList);
3890 WRAPPER_CLASS(Bind, Name);
3891 EMPTY_CLASS(Capture);
3892 WRAPPER_CLASS(Collapse, ScalarIntConstantExpr);
3893 WRAPPER_CLASS(Copy, AccObjectList);
3894 WRAPPER_CLASS(Copyin, AccObjectListWithModifier);
3895 WRAPPER_CLASS(Copyout, AccObjectListWithModifier);
3896 WRAPPER_CLASS(Create, AccObjectListWithModifier);
3897 WRAPPER_CLASS(Default, AccDefaultClause);
3898 WRAPPER_CLASS(DefaultAsync, ScalarIntExpr);
3899 WRAPPER_CLASS(Delete, AccObjectList);
3900 WRAPPER_CLASS(Detach, AccObjectList);
3901 WRAPPER_CLASS(Device, AccObjectList);
3902 WRAPPER_CLASS(DeviceNum, ScalarIntConstantExpr);
3903 WRAPPER_CLASS(DevicePtr, AccObjectList);
3904 WRAPPER_CLASS(DeviceResident, AccObjectList);
3905 WRAPPER_CLASS(DeviceType, std::optional<std::list<Name>>);
3906 EMPTY_CLASS(Finalize);
3907 WRAPPER_CLASS(FirstPrivate, AccObjectList);
3908 WRAPPER_CLASS(Gang, std::optional<AccGangArgument>);
3909 WRAPPER_CLASS(Host, AccObjectList);
3910 WRAPPER_CLASS(If, ScalarLogicalExpr);
3911 EMPTY_CLASS(IfPresent);
3912 EMPTY_CLASS(Independent);
3913 WRAPPER_CLASS(Link, AccObjectList);
3914 WRAPPER_CLASS(NoCreate, AccObjectList);
3915 EMPTY_CLASS(NoHost);
3916 WRAPPER_CLASS(NumGangs, ScalarIntExpr);
3917 WRAPPER_CLASS(NumWorkers, ScalarIntExpr);
3918 WRAPPER_CLASS(Present, AccObjectList);
3919 WRAPPER_CLASS(Private, AccObjectList);
3920 WRAPPER_CLASS(Tile, AccSizeExprList);
3921 WRAPPER_CLASS(UseDevice, AccObjectList);
3922 EMPTY_CLASS(Read);
3923 WRAPPER_CLASS(Reduction, AccObjectListWithReduction);
3924 WRAPPER_CLASS(Self, std::optional<ScalarLogicalExpr>);
3925 EMPTY_CLASS(Seq);
3926 WRAPPER_CLASS(Vector, std::optional<ScalarIntExpr>);
3927 WRAPPER_CLASS(VectorLength, ScalarIntExpr);
3928 WRAPPER_CLASS(Wait, std::optional<AccWaitArgument>);
3929 WRAPPER_CLASS(Worker, std::optional<ScalarIntExpr>);
3930 EMPTY_CLASS(Write);
3931 EMPTY_CLASS(Unknown);
3932
3933 CharBlock source;
3934
3935 std::variant<Auto, Async, Attach, Bind, Capture, Collapse, Copy, Copyin,
3936 Copyout, Create, Default, DefaultAsync, Delete, Detach, Device, DeviceNum,
3937 DevicePtr, DeviceResident, DeviceType, Finalize, FirstPrivate, Gang, Host,
3938 If, IfPresent, Independent, Link, NoCreate, NoHost, NumGangs, NumWorkers,
3939 Present, Private, Tile, UseDevice, Read, Reduction, Self, Seq, Vector,
3940 VectorLength, Wait, Worker, Write, Unknown>
3941 u;
3942 };
3943
3944 struct AccClauseList {
3945 WRAPPER_CLASS_BOILERPLATE(AccClauseList, std::list<AccClause>);
3946 CharBlock source;
3947 };
3948
3949 struct OpenACCRoutineConstruct {
3950 TUPLE_CLASS_BOILERPLATE(OpenACCRoutineConstruct);
3951 CharBlock source;
3952 std::tuple<Verbatim, std::optional<Name>, AccClauseList> t;
3953 };
3954
3955 struct OpenACCCacheConstruct {
3956 TUPLE_CLASS_BOILERPLATE(OpenACCCacheConstruct);
3957 CharBlock source;
3958 std::tuple<Verbatim, AccObjectListWithModifier> t;
3959 };
3960
3961 struct OpenACCWaitConstruct {
3962 TUPLE_CLASS_BOILERPLATE(OpenACCWaitConstruct);
3963 CharBlock source;
3964 std::tuple<Verbatim, std::optional<AccWaitArgument>, AccClauseList> t;
3965 };
3966
3967 struct AccBeginLoopDirective {
3968 TUPLE_CLASS_BOILERPLATE(AccBeginLoopDirective);
3969 std::tuple<AccLoopDirective, AccClauseList> t;
3970 CharBlock source;
3971 };
3972
3973 struct AccBeginBlockDirective {
3974 TUPLE_CLASS_BOILERPLATE(AccBeginBlockDirective);
3975 CharBlock source;
3976 std::tuple<AccBlockDirective, AccClauseList> t;
3977 };
3978
3979 struct AccEndBlockDirective {
3980 CharBlock source;
3981 WRAPPER_CLASS_BOILERPLATE(AccEndBlockDirective, AccBlockDirective);
3982 };
3983
3984 // ACC END ATOMIC
3985 EMPTY_CLASS(AccEndAtomic);
3986
3987 // ACC ATOMIC READ
3988 struct AccAtomicRead {
3989 TUPLE_CLASS_BOILERPLATE(AccAtomicRead);
3990 std::tuple<Verbatim, Statement<AssignmentStmt>, std::optional<AccEndAtomic>>
3991 t;
3992 };
3993
3994 // ACC ATOMIC WRITE
3995 struct AccAtomicWrite {
3996 TUPLE_CLASS_BOILERPLATE(AccAtomicWrite);
3997 std::tuple<Verbatim, Statement<AssignmentStmt>, std::optional<AccEndAtomic>>
3998 t;
3999 };
4000
4001 // ACC ATOMIC UPDATE
4002 struct AccAtomicUpdate {
4003 TUPLE_CLASS_BOILERPLATE(AccAtomicUpdate);
4004 std::tuple<std::optional<Verbatim>, Statement<AssignmentStmt>,
4005 std::optional<AccEndAtomic>>
4006 t;
4007 };
4008
4009 // ACC ATOMIC CAPTURE
4010 struct AccAtomicCapture {
4011 TUPLE_CLASS_BOILERPLATE(AccAtomicCapture);
4012 WRAPPER_CLASS(Stmt1, Statement<AssignmentStmt>);
4013 WRAPPER_CLASS(Stmt2, Statement<AssignmentStmt>);
4014 std::tuple<Verbatim, Stmt1, Stmt2, AccEndAtomic> t;
4015 };
4016
4017 struct OpenACCAtomicConstruct {
4018 UNION_CLASS_BOILERPLATE(OpenACCAtomicConstruct);
4019 std::variant<AccAtomicRead, AccAtomicWrite, AccAtomicCapture, AccAtomicUpdate>
4020 u;
4021 };
4022
4023 struct OpenACCBlockConstruct {
4024 TUPLE_CLASS_BOILERPLATE(OpenACCBlockConstruct);
4025 std::tuple<AccBeginBlockDirective, Block, AccEndBlockDirective> t;
4026 };
4027
4028 struct OpenACCStandaloneDeclarativeConstruct {
4029 TUPLE_CLASS_BOILERPLATE(OpenACCStandaloneDeclarativeConstruct);
4030 CharBlock source;
4031 std::tuple<AccDeclarativeDirective, AccClauseList> t;
4032 };
4033
4034 struct AccBeginCombinedDirective {
4035 TUPLE_CLASS_BOILERPLATE(AccBeginCombinedDirective);
4036 std::tuple<AccCombinedDirective, AccClauseList> t;
4037 };
4038
4039 struct AccEndCombinedDirective {
4040 WRAPPER_CLASS_BOILERPLATE(AccEndCombinedDirective, AccCombinedDirective);
4041 CharBlock source;
4042 };
4043
4044 struct OpenACCCombinedConstruct {
4045 TUPLE_CLASS_BOILERPLATE(OpenACCCombinedConstruct);
4046 CharBlock source;
4047 std::tuple<AccBeginCombinedDirective, Block,
4048 std::optional<AccEndCombinedDirective>>
4049 t;
4050 };
4051
4052 struct OpenACCDeclarativeConstruct {
4053 UNION_CLASS_BOILERPLATE(OpenACCDeclarativeConstruct);
4054 CharBlock source;
4055 std::variant<OpenACCStandaloneDeclarativeConstruct> u;
4056 };
4057
4058 // OpenACC directives enclosing do loop
4059 struct OpenACCLoopConstruct {
4060 TUPLE_CLASS_BOILERPLATE(OpenACCLoopConstruct);
OpenACCLoopConstructOpenACCLoopConstruct4061 OpenACCLoopConstruct(AccBeginLoopDirective &&a)
4062 : t({std::move(a), std::nullopt}) {}
4063 std::tuple<AccBeginLoopDirective, std::optional<DoConstruct>> t;
4064 };
4065
4066 struct OpenACCStandaloneConstruct {
4067 TUPLE_CLASS_BOILERPLATE(OpenACCStandaloneConstruct);
4068 CharBlock source;
4069 std::tuple<AccStandaloneDirective, AccClauseList> t;
4070 };
4071
4072 struct OpenACCConstruct {
4073 UNION_CLASS_BOILERPLATE(OpenACCConstruct);
4074 std::variant<OpenACCBlockConstruct, OpenACCCombinedConstruct,
4075 OpenACCLoopConstruct, OpenACCStandaloneConstruct, OpenACCRoutineConstruct,
4076 OpenACCCacheConstruct, OpenACCWaitConstruct, OpenACCAtomicConstruct>
4077 u;
4078 };
4079
4080 } // namespace Fortran::parser
4081 #endif // FORTRAN_PARSER_PARSE_TREE_H_
4082