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