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