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